//===-- Unittests for the printf Converter --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "src/stdio/printf_core/converter.h" #include "src/stdio/printf_core/core_structs.h" #include "src/stdio/printf_core/string_writer.h" #include "src/stdio/printf_core/writer.h" #include "utils/UnitTest/Test.h" class LlvmLibcPrintfConverterTest : public __llvm_libc::testing::Test { protected: // void SetUp() override {} // void TearDown() override {} char str[60]; __llvm_libc::printf_core::StringWriter str_writer = __llvm_libc::printf_core::StringWriter(str); __llvm_libc::printf_core::Writer writer = __llvm_libc::printf_core::Writer( reinterpret_cast(&str_writer), __llvm_libc::printf_core::write_to_string); }; TEST_F(LlvmLibcPrintfConverterTest, SimpleRawConversion) { __llvm_libc::printf_core::FormatSection raw_section; raw_section.has_conv = false; raw_section.raw_string = "abc"; raw_section.raw_len = 3; __llvm_libc::printf_core::convert(&writer, raw_section); str_writer.terminate(); ASSERT_STREQ(str, "abc"); ASSERT_EQ(writer.get_chars_written(), 3); } TEST_F(LlvmLibcPrintfConverterTest, PercentConversion) { __llvm_libc::printf_core::FormatSection simple_conv; simple_conv.has_conv = true; simple_conv.raw_string = "%%"; simple_conv.conv_name = '%'; __llvm_libc::printf_core::convert(&writer, simple_conv); str[1] = '\0'; ASSERT_STREQ(str, "%"); ASSERT_EQ(writer.get_chars_written(), 1); } TEST_F(LlvmLibcPrintfConverterTest, CharConversionSimple) { __llvm_libc::printf_core::FormatSection simple_conv; simple_conv.has_conv = true; // If has_conv is true, the raw string is ignored. They are not being parsed // and match the actual conversion taking place so that you can compare these // tests with other implmentations. The raw strings are completely optional. simple_conv.raw_string = "%c"; simple_conv.conv_name = 'c'; simple_conv.conv_val_raw = 'D'; __llvm_libc::printf_core::convert(&writer, simple_conv); str_writer.terminate(); ASSERT_STREQ(str, "D"); ASSERT_EQ(writer.get_chars_written(), 1); } TEST_F(LlvmLibcPrintfConverterTest, CharConversionRightJustified) { __llvm_libc::printf_core::FormatSection right_justified_conv; right_justified_conv.has_conv = true; right_justified_conv.raw_string = "%4c"; right_justified_conv.conv_name = 'c'; right_justified_conv.min_width = 4; right_justified_conv.conv_val_raw = 'E'; __llvm_libc::printf_core::convert(&writer, right_justified_conv); str_writer.terminate(); ASSERT_STREQ(str, " E"); ASSERT_EQ(writer.get_chars_written(), 4); } TEST_F(LlvmLibcPrintfConverterTest, CharConversionLeftJustified) { __llvm_libc::printf_core::FormatSection left_justified_conv; left_justified_conv.has_conv = true; left_justified_conv.raw_string = "%-4c"; left_justified_conv.conv_name = 'c'; left_justified_conv.flags = __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED; left_justified_conv.min_width = 4; left_justified_conv.conv_val_raw = 'F'; __llvm_libc::printf_core::convert(&writer, left_justified_conv); str_writer.terminate(); ASSERT_STREQ(str, "F "); ASSERT_EQ(writer.get_chars_written(), 4); } TEST_F(LlvmLibcPrintfConverterTest, StringConversionSimple) { __llvm_libc::printf_core::FormatSection simple_conv; simple_conv.has_conv = true; simple_conv.raw_string = "%s"; simple_conv.conv_name = 's'; simple_conv.conv_val_ptr = const_cast("DEF"); __llvm_libc::printf_core::convert(&writer, simple_conv); str_writer.terminate(); ASSERT_STREQ(str, "DEF"); ASSERT_EQ(writer.get_chars_written(), 3); } TEST_F(LlvmLibcPrintfConverterTest, StringConversionPrecisionHigh) { __llvm_libc::printf_core::FormatSection high_precision_conv; high_precision_conv.has_conv = true; high_precision_conv.raw_string = "%4s"; high_precision_conv.conv_name = 's'; high_precision_conv.precision = 4; high_precision_conv.conv_val_ptr = const_cast("456"); __llvm_libc::printf_core::convert(&writer, high_precision_conv); str_writer.terminate(); ASSERT_STREQ(str, "456"); ASSERT_EQ(writer.get_chars_written(), 3); } TEST_F(LlvmLibcPrintfConverterTest, StringConversionPrecisionLow) { __llvm_libc::printf_core::FormatSection low_precision_conv; low_precision_conv.has_conv = true; low_precision_conv.raw_string = "%.2s"; low_precision_conv.conv_name = 's'; low_precision_conv.precision = 2; low_precision_conv.conv_val_ptr = const_cast("xyz"); __llvm_libc::printf_core::convert(&writer, low_precision_conv); str_writer.terminate(); ASSERT_STREQ(str, "xy"); ASSERT_EQ(writer.get_chars_written(), 2); } TEST_F(LlvmLibcPrintfConverterTest, StringConversionRightJustified) { __llvm_libc::printf_core::FormatSection right_justified_conv; right_justified_conv.has_conv = true; right_justified_conv.raw_string = "%4s"; right_justified_conv.conv_name = 's'; right_justified_conv.min_width = 4; right_justified_conv.conv_val_ptr = const_cast("789"); __llvm_libc::printf_core::convert(&writer, right_justified_conv); str_writer.terminate(); ASSERT_STREQ(str, " 789"); ASSERT_EQ(writer.get_chars_written(), 4); } TEST_F(LlvmLibcPrintfConverterTest, StringConversionLeftJustified) { __llvm_libc::printf_core::FormatSection left_justified_conv; left_justified_conv.has_conv = true; left_justified_conv.raw_string = "%-4s"; left_justified_conv.conv_name = 's'; left_justified_conv.flags = __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED; left_justified_conv.min_width = 4; left_justified_conv.conv_val_ptr = const_cast("ghi"); __llvm_libc::printf_core::convert(&writer, left_justified_conv); str_writer.terminate(); ASSERT_STREQ(str, "ghi "); ASSERT_EQ(writer.get_chars_written(), 4); } TEST_F(LlvmLibcPrintfConverterTest, IntConversionSimple) { __llvm_libc::printf_core::FormatSection section; section.has_conv = true; section.raw_string = "%d"; section.conv_name = 'd'; section.conv_val_raw = 12345; __llvm_libc::printf_core::convert(&writer, section); str_writer.terminate(); ASSERT_STREQ(str, "12345"); ASSERT_EQ(writer.get_chars_written(), 5); } TEST(LlvmLibcPrintfConverterTest, HexConversion) { char str[20]; __llvm_libc::printf_core::StringWriter str_writer(str); __llvm_libc::printf_core::Writer writer( reinterpret_cast(&str_writer), __llvm_libc::printf_core::write_to_string); __llvm_libc::printf_core::FormatSection section; section.has_conv = true; section.raw_string = "%#018x"; section.raw_len = 6; section.conv_name = 'x'; section.flags = static_cast<__llvm_libc::printf_core::FormatFlags>( __llvm_libc::printf_core::FormatFlags::ALTERNATE_FORM | __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES); section.min_width = 18; section.conv_val_raw = 0x123456ab; __llvm_libc::printf_core::convert(&writer, section); str_writer.terminate(); ASSERT_STREQ(str, "0x00000000123456ab"); ASSERT_EQ(writer.get_chars_written(), 18); } TEST(LlvmLibcPrintfConverterTest, PointerConversion) { char str[20]; __llvm_libc::printf_core::StringWriter str_writer(str); __llvm_libc::printf_core::Writer writer( reinterpret_cast(&str_writer), __llvm_libc::printf_core::write_to_string); __llvm_libc::printf_core::FormatSection section; section.has_conv = true; section.raw_string = "%p"; section.raw_len = 2; section.conv_name = 'p'; section.conv_val_ptr = (void *)(0x123456ab); __llvm_libc::printf_core::convert(&writer, section); str_writer.terminate(); ASSERT_STREQ(str, "0x123456ab"); ASSERT_EQ(writer.get_chars_written(), 10); } TEST(LlvmLibcPrintfConverterTest, OctConversion) { char str[20]; __llvm_libc::printf_core::StringWriter str_writer(str); __llvm_libc::printf_core::Writer writer( reinterpret_cast(&str_writer), __llvm_libc::printf_core::write_to_string); __llvm_libc::printf_core::FormatSection section; section.has_conv = true; section.raw_string = "%o"; section.raw_len = 2; section.conv_name = 'o'; section.conv_val_raw = 01234; __llvm_libc::printf_core::convert(&writer, section); str_writer.terminate(); ASSERT_STREQ(str, "1234"); ASSERT_EQ(writer.get_chars_written(), 4); }