1 //===-- Unittests for the printf Parser -----------------------------------===//
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/__support/CPP/Bit.h"
10 #include "src/__support/arg_list.h"
11 #include "src/stdio/printf_core/parser.h"
12
13 #include <stdarg.h>
14
15 #include "utils/UnitTest/PrintfMatcher.h"
16 #include "utils/UnitTest/Test.h"
17
init(const char * __restrict str,...)18 void init(const char *__restrict str, ...) {
19 va_list vlist;
20 va_start(vlist, str);
21 __llvm_libc::internal::ArgList v(vlist);
22 va_end(vlist);
23
24 __llvm_libc::printf_core::Parser parser(str, v);
25 }
26
evaluate(__llvm_libc::printf_core::FormatSection * format_arr,const char * __restrict str,...)27 void evaluate(__llvm_libc::printf_core::FormatSection *format_arr,
28 const char *__restrict str, ...) {
29 va_list vlist;
30 va_start(vlist, str);
31 __llvm_libc::internal::ArgList v(vlist);
32 va_end(vlist);
33
34 __llvm_libc::printf_core::Parser parser(str, v);
35
36 for (auto cur_section = parser.get_next_section(); cur_section.raw_len > 0;
37 cur_section = parser.get_next_section()) {
38 *format_arr = cur_section;
39 ++format_arr;
40 }
41 }
42
TEST(LlvmLibcPrintfParserTest,Constructor)43 TEST(LlvmLibcPrintfParserTest, Constructor) { init("test", 1, 2); }
44
TEST(LlvmLibcPrintfParserTest,EvalRaw)45 TEST(LlvmLibcPrintfParserTest, EvalRaw) {
46 __llvm_libc::printf_core::FormatSection format_arr[10];
47 const char *str = "test";
48 evaluate(format_arr, str);
49
50 __llvm_libc::printf_core::FormatSection expected;
51 expected.has_conv = false;
52 expected.raw_len = 4;
53 expected.raw_string = str;
54
55 ASSERT_FORMAT_EQ(expected, format_arr[0]);
56 // TODO: add checks that the format_arr after the last one has length 0
57 }
58
TEST(LlvmLibcPrintfParserTest,EvalSimple)59 TEST(LlvmLibcPrintfParserTest, EvalSimple) {
60 __llvm_libc::printf_core::FormatSection format_arr[10];
61 const char *str = "test %% test";
62 evaluate(format_arr, str);
63
64 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
65 expected0.has_conv = false;
66 expected0.raw_len = 5;
67 expected0.raw_string = str;
68
69 ASSERT_FORMAT_EQ(expected0, format_arr[0]);
70
71 expected1.has_conv = true;
72 expected1.raw_len = 2;
73 expected1.raw_string = str + 5;
74 expected1.conv_name = '%';
75
76 ASSERT_FORMAT_EQ(expected1, format_arr[1]);
77
78 expected2.has_conv = false;
79 expected2.raw_len = 5;
80 expected2.raw_string = str + 7;
81
82 ASSERT_FORMAT_EQ(expected2, format_arr[2]);
83 }
84
TEST(LlvmLibcPrintfParserTest,EvalOneArg)85 TEST(LlvmLibcPrintfParserTest, EvalOneArg) {
86 __llvm_libc::printf_core::FormatSection format_arr[10];
87 const char *str = "%d";
88 int arg1 = 12345;
89 evaluate(format_arr, str, arg1);
90
91 __llvm_libc::printf_core::FormatSection expected;
92 expected.has_conv = true;
93 expected.raw_len = 2;
94 expected.raw_string = str;
95 expected.conv_val_raw = arg1;
96 expected.conv_name = 'd';
97
98 ASSERT_FORMAT_EQ(expected, format_arr[0]);
99 }
100
TEST(LlvmLibcPrintfParserTest,EvalOneArgWithFlags)101 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithFlags) {
102 __llvm_libc::printf_core::FormatSection format_arr[10];
103 const char *str = "%+-0 #d";
104 int arg1 = 12345;
105 evaluate(format_arr, str, arg1);
106
107 __llvm_libc::printf_core::FormatSection expected;
108 expected.has_conv = true;
109 expected.raw_len = 7;
110 expected.raw_string = str;
111 expected.flags = static_cast<__llvm_libc::printf_core::FormatFlags>(
112 __llvm_libc::printf_core::FormatFlags::FORCE_SIGN |
113 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED |
114 __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES |
115 __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX |
116 __llvm_libc::printf_core::FormatFlags::ALTERNATE_FORM);
117 expected.conv_val_raw = arg1;
118 expected.conv_name = 'd';
119
120 ASSERT_FORMAT_EQ(expected, format_arr[0]);
121 }
122
TEST(LlvmLibcPrintfParserTest,EvalOneArgWithWidth)123 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithWidth) {
124 __llvm_libc::printf_core::FormatSection format_arr[10];
125 const char *str = "%12d";
126 int arg1 = 12345;
127 evaluate(format_arr, str, arg1);
128
129 __llvm_libc::printf_core::FormatSection expected;
130 expected.has_conv = true;
131 expected.raw_len = 4;
132 expected.raw_string = str;
133 expected.min_width = 12;
134 expected.conv_val_raw = arg1;
135 expected.conv_name = 'd';
136
137 ASSERT_FORMAT_EQ(expected, format_arr[0]);
138 }
139
TEST(LlvmLibcPrintfParserTest,EvalOneArgWithPrecision)140 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithPrecision) {
141 __llvm_libc::printf_core::FormatSection format_arr[10];
142 const char *str = "%.34d";
143 int arg1 = 12345;
144 evaluate(format_arr, str, arg1);
145
146 __llvm_libc::printf_core::FormatSection expected;
147 expected.has_conv = true;
148 expected.raw_len = 5;
149 expected.raw_string = str;
150 expected.precision = 34;
151 expected.conv_val_raw = arg1;
152 expected.conv_name = 'd';
153
154 ASSERT_FORMAT_EQ(expected, format_arr[0]);
155 }
156
TEST(LlvmLibcPrintfParserTest,EvalOneArgWithTrivialPrecision)157 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithTrivialPrecision) {
158 __llvm_libc::printf_core::FormatSection format_arr[10];
159 const char *str = "%.d";
160 int arg1 = 12345;
161 evaluate(format_arr, str, arg1);
162
163 __llvm_libc::printf_core::FormatSection expected;
164 expected.has_conv = true;
165 expected.raw_len = 3;
166 expected.raw_string = str;
167 expected.precision = 0;
168 expected.conv_val_raw = arg1;
169 expected.conv_name = 'd';
170
171 ASSERT_FORMAT_EQ(expected, format_arr[0]);
172 }
173
TEST(LlvmLibcPrintfParserTest,EvalOneArgWithShortLengthModifier)174 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithShortLengthModifier) {
175 __llvm_libc::printf_core::FormatSection format_arr[10];
176 const char *str = "%hd";
177 int arg1 = 12345;
178 evaluate(format_arr, str, arg1);
179
180 __llvm_libc::printf_core::FormatSection expected;
181 expected.has_conv = true;
182 expected.raw_len = 3;
183 expected.raw_string = str;
184 expected.length_modifier = __llvm_libc::printf_core::LengthModifier::h;
185 expected.conv_val_raw = arg1;
186 expected.conv_name = 'd';
187
188 ASSERT_FORMAT_EQ(expected, format_arr[0]);
189 }
190
TEST(LlvmLibcPrintfParserTest,EvalOneArgWithLongLengthModifier)191 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithLongLengthModifier) {
192 __llvm_libc::printf_core::FormatSection format_arr[10];
193 const char *str = "%lld";
194 int arg1 = 12345;
195 evaluate(format_arr, str, arg1);
196
197 __llvm_libc::printf_core::FormatSection expected;
198 expected.has_conv = true;
199 expected.raw_len = 4;
200 expected.raw_string = str;
201 expected.length_modifier = __llvm_libc::printf_core::LengthModifier::ll;
202 expected.conv_val_raw = arg1;
203 expected.conv_name = 'd';
204
205 ASSERT_FORMAT_EQ(expected, format_arr[0]);
206 }
207
TEST(LlvmLibcPrintfParserTest,EvalOneArgWithAllOptions)208 TEST(LlvmLibcPrintfParserTest, EvalOneArgWithAllOptions) {
209 __llvm_libc::printf_core::FormatSection format_arr[10];
210 const char *str = "% -056.78jd";
211 int arg1 = 12345;
212 evaluate(format_arr, str, arg1);
213
214 __llvm_libc::printf_core::FormatSection expected;
215 expected.has_conv = true;
216 expected.raw_len = 11;
217 expected.raw_string = str;
218 expected.flags = static_cast<__llvm_libc::printf_core::FormatFlags>(
219 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED |
220 __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES |
221 __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX);
222 expected.min_width = 56;
223 expected.precision = 78;
224 expected.length_modifier = __llvm_libc::printf_core::LengthModifier::j;
225 expected.conv_val_raw = arg1;
226 expected.conv_name = 'd';
227
228 ASSERT_FORMAT_EQ(expected, format_arr[0]);
229 }
230
TEST(LlvmLibcPrintfParserTest,EvalThreeArgs)231 TEST(LlvmLibcPrintfParserTest, EvalThreeArgs) {
232 __llvm_libc::printf_core::FormatSection format_arr[10];
233 const char *str = "%d%f%s";
234 int arg1 = 12345;
235 double arg2 = 123.45;
236 const char *arg3 = "12345";
237 evaluate(format_arr, str, arg1, arg2, arg3);
238
239 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
240 expected0.has_conv = true;
241 expected0.raw_len = 2;
242 expected0.raw_string = str;
243 expected0.conv_val_raw = arg1;
244 expected0.conv_name = 'd';
245
246 ASSERT_FORMAT_EQ(expected0, format_arr[0]);
247
248 expected1.has_conv = true;
249 expected1.raw_len = 2;
250 expected1.raw_string = str + 2;
251 expected1.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
252 expected1.conv_name = 'f';
253
254 ASSERT_FORMAT_EQ(expected1, format_arr[1]);
255
256 expected2.has_conv = true;
257 expected2.raw_len = 2;
258 expected2.raw_string = str + 4;
259 expected2.conv_val_ptr = const_cast<char *>(arg3);
260 expected2.conv_name = 's';
261
262 ASSERT_FORMAT_EQ(expected2, format_arr[2]);
263 }
264
265 #ifndef LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
266
TEST(LlvmLibcPrintfParserTest,IndexModeOneArg)267 TEST(LlvmLibcPrintfParserTest, IndexModeOneArg) {
268 __llvm_libc::printf_core::FormatSection format_arr[10];
269 const char *str = "%1$d";
270 int arg1 = 12345;
271 evaluate(format_arr, str, arg1);
272
273 __llvm_libc::printf_core::FormatSection expected;
274 expected.has_conv = true;
275 expected.raw_len = 4;
276 expected.raw_string = str;
277 expected.conv_val_raw = arg1;
278 expected.conv_name = 'd';
279
280 ASSERT_FORMAT_EQ(expected, format_arr[0]);
281 }
282
TEST(LlvmLibcPrintfParserTest,IndexModeThreeArgsSequential)283 TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsSequential) {
284 __llvm_libc::printf_core::FormatSection format_arr[10];
285 const char *str = "%1$d%2$f%3$s";
286 int arg1 = 12345;
287 double arg2 = 123.45;
288 const char *arg3 = "12345";
289 evaluate(format_arr, str, arg1, arg2, arg3);
290
291 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
292 expected0.has_conv = true;
293 expected0.raw_len = 4;
294 expected0.raw_string = str;
295 expected0.conv_val_raw = arg1;
296 expected0.conv_name = 'd';
297
298 ASSERT_FORMAT_EQ(expected0, format_arr[0]);
299
300 expected1.has_conv = true;
301 expected1.raw_len = 4;
302 expected1.raw_string = str + 4;
303 expected1.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
304 expected1.conv_name = 'f';
305
306 ASSERT_FORMAT_EQ(expected1, format_arr[1]);
307
308 expected2.has_conv = true;
309 expected2.raw_len = 4;
310 expected2.raw_string = str + 8;
311 expected2.conv_val_ptr = const_cast<char *>(arg3);
312 expected2.conv_name = 's';
313
314 ASSERT_FORMAT_EQ(expected2, format_arr[2]);
315 }
316
TEST(LlvmLibcPrintfParserTest,IndexModeThreeArgsReverse)317 TEST(LlvmLibcPrintfParserTest, IndexModeThreeArgsReverse) {
318 __llvm_libc::printf_core::FormatSection format_arr[10];
319 const char *str = "%3$d%2$f%1$s";
320 int arg1 = 12345;
321 double arg2 = 123.45;
322 const char *arg3 = "12345";
323 evaluate(format_arr, str, arg3, arg2, arg1);
324
325 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2;
326 expected0.has_conv = true;
327 expected0.raw_len = 4;
328 expected0.raw_string = str;
329 expected0.conv_val_raw = arg1;
330 expected0.conv_name = 'd';
331
332 ASSERT_FORMAT_EQ(expected0, format_arr[0]);
333
334 expected1.has_conv = true;
335 expected1.raw_len = 4;
336 expected1.raw_string = str + 4;
337 expected1.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
338 expected1.conv_name = 'f';
339
340 ASSERT_FORMAT_EQ(expected1, format_arr[1]);
341
342 expected2.has_conv = true;
343 expected2.raw_len = 4;
344 expected2.raw_string = str + 8;
345 expected2.conv_val_ptr = const_cast<char *>(arg3);
346 expected2.conv_name = 's';
347
348 ASSERT_FORMAT_EQ(expected2, format_arr[2]);
349 }
350
TEST(LlvmLibcPrintfParserTest,IndexModeTenArgsRandom)351 TEST(LlvmLibcPrintfParserTest, IndexModeTenArgsRandom) {
352 __llvm_libc::printf_core::FormatSection format_arr[10];
353 const char *str = "%6$d%3$d%7$d%2$d%8$d%1$d%4$d%9$d%5$d%10$d";
354 int args[10] = {6, 4, 2, 7, 9, 1, 3, 5, 8, 10};
355 evaluate(format_arr, str, args[0], args[1], args[2], args[3], args[4],
356 args[5], args[6], args[7], args[8], args[9]);
357
358 for (size_t i = 0; i < 10; ++i) {
359 __llvm_libc::printf_core::FormatSection expected;
360 expected.has_conv = true;
361 expected.raw_len = 4 + (i >= 9 ? 1 : 0);
362 expected.raw_string = str + (4 * i);
363 expected.conv_val_raw = i + 1;
364 expected.conv_name = 'd';
365 EXPECT_FORMAT_EQ(expected, format_arr[i]);
366 }
367 }
368
TEST(LlvmLibcPrintfParserTest,IndexModeComplexParsing)369 TEST(LlvmLibcPrintfParserTest, IndexModeComplexParsing) {
370 __llvm_libc::printf_core::FormatSection format_arr[10];
371 const char *str = "normal text %3$llu %% %2$ *4$f %2$ .*4$f %1$1.1c";
372 char arg1 = '1';
373 double arg2 = 123.45;
374 unsigned long long arg3 = 12345;
375 int arg4 = 10;
376 evaluate(format_arr, str, arg1, arg2, arg3, arg4);
377
378 __llvm_libc::printf_core::FormatSection expected0, expected1, expected2,
379 expected3, expected4, expected5, expected6, expected7, expected8,
380 expected9;
381
382 expected0.has_conv = false;
383 expected0.raw_len = 12;
384 expected0.raw_string = str;
385
386 EXPECT_FORMAT_EQ(expected0, format_arr[0]);
387
388 expected1.has_conv = true;
389 expected1.raw_len = 6;
390 expected1.raw_string = str + 12;
391 expected1.length_modifier = __llvm_libc::printf_core::LengthModifier::ll;
392 expected1.conv_val_raw = arg3;
393 expected1.conv_name = 'u';
394
395 EXPECT_FORMAT_EQ(expected1, format_arr[1]);
396
397 expected2.has_conv = false;
398 expected2.raw_len = 1;
399 expected2.raw_string = str + 18;
400
401 EXPECT_FORMAT_EQ(expected2, format_arr[2]);
402
403 expected3.has_conv = true;
404 expected3.raw_len = 2;
405 expected3.raw_string = str + 19;
406 expected3.conv_name = '%';
407
408 EXPECT_FORMAT_EQ(expected3, format_arr[3]);
409
410 expected4.has_conv = false;
411 expected4.raw_len = 1;
412 expected4.raw_string = str + 21;
413
414 EXPECT_FORMAT_EQ(expected4, format_arr[4]);
415
416 expected5.has_conv = true;
417 expected5.raw_len = 8;
418 expected5.raw_string = str + 22;
419 expected5.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX;
420 expected5.min_width = arg4;
421 expected5.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
422 expected5.conv_name = 'f';
423
424 EXPECT_FORMAT_EQ(expected5, format_arr[5]);
425
426 expected6.has_conv = false;
427 expected6.raw_len = 1;
428 expected6.raw_string = str + 30;
429
430 EXPECT_FORMAT_EQ(expected6, format_arr[6]);
431
432 expected7.has_conv = true;
433 expected7.raw_len = 9;
434 expected7.raw_string = str + 31;
435 expected7.flags = __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX;
436 expected7.precision = arg4;
437 expected7.conv_val_raw = __llvm_libc::bit_cast<uint64_t>(arg2);
438 expected7.conv_name = 'f';
439
440 EXPECT_FORMAT_EQ(expected7, format_arr[7]);
441
442 expected8.has_conv = false;
443 expected8.raw_len = 1;
444 expected8.raw_string = str + 40;
445
446 EXPECT_FORMAT_EQ(expected8, format_arr[8]);
447
448 expected9.has_conv = true;
449 expected9.raw_len = 7;
450 expected9.raw_string = str + 41;
451 expected9.min_width = 1;
452 expected9.precision = 1;
453 expected9.conv_val_raw = arg1;
454 expected9.conv_name = 'c';
455
456 EXPECT_FORMAT_EQ(expected9, format_arr[9]);
457 }
458
459 #endif // LLVM_LIBC_PRINTF_DISABLE_INDEX_MODE
460