1 //===-- Unittests for the printf Converter --------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "src/stdio/printf_core/converter.h"
10 #include "src/stdio/printf_core/core_structs.h"
11 #include "src/stdio/printf_core/string_writer.h"
12 #include "src/stdio/printf_core/writer.h"
13
14 #include "utils/UnitTest/Test.h"
15
16 class LlvmLibcPrintfConverterTest : public __llvm_libc::testing::Test {
17 protected:
18 // void SetUp() override {}
19 // void TearDown() override {}
20
21 char str[60];
22 __llvm_libc::printf_core::StringWriter str_writer =
23 __llvm_libc::printf_core::StringWriter(str);
24 __llvm_libc::printf_core::Writer writer = __llvm_libc::printf_core::Writer(
25 reinterpret_cast<void *>(&str_writer),
26 __llvm_libc::printf_core::write_to_string);
27 };
28
TEST_F(LlvmLibcPrintfConverterTest,SimpleRawConversion)29 TEST_F(LlvmLibcPrintfConverterTest, SimpleRawConversion) {
30 __llvm_libc::printf_core::FormatSection raw_section;
31 raw_section.has_conv = false;
32 raw_section.raw_string = "abc";
33 raw_section.raw_len = 3;
34
35 __llvm_libc::printf_core::convert(&writer, raw_section);
36
37 str_writer.terminate();
38
39 ASSERT_STREQ(str, "abc");
40 ASSERT_EQ(writer.get_chars_written(), 3);
41 }
42
TEST_F(LlvmLibcPrintfConverterTest,PercentConversion)43 TEST_F(LlvmLibcPrintfConverterTest, PercentConversion) {
44 __llvm_libc::printf_core::FormatSection simple_conv;
45 simple_conv.has_conv = true;
46 simple_conv.raw_string = "%%";
47 simple_conv.conv_name = '%';
48
49 __llvm_libc::printf_core::convert(&writer, simple_conv);
50
51 str[1] = '\0';
52
53 ASSERT_STREQ(str, "%");
54 ASSERT_EQ(writer.get_chars_written(), 1);
55 }
56
TEST_F(LlvmLibcPrintfConverterTest,CharConversionSimple)57 TEST_F(LlvmLibcPrintfConverterTest, CharConversionSimple) {
58 __llvm_libc::printf_core::FormatSection simple_conv;
59 simple_conv.has_conv = true;
60 // If has_conv is true, the raw string is ignored. They are not being parsed
61 // and match the actual conversion taking place so that you can compare these
62 // tests with other implmentations. The raw strings are completely optional.
63 simple_conv.raw_string = "%c";
64 simple_conv.conv_name = 'c';
65 simple_conv.conv_val_raw = 'D';
66
67 __llvm_libc::printf_core::convert(&writer, simple_conv);
68
69 str_writer.terminate();
70
71 ASSERT_STREQ(str, "D");
72 ASSERT_EQ(writer.get_chars_written(), 1);
73 }
74
TEST_F(LlvmLibcPrintfConverterTest,CharConversionRightJustified)75 TEST_F(LlvmLibcPrintfConverterTest, CharConversionRightJustified) {
76 __llvm_libc::printf_core::FormatSection right_justified_conv;
77 right_justified_conv.has_conv = true;
78 right_justified_conv.raw_string = "%4c";
79 right_justified_conv.conv_name = 'c';
80 right_justified_conv.min_width = 4;
81 right_justified_conv.conv_val_raw = 'E';
82 __llvm_libc::printf_core::convert(&writer, right_justified_conv);
83
84 str_writer.terminate();
85
86 ASSERT_STREQ(str, " E");
87 ASSERT_EQ(writer.get_chars_written(), 4);
88 }
89
TEST_F(LlvmLibcPrintfConverterTest,CharConversionLeftJustified)90 TEST_F(LlvmLibcPrintfConverterTest, CharConversionLeftJustified) {
91 __llvm_libc::printf_core::FormatSection left_justified_conv;
92 left_justified_conv.has_conv = true;
93 left_justified_conv.raw_string = "%-4c";
94 left_justified_conv.conv_name = 'c';
95 left_justified_conv.flags =
96 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED;
97 left_justified_conv.min_width = 4;
98 left_justified_conv.conv_val_raw = 'F';
99 __llvm_libc::printf_core::convert(&writer, left_justified_conv);
100
101 str_writer.terminate();
102
103 ASSERT_STREQ(str, "F ");
104 ASSERT_EQ(writer.get_chars_written(), 4);
105 }
106
TEST_F(LlvmLibcPrintfConverterTest,StringConversionSimple)107 TEST_F(LlvmLibcPrintfConverterTest, StringConversionSimple) {
108
109 __llvm_libc::printf_core::FormatSection simple_conv;
110 simple_conv.has_conv = true;
111 simple_conv.raw_string = "%s";
112 simple_conv.conv_name = 's';
113 simple_conv.conv_val_ptr = const_cast<char *>("DEF");
114
115 __llvm_libc::printf_core::convert(&writer, simple_conv);
116
117 str_writer.terminate();
118
119 ASSERT_STREQ(str, "DEF");
120 ASSERT_EQ(writer.get_chars_written(), 3);
121 }
122
TEST_F(LlvmLibcPrintfConverterTest,StringConversionPrecisionHigh)123 TEST_F(LlvmLibcPrintfConverterTest, StringConversionPrecisionHigh) {
124 __llvm_libc::printf_core::FormatSection high_precision_conv;
125 high_precision_conv.has_conv = true;
126 high_precision_conv.raw_string = "%4s";
127 high_precision_conv.conv_name = 's';
128 high_precision_conv.precision = 4;
129 high_precision_conv.conv_val_ptr = const_cast<char *>("456");
130 __llvm_libc::printf_core::convert(&writer, high_precision_conv);
131
132 str_writer.terminate();
133
134 ASSERT_STREQ(str, "456");
135 ASSERT_EQ(writer.get_chars_written(), 3);
136 }
137
TEST_F(LlvmLibcPrintfConverterTest,StringConversionPrecisionLow)138 TEST_F(LlvmLibcPrintfConverterTest, StringConversionPrecisionLow) {
139 __llvm_libc::printf_core::FormatSection low_precision_conv;
140 low_precision_conv.has_conv = true;
141 low_precision_conv.raw_string = "%.2s";
142 low_precision_conv.conv_name = 's';
143 low_precision_conv.precision = 2;
144 low_precision_conv.conv_val_ptr = const_cast<char *>("xyz");
145 __llvm_libc::printf_core::convert(&writer, low_precision_conv);
146
147 str_writer.terminate();
148
149 ASSERT_STREQ(str, "xy");
150 ASSERT_EQ(writer.get_chars_written(), 2);
151 }
152
TEST_F(LlvmLibcPrintfConverterTest,StringConversionRightJustified)153 TEST_F(LlvmLibcPrintfConverterTest, StringConversionRightJustified) {
154 __llvm_libc::printf_core::FormatSection right_justified_conv;
155 right_justified_conv.has_conv = true;
156 right_justified_conv.raw_string = "%4s";
157 right_justified_conv.conv_name = 's';
158 right_justified_conv.min_width = 4;
159 right_justified_conv.conv_val_ptr = const_cast<char *>("789");
160 __llvm_libc::printf_core::convert(&writer, right_justified_conv);
161
162 str_writer.terminate();
163
164 ASSERT_STREQ(str, " 789");
165 ASSERT_EQ(writer.get_chars_written(), 4);
166 }
167
TEST_F(LlvmLibcPrintfConverterTest,StringConversionLeftJustified)168 TEST_F(LlvmLibcPrintfConverterTest, StringConversionLeftJustified) {
169 __llvm_libc::printf_core::FormatSection left_justified_conv;
170 left_justified_conv.has_conv = true;
171 left_justified_conv.raw_string = "%-4s";
172 left_justified_conv.conv_name = 's';
173 left_justified_conv.flags =
174 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED;
175 left_justified_conv.min_width = 4;
176 left_justified_conv.conv_val_ptr = const_cast<char *>("ghi");
177 __llvm_libc::printf_core::convert(&writer, left_justified_conv);
178
179 str_writer.terminate();
180
181 ASSERT_STREQ(str, "ghi ");
182 ASSERT_EQ(writer.get_chars_written(), 4);
183 }
184
TEST_F(LlvmLibcPrintfConverterTest,IntConversionSimple)185 TEST_F(LlvmLibcPrintfConverterTest, IntConversionSimple) {
186 __llvm_libc::printf_core::FormatSection section;
187 section.has_conv = true;
188 section.raw_string = "%d";
189 section.conv_name = 'd';
190 section.conv_val_raw = 12345;
191 __llvm_libc::printf_core::convert(&writer, section);
192
193 str_writer.terminate();
194
195 ASSERT_STREQ(str, "12345");
196 ASSERT_EQ(writer.get_chars_written(), 5);
197 }
198
TEST(LlvmLibcPrintfConverterTest,HexConversion)199 TEST(LlvmLibcPrintfConverterTest, HexConversion) {
200 char str[20];
201 __llvm_libc::printf_core::StringWriter str_writer(str);
202 __llvm_libc::printf_core::Writer writer(
203 reinterpret_cast<void *>(&str_writer),
204 __llvm_libc::printf_core::write_to_string);
205
206 __llvm_libc::printf_core::FormatSection section;
207 section.has_conv = true;
208 section.raw_string = "%#018x";
209 section.raw_len = 6;
210 section.conv_name = 'x';
211 section.flags = static_cast<__llvm_libc::printf_core::FormatFlags>(
212 __llvm_libc::printf_core::FormatFlags::ALTERNATE_FORM |
213 __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES);
214 section.min_width = 18;
215 section.conv_val_raw = 0x123456ab;
216 __llvm_libc::printf_core::convert(&writer, section);
217
218 str_writer.terminate();
219 ASSERT_STREQ(str, "0x00000000123456ab");
220 ASSERT_EQ(writer.get_chars_written(), 18);
221 }
222
TEST(LlvmLibcPrintfConverterTest,PointerConversion)223 TEST(LlvmLibcPrintfConverterTest, PointerConversion) {
224 char str[20];
225 __llvm_libc::printf_core::StringWriter str_writer(str);
226 __llvm_libc::printf_core::Writer writer(
227 reinterpret_cast<void *>(&str_writer),
228 __llvm_libc::printf_core::write_to_string);
229
230 __llvm_libc::printf_core::FormatSection section;
231 section.has_conv = true;
232 section.raw_string = "%p";
233 section.raw_len = 2;
234 section.conv_name = 'p';
235 section.conv_val_ptr = (void *)(0x123456ab);
236 __llvm_libc::printf_core::convert(&writer, section);
237
238 str_writer.terminate();
239 ASSERT_STREQ(str, "0x123456ab");
240 ASSERT_EQ(writer.get_chars_written(), 10);
241 }
242
TEST(LlvmLibcPrintfConverterTest,OctConversion)243 TEST(LlvmLibcPrintfConverterTest, OctConversion) {
244 char str[20];
245 __llvm_libc::printf_core::StringWriter str_writer(str);
246 __llvm_libc::printf_core::Writer writer(
247 reinterpret_cast<void *>(&str_writer),
248 __llvm_libc::printf_core::write_to_string);
249
250 __llvm_libc::printf_core::FormatSection section;
251 section.has_conv = true;
252 section.raw_string = "%o";
253 section.raw_len = 2;
254 section.conv_name = 'o';
255 section.conv_val_raw = 01234;
256 __llvm_libc::printf_core::convert(&writer, section);
257
258 str_writer.terminate();
259 ASSERT_STREQ(str, "1234");
260 ASSERT_EQ(writer.get_chars_written(), 4);
261 }
262