196 changes: 196 additions & 0 deletions libc/test/src/stdio/printf_core/parser_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,3 +260,199 @@ TEST(LlvmLibcPrintfParserTest, EvalThreeArgs) {

ASSERT_FORMAT_EQ(expected2, format_arr[2]);
}

#ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE

TEST(LlvmLibcPrintfParserTest, IndexModeOneArg) {
__llvm_libc::printf_core::FormatSection format_arr[10];
const char *str = "%1$d";
int arg1 = 12345;
evaluate(format_arr, str, arg1);

__llvm_libc::printf_core::FormatSection expected;
expected.has_conv = true;
expected.raw_len = 4;
expected.raw_string = str;
expected.conv_val_raw = arg1;
expected.conv_name = 'd';

ASSERT_FORMAT_EQ(expected, format_arr[0]);
}

TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsSequential) {
__llvm_libc::printf_core::FormatSection format_arr[10];
const char *str = "%1$d%2$f%3$s";
int arg1 = 12345;
double arg2 = 123.45;
const char *arg3 = "12345";
evaluate(format_arr, str, arg1, arg2, arg3);

__llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
expected0.has_conv = true;
expected0.raw_len = 4;
expected0.raw_string = str;
expected0.conv_val_raw = arg1;
expected0.conv_name = 'd';

ASSERT_FORMAT_EQ(expected0, format_arr[0]);

expected1.has_conv = true;
expected1.raw_len = 4;
expected1.raw_string = str + 4;
expected1.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
expected1.conv_name = 'f';

ASSERT_FORMAT_EQ(expected1, format_arr[1]);

expected2.has_conv = true;
expected2.raw_len = 4;
expected2.raw_string = str + 8;
expected2.conv_val_ptr = const_cast<char *>(arg3);
expected2.conv_name = 's';

ASSERT_FORMAT_EQ(expected2, format_arr[2]);
}

TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsReverse) {
__llvm_libc::printf_core::FormatSection format_arr[10];
const char *str = "%3$d%2$f%1$s";
int arg1 = 12345;
double arg2 = 123.45;
const char *arg3 = "12345";
evaluate(format_arr, str, arg3, arg2, arg1);

__llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
expected0.has_conv = true;
expected0.raw_len = 4;
expected0.raw_string = str;
expected0.conv_val_raw = arg1;
expected0.conv_name = 'd';

ASSERT_FORMAT_EQ(expected0, format_arr[0]);

expected1.has_conv = true;
expected1.raw_len = 4;
expected1.raw_string = str + 4;
expected1.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
expected1.conv_name = 'f';

ASSERT_FORMAT_EQ(expected1, format_arr[1]);

expected2.has_conv = true;
expected2.raw_len = 4;
expected2.raw_string = str + 8;
expected2.conv_val_ptr = const_cast<char *>(arg3);
expected2.conv_name = 's';

ASSERT_FORMAT_EQ(expected2, format_arr[2]);
}

TEST(LlvmLibcPrintfParserTest, IndexModeTenArgsRandom) {
__llvm_libc::printf_core::FormatSection format_arr[10];
const char *str = "%6$d%3$d%7$d%2$d%8$d%1$d%4$d%9$d%5$d%10$d";
int args[10] = {6, 4, 2, 7, 9, 1, 3, 5, 8, 10};
evaluate(format_arr, str, args[0], args[1], args[2], args[3], args[4],
args[5], args[6], args[7], args[8], args[9]);

for (size_t i = 0; i < 10; ++i) {
__llvm_libc::printf_core::FormatSection expected;
expected.has_conv = true;
expected.raw_len = 4 + (i >= 9 ? 1 : 0);
expected.raw_string = str + (4 * i);
expected.conv_val_raw = i + 1;
expected.conv_name = 'd';
EXPECT_FORMAT_EQ(expected, format_arr[i]);
}
}

TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) {
__llvm_libc::printf_core::FormatSection format_arr[10];
const char *str = "normal text %3$llu %% %2$ *4$f %2$ .*4$f %1$1.1c";
char arg1 = '1';
double arg2 = 123.45;
unsigned long long arg3 = 12345;
int arg4 = 10;
evaluate(format_arr, str, arg1, arg2, arg3, arg4);

__llvm_libc::printf_core::FormatSection expected0, expected1, expected2,
expected3, expected4, expected5, expected6, expected7, expected8,
expected9;

expected0.has_conv = false;
expected0.raw_len = 12;
expected0.raw_string = str;

EXPECT_FORMAT_EQ(expected0, format_arr[0]);

expected1.has_conv = true;
expected1.raw_len = 6;
expected1.raw_string = str + 12;
expected1.length_modifier = __llvm_libc::printf_core::LengthModifier::ll;
expected1.conv_val_raw = arg3;
expected1.conv_name = 'u';

EXPECT_FORMAT_EQ(expected1, format_arr[1]);

expected2.has_conv = false;
expected2.raw_len = 1;
expected2.raw_string = str + 18;

EXPECT_FORMAT_EQ(expected2, format_arr[2]);

expected3.has_conv = true;
expected3.raw_len = 2;
expected3.raw_string = str + 19;
expected3.conv_name = '%';

EXPECT_FORMAT_EQ(expected3, format_arr[3]);

expected4.has_conv = false;
expected4.raw_len = 1;
expected4.raw_string = str + 21;

EXPECT_FORMAT_EQ(expected4, format_arr[4]);

expected5.has_conv = true;
expected5.raw_len = 8;
expected5.raw_string = str + 22;
expected5.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX;
expected5.min_width = arg4;
expected5.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
expected5.conv_name = 'f';

EXPECT_FORMAT_EQ(expected5, format_arr[5]);

expected6.has_conv = false;
expected6.raw_len = 1;
expected6.raw_string = str + 30;

EXPECT_FORMAT_EQ(expected6, format_arr[6]);

expected7.has_conv = true;
expected7.raw_len = 9;
expected7.raw_string = str + 31;
expected7.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX;
expected7.precision = arg4;
expected7.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
expected7.conv_name = 'f';

EXPECT_FORMAT_EQ(expected7, format_arr[7]);

expected8.has_conv = false;
expected8.raw_len = 1;
expected8.raw_string = str + 40;

EXPECT_FORMAT_EQ(expected8, format_arr[8]);

expected9.has_conv = true;
expected9.raw_len = 7;
expected9.raw_string = str + 41;
expected9.min_width = 1;
expected9.precision = 1;
expected9.conv_val_raw = arg1;
expected9.conv_name = 'c';

EXPECT_FORMAT_EQ(expected9, format_arr[9]);
}

#endif // LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE