comparison dep/fmt/test/printf-test.cc @ 343:1faa72660932

*: transfer back to cmake from autotools autotools just made lots of things more complicated than they should have and many things broke (i.e. translations)
author Paper <paper@paper.us.eu.org>
date Thu, 20 Jun 2024 05:56:06 -0400
parents
children
comparison
equal deleted inserted replaced
342:adb79bdde329 343:1faa72660932
1 // Formatting library for C++ - printf tests
2 //
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7
8 #include "fmt/printf.h"
9
10 #include <cctype>
11 #include <climits>
12 #include <cstring>
13
14 #include "fmt/xchar.h"
15 #include "gtest-extra.h"
16 #include "util.h"
17
18 using fmt::format;
19 using fmt::format_error;
20 using fmt::detail::max_value;
21
22 const unsigned big_num = INT_MAX + 1u;
23
24 // Makes format string argument positional.
25 static std::string make_positional(fmt::string_view format) {
26 std::string s(format.data(), format.size());
27 s.replace(s.find('%'), 1, "%1$");
28 return s;
29 }
30
31 static std::wstring make_positional(fmt::basic_string_view<wchar_t> format) {
32 std::wstring s(format.data(), format.size());
33 s.replace(s.find(L'%'), 1, L"%1$");
34 return s;
35 }
36
37 // A wrapper around fmt::sprintf to workaround bogus warnings about invalid
38 // format strings in MSVC.
39 template <typename... Args>
40 std::string test_sprintf(fmt::string_view format, const Args&... args) {
41 return fmt::sprintf(format, args...);
42 }
43 template <typename... Args>
44 std::wstring test_sprintf(fmt::basic_string_view<wchar_t> format,
45 const Args&... args) {
46 return fmt::sprintf(format, args...);
47 }
48
49 #define EXPECT_PRINTF(expected_output, format, arg) \
50 EXPECT_EQ(expected_output, test_sprintf(format, arg)) \
51 << "format: " << format; \
52 EXPECT_EQ(expected_output, fmt::sprintf(make_positional(format), arg))
53
54 TEST(printf_test, no_args) {
55 EXPECT_EQ("test", test_sprintf("test"));
56 EXPECT_EQ(L"test", fmt::sprintf(L"test"));
57 }
58
59 TEST(printf_test, escape) {
60 EXPECT_EQ("%", test_sprintf("%%"));
61 EXPECT_EQ("before %", test_sprintf("before %%"));
62 EXPECT_EQ("% after", test_sprintf("%% after"));
63 EXPECT_EQ("before % after", test_sprintf("before %% after"));
64 EXPECT_EQ("%s", test_sprintf("%%s"));
65 EXPECT_EQ(L"%", fmt::sprintf(L"%%"));
66 EXPECT_EQ(L"before %", fmt::sprintf(L"before %%"));
67 EXPECT_EQ(L"% after", fmt::sprintf(L"%% after"));
68 EXPECT_EQ(L"before % after", fmt::sprintf(L"before %% after"));
69 EXPECT_EQ(L"%s", fmt::sprintf(L"%%s"));
70 }
71
72 TEST(printf_test, positional_args) {
73 EXPECT_EQ("42", test_sprintf("%1$d", 42));
74 EXPECT_EQ("before 42", test_sprintf("before %1$d", 42));
75 EXPECT_EQ("42 after", test_sprintf("%1$d after", 42));
76 EXPECT_EQ("before 42 after", test_sprintf("before %1$d after", 42));
77 EXPECT_EQ("answer = 42", test_sprintf("%1$s = %2$d", "answer", 42));
78 EXPECT_EQ("42 is the answer", test_sprintf("%2$d is the %1$s", "answer", 42));
79 EXPECT_EQ("abracadabra", test_sprintf("%1$s%2$s%1$s", "abra", "cad"));
80 }
81
82 TEST(printf_test, automatic_arg_indexing) {
83 EXPECT_EQ("abc", test_sprintf("%c%c%c", 'a', 'b', 'c'));
84 }
85
86 TEST(printf_test, number_is_too_big_in_arg_index) {
87 EXPECT_THROW_MSG(test_sprintf(format("%{}$", big_num)), format_error,
88 "argument not found");
89 EXPECT_THROW_MSG(test_sprintf(format("%{}$d", big_num)), format_error,
90 "argument not found");
91 }
92
93 TEST(printf_test, switch_arg_indexing) {
94 EXPECT_THROW_MSG(test_sprintf("%1$d%", 1, 2), format_error,
95 "cannot switch from manual to automatic argument indexing");
96 EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", big_num), 1, 2),
97 format_error, "number is too big");
98 EXPECT_THROW_MSG(test_sprintf("%1$d%d", 1, 2), format_error,
99 "cannot switch from manual to automatic argument indexing");
100
101 EXPECT_THROW_MSG(test_sprintf("%d%1$", 1, 2), format_error,
102 "cannot switch from automatic to manual argument indexing");
103 EXPECT_THROW_MSG(test_sprintf(format("%d%{}$d", big_num), 1, 2), format_error,
104 "cannot switch from automatic to manual argument indexing");
105 EXPECT_THROW_MSG(test_sprintf("%d%1$d", 1, 2), format_error,
106 "cannot switch from automatic to manual argument indexing");
107
108 // Indexing errors override width errors.
109 EXPECT_THROW_MSG(test_sprintf(format("%d%1${}d", big_num), 1, 2),
110 format_error, "number is too big");
111 EXPECT_THROW_MSG(test_sprintf(format("%1$d%{}d", big_num), 1, 2),
112 format_error, "number is too big");
113 }
114
115 TEST(printf_test, invalid_arg_index) {
116 EXPECT_THROW_MSG(test_sprintf("%0$d", 42), format_error,
117 "argument not found");
118 EXPECT_THROW_MSG(test_sprintf("%2$d", 42), format_error,
119 "argument not found");
120 EXPECT_THROW_MSG(test_sprintf(format("%{}$d", INT_MAX), 42), format_error,
121 "argument not found");
122
123 EXPECT_THROW_MSG(test_sprintf("%2$", 42), format_error, "argument not found");
124 EXPECT_THROW_MSG(test_sprintf(format("%{}$d", big_num), 42), format_error,
125 "argument not found");
126 }
127
128 TEST(printf_test, default_align_right) {
129 EXPECT_PRINTF(" 42", "%5d", 42);
130 EXPECT_PRINTF(" abc", "%5s", "abc");
131 }
132
133 TEST(printf_test, zero_flag) {
134 EXPECT_PRINTF("00042", "%05d", 42);
135 EXPECT_PRINTF("-0042", "%05d", -42);
136
137 EXPECT_PRINTF("00042", "%05d", 42);
138 EXPECT_PRINTF("-0042", "%05d", -42);
139 EXPECT_PRINTF("-004.2", "%06g", -4.2);
140
141 EXPECT_PRINTF("+00042", "%00+6d", 42);
142
143 EXPECT_PRINTF(" 42", "%05.d", 42);
144 EXPECT_PRINTF(" 0042", "%05.4d", 42);
145
146 // '0' flag is ignored for non-numeric types.
147 EXPECT_PRINTF(" x", "%05c", 'x');
148 }
149
150 TEST(printf_test, plus_flag) {
151 EXPECT_PRINTF("+42", "%+d", 42);
152 EXPECT_PRINTF("-42", "%+d", -42);
153 EXPECT_PRINTF("+0042", "%+05d", 42);
154 EXPECT_PRINTF("+0042", "%0++5d", 42);
155
156 // '+' flag is ignored for non-numeric types.
157 EXPECT_PRINTF("x", "%+c", 'x');
158
159 // '+' flag wins over space flag
160 EXPECT_PRINTF("+42", "%+ d", 42);
161 EXPECT_PRINTF("-42", "%+ d", -42);
162 EXPECT_PRINTF("+42", "% +d", 42);
163 EXPECT_PRINTF("-42", "% +d", -42);
164 EXPECT_PRINTF("+0042", "% +05d", 42);
165 EXPECT_PRINTF("+0042", "%0+ 5d", 42);
166
167 // '+' flag and space flag are both ignored for non-numeric types.
168 EXPECT_PRINTF("x", "%+ c", 'x');
169 EXPECT_PRINTF("x", "% +c", 'x');
170 }
171
172 TEST(printf_test, minus_flag) {
173 EXPECT_PRINTF("abc ", "%-5s", "abc");
174 EXPECT_PRINTF("abc ", "%0--5s", "abc");
175
176 EXPECT_PRINTF("7 ", "%-5d", 7);
177 EXPECT_PRINTF("97 ", "%-5hhi", 'a');
178 EXPECT_PRINTF("a ", "%-5c", 'a');
179
180 // '0' flag is ignored if '-' flag is given
181 EXPECT_PRINTF("7 ", "%-05d", 7);
182 EXPECT_PRINTF("7 ", "%0-5d", 7);
183 EXPECT_PRINTF("a ", "%-05c", 'a');
184 EXPECT_PRINTF("a ", "%0-5c", 'a');
185 EXPECT_PRINTF("97 ", "%-05hhi", 'a');
186 EXPECT_PRINTF("97 ", "%0-5hhi", 'a');
187
188 // '-' and space flag don't interfere
189 EXPECT_PRINTF(" 42", "%- d", 42);
190 }
191
192 TEST(printf_test, space_flag) {
193 EXPECT_PRINTF(" 42", "% d", 42);
194 EXPECT_PRINTF("-42", "% d", -42);
195 EXPECT_PRINTF(" 0042", "% 05d", 42);
196 EXPECT_PRINTF(" 0042", "%0 5d", 42);
197
198 // ' ' flag is ignored for non-numeric types.
199 EXPECT_PRINTF("x", "% c", 'x');
200 }
201
202 TEST(printf_test, hash_flag) {
203 EXPECT_PRINTF("042", "%#o", 042);
204 EXPECT_PRINTF(fmt::format("0{:o}", static_cast<unsigned>(-042)), "%#o", -042);
205 EXPECT_PRINTF("0", "%#o", 0);
206
207 EXPECT_PRINTF("0x42", "%#x", 0x42);
208 EXPECT_PRINTF("0X42", "%#X", 0x42);
209 EXPECT_PRINTF(fmt::format("0x{:x}", static_cast<unsigned>(-0x42)), "%#x",
210 -0x42);
211 EXPECT_PRINTF("0", "%#x", 0);
212
213 EXPECT_PRINTF("0x0042", "%#06x", 0x42);
214 EXPECT_PRINTF("0x0042", "%0##6x", 0x42);
215
216 EXPECT_PRINTF("-42.000000", "%#f", -42.0);
217 EXPECT_PRINTF("-42.000000", "%#F", -42.0);
218
219 char buffer[256];
220 safe_sprintf(buffer, "%#e", -42.0);
221 EXPECT_PRINTF(buffer, "%#e", -42.0);
222 safe_sprintf(buffer, "%#E", -42.0);
223 EXPECT_PRINTF(buffer, "%#E", -42.0);
224
225 EXPECT_PRINTF("-42.0000", "%#g", -42.0);
226 EXPECT_PRINTF("-42.0000", "%#G", -42.0);
227
228 EXPECT_PRINTF("0x1.p+4", "%#a", 16.0);
229 EXPECT_PRINTF("0X1.P+4", "%#A", 16.0);
230
231 // '#' flag is ignored for non-numeric types.
232 EXPECT_PRINTF("x", "%#c", 'x');
233 }
234
235 TEST(printf_test, width) {
236 EXPECT_PRINTF(" abc", "%5s", "abc");
237
238 // Width cannot be specified twice.
239 EXPECT_THROW_MSG(test_sprintf("%5-5d", 42), format_error,
240 "invalid format specifier");
241
242 EXPECT_THROW_MSG(test_sprintf(format("%{}d", big_num), 42), format_error,
243 "number is too big");
244 EXPECT_THROW_MSG(test_sprintf(format("%1${}d", big_num), 42), format_error,
245 "number is too big");
246 }
247
248 TEST(printf_test, dynamic_width) {
249 EXPECT_EQ(" 42", test_sprintf("%*d", 5, 42));
250 EXPECT_EQ("42 ", test_sprintf("%*d", -5, 42));
251 EXPECT_THROW_MSG(test_sprintf("%*d", 5.0, 42), format_error,
252 "width is not integer");
253 EXPECT_THROW_MSG(test_sprintf("%*d"), format_error, "argument not found");
254 EXPECT_THROW_MSG(test_sprintf("%*d", big_num, 42), format_error,
255 "number is too big");
256 }
257
258 TEST(printf_test, int_precision) {
259 EXPECT_PRINTF("00042", "%.5d", 42);
260 EXPECT_PRINTF("-00042", "%.5d", -42);
261 EXPECT_PRINTF("00042", "%.5x", 0x42);
262 EXPECT_PRINTF("0x00042", "%#.5x", 0x42);
263 EXPECT_PRINTF("00042", "%.5o", 042);
264 EXPECT_PRINTF("00042", "%#.5o", 042);
265
266 EXPECT_PRINTF(" 00042", "%7.5d", 42);
267 EXPECT_PRINTF(" 00042", "%7.5x", 0x42);
268 EXPECT_PRINTF(" 0x00042", "%#10.5x", 0x42);
269 EXPECT_PRINTF(" 00042", "%7.5o", 042);
270 EXPECT_PRINTF(" 00042", "%#10.5o", 042);
271
272 EXPECT_PRINTF("00042 ", "%-7.5d", 42);
273 EXPECT_PRINTF("00042 ", "%-7.5x", 0x42);
274 EXPECT_PRINTF("0x00042 ", "%-#10.5x", 0x42);
275 EXPECT_PRINTF("00042 ", "%-7.5o", 042);
276 EXPECT_PRINTF("00042 ", "%-#10.5o", 042);
277 }
278
279 TEST(printf_test, float_precision) {
280 char buffer[256];
281 safe_sprintf(buffer, "%.3e", 1234.5678);
282 EXPECT_PRINTF(buffer, "%.3e", 1234.5678);
283 EXPECT_PRINTF("1234.568", "%.3f", 1234.5678);
284 EXPECT_PRINTF("1.23e+03", "%.3g", 1234.5678);
285 safe_sprintf(buffer, "%.3a", 1234.5678);
286 EXPECT_PRINTF(buffer, "%.3a", 1234.5678);
287 }
288
289 TEST(printf_test, string_precision) {
290 char test[] = {'H', 'e', 'l', 'l', 'o'};
291 EXPECT_EQ(fmt::sprintf("%.4s", test), "Hell");
292 }
293
294 TEST(printf_test, ignore_precision_for_non_numeric_arg) {
295 EXPECT_PRINTF("abc", "%.5s", "abc");
296 }
297
298 TEST(printf_test, dynamic_precision) {
299 EXPECT_EQ("00042", test_sprintf("%.*d", 5, 42));
300 EXPECT_EQ("42", test_sprintf("%.*d", -5, 42));
301 EXPECT_THROW_MSG(test_sprintf("%.*d", 5.0, 42), format_error,
302 "precision is not integer");
303 EXPECT_THROW_MSG(test_sprintf("%.*d"), format_error, "argument not found");
304 EXPECT_THROW_MSG(test_sprintf("%.*d", big_num, 42), format_error,
305 "number is too big");
306 if (sizeof(long long) != sizeof(int)) {
307 long long prec = static_cast<long long>(INT_MIN) - 1;
308 EXPECT_THROW_MSG(test_sprintf("%.*d", prec, 42), format_error,
309 "number is too big");
310 }
311 }
312
313 template <typename T> struct make_signed { using type = T; };
314
315 #define SPECIALIZE_MAKE_SIGNED(T, S) \
316 template <> struct make_signed<T> { using type = S; }
317
318 SPECIALIZE_MAKE_SIGNED(char, signed char);
319 SPECIALIZE_MAKE_SIGNED(unsigned char, signed char);
320 SPECIALIZE_MAKE_SIGNED(unsigned short, short);
321 SPECIALIZE_MAKE_SIGNED(unsigned, int);
322 SPECIALIZE_MAKE_SIGNED(unsigned long, long);
323 SPECIALIZE_MAKE_SIGNED(unsigned long long, long long);
324
325 // Test length format specifier ``length_spec``.
326 template <typename T, typename U>
327 void test_length(const char* length_spec, U value) {
328 long long signed_value = 0;
329 unsigned long long unsigned_value = 0;
330 // Apply integer promotion to the argument.
331 unsigned long long max = max_value<U>();
332 using fmt::detail::const_check;
333 if (const_check(max <= static_cast<unsigned>(max_value<int>()))) {
334 signed_value = static_cast<int>(value);
335 unsigned_value = static_cast<unsigned long long>(value);
336 } else if (const_check(max <= max_value<unsigned>())) {
337 signed_value = static_cast<unsigned>(value);
338 unsigned_value = static_cast<unsigned long long>(value);
339 }
340 if (sizeof(U) <= sizeof(int) && sizeof(int) < sizeof(T)) {
341 signed_value = static_cast<long long>(value);
342 unsigned_value = static_cast<unsigned long long>(
343 static_cast<typename std::make_unsigned<unsigned>::type>(value));
344 } else {
345 signed_value = static_cast<typename make_signed<T>::type>(value);
346 unsigned_value = static_cast<typename std::make_unsigned<T>::type>(value);
347 }
348 std::ostringstream os;
349 os << signed_value;
350 EXPECT_PRINTF(os.str(), fmt::format("%{}d", length_spec), value);
351 EXPECT_PRINTF(os.str(), fmt::format("%{}i", length_spec), value);
352 os.str("");
353 os << unsigned_value;
354 EXPECT_PRINTF(os.str(), fmt::format("%{}u", length_spec), value);
355 os.str("");
356 os << std::oct << unsigned_value;
357 EXPECT_PRINTF(os.str(), fmt::format("%{}o", length_spec), value);
358 os.str("");
359 os << std::hex << unsigned_value;
360 EXPECT_PRINTF(os.str(), fmt::format("%{}x", length_spec), value);
361 os.str("");
362 os << std::hex << std::uppercase << unsigned_value;
363 EXPECT_PRINTF(os.str(), fmt::format("%{}X", length_spec), value);
364 }
365
366 template <typename T> void test_length(const char* length_spec) {
367 T min = std::numeric_limits<T>::min(), max = max_value<T>();
368 test_length<T>(length_spec, 42);
369 test_length<T>(length_spec, -42);
370 test_length<T>(length_spec, min);
371 test_length<T>(length_spec, max);
372 long long long_long_min = std::numeric_limits<long long>::min();
373 if (static_cast<long long>(min) > long_long_min)
374 test_length<T>(length_spec, static_cast<long long>(min) - 1);
375 unsigned long long long_long_max = max_value<long long>();
376 if (static_cast<unsigned long long>(max) < long_long_max)
377 test_length<T>(length_spec, static_cast<long long>(max) + 1);
378 test_length<T>(length_spec, std::numeric_limits<short>::min());
379 test_length<T>(length_spec, max_value<unsigned short>());
380 test_length<T>(length_spec, std::numeric_limits<int>::min());
381 test_length<T>(length_spec, max_value<int>());
382 test_length<T>(length_spec, std::numeric_limits<unsigned>::min());
383 test_length<T>(length_spec, max_value<unsigned>());
384 test_length<T>(length_spec, std::numeric_limits<long long>::min());
385 test_length<T>(length_spec, max_value<long long>());
386 test_length<T>(length_spec, std::numeric_limits<unsigned long long>::min());
387 test_length<T>(length_spec, max_value<unsigned long long>());
388 }
389
390 TEST(printf_test, length) {
391 test_length<char>("hh");
392 test_length<signed char>("hh");
393 test_length<unsigned char>("hh");
394 test_length<short>("h");
395 test_length<unsigned short>("h");
396 test_length<long>("l");
397 test_length<unsigned long>("l");
398 test_length<long long>("ll");
399 test_length<unsigned long long>("ll");
400 test_length<intmax_t>("j");
401 test_length<size_t>("z");
402 test_length<std::ptrdiff_t>("t");
403 long double max = max_value<long double>();
404 EXPECT_PRINTF(fmt::format("{:.6}", max), "%g", max);
405 EXPECT_PRINTF(fmt::format("{:.6}", max), "%Lg", max);
406 }
407
408 TEST(printf_test, bool) { EXPECT_PRINTF("1", "%d", true); }
409
410 TEST(printf_test, int) {
411 EXPECT_PRINTF("-42", "%d", -42);
412 EXPECT_PRINTF("-42", "%i", -42);
413 unsigned u = 0 - 42u;
414 EXPECT_PRINTF(fmt::format("{}", u), "%u", -42);
415 EXPECT_PRINTF(fmt::format("{:o}", u), "%o", -42);
416 EXPECT_PRINTF(fmt::format("{:x}", u), "%x", -42);
417 EXPECT_PRINTF(fmt::format("{:X}", u), "%X", -42);
418 }
419
420 TEST(printf_test, long_long) {
421 // fmt::printf allows passing long long arguments to %d without length
422 // specifiers.
423 long long max = max_value<long long>();
424 EXPECT_PRINTF(fmt::format("{}", max), "%d", max);
425 }
426
427 TEST(printf_test, float) {
428 EXPECT_PRINTF("392.650000", "%f", 392.65);
429 EXPECT_PRINTF("392.65", "%.2f", 392.65);
430 EXPECT_PRINTF("392.6", "%.1f", 392.65);
431 EXPECT_PRINTF("393", "%.f", 392.65);
432 EXPECT_PRINTF("392.650000", "%F", 392.65);
433 char buffer[256];
434 safe_sprintf(buffer, "%e", 392.65);
435 EXPECT_PRINTF(buffer, "%e", 392.65);
436 safe_sprintf(buffer, "%E", 392.65);
437 EXPECT_PRINTF(buffer, "%E", 392.65);
438 EXPECT_PRINTF("392.65", "%g", 392.65);
439 EXPECT_PRINTF("392.65", "%G", 392.65);
440 EXPECT_PRINTF("392", "%g", 392.0);
441 EXPECT_PRINTF("392", "%G", 392.0);
442 EXPECT_PRINTF("4.56e-07", "%g", 0.000000456);
443 safe_sprintf(buffer, "%a", -392.65);
444 EXPECT_EQ(buffer, format("{:a}", -392.65));
445 safe_sprintf(buffer, "%A", -392.65);
446 EXPECT_EQ(buffer, format("{:A}", -392.65));
447 }
448
449 TEST(printf_test, inf) {
450 double inf = std::numeric_limits<double>::infinity();
451 for (const char* type = "fega"; *type; ++type) {
452 EXPECT_PRINTF("inf", fmt::format("%{}", *type), inf);
453 char upper = static_cast<char>(std::toupper(*type));
454 EXPECT_PRINTF("INF", fmt::format("%{}", upper), inf);
455 }
456 }
457
458 TEST(printf_test, char) {
459 EXPECT_PRINTF("x", "%c", 'x');
460 int max = max_value<int>();
461 EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
462 // EXPECT_PRINTF("x", "%lc", L'x');
463 EXPECT_PRINTF(L"x", L"%c", L'x');
464 EXPECT_PRINTF(fmt::format(L"{}", static_cast<wchar_t>(max)), L"%c", max);
465 }
466
467 TEST(printf_test, string) {
468 EXPECT_PRINTF("abc", "%s", "abc");
469 const char* null_str = nullptr;
470 EXPECT_PRINTF("(null)", "%s", null_str);
471 EXPECT_PRINTF(" (null)", "%10s", null_str);
472 EXPECT_PRINTF(L"abc", L"%s", L"abc");
473 const wchar_t* null_wstr = nullptr;
474 EXPECT_PRINTF(L"(null)", L"%s", null_wstr);
475 EXPECT_PRINTF(L" (null)", L"%10s", null_wstr);
476 }
477
478 TEST(printf_test, pointer) {
479 int n;
480 void* p = &n;
481 EXPECT_PRINTF(fmt::format("{}", p), "%p", p);
482 p = nullptr;
483 EXPECT_PRINTF("(nil)", "%p", p);
484 EXPECT_PRINTF(" (nil)", "%10p", p);
485 const char* s = "test";
486 EXPECT_PRINTF(fmt::format("{:p}", s), "%p", s);
487 const char* null_str = nullptr;
488 EXPECT_PRINTF("(nil)", "%p", null_str);
489
490 p = &n;
491 EXPECT_PRINTF(fmt::format(L"{}", p), L"%p", p);
492 p = nullptr;
493 EXPECT_PRINTF(L"(nil)", L"%p", p);
494 EXPECT_PRINTF(L" (nil)", L"%10p", p);
495 const wchar_t* w = L"test";
496 EXPECT_PRINTF(fmt::format(L"{:p}", w), L"%p", w);
497 const wchar_t* null_wstr = nullptr;
498 EXPECT_PRINTF(L"(nil)", L"%p", null_wstr);
499 }
500
501 enum test_enum { answer = 42 };
502 auto format_as(test_enum e) -> int { return e; }
503
504 TEST(printf_test, enum) {
505 EXPECT_PRINTF("42", "%d", answer);
506 volatile test_enum volatile_enum = answer;
507 EXPECT_PRINTF("42", "%d", volatile_enum);
508 }
509
510 #if FMT_USE_FCNTL
511 TEST(printf_test, examples) {
512 const char* weekday = "Thursday";
513 const char* month = "August";
514 int day = 21;
515 EXPECT_WRITE(stdout, fmt::printf("%1$s, %3$d %2$s", weekday, month, day),
516 "Thursday, 21 August");
517 }
518
519 TEST(printf_test, printf_error) {
520 fmt::file read_end, write_end;
521 fmt::file::pipe(read_end, write_end);
522 int result = fmt::fprintf(read_end.fdopen("r").get(), "test");
523 EXPECT_LT(result, 0);
524 }
525 #endif
526
527 TEST(printf_test, wide_string) {
528 EXPECT_EQ(L"abc", fmt::sprintf(L"%s", L"abc"));
529 }
530
531 TEST(printf_test, vprintf) {
532 int n = 42;
533 auto store = fmt::format_arg_store<fmt::printf_context, int>(n);
534 auto args = fmt::basic_format_args<fmt::printf_context>(store);
535 EXPECT_EQ(fmt::vsprintf(fmt::string_view("%d"), args), "42");
536 EXPECT_WRITE(stdout, fmt::vfprintf(stdout, fmt::string_view("%d"), args),
537 "42");
538 }
539
540 template <typename... Args>
541 void check_format_string_regression(fmt::string_view s, const Args&... args) {
542 fmt::sprintf(s, args...);
543 }
544
545 TEST(printf_test, check_format_string_regression) {
546 check_format_string_regression("%c%s", 'x', "");
547 }
548
549 TEST(printf_test, fixed_large_exponent) {
550 EXPECT_EQ("1000000000000000000000", fmt::sprintf("%.*f", -13, 1e21));
551 }
552
553 TEST(printf_test, make_printf_args) {
554 EXPECT_EQ("[42] something happened",
555 fmt::vsprintf(fmt::string_view("[%d] %s happened"),
556 {fmt::make_printf_args(42, "something")}));
557 EXPECT_EQ(L"[42] something happened",
558 fmt::vsprintf(fmt::basic_string_view<wchar_t>(L"[%d] %s happened"),
559 {fmt::make_wprintf_args(42, L"something")}));
560 }