1/* Unit tests for gprintf
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This work is provided "as is"; redistribution and modification
5 * in whole or in part, in any medium, physical or electronic is
6 * permitted without restriction.
7 *
8 * This work is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * In no event shall the authors or contributors be liable for any
13 * direct, indirect, incidental, special, exemplary, or consequential
14 * damages (including, but not limited to, procurement of substitute
15 * goods or services; loss of use, data, or profits; or business
16 * interruption) however caused and on any theory of liability, whether
17 * in contract, strict liability, or tort (including negligence or
18 * otherwise) arising in any way out of the use of this software, even
19 * if advised of the possibility of such damage.
20 */
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include "glib.h"
26#include "gstdio.h"
27#ifdef G_OS_WIN32
28#include <io.h>
29#include <fcntl.h>
30#endif
31
32static void
33test_retval_and_trunc (void)
34{
35 gchar buf[128];
36 gint res;
37
38 res = g_snprintf (string: buf, n: 0, format: "abc");
39 g_assert_cmpint (res, ==, 3);
40
41 res = g_snprintf (NULL, n: 0, format: "abc");
42 g_assert_cmpint (res, ==, 3);
43
44 res = g_snprintf (string: buf, n: 5, format: "abc");
45 g_assert_cmpint (res, ==, 3);
46
47 res = g_snprintf (string: buf, n: 1, format: "abc");
48 g_assert_cmpint (res, ==, 3);
49 g_assert (buf[0] == '\0');
50 g_assert_cmpstr (buf, ==, "");
51
52 res = g_snprintf (string: buf, n: 2, format: "abc");
53 g_assert_cmpint (res, ==, 3);
54 g_assert (buf[1] == '\0');
55 g_assert_cmpstr (buf, ==, "a");
56
57 res = g_snprintf (string: buf, n: 3, format: "abc");
58 g_assert_cmpint (res, ==, 3);
59 g_assert (buf[2] == '\0');
60 g_assert_cmpstr (buf, ==, "ab");
61
62 res = g_snprintf (string: buf, n: 4, format: "abc");
63 g_assert_cmpint (res, ==, 3);
64 g_assert (buf[3] == '\0');
65 g_assert_cmpstr (buf, ==, "abc");
66
67 res = g_snprintf (string: buf, n: 5, format: "abc");
68 g_assert_cmpint (res, ==, 3);
69 g_assert (buf[3] == '\0');
70 g_assert_cmpstr (buf, ==, "abc");
71}
72
73static void
74test_d (void)
75{
76 gchar buf[128];
77 gint res;
78
79 /* %d basic formatting */
80
81 res = g_snprintf (string: buf, n: 128, format: "%d", 5);
82 g_assert_cmpint (res, ==, 1);
83 g_assert_cmpstr (buf, ==, "5");
84
85 res = g_snprintf (string: buf, n: 128, format: "%d", 0);
86 g_assert_cmpint (res, ==, 1);
87 g_assert_cmpstr (buf, ==, "0");
88
89 res = g_snprintf (string: buf, n: 128, format: "%.0d", 0);
90 g_assert_cmpint (res, ==, 0);
91 g_assert_cmpstr (buf, ==, "");
92
93 res = g_snprintf (string: buf, n: 128, format: "%.0d", 1);
94 g_assert_cmpint (res, ==, 1);
95 g_assert_cmpstr (buf, ==, "1");
96
97 res = g_snprintf (string: buf, n: 128, format: "%.d", 2);
98 g_assert_cmpint (res, ==, 1);
99 g_assert_cmpstr (buf, ==, "2");
100
101 res = g_snprintf (string: buf, n: 128, format: "%d", -1);
102 g_assert_cmpint (res, ==, 2);
103 g_assert_cmpstr (buf, ==, "-1");
104
105 res = g_snprintf (string: buf, n: 128, format: "%.3d", 5);
106 g_assert_cmpint (res, ==, 3);
107 g_assert_cmpstr (buf, ==, "005");
108
109 res = g_snprintf (string: buf, n: 128, format: "%.3d", -5);
110 g_assert_cmpint (res, ==, 4);
111 g_assert_cmpstr (buf, ==, "-005");
112
113 res = g_snprintf (string: buf, n: 128, format: "%5.3d", 5);
114 g_assert_cmpint (res, ==, 5);
115 g_assert_cmpstr (buf, ==, " 005");
116
117 res = g_snprintf (string: buf, n: 128, format: "%-5.3d", -5);
118 g_assert_cmpint (res, ==, 5);
119 g_assert_cmpstr (buf, ==, "-005 ");
120
121 /* %d, length modifiers */
122
123 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT16_FORMAT, (gint16)-5);
124 g_assert_cmpint (res, ==, 2);
125 g_assert_cmpstr (buf, ==, "-5");
126
127 res = g_snprintf (string: buf, n: 128, format: "%" G_GUINT16_FORMAT, (guint16)5);
128 g_assert_cmpint (res, ==, 1);
129 g_assert_cmpstr (buf, ==, "5");
130
131 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT32_FORMAT, (gint32)-5);
132 g_assert_cmpint (res, ==, 2);
133 g_assert_cmpstr (buf, ==, "-5");
134
135 res = g_snprintf (string: buf, n: 128, format: "%" G_GUINT32_FORMAT, (guint32)5);
136 g_assert_cmpint (res, ==, 1);
137 g_assert_cmpstr (buf, ==, "5");
138
139 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT64_FORMAT, (gint64)-5);
140 g_assert_cmpint (res, ==, 2);
141 g_assert_cmpstr (buf, ==, "-5");
142
143 res = g_snprintf (string: buf, n: 128, format: "%" G_GUINT64_FORMAT, (guint64)5);
144 g_assert_cmpint (res, ==, 1);
145 g_assert_cmpstr (buf, ==, "5");
146
147 res = g_snprintf (string: buf, n: 128, format: "%" G_GSSIZE_FORMAT, (gssize)-5);
148 g_assert_cmpint (res, ==, 2);
149 g_assert_cmpstr (buf, ==, "-5");
150
151 res = g_snprintf (string: buf, n: 128, format: "%" G_GSIZE_FORMAT, (gsize)5);
152 g_assert_cmpint (res, ==, 1);
153 g_assert_cmpstr (buf, ==, "5");
154
155 /* %d, flags */
156
157 res = g_snprintf (string: buf, n: 128, format: "%-d", 5);
158 g_assert_cmpint (res, ==, 1);
159 g_assert_cmpstr (buf, ==, "5");
160
161 res = g_snprintf (string: buf, n: 128, format: "%-+d", 5);
162 g_assert_cmpint (res, ==, 2);
163 g_assert_cmpstr (buf, ==, "+5");
164
165 res = g_snprintf (string: buf, n: 128, format: "%+-d", 5);
166 g_assert_cmpint (res, ==, 2);
167 g_assert_cmpstr (buf, ==, "+5");
168
169 res = g_snprintf (string: buf, n: 128, format: "%+d", -5);
170 g_assert_cmpint (res, ==, 2);
171 g_assert_cmpstr (buf, ==, "-5");
172
173 res = g_snprintf (string: buf, n: 128, format: "% d", 5);
174 g_assert_cmpint (res, ==, 2);
175 g_assert_cmpstr (buf, ==, " 5");
176
177 res = g_snprintf (string: buf, n: 128, format: "% .0d", 0);
178 g_assert_cmpint (res, ==, 1);
179 g_assert_cmpstr (buf, ==, " ");
180
181 res = g_snprintf (string: buf, n: 128, format: "%03d", 5);
182 g_assert_cmpint (res, ==, 3);
183 g_assert_cmpstr (buf, ==, "005");
184
185 res = g_snprintf (string: buf, n: 128, format: "%03d", -5);
186 g_assert_cmpint (res, ==, 3);
187 g_assert_cmpstr (buf, ==, "-05");
188}
189
190/* gcc emits warnings for the following formats, since the C spec
191 * says some of the flags must be ignored. (The " " in "% +d" and
192 * the "0" in "%-03d".) But we need to test that our printf gets
193 * those rules right. So we fool gcc into not warning.
194 *
195 * These have to be in a separate function in order to use #pragma.
196 */
197#pragma GCC diagnostic push
198#pragma GCC diagnostic ignored "-Wformat-nonliteral"
199static void
200test_d_invalid (void)
201{
202 const gchar *fmt;
203 gchar buf[128];
204 gint res;
205
206 fmt = "% +d";
207 res = g_snprintf (string: buf, n: 128, format: fmt, 5);
208 g_assert_cmpint (res, ==, 2);
209 g_assert_cmpstr (buf, ==, "+5");
210
211 fmt = "%-03d";
212 res = g_snprintf (string: buf, n: 128, format: fmt, -5);
213 g_assert_cmpint (res, ==, 3);
214 g_assert_cmpstr (buf, ==, "-5 ");
215}
216#pragma GCC diagnostic pop
217
218static void
219test_o (void)
220{
221 gchar buf[128];
222 gint res;
223
224 /* %o basic formatting */
225
226 res = g_snprintf (string: buf, n: 128, format: "%o", 5);
227 g_assert_cmpint (res, ==, 1);
228 g_assert_cmpstr (buf, ==, "5");
229
230 res = g_snprintf (string: buf, n: 128, format: "%o", 8);
231 g_assert_cmpint (res, ==, 2);
232 g_assert_cmpstr (buf, ==, "10");
233
234 res = g_snprintf (string: buf, n: 128, format: "%o", 0);
235 g_assert_cmpint (res, ==, 1);
236 g_assert_cmpstr (buf, ==, "0");
237
238 res = g_snprintf (string: buf, n: 128, format: "%.0o", 0);
239 g_assert_cmpint (res, ==, 0);
240 g_assert_cmpstr (buf, ==, "");
241
242 res = g_snprintf (string: buf, n: 128, format: "%.0o", 1);
243 g_assert_cmpint (res, ==, 1);
244 g_assert_cmpstr (buf, ==, "1");
245
246 res = g_snprintf (string: buf, n: 128, format: "%.3o", 5);
247 g_assert_cmpint (res, ==, 3);
248 g_assert_cmpstr (buf, ==, "005");
249
250 res = g_snprintf (string: buf, n: 128, format: "%.3o", 8);
251 g_assert_cmpint (res, ==, 3);
252 g_assert_cmpstr (buf, ==, "010");
253
254 res = g_snprintf (string: buf, n: 128, format: "%5.3o", 5);
255 g_assert_cmpint (res, ==, 5);
256 g_assert_cmpstr (buf, ==, " 005");
257}
258
259static void
260test_u (void)
261{
262 gchar buf[128];
263 gint res;
264
265 /* %u, basic formatting */
266
267 res = g_snprintf (string: buf, n: 128, format: "%u", 5);
268 g_assert_cmpint (res, ==, 1);
269 g_assert_cmpstr (buf, ==, "5");
270
271 res = g_snprintf (string: buf, n: 128, format: "%u", 0);
272 g_assert_cmpint (res, ==, 1);
273 g_assert_cmpstr (buf, ==, "0");
274
275 res = g_snprintf (string: buf, n: 128, format: "%.0u", 0);
276 g_assert_cmpint (res, ==, 0);
277 g_assert_cmpstr (buf, ==, "");
278
279 res = g_snprintf (string: buf, n: 128, format: "%.0u", 1);
280 g_assert_cmpint (res, ==, 1);
281 g_assert_cmpstr (buf, ==, "1");
282
283 res = g_snprintf (string: buf, n: 128, format: "%.3u", 5);
284 g_assert_cmpint (res, ==, 3);
285 g_assert_cmpstr (buf, ==, "005");
286
287 res = g_snprintf (string: buf, n: 128, format: "%5.3u", 5);
288 g_assert_cmpint (res, ==, 5);
289 g_assert_cmpstr (buf, ==, " 005");
290}
291
292static void
293test_x (void)
294{
295 gchar buf[128];
296 gint res;
297
298 /* %x, basic formatting */
299
300 res = g_snprintf (string: buf, n: 128, format: "%x", 5);
301 g_assert_cmpint (res, ==, 1);
302 g_assert_cmpstr (buf, ==, "5");
303
304 res = g_snprintf (string: buf, n: 128, format: "%x", 31);
305 g_assert_cmpint (res, ==, 2);
306 g_assert_cmpstr (buf, ==, "1f");
307
308 res = g_snprintf (string: buf, n: 128, format: "%x", 0);
309 g_assert_cmpint (res, ==, 1);
310 g_assert_cmpstr (buf, ==, "0");
311
312 res = g_snprintf (string: buf, n: 128, format: "%.0x", 0);
313 g_assert_cmpint (res, ==, 0);
314 g_assert_cmpstr (buf, ==, "");
315
316 res = g_snprintf (string: buf, n: 128, format: "%.0x", 1);
317 g_assert_cmpint (res, ==, 1);
318 g_assert_cmpstr (buf, ==, "1");
319
320 res = g_snprintf (string: buf, n: 128, format: "%.3x", 5);
321 g_assert_cmpint (res, ==, 3);
322 g_assert_cmpstr (buf, ==, "005");
323
324 res = g_snprintf (string: buf, n: 128, format: "%.3x", 31);
325 g_assert_cmpint (res, ==, 3);
326 g_assert_cmpstr (buf, ==, "01f");
327
328 res = g_snprintf (string: buf, n: 128, format: "%5.3x", 5);
329 g_assert_cmpint (res, ==, 5);
330 g_assert_cmpstr (buf, ==, " 005");
331
332 /* %x, flags */
333
334 res = g_snprintf (string: buf, n: 128, format: "%-x", 5);
335 g_assert_cmpint (res, ==, 1);
336 g_assert_cmpstr (buf, ==, "5");
337
338 res = g_snprintf (string: buf, n: 128, format: "%03x", 5);
339 g_assert_cmpint (res, ==, 3);
340 g_assert_cmpstr (buf, ==, "005");
341
342 res = g_snprintf (string: buf, n: 128, format: "%#x", 31);
343 g_assert_cmpint (res, ==, 4);
344 g_assert_cmpstr (buf, ==, "0x1f");
345
346 res = g_snprintf (string: buf, n: 128, format: "%#x", 0);
347 g_assert_cmpint (res, ==, 1);
348 g_assert_cmpstr (buf, ==, "0");
349}
350
351static void
352test_X (void)
353{
354 gchar buf[128];
355 gint res;
356
357 /* %X, basic formatting */
358
359 res = g_snprintf (string: buf, n: 128, format: "%X", 5);
360 g_assert_cmpint (res, ==, 1);
361 g_assert_cmpstr (buf, ==, "5");
362
363 res = g_snprintf (string: buf, n: 128, format: "%X", 31);
364 g_assert_cmpint (res, ==, 2);
365 g_assert_cmpstr (buf, ==, "1F");
366
367 res = g_snprintf (string: buf, n: 128, format: "%X", 0);
368 g_assert_cmpint (res, ==, 1);
369 g_assert_cmpstr (buf, ==, "0");
370
371 res = g_snprintf (string: buf, n: 128, format: "%.0X", 0);
372 g_assert_cmpint (res, ==, 0);
373 g_assert_cmpstr (buf, ==, "");
374
375 res = g_snprintf (string: buf, n: 128, format: "%.0X", 1);
376 g_assert_cmpint (res, ==, 1);
377 g_assert_cmpstr (buf, ==, "1");
378
379 res = g_snprintf (string: buf, n: 128, format: "%.3X", 5);
380 g_assert_cmpint (res, ==, 3);
381 g_assert_cmpstr (buf, ==, "005");
382
383 res = g_snprintf (string: buf, n: 128, format: "%.3X", 31);
384 g_assert_cmpint (res, ==, 3);
385 g_assert_cmpstr (buf, ==, "01F");
386
387 res = g_snprintf (string: buf, n: 128, format: "%5.3X", 5);
388 g_assert_cmpint (res, ==, 5);
389 g_assert_cmpstr (buf, ==, " 005");
390
391 /* %X, flags */
392
393 res = g_snprintf (string: buf, n: 128, format: "%-X", 5);
394 g_assert_cmpint (res, ==, 1);
395 g_assert_cmpstr (buf, ==, "5");
396
397 res = g_snprintf (string: buf, n: 128, format: "%03X", 5);
398 g_assert_cmpint (res, ==, 3);
399 g_assert_cmpstr (buf, ==, "005");
400
401 res = g_snprintf (string: buf, n: 128, format: "%#X", 31);
402 g_assert_cmpint (res, ==, 4);
403 g_assert_cmpstr (buf, ==, "0X1F");
404
405 res = g_snprintf (string: buf, n: 128, format: "%#X", 0);
406 g_assert_cmpint (res, ==, 1);
407 g_assert_cmpstr (buf, ==, "0");
408}
409
410static void
411test_f (void)
412{
413 gchar buf[128];
414 gint res;
415
416 /* %f, basic formatting */
417
418 res = g_snprintf (string: buf, n: 128, format: "%f", G_PI);
419 g_assert_cmpint (res, ==, 8);
420 g_assert (0 == strncmp (buf, "3.14159", 7));
421
422 res = g_snprintf (string: buf, n: 128, format: "%.8f", G_PI);
423 g_assert_cmpint (res, ==, 10);
424 g_assert (0 == strncmp (buf, "3.1415926", 9));
425
426 res = g_snprintf (string: buf, n: 128, format: "%.0f", G_PI);
427 g_assert_cmpint (res, ==, 1);
428 g_assert_cmpstr (buf, ==, "3");
429
430 res = g_snprintf (string: buf, n: 128, format: "%1.f", G_PI);
431 g_assert_cmpint (res, ==, 1);
432 g_assert_cmpstr (buf, ==, "3");
433
434 res = g_snprintf (string: buf, n: 128, format: "%3.f", G_PI);
435 g_assert_cmpint (res, ==, 3);
436 g_assert_cmpstr (buf, ==, " 3");
437
438 /* %f, flags */
439
440 res = g_snprintf (string: buf, n: 128, format: "%+f", G_PI);
441 g_assert_cmpint (res, ==, 9);
442 g_assert (0 == strncmp (buf, "+3.14159", 8));
443
444 res = g_snprintf (string: buf, n: 128, format: "% f", G_PI);
445 g_assert_cmpint (res, ==, 9);
446 g_assert (0 == strncmp (buf, " 3.14159", 8));
447
448 res = g_snprintf (string: buf, n: 128, format: "%#.0f", G_PI);
449 g_assert_cmpint (res, ==, 2);
450 g_assert_cmpstr (buf, ==, "3.");
451
452 res = g_snprintf (string: buf, n: 128, format: "%05.2f", G_PI);
453 g_assert_cmpint (res, ==, 5);
454 g_assert_cmpstr (buf, ==, "03.14");
455}
456
457static gboolean
458same_value (const gchar *actual,
459 const gchar *expected)
460{
461 gdouble actual_value, expected_value;
462
463 actual_value = g_ascii_strtod (nptr: actual, NULL);
464 expected_value = g_ascii_strtod (nptr: expected, NULL);
465
466 return actual_value == expected_value;
467}
468
469static void
470test_e (void)
471{
472 gchar buf[128];
473 gint res;
474
475 /* %e, basic formatting */
476 /* for %e we can't expect to reproduce exact strings and lengths, since SUS
477 * only guarantees that the exponent shall always contain at least two
478 * digits. On Windows, it seems to be at least three digits long.
479 * Therefore, we compare the results of parsing the expected result and the
480 * actual result.
481 */
482
483 res = g_snprintf (string: buf, n: 128, format: "%e", G_PI);
484 g_assert_cmpint (res, >=, 12);
485 g_assert (same_value (buf, "3.141593e+00"));
486
487 res = g_snprintf (string: buf, n: 128, format: "%.8e", G_PI);
488 g_assert_cmpint (res, >=, 14);
489 g_assert (same_value (buf, "3.14159265e+00"));
490
491 res = g_snprintf (string: buf, n: 128, format: "%.0e", G_PI);
492 g_assert_cmpint (res, >=, 5);
493 g_assert (same_value (buf, "3e+00"));
494
495 res = g_snprintf (string: buf, n: 128, format: "%.1e", 0.0);
496 g_assert_cmpint (res, >=, 7);
497 g_assert (same_value (buf, "0.0e+00"));
498
499 res = g_snprintf (string: buf, n: 128, format: "%.1e", 0.00001);
500 g_assert_cmpint (res, >=, 7);
501 g_assert (same_value (buf, "1.0e-05"));
502
503 res = g_snprintf (string: buf, n: 128, format: "%.1e", 10000.0);
504 g_assert_cmpint (res, >=, 7);
505 g_assert (same_value (buf, "1.0e+04"));
506
507 /* %e, flags */
508
509 res = g_snprintf (string: buf, n: 128, format: "%+e", G_PI);
510 g_assert_cmpint (res, >=, 13);
511 g_assert (same_value (buf, "+3.141593e+00"));
512
513 res = g_snprintf (string: buf, n: 128, format: "% e", G_PI);
514 g_assert_cmpint (res, >=, 13);
515 g_assert (same_value (buf, " 3.141593e+00"));
516
517 res = g_snprintf (string: buf, n: 128, format: "%#.0e", G_PI);
518 g_assert_cmpint (res, >=, 6);
519 g_assert (same_value (buf, "3.e+00"));
520
521 res = g_snprintf (string: buf, n: 128, format: "%09.2e", G_PI);
522 g_assert_cmpint (res, >=, 9);
523 g_assert (same_value (buf, "03.14e+00"));
524}
525
526static void
527test_c (void)
528{
529 gchar buf[128];
530 gint res;
531
532 res = g_snprintf (string: buf, n: 128, format: "%c", 'a');
533 g_assert_cmpint (res, ==, 1);
534 g_assert_cmpstr (buf, ==, "a");
535}
536
537static void
538test_s (void)
539{
540 gchar buf[128];
541 gint res;
542
543 res = g_snprintf (string: buf, n: 128, format: "%.2s", "abc");
544 g_assert_cmpint (res, ==, 2);
545 g_assert_cmpstr (buf, ==, "ab");
546
547 res = g_snprintf (string: buf, n: 128, format: "%.6s", "abc");
548 g_assert_cmpint (res, ==, 3);
549 g_assert_cmpstr (buf, ==, "abc");
550
551 res = g_snprintf (string: buf, n: 128, format: "%5s", "abc");
552 g_assert_cmpint (res, ==, 5);
553 g_assert_cmpstr (buf, ==, " abc");
554
555 res = g_snprintf (string: buf, n: 128, format: "%-5s", "abc");
556 g_assert_cmpint (res, ==, 5);
557 g_assert_cmpstr (buf, ==, "abc ");
558
559 res = g_snprintf (string: buf, n: 128, format: "%5.2s", "abc");
560 g_assert_cmpint (res, ==, 5);
561 g_assert_cmpstr (buf, ==, " ab");
562
563 res = g_snprintf (string: buf, n: 128, format: "%*s", 5, "abc");
564 g_assert_cmpint (res, ==, 5);
565 g_assert_cmpstr (buf, ==, " abc");
566
567 res = g_snprintf (string: buf, n: 128, format: "%*s", -5, "abc");
568 g_assert_cmpint (res, ==, 5);
569 g_assert_cmpstr (buf, ==, "abc ");
570
571 res = g_snprintf (string: buf, n: 128, format: "%*.*s", 5, 2, "abc");
572 g_assert_cmpint (res, ==, 5);
573 g_assert_cmpstr (buf, ==, " ab");
574}
575
576static void
577test_n (void)
578{
579 gchar buf[128];
580 gint res;
581 gint i;
582 glong l;
583
584 res = g_snprintf (string: buf, n: 128, format: "abc%n", &i);
585 g_assert_cmpint (res, ==, 3);
586 g_assert_cmpstr (buf, ==, "abc");
587 g_assert_cmpint (i, ==, 3);
588
589 res = g_snprintf (string: buf, n: 128, format: "abc%ln", &l);
590 g_assert_cmpint (res, ==, 3);
591 g_assert_cmpstr (buf, ==, "abc");
592 g_assert_cmpint (l, ==, 3);
593}
594
595static void
596test_percent (void)
597{
598 gchar buf[128];
599 gint res;
600
601 res = g_snprintf (string: buf, n: 128, format: "%%");
602 g_assert_cmpint (res, ==, 1);
603 g_assert_cmpstr (buf, ==, "%");
604}
605
606static void
607test_positional_params (void)
608{
609 gchar buf[128];
610 gint res;
611
612 res = g_snprintf (string: buf, n: 128, format: "%2$c %1$c", 'b', 'a');
613 g_assert_cmpint (res, ==, 3);
614 g_assert_cmpstr (buf, ==, "a b");
615
616 res = g_snprintf (string: buf, n: 128, format: "%1$*2$.*3$s", "abc", 5, 2);
617 g_assert_cmpint (res, ==, 5);
618 g_assert_cmpstr (buf, ==, " ab");
619
620 res = g_snprintf (string: buf, n: 128, format: "%1$s%1$s", "abc");
621 g_assert_cmpint (res, ==, 6);
622 g_assert_cmpstr (buf, ==, "abcabc");
623}
624
625static void
626test_positional_params2 (void)
627{
628 if (g_test_subprocess ())
629 {
630 gint res;
631
632 res = g_printf (format: "%2$c %1$c\n", 'b', 'a');
633 g_assert_cmpint (res, ==, 4);
634
635 res = g_printf (format: "%1$*2$.*3$s\n", "abc", 5, 2);
636 g_assert_cmpint (res, ==, 6);
637
638 res = g_printf (format: "%1$s%1$s\n", "abc");
639 g_assert_cmpint (res, ==, 7);
640 return;
641 }
642 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0);
643 g_test_trap_assert_passed ();
644 g_test_trap_assert_stdout ("a b\n ab\nabcabc\n");
645}
646
647static void
648test_positional_params3 (void)
649{
650 gchar buf[128];
651 gint res;
652
653 res = g_sprintf (string: buf, format: "%2$c %1$c", 'b', 'a');
654 g_assert_cmpint (res, ==, 3);
655 g_assert_cmpstr (buf, ==, "a b");
656
657 res = g_sprintf (string: buf, format: "%1$*2$.*3$s", "abc", 5, 2);
658 g_assert_cmpint (res, ==, 5);
659 g_assert_cmpstr (buf, ==, " ab");
660
661 res = g_sprintf (string: buf, format: "%1$s%1$s", "abc");
662 g_assert_cmpint (res, ==, 6);
663 g_assert_cmpstr (buf, ==, "abcabc");
664}
665
666static void
667test_percent2 (void)
668{
669 if (g_test_subprocess ())
670 {
671 gint res;
672
673 res = g_printf (format: "%%");
674 g_assert_cmpint (res, ==, 1);
675 return;
676 }
677 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0);
678 g_test_trap_assert_passed ();
679 g_test_trap_assert_stdout ("*%*");
680}
681
682static void
683test_64bit (void)
684{
685 gchar buf[128];
686 gint res;
687
688 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT64_FORMAT, (gint64)123456);
689 g_assert_cmpint (res, ==, 6);
690 g_assert_cmpstr (buf, ==, "123456");
691
692 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT64_FORMAT, (gint64)-123456);
693 g_assert_cmpint (res, ==, 7);
694 g_assert_cmpstr (buf, ==, "-123456");
695
696 res = g_snprintf (string: buf, n: 128, format: "%" G_GUINT64_FORMAT, (guint64)123456);
697 g_assert_cmpint (res, ==, 6);
698 g_assert_cmpstr (buf, ==, "123456");
699
700 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT64_MODIFIER "o", (gint64)123456);
701 g_assert_cmpint (res, ==, 6);
702 g_assert_cmpstr (buf, ==, "361100");
703
704 res = g_snprintf (string: buf, n: 128, format: "%#" G_GINT64_MODIFIER "o", (gint64)123456);
705 g_assert_cmpint (res, ==, 7);
706 g_assert_cmpstr (buf, ==, "0361100");
707
708 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT64_MODIFIER "x", (gint64)123456);
709 g_assert_cmpint (res, ==, 5);
710 g_assert_cmpstr (buf, ==, "1e240");
711
712 res = g_snprintf (string: buf, n: 128, format: "%#" G_GINT64_MODIFIER "x", (gint64)123456);
713 g_assert_cmpint (res, ==, 7);
714 g_assert_cmpstr (buf, ==, "0x1e240");
715
716 res = g_snprintf (string: buf, n: 128, format: "%" G_GINT64_MODIFIER "X", (gint64)123456);
717 g_assert_cmpint (res, ==, 5);
718 g_assert_cmpstr (buf, ==, "1E240");
719
720#ifdef G_OS_WIN32
721 /* On Win32, test that the "ll" modifier also works, for backward
722 * compatibility. One really should use the G_GINT64_MODIFIER (which
723 * on Win32 is the "I64" that the (msvcrt) C library's printf uses),
724 * but "ll" used to work with the "trio" g_printf implementation in
725 * GLib 2.2, so it's best if it continues to work.
726 */
727
728 /* However, gcc doesn't know about this, so we need to disable printf
729 * format warnings...
730 */
731#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
732_Pragma ("GCC diagnostic push")
733_Pragma ("GCC diagnostic ignored \"-Wformat\"")
734_Pragma ("GCC diagnostic ignored \"-Wformat-extra-args\"")
735#endif
736
737 res = g_snprintf (buf, 128, "%" "lli", (gint64)123456);
738 g_assert_cmpint (res, ==, 6);
739 g_assert_cmpstr (buf, ==, "123456");
740
741 res = g_snprintf (buf, 128, "%" "lli", (gint64)-123456);
742 g_assert_cmpint (res, ==, 7);
743 g_assert_cmpstr (buf, ==, "-123456");
744
745 res = g_snprintf (buf, 128, "%" "llu", (guint64)123456);
746 g_assert_cmpint (res, ==, 6);
747 g_assert_cmpstr (buf, ==, "123456");
748
749 res = g_snprintf (buf, 128, "%" "ll" "o", (gint64)123456);
750 g_assert_cmpint (res, ==, 6);
751 g_assert_cmpstr (buf, ==, "361100");
752
753 res = g_snprintf (buf, 128, "%#" "ll" "o", (gint64)123456);
754 g_assert_cmpint (res, ==, 7);
755 g_assert_cmpstr (buf, ==, "0361100");
756
757 res = g_snprintf (buf, 128, "%" "ll" "x", (gint64)123456);
758 g_assert_cmpint (res, ==, 5);
759 g_assert_cmpstr (buf, ==, "1e240");
760
761 res = g_snprintf (buf, 128, "%#" "ll" "x", (gint64)123456);
762 g_assert_cmpint (res, ==, 7);
763 g_assert_cmpstr (buf, ==, "0x1e240");
764
765 res = g_snprintf (buf, 128, "%" "ll" "X", (gint64)123456);
766 g_assert_cmpint (res, ==, 5);
767 g_assert_cmpstr (buf, ==, "1E240");
768
769#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
770_Pragma ("GCC diagnostic pop")
771#endif
772
773#endif
774}
775
776static void
777test_64bit2_base (void)
778{
779 gint res;
780
781 res = g_printf (format: "%" G_GINT64_FORMAT "\n", (gint64)123456);
782 g_assert_cmpint (res, ==, 7);
783
784 res = g_printf (format: "%" G_GINT64_FORMAT "\n", (gint64)-123456);
785 g_assert_cmpint (res, ==, 8);
786
787 res = g_printf (format: "%" G_GUINT64_FORMAT "\n", (guint64)123456);
788 g_assert_cmpint (res, ==, 7);
789
790 res = g_printf (format: "%" G_GINT64_MODIFIER "o\n", (gint64)123456);
791 g_assert_cmpint (res, ==, 7);
792
793 res = g_printf (format: "%#" G_GINT64_MODIFIER "o\n", (gint64)123456);
794 g_assert_cmpint (res, ==, 8);
795
796 res = g_printf (format: "%" G_GINT64_MODIFIER "x\n", (gint64)123456);
797 g_assert_cmpint (res, ==, 6);
798
799 res = g_printf (format: "%#" G_GINT64_MODIFIER "x\n", (gint64)123456);
800 g_assert_cmpint (res, ==, 8);
801
802 res = g_printf (format: "%" G_GINT64_MODIFIER "X\n", (gint64)123456);
803 g_assert_cmpint (res, ==, 6);
804}
805
806#ifdef G_OS_WIN32
807static void
808test_64bit2_win32 (void)
809{
810 gint res;
811
812 /* On Win32, test that the "ll" modifier also works, for backward
813 * compatibility. One really should use the G_GINT64_MODIFIER (which
814 * on Win32 is the "I64" that the (msvcrt) C library's printf uses),
815 * but "ll" used to work with the "trio" g_printf implementation in
816 * GLib 2.2, so it's best if it continues to work.
817 */
818
819 /* However, gcc doesn't know about this, so we need to disable printf
820 * format warnings...
821 */
822#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
823_Pragma ("GCC diagnostic push")
824_Pragma ("GCC diagnostic ignored \"-Wformat\"")
825_Pragma ("GCC diagnostic ignored \"-Wformat-extra-args\"")
826#endif
827
828 res = g_printf ("%" "lli\n", (gint64)123456);
829 g_assert_cmpint (res, ==, 7);
830
831 res = g_printf ("%" "lli\n", (gint64)-123456);
832 g_assert_cmpint (res, ==, 8);
833
834 res = g_printf ("%" "llu\n", (guint64)123456);
835 g_assert_cmpint (res, ==, 7);
836
837 res = g_printf ("%" "ll" "o\n", (gint64)123456);
838 g_assert_cmpint (res, ==, 7);
839
840 res = g_printf ("%#" "ll" "o\n", (gint64)123456);
841 g_assert_cmpint (res, ==, 8);
842
843 res = g_printf ("%" "ll" "x\n", (gint64)123456);
844 g_assert_cmpint (res, ==, 6);
845
846 res = g_printf ("%#" "ll" "x\n", (gint64)123456);
847 g_assert_cmpint (res, ==, 8);
848
849 res = g_printf ("%" "ll" "X\n", (gint64)123456);
850 g_assert_cmpint (res, ==, 6);
851
852#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
853_Pragma ("GCC diagnostic pop")
854#endif
855}
856#endif
857
858static void
859test_64bit2 (void)
860{
861 g_test_trap_subprocess (test_path: "/printf/test-64bit/subprocess/base", usec_timeout: 0, test_flags: 0);
862 g_test_trap_assert_passed ();
863 g_test_trap_assert_stdout ("123456\n-123456\n123456\n"
864 "361100\n0361100\n1e240\n"
865 "0x1e240\n1E240\n");
866#ifdef G_OS_WIN32
867 g_test_trap_subprocess ("/printf/test-64bit/subprocess/win32", 0, 0);
868 g_test_trap_assert_passed ();
869 g_test_trap_assert_stdout ("123456\n-123456\n123456\n"
870 "361100\n0361100\n1e240\n"
871 "0x1e240\n1E240\n");
872#endif
873}
874
875G_GNUC_PRINTF(1, 2)
876static gsize
877upper_bound (const gchar *format, ...)
878{
879 va_list args;
880 gsize res;
881
882 va_start (args, format);
883 res = g_printf_string_upper_bound (format, args);
884 va_end (args);
885
886 return res;
887}
888
889static void
890test_upper_bound (void)
891{
892 gsize res;
893
894 res = upper_bound (format: "bla %s %d: %g\n", "bla", 123, 0.123);
895 g_assert_cmpint (res, ==, 20);
896}
897
898int
899main (int argc,
900 char *argv[])
901{
902#ifdef G_OS_WIN32
903 /* Ensure binary mode for stdout, this way
904 * tests produce \n line endings on Windows instead of the
905 * default \r\n.
906 */
907 _setmode (fileno (stdout), _O_BINARY);
908#endif
909 g_test_init (argc: &argc, argv: &argv, NULL);
910
911 g_test_add_func (testpath: "/snprintf/retval-and-trunc", test_func: test_retval_and_trunc);
912 g_test_add_func (testpath: "/snprintf/%d", test_func: test_d);
913 g_test_add_func (testpath: "/snprintf/%d-invalid", test_func: test_d_invalid);
914 g_test_add_func (testpath: "/snprintf/%o", test_func: test_o);
915 g_test_add_func (testpath: "/snprintf/%u", test_func: test_u);
916 g_test_add_func (testpath: "/snprintf/%x", test_func: test_x);
917 g_test_add_func (testpath: "/snprintf/%X", test_func: test_X);
918 g_test_add_func (testpath: "/snprintf/%f", test_func: test_f);
919 g_test_add_func (testpath: "/snprintf/%e", test_func: test_e);
920 g_test_add_func (testpath: "/snprintf/%c", test_func: test_c);
921 g_test_add_func (testpath: "/snprintf/%s", test_func: test_s);
922 g_test_add_func (testpath: "/snprintf/%n", test_func: test_n);
923 g_test_add_func (testpath: "/snprintf/test-percent", test_func: test_percent);
924 g_test_add_func (testpath: "/snprintf/test-positional-params", test_func: test_positional_params);
925 g_test_add_func (testpath: "/snprintf/test-64bit", test_func: test_64bit);
926
927 g_test_add_func (testpath: "/printf/test-percent", test_func: test_percent2);
928 g_test_add_func (testpath: "/printf/test-positional-params", test_func: test_positional_params2);
929 g_test_add_func (testpath: "/printf/test-64bit", test_func: test_64bit2);
930 g_test_add_func (testpath: "/printf/test-64bit/subprocess/base", test_func: test_64bit2_base);
931#ifdef G_OS_WIN32
932 g_test_add_func ("/printf/test-64bit/subprocess/win32", test_64bit2_win32);
933#endif
934
935 g_test_add_func (testpath: "/sprintf/test-positional-params", test_func: test_positional_params3);
936 g_test_add_func (testpath: "/sprintf/upper-bound", test_func: test_upper_bound);
937
938 return g_test_run();
939}
940

source code of gtk/subprojects/glib/glib/tests/test-printf.c