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