1 //===-- Unittests for the printf Parser -----------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/CPP/bit.h"
10 #include "src/__support/CPP/string_view.h"
11 #include "src/__support/arg_list.h"
12 #include "src/stdio/printf_core/parser.h"
16 #include "test/UnitTest/PrintfMatcher.h"
17 #include "test/UnitTest/Test.h"
19 using __llvm_libc::cpp::string_view
;
21 void init(const char *__restrict str
, ...) {
24 __llvm_libc::internal::ArgList
v(vlist
);
27 __llvm_libc::printf_core::Parser
parser(str
, v
);
30 void evaluate(__llvm_libc::printf_core::FormatSection
*format_arr
,
31 const char *__restrict str
, ...) {
34 __llvm_libc::internal::ArgList
v(vlist
);
37 __llvm_libc::printf_core::Parser
parser(str
, v
);
39 for (auto cur_section
= parser
.get_next_section();
40 !cur_section
.raw_string
.empty();
41 cur_section
= parser
.get_next_section()) {
42 *format_arr
= cur_section
;
47 TEST(LlvmLibcPrintfParserTest
, Constructor
) { init("test", 1, 2); }
49 TEST(LlvmLibcPrintfParserTest
, EvalRaw
) {
50 __llvm_libc::printf_core::FormatSection format_arr
[10];
51 const char *str
= "test";
52 evaluate(format_arr
, str
);
54 __llvm_libc::printf_core::FormatSection expected
;
55 expected
.has_conv
= false;
57 expected
.raw_string
= {str
, 4};
59 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
60 // TODO: add checks that the format_arr after the last one has length 0
63 TEST(LlvmLibcPrintfParserTest
, EvalSimple
) {
64 __llvm_libc::printf_core::FormatSection format_arr
[10];
65 const char *str
= "test %% test";
66 evaluate(format_arr
, str
);
68 __llvm_libc::printf_core::FormatSection expected0
, expected1
, expected2
;
69 expected0
.has_conv
= false;
71 expected0
.raw_string
= {str
, 5};
73 ASSERT_PFORMAT_EQ(expected0
, format_arr
[0]);
75 expected1
.has_conv
= true;
77 expected1
.raw_string
= {str
+ 5, 2};
78 expected1
.conv_name
= '%';
80 ASSERT_PFORMAT_EQ(expected1
, format_arr
[1]);
82 expected2
.has_conv
= false;
84 expected2
.raw_string
= {str
+ 7, 5};
86 ASSERT_PFORMAT_EQ(expected2
, format_arr
[2]);
89 TEST(LlvmLibcPrintfParserTest
, EvalOneArg
) {
90 __llvm_libc::printf_core::FormatSection format_arr
[10];
91 const char *str
= "%d";
93 evaluate(format_arr
, str
, arg1
);
95 __llvm_libc::printf_core::FormatSection expected
;
96 expected
.has_conv
= true;
98 expected
.raw_string
= {str
, 2};
99 expected
.conv_val_raw
= arg1
;
100 expected
.conv_name
= 'd';
102 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
105 TEST(LlvmLibcPrintfParserTest
, EvalBadArg
) {
106 __llvm_libc::printf_core::FormatSection format_arr
[10];
107 const char *str
= "%\0abc";
109 evaluate(format_arr
, str
, arg1
);
111 __llvm_libc::printf_core::FormatSection expected
;
112 expected
.has_conv
= false;
113 expected
.raw_string
= {str
, 1};
115 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
118 TEST(LlvmLibcPrintfParserTest
, EvalOneArgWithFlags
) {
119 __llvm_libc::printf_core::FormatSection format_arr
[10];
120 const char *str
= "%+-0 #d";
122 evaluate(format_arr
, str
, arg1
);
124 __llvm_libc::printf_core::FormatSection expected
;
125 expected
.has_conv
= true;
127 expected
.raw_string
= {str
, 7};
128 expected
.flags
= static_cast<__llvm_libc::printf_core::FormatFlags
>(
129 __llvm_libc::printf_core::FormatFlags::FORCE_SIGN
|
130 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED
|
131 __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES
|
132 __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX
|
133 __llvm_libc::printf_core::FormatFlags::ALTERNATE_FORM
);
134 expected
.conv_val_raw
= arg1
;
135 expected
.conv_name
= 'd';
137 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
140 TEST(LlvmLibcPrintfParserTest
, EvalOneArgWithWidth
) {
141 __llvm_libc::printf_core::FormatSection format_arr
[10];
142 const char *str
= "%12d";
144 evaluate(format_arr
, str
, arg1
);
146 __llvm_libc::printf_core::FormatSection expected
;
147 expected
.has_conv
= true;
149 expected
.raw_string
= {str
, 4};
150 expected
.min_width
= 12;
151 expected
.conv_val_raw
= arg1
;
152 expected
.conv_name
= 'd';
154 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
157 TEST(LlvmLibcPrintfParserTest
, EvalOneArgWithPrecision
) {
158 __llvm_libc::printf_core::FormatSection format_arr
[10];
159 const char *str
= "%.34d";
161 evaluate(format_arr
, str
, arg1
);
163 __llvm_libc::printf_core::FormatSection expected
;
164 expected
.has_conv
= true;
166 expected
.raw_string
= {str
, 5};
167 expected
.precision
= 34;
168 expected
.conv_val_raw
= arg1
;
169 expected
.conv_name
= 'd';
171 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
174 TEST(LlvmLibcPrintfParserTest
, EvalOneArgWithTrivialPrecision
) {
175 __llvm_libc::printf_core::FormatSection format_arr
[10];
176 const char *str
= "%.d";
178 evaluate(format_arr
, str
, arg1
);
180 __llvm_libc::printf_core::FormatSection expected
;
181 expected
.has_conv
= true;
183 expected
.raw_string
= {str
, 3};
184 expected
.precision
= 0;
185 expected
.conv_val_raw
= arg1
;
186 expected
.conv_name
= 'd';
188 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
191 TEST(LlvmLibcPrintfParserTest
, EvalOneArgWithShortLengthModifier
) {
192 __llvm_libc::printf_core::FormatSection format_arr
[10];
193 const char *str
= "%hd";
195 evaluate(format_arr
, str
, arg1
);
197 __llvm_libc::printf_core::FormatSection expected
;
198 expected
.has_conv
= true;
200 expected
.raw_string
= {str
, 3};
201 expected
.length_modifier
= __llvm_libc::printf_core::LengthModifier::h
;
202 expected
.conv_val_raw
= arg1
;
203 expected
.conv_name
= 'd';
205 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
208 TEST(LlvmLibcPrintfParserTest
, EvalOneArgWithLongLengthModifier
) {
209 __llvm_libc::printf_core::FormatSection format_arr
[10];
210 const char *str
= "%lld";
211 long long arg1
= 12345;
212 evaluate(format_arr
, str
, arg1
);
214 __llvm_libc::printf_core::FormatSection expected
;
215 expected
.has_conv
= true;
217 expected
.raw_string
= {str
, 4};
218 expected
.length_modifier
= __llvm_libc::printf_core::LengthModifier::ll
;
219 expected
.conv_val_raw
= arg1
;
220 expected
.conv_name
= 'd';
222 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
225 TEST(LlvmLibcPrintfParserTest
, EvalOneArgWithAllOptions
) {
226 __llvm_libc::printf_core::FormatSection format_arr
[10];
227 const char *str
= "% -056.78jd";
228 intmax_t arg1
= 12345;
229 evaluate(format_arr
, str
, arg1
);
231 __llvm_libc::printf_core::FormatSection expected
;
232 expected
.has_conv
= true;
234 expected
.raw_string
= {str
, 11};
235 expected
.flags
= static_cast<__llvm_libc::printf_core::FormatFlags
>(
236 __llvm_libc::printf_core::FormatFlags::LEFT_JUSTIFIED
|
237 __llvm_libc::printf_core::FormatFlags::LEADING_ZEROES
|
238 __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX
);
239 expected
.min_width
= 56;
240 expected
.precision
= 78;
241 expected
.length_modifier
= __llvm_libc::printf_core::LengthModifier::j
;
242 expected
.conv_val_raw
= arg1
;
243 expected
.conv_name
= 'd';
245 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
248 TEST(LlvmLibcPrintfParserTest
, EvalThreeArgs
) {
249 __llvm_libc::printf_core::FormatSection format_arr
[10];
250 const char *str
= "%d%f%s";
252 double arg2
= 123.45;
253 const char *arg3
= "12345";
254 evaluate(format_arr
, str
, arg1
, arg2
, arg3
);
256 __llvm_libc::printf_core::FormatSection expected0
, expected1
, expected2
;
257 expected0
.has_conv
= true;
259 expected0
.raw_string
= {str
, 2};
260 expected0
.conv_val_raw
= arg1
;
261 expected0
.conv_name
= 'd';
263 ASSERT_PFORMAT_EQ(expected0
, format_arr
[0]);
265 expected1
.has_conv
= true;
267 expected1
.raw_string
= {str
+ 2, 2};
268 expected1
.conv_val_raw
= __llvm_libc::cpp::bit_cast
<uint64_t>(arg2
);
269 expected1
.conv_name
= 'f';
271 ASSERT_PFORMAT_EQ(expected1
, format_arr
[1]);
273 expected2
.has_conv
= true;
275 expected2
.raw_string
= {str
+ 4, 2};
276 expected2
.conv_val_ptr
= const_cast<char *>(arg3
);
277 expected2
.conv_name
= 's';
279 ASSERT_PFORMAT_EQ(expected2
, format_arr
[2]);
282 #ifndef LIBC_COPT_PRINTF_DISABLE_INDEX_MODE
284 TEST(LlvmLibcPrintfParserTest
, IndexModeOneArg
) {
285 __llvm_libc::printf_core::FormatSection format_arr
[10];
286 const char *str
= "%1$d";
288 evaluate(format_arr
, str
, arg1
);
290 __llvm_libc::printf_core::FormatSection expected
;
291 expected
.has_conv
= true;
293 expected
.raw_string
= {str
, 4};
294 expected
.conv_val_raw
= arg1
;
295 expected
.conv_name
= 'd';
297 ASSERT_PFORMAT_EQ(expected
, format_arr
[0]);
300 TEST(LlvmLibcPrintfParserTest
, IndexModeThreeArgsSequential
) {
301 __llvm_libc::printf_core::FormatSection format_arr
[10];
302 const char *str
= "%1$d%2$f%3$s";
304 double arg2
= 123.45;
305 const char *arg3
= "12345";
306 evaluate(format_arr
, str
, arg1
, arg2
, arg3
);
308 __llvm_libc::printf_core::FormatSection expected0
, expected1
, expected2
;
309 expected0
.has_conv
= true;
311 expected0
.raw_string
= {str
, 4};
312 expected0
.conv_val_raw
= arg1
;
313 expected0
.conv_name
= 'd';
315 ASSERT_PFORMAT_EQ(expected0
, format_arr
[0]);
317 expected1
.has_conv
= true;
319 expected1
.raw_string
= {str
+ 4, 4};
320 expected1
.conv_val_raw
= __llvm_libc::cpp::bit_cast
<uint64_t>(arg2
);
321 expected1
.conv_name
= 'f';
323 ASSERT_PFORMAT_EQ(expected1
, format_arr
[1]);
325 expected2
.has_conv
= true;
327 expected2
.raw_string
= {str
+ 8, 4};
328 expected2
.conv_val_ptr
= const_cast<char *>(arg3
);
329 expected2
.conv_name
= 's';
331 ASSERT_PFORMAT_EQ(expected2
, format_arr
[2]);
334 TEST(LlvmLibcPrintfParserTest
, IndexModeThreeArgsReverse
) {
335 __llvm_libc::printf_core::FormatSection format_arr
[10];
336 const char *str
= "%3$d%2$f%1$s";
338 double arg2
= 123.45;
339 const char *arg3
= "12345";
340 evaluate(format_arr
, str
, arg3
, arg2
, arg1
);
342 __llvm_libc::printf_core::FormatSection expected0
, expected1
, expected2
;
343 expected0
.has_conv
= true;
345 expected0
.raw_string
= {str
, 4};
346 expected0
.conv_val_raw
= arg1
;
347 expected0
.conv_name
= 'd';
349 ASSERT_PFORMAT_EQ(expected0
, format_arr
[0]);
351 expected1
.has_conv
= true;
353 expected1
.raw_string
= {str
+ 4, 4};
354 expected1
.conv_val_raw
= __llvm_libc::cpp::bit_cast
<uint64_t>(arg2
);
355 expected1
.conv_name
= 'f';
357 ASSERT_PFORMAT_EQ(expected1
, format_arr
[1]);
359 expected2
.has_conv
= true;
361 expected2
.raw_string
= {str
+ 8, 4};
362 expected2
.conv_val_ptr
= const_cast<char *>(arg3
);
363 expected2
.conv_name
= 's';
365 ASSERT_PFORMAT_EQ(expected2
, format_arr
[2]);
368 TEST(LlvmLibcPrintfParserTest
, IndexModeTenArgsRandom
) {
369 __llvm_libc::printf_core::FormatSection format_arr
[10];
370 const char *str
= "%6$d%3$d%7$d%2$d%8$d%1$d%4$d%9$d%5$d%10$d";
371 int args
[10] = {6, 4, 2, 7, 9, 1, 3, 5, 8, 10};
372 evaluate(format_arr
, str
, args
[0], args
[1], args
[2], args
[3], args
[4],
373 args
[5], args
[6], args
[7], args
[8], args
[9]);
375 for (size_t i
= 0; i
< 10; ++i
) {
376 __llvm_libc::printf_core::FormatSection expected
;
377 expected
.has_conv
= true;
379 expected
.raw_string
= {str
+ (4 * i
),
380 static_cast<size_t>(4 + (i
>= 9 ? 1 : 0))};
381 expected
.conv_val_raw
= i
+ 1;
382 expected
.conv_name
= 'd';
383 EXPECT_PFORMAT_EQ(expected
, format_arr
[i
]);
387 TEST(LlvmLibcPrintfParserTest
, IndexModeComplexParsing
) {
388 __llvm_libc::printf_core::FormatSection format_arr
[10];
389 const char *str
= "normal text %3$llu %% %2$ *4$f %2$ .*4$f %1$1.1c";
391 double arg2
= 123.45;
392 unsigned long long arg3
= 12345;
394 evaluate(format_arr
, str
, arg1
, arg2
, arg3
, arg4
);
396 __llvm_libc::printf_core::FormatSection expected0
, expected1
, expected2
,
397 expected3
, expected4
, expected5
, expected6
, expected7
, expected8
,
400 expected0
.has_conv
= false;
402 expected0
.raw_string
= {str
, 12};
404 EXPECT_PFORMAT_EQ(expected0
, format_arr
[0]);
406 expected1
.has_conv
= true;
408 expected1
.raw_string
= {str
+ 12, 6};
409 expected1
.length_modifier
= __llvm_libc::printf_core::LengthModifier::ll
;
410 expected1
.conv_val_raw
= arg3
;
411 expected1
.conv_name
= 'u';
413 EXPECT_PFORMAT_EQ(expected1
, format_arr
[1]);
415 expected2
.has_conv
= false;
417 expected2
.raw_string
= {str
+ 18, 1};
419 EXPECT_PFORMAT_EQ(expected2
, format_arr
[2]);
421 expected3
.has_conv
= true;
423 expected3
.raw_string
= {str
+ 19, 2};
424 expected3
.conv_name
= '%';
426 EXPECT_PFORMAT_EQ(expected3
, format_arr
[3]);
428 expected4
.has_conv
= false;
430 expected4
.raw_string
= {str
+ 21, 1};
432 EXPECT_PFORMAT_EQ(expected4
, format_arr
[4]);
434 expected5
.has_conv
= true;
436 expected5
.raw_string
= {str
+ 22, 8};
437 expected5
.flags
= __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX
;
438 expected5
.min_width
= arg4
;
439 expected5
.conv_val_raw
= __llvm_libc::cpp::bit_cast
<uint64_t>(arg2
);
440 expected5
.conv_name
= 'f';
442 EXPECT_PFORMAT_EQ(expected5
, format_arr
[5]);
444 expected6
.has_conv
= false;
446 expected6
.raw_string
= {str
+ 30, 1};
448 EXPECT_PFORMAT_EQ(expected6
, format_arr
[6]);
450 expected7
.has_conv
= true;
452 expected7
.raw_string
= {str
+ 31, 9};
453 expected7
.flags
= __llvm_libc::printf_core::FormatFlags::SPACE_PREFIX
;
454 expected7
.precision
= arg4
;
455 expected7
.conv_val_raw
= __llvm_libc::cpp::bit_cast
<uint64_t>(arg2
);
456 expected7
.conv_name
= 'f';
458 EXPECT_PFORMAT_EQ(expected7
, format_arr
[7]);
460 expected8
.has_conv
= false;
462 expected8
.raw_string
= {str
+ 40, 1};
464 EXPECT_PFORMAT_EQ(expected8
, format_arr
[8]);
466 expected9
.has_conv
= true;
468 expected9
.raw_string
= {str
+ 41, 7};
469 expected9
.min_width
= 1;
470 expected9
.precision
= 1;
471 expected9
.conv_val_raw
= arg1
;
472 expected9
.conv_name
= 'c';
474 EXPECT_PFORMAT_EQ(expected9
, format_arr
[9]);
477 TEST(LlvmLibcPrintfParserTest
, IndexModeGapCheck
) {
478 __llvm_libc::printf_core::FormatSection format_arr
[10];
479 const char *str
= "%1$d%2$d%4$d";
485 evaluate(format_arr
, str
, arg1
, arg2
, arg3
, arg4
);
487 __llvm_libc::printf_core::FormatSection expected0
, expected1
, expected2
;
489 expected0
.has_conv
= true;
490 expected0
.raw_string
= {str
, 4};
491 expected0
.conv_val_raw
= arg1
;
492 expected0
.conv_name
= 'd';
494 EXPECT_PFORMAT_EQ(expected0
, format_arr
[0]);
496 expected1
.has_conv
= true;
497 expected1
.raw_string
= {str
+ 4, 4};
498 expected1
.conv_val_raw
= arg2
;
499 expected1
.conv_name
= 'd';
501 EXPECT_PFORMAT_EQ(expected1
, format_arr
[1]);
503 expected2
.has_conv
= false;
504 expected2
.raw_string
= {str
+ 8, 4};
506 EXPECT_PFORMAT_EQ(expected2
, format_arr
[2]);
509 TEST(LlvmLibcPrintfParserTest
, IndexModeTrailingPercentCrash
) {
510 __llvm_libc::printf_core::FormatSection format_arr
[10];
511 const char *str
= "%2$d%";
512 evaluate(format_arr
, str
, 1, 2);
514 __llvm_libc::printf_core::FormatSection expected0
, expected1
;
515 expected0
.has_conv
= false;
517 expected0
.raw_string
= {str
, 4};
518 EXPECT_PFORMAT_EQ(expected0
, format_arr
[0]);
520 expected1
.has_conv
= false;
522 expected1
.raw_string
= {str
+ 4, 1};
523 EXPECT_PFORMAT_EQ(expected1
, format_arr
[1]);
526 #endif // LIBC_COPT_PRINTF_DISABLE_INDEX_MODE