• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 static void
test_retval_and_trunc(void)33 test_retval_and_trunc (void)
34 {
35   gchar buf[128];
36   gint res;
37 
38   res = g_snprintf (buf, 0, "abc");
39   g_assert_cmpint (res, ==, 3);
40 
41   res = g_snprintf (NULL, 0, "abc");
42   g_assert_cmpint (res, ==, 3);
43 
44   res = g_snprintf (buf, 5, "abc");
45   g_assert_cmpint (res, ==, 3);
46 
47   res = g_snprintf (buf, 1, "abc");
48   g_assert_cmpint (res, ==, 3);
49   g_assert (buf[0] == '\0');
50   g_assert_cmpstr (buf, ==, "");
51 
52   res = g_snprintf (buf, 2, "abc");
53   g_assert_cmpint (res, ==, 3);
54   g_assert (buf[1] == '\0');
55   g_assert_cmpstr (buf, ==, "a");
56 
57   res = g_snprintf (buf, 3, "abc");
58   g_assert_cmpint (res, ==, 3);
59   g_assert (buf[2] == '\0');
60   g_assert_cmpstr (buf, ==, "ab");
61 
62   res = g_snprintf (buf, 4, "abc");
63   g_assert_cmpint (res, ==, 3);
64   g_assert (buf[3] == '\0');
65   g_assert_cmpstr (buf, ==, "abc");
66 
67   res = g_snprintf (buf, 5, "abc");
68   g_assert_cmpint (res, ==, 3);
69   g_assert (buf[3] == '\0');
70   g_assert_cmpstr (buf, ==, "abc");
71 }
72 
73 static void
test_d(void)74 test_d (void)
75 {
76   gchar buf[128];
77   gint res;
78 
79   /* %d basic formatting */
80 
81   res = g_snprintf (buf, 128, "%d", 5);
82   g_assert_cmpint (res, ==, 1);
83   g_assert_cmpstr (buf, ==, "5");
84 
85   res = g_snprintf (buf, 128, "%d", 0);
86   g_assert_cmpint (res, ==, 1);
87   g_assert_cmpstr (buf, ==, "0");
88 
89   res = g_snprintf (buf, 128, "%.0d", 0);
90   g_assert_cmpint (res, ==, 0);
91   g_assert_cmpstr (buf, ==, "");
92 
93   res = g_snprintf (buf, 128, "%.0d", 1);
94   g_assert_cmpint (res, ==, 1);
95   g_assert_cmpstr (buf, ==, "1");
96 
97   res = g_snprintf (buf, 128, "%.d", 2);
98   g_assert_cmpint (res, ==, 1);
99   g_assert_cmpstr (buf, ==, "2");
100 
101   res = g_snprintf (buf, 128, "%d", -1);
102   g_assert_cmpint (res, ==, 2);
103   g_assert_cmpstr (buf, ==, "-1");
104 
105   res = g_snprintf (buf, 128, "%.3d", 5);
106   g_assert_cmpint (res, ==, 3);
107   g_assert_cmpstr (buf, ==, "005");
108 
109   res = g_snprintf (buf, 128, "%.3d", -5);
110   g_assert_cmpint (res, ==, 4);
111   g_assert_cmpstr (buf, ==, "-005");
112 
113   res = g_snprintf (buf, 128, "%5.3d", 5);
114   g_assert_cmpint (res, ==, 5);
115   g_assert_cmpstr (buf, ==, "  005");
116 
117   res = g_snprintf (buf, 128, "%-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 (buf, 128, "%" G_GINT16_FORMAT, (gint16)-5);
124   g_assert_cmpint (res, ==, 2);
125   g_assert_cmpstr (buf, ==, "-5");
126 
127   res = g_snprintf (buf, 128, "%" G_GUINT16_FORMAT, (guint16)5);
128   g_assert_cmpint (res, ==, 1);
129   g_assert_cmpstr (buf, ==, "5");
130 
131   res = g_snprintf (buf, 128, "%" G_GINT32_FORMAT, (gint32)-5);
132   g_assert_cmpint (res, ==, 2);
133   g_assert_cmpstr (buf, ==, "-5");
134 
135   res = g_snprintf (buf, 128, "%" G_GUINT32_FORMAT, (guint32)5);
136   g_assert_cmpint (res, ==, 1);
137   g_assert_cmpstr (buf, ==, "5");
138 
139   res = g_snprintf (buf, 128, "%" G_GINT64_FORMAT, (gint64)-5);
140   g_assert_cmpint (res, ==, 2);
141   g_assert_cmpstr (buf, ==, "-5");
142 
143   res = g_snprintf (buf, 128, "%" G_GUINT64_FORMAT, (guint64)5);
144   g_assert_cmpint (res, ==, 1);
145   g_assert_cmpstr (buf, ==, "5");
146 
147   res = g_snprintf (buf, 128, "%" G_GSSIZE_FORMAT, (gssize)-5);
148   g_assert_cmpint (res, ==, 2);
149   g_assert_cmpstr (buf, ==, "-5");
150 
151   res = g_snprintf (buf, 128, "%" 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 (buf, 128, "%-d", 5);
158   g_assert_cmpint (res, ==, 1);
159   g_assert_cmpstr (buf, ==, "5");
160 
161   res = g_snprintf (buf, 128, "%-+d", 5);
162   g_assert_cmpint (res, ==, 2);
163   g_assert_cmpstr (buf, ==, "+5");
164 
165   res = g_snprintf (buf, 128, "%+-d", 5);
166   g_assert_cmpint (res, ==, 2);
167   g_assert_cmpstr (buf, ==, "+5");
168 
169   res = g_snprintf (buf, 128, "%+d", -5);
170   g_assert_cmpint (res, ==, 2);
171   g_assert_cmpstr (buf, ==, "-5");
172 
173   res = g_snprintf (buf, 128, "% d", 5);
174   g_assert_cmpint (res, ==, 2);
175   g_assert_cmpstr (buf, ==, " 5");
176 
177   res = g_snprintf (buf, 128, "% .0d", 0);
178   g_assert_cmpint (res, ==, 1);
179   g_assert_cmpstr (buf, ==, " ");
180 
181   res = g_snprintf (buf, 128, "%03d", 5);
182   g_assert_cmpint (res, ==, 3);
183   g_assert_cmpstr (buf, ==, "005");
184 
185   res = g_snprintf (buf, 128, "%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"
199 static void
test_d_invalid(void)200 test_d_invalid (void)
201 {
202   const gchar *fmt;
203   gchar buf[128];
204   gint res;
205 
206   fmt = "% +d";
207   res = g_snprintf (buf, 128, fmt, 5);
208   g_assert_cmpint (res, ==, 2);
209   g_assert_cmpstr (buf, ==, "+5");
210 
211   fmt = "%-03d";
212   res = g_snprintf (buf, 128, fmt, -5);
213   g_assert_cmpint (res, ==, 3);
214   g_assert_cmpstr (buf, ==, "-5 ");
215 }
216 #pragma GCC diagnostic pop
217 
218 static void
test_o(void)219 test_o (void)
220 {
221   gchar buf[128];
222   gint res;
223 
224   /* %o basic formatting */
225 
226   res = g_snprintf (buf, 128, "%o", 5);
227   g_assert_cmpint (res, ==, 1);
228   g_assert_cmpstr (buf, ==, "5");
229 
230   res = g_snprintf (buf, 128, "%o", 8);
231   g_assert_cmpint (res, ==, 2);
232   g_assert_cmpstr (buf, ==, "10");
233 
234   res = g_snprintf (buf, 128, "%o", 0);
235   g_assert_cmpint (res, ==, 1);
236   g_assert_cmpstr (buf, ==, "0");
237 
238   res = g_snprintf (buf, 128, "%.0o", 0);
239   g_assert_cmpint (res, ==, 0);
240   g_assert_cmpstr (buf, ==, "");
241 
242   res = g_snprintf (buf, 128, "%.0o", 1);
243   g_assert_cmpint (res, ==, 1);
244   g_assert_cmpstr (buf, ==, "1");
245 
246   res = g_snprintf (buf, 128, "%.3o", 5);
247   g_assert_cmpint (res, ==, 3);
248   g_assert_cmpstr (buf, ==, "005");
249 
250   res = g_snprintf (buf, 128, "%.3o", 8);
251   g_assert_cmpint (res, ==, 3);
252   g_assert_cmpstr (buf, ==, "010");
253 
254   res = g_snprintf (buf, 128, "%5.3o", 5);
255   g_assert_cmpint (res, ==, 5);
256   g_assert_cmpstr (buf, ==, "  005");
257 }
258 
259 static void
test_u(void)260 test_u (void)
261 {
262   gchar buf[128];
263   gint res;
264 
265   /* %u, basic formatting */
266 
267   res = g_snprintf (buf, 128, "%u", 5);
268   g_assert_cmpint (res, ==, 1);
269   g_assert_cmpstr (buf, ==, "5");
270 
271   res = g_snprintf (buf, 128, "%u", 0);
272   g_assert_cmpint (res, ==, 1);
273   g_assert_cmpstr (buf, ==, "0");
274 
275   res = g_snprintf (buf, 128, "%.0u", 0);
276   g_assert_cmpint (res, ==, 0);
277   g_assert_cmpstr (buf, ==, "");
278 
279   res = g_snprintf (buf, 128, "%.0u", 1);
280   g_assert_cmpint (res, ==, 1);
281   g_assert_cmpstr (buf, ==, "1");
282 
283   res = g_snprintf (buf, 128, "%.3u", 5);
284   g_assert_cmpint (res, ==, 3);
285   g_assert_cmpstr (buf, ==, "005");
286 
287   res = g_snprintf (buf, 128, "%5.3u", 5);
288   g_assert_cmpint (res, ==, 5);
289   g_assert_cmpstr (buf, ==, "  005");
290 }
291 
292 static void
test_x(void)293 test_x (void)
294 {
295   gchar buf[128];
296   gint res;
297 
298   /* %x, basic formatting */
299 
300   res = g_snprintf (buf, 128, "%x", 5);
301   g_assert_cmpint (res, ==, 1);
302   g_assert_cmpstr (buf, ==, "5");
303 
304   res = g_snprintf (buf, 128, "%x", 31);
305   g_assert_cmpint (res, ==, 2);
306   g_assert_cmpstr (buf, ==, "1f");
307 
308   res = g_snprintf (buf, 128, "%x", 0);
309   g_assert_cmpint (res, ==, 1);
310   g_assert_cmpstr (buf, ==, "0");
311 
312   res = g_snprintf (buf, 128, "%.0x", 0);
313   g_assert_cmpint (res, ==, 0);
314   g_assert_cmpstr (buf, ==, "");
315 
316   res = g_snprintf (buf, 128, "%.0x", 1);
317   g_assert_cmpint (res, ==, 1);
318   g_assert_cmpstr (buf, ==, "1");
319 
320   res = g_snprintf (buf, 128, "%.3x", 5);
321   g_assert_cmpint (res, ==, 3);
322   g_assert_cmpstr (buf, ==, "005");
323 
324   res = g_snprintf (buf, 128, "%.3x", 31);
325   g_assert_cmpint (res, ==, 3);
326   g_assert_cmpstr (buf, ==, "01f");
327 
328   res = g_snprintf (buf, 128, "%5.3x", 5);
329   g_assert_cmpint (res, ==, 5);
330   g_assert_cmpstr (buf, ==, "  005");
331 
332   /* %x, flags */
333 
334   res = g_snprintf (buf, 128, "%-x", 5);
335   g_assert_cmpint (res, ==, 1);
336   g_assert_cmpstr (buf, ==, "5");
337 
338   res = g_snprintf (buf, 128, "%03x", 5);
339   g_assert_cmpint (res, ==, 3);
340   g_assert_cmpstr (buf, ==, "005");
341 
342   res = g_snprintf (buf, 128, "%#x", 31);
343   g_assert_cmpint (res, ==, 4);
344   g_assert_cmpstr (buf, ==, "0x1f");
345 
346   res = g_snprintf (buf, 128, "%#x", 0);
347   g_assert_cmpint (res, ==, 1);
348   g_assert_cmpstr (buf, ==, "0");
349 }
350 
351 static void
test_X(void)352 test_X (void)
353 {
354   gchar buf[128];
355   gint res;
356 
357   /* %X, basic formatting */
358 
359   res = g_snprintf (buf, 128, "%X", 5);
360   g_assert_cmpint (res, ==, 1);
361   g_assert_cmpstr (buf, ==, "5");
362 
363   res = g_snprintf (buf, 128, "%X", 31);
364   g_assert_cmpint (res, ==, 2);
365   g_assert_cmpstr (buf, ==, "1F");
366 
367   res = g_snprintf (buf, 128, "%X", 0);
368   g_assert_cmpint (res, ==, 1);
369   g_assert_cmpstr (buf, ==, "0");
370 
371   res = g_snprintf (buf, 128, "%.0X", 0);
372   g_assert_cmpint (res, ==, 0);
373   g_assert_cmpstr (buf, ==, "");
374 
375   res = g_snprintf (buf, 128, "%.0X", 1);
376   g_assert_cmpint (res, ==, 1);
377   g_assert_cmpstr (buf, ==, "1");
378 
379   res = g_snprintf (buf, 128, "%.3X", 5);
380   g_assert_cmpint (res, ==, 3);
381   g_assert_cmpstr (buf, ==, "005");
382 
383   res = g_snprintf (buf, 128, "%.3X", 31);
384   g_assert_cmpint (res, ==, 3);
385   g_assert_cmpstr (buf, ==, "01F");
386 
387   res = g_snprintf (buf, 128, "%5.3X", 5);
388   g_assert_cmpint (res, ==, 5);
389   g_assert_cmpstr (buf, ==, "  005");
390 
391   /* %X, flags */
392 
393   res = g_snprintf (buf, 128, "%-X", 5);
394   g_assert_cmpint (res, ==, 1);
395   g_assert_cmpstr (buf, ==, "5");
396 
397   res = g_snprintf (buf, 128, "%03X", 5);
398   g_assert_cmpint (res, ==, 3);
399   g_assert_cmpstr (buf, ==, "005");
400 
401   res = g_snprintf (buf, 128, "%#X", 31);
402   g_assert_cmpint (res, ==, 4);
403   g_assert_cmpstr (buf, ==, "0X1F");
404 
405   res = g_snprintf (buf, 128, "%#X", 0);
406   g_assert_cmpint (res, ==, 1);
407   g_assert_cmpstr (buf, ==, "0");
408 }
409 
410 static void
test_f(void)411 test_f (void)
412 {
413   gchar buf[128];
414   gint res;
415 
416   /* %f, basic formattting */
417 
418   res = g_snprintf (buf, 128, "%f", G_PI);
419   g_assert_cmpint (res, ==, 8);
420   g_assert (0 == strncmp (buf, "3.14159", 7));
421 
422   res = g_snprintf (buf, 128, "%.8f", G_PI);
423   g_assert_cmpint (res, ==, 10);
424   g_assert (0 == strncmp (buf, "3.1415926", 9));
425 
426   res = g_snprintf (buf, 128, "%.0f", G_PI);
427   g_assert_cmpint (res, ==, 1);
428   g_assert_cmpstr (buf, ==, "3");
429 
430   res = g_snprintf (buf, 128, "%1.f", G_PI);
431   g_assert_cmpint (res, ==, 1);
432   g_assert_cmpstr (buf, ==, "3");
433 
434   res = g_snprintf (buf, 128, "%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 (buf, 128, "%+f", G_PI);
441   g_assert_cmpint (res, ==, 9);
442   g_assert (0 == strncmp (buf, "+3.14159", 8));
443 
444   res = g_snprintf (buf, 128, "% f", G_PI);
445   g_assert_cmpint (res, ==, 9);
446   g_assert (0 == strncmp (buf, " 3.14159", 8));
447 
448   res = g_snprintf (buf, 128, "%#.0f", G_PI);
449   g_assert_cmpint (res, ==, 2);
450   g_assert_cmpstr (buf, ==, "3.");
451 
452   res = g_snprintf (buf, 128, "%05.2f", G_PI);
453   g_assert_cmpint (res, ==, 5);
454   g_assert_cmpstr (buf, ==, "03.14");
455 }
456 
457 static gboolean
same_value(const gchar * actual,const gchar * expected)458 same_value (const gchar *actual,
459             const gchar *expected)
460 {
461   gdouble actual_value, expected_value;
462 
463   actual_value = g_ascii_strtod (actual, NULL);
464   expected_value = g_ascii_strtod (expected, NULL);
465 
466   return actual_value == expected_value;
467 }
468 
469 static void
test_e(void)470 test_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 (buf, 128, "%e", G_PI);
484   g_assert_cmpint (res, >=, 12);
485   g_assert (same_value (buf, "3.141593e+00"));
486 
487   res = g_snprintf (buf, 128, "%.8e", G_PI);
488   g_assert_cmpint (res, >=, 14);
489   g_assert (same_value (buf, "3.14159265e+00"));
490 
491   res = g_snprintf (buf, 128, "%.0e", G_PI);
492   g_assert_cmpint (res, >=, 5);
493   g_assert (same_value (buf, "3e+00"));
494 
495   res = g_snprintf (buf, 128, "%.1e", 0.0);
496   g_assert_cmpint (res, >=, 7);
497   g_assert (same_value (buf, "0.0e+00"));
498 
499   res = g_snprintf (buf, 128, "%.1e", 0.00001);
500   g_assert_cmpint (res, >=, 7);
501   g_assert (same_value (buf, "1.0e-05"));
502 
503   res = g_snprintf (buf, 128, "%.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 (buf, 128, "%+e", G_PI);
510   g_assert_cmpint (res, >=, 13);
511   g_assert (same_value (buf, "+3.141593e+00"));
512 
513   res = g_snprintf (buf, 128, "% e", G_PI);
514   g_assert_cmpint (res, >=, 13);
515   g_assert (same_value (buf, " 3.141593e+00"));
516 
517   res = g_snprintf (buf, 128, "%#.0e", G_PI);
518   g_assert_cmpint (res, >=, 6);
519   g_assert (same_value (buf, "3.e+00"));
520 
521   res = g_snprintf (buf, 128, "%09.2e", G_PI);
522   g_assert_cmpint (res, >=, 9);
523   g_assert (same_value (buf, "03.14e+00"));
524 }
525 
526 static void
test_c(void)527 test_c (void)
528 {
529   gchar buf[128];
530   gint res;
531 
532   res = g_snprintf (buf, 128, "%c", 'a');
533   g_assert_cmpint (res, ==, 1);
534   g_assert_cmpstr (buf, ==, "a");
535 }
536 
537 static void
test_s(void)538 test_s (void)
539 {
540   gchar buf[128];
541   gint res;
542 
543   res = g_snprintf (buf, 128, "%.2s", "abc");
544   g_assert_cmpint (res, ==, 2);
545   g_assert_cmpstr (buf, ==, "ab");
546 
547   res = g_snprintf (buf, 128, "%.6s", "abc");
548   g_assert_cmpint (res, ==, 3);
549   g_assert_cmpstr (buf, ==, "abc");
550 
551   res = g_snprintf (buf, 128, "%5s", "abc");
552   g_assert_cmpint (res, ==, 5);
553   g_assert_cmpstr (buf, ==, "  abc");
554 
555   res = g_snprintf (buf, 128, "%-5s", "abc");
556   g_assert_cmpint (res, ==, 5);
557   g_assert_cmpstr (buf, ==, "abc  ");
558 
559   res = g_snprintf (buf, 128, "%5.2s", "abc");
560   g_assert_cmpint (res, ==, 5);
561   g_assert_cmpstr (buf, ==, "   ab");
562 
563   res = g_snprintf (buf, 128, "%*s", 5, "abc");
564   g_assert_cmpint (res, ==, 5);
565   g_assert_cmpstr (buf, ==, "  abc");
566 
567   res = g_snprintf (buf, 128, "%*s", -5, "abc");
568   g_assert_cmpint (res, ==, 5);
569   g_assert_cmpstr (buf, ==, "abc  ");
570 
571   res = g_snprintf (buf, 128, "%*.*s", 5, 2, "abc");
572   g_assert_cmpint (res, ==, 5);
573   g_assert_cmpstr (buf, ==, "   ab");
574 }
575 
576 static void
test_n(void)577 test_n (void)
578 {
579   gchar buf[128];
580   gint res;
581   gint i;
582   glong l;
583 
584   res = g_snprintf (buf, 128, "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 (buf, 128, "abc%ln", &l);
590   g_assert_cmpint (res, ==, 3);
591   g_assert_cmpstr (buf, ==, "abc");
592   g_assert_cmpint (l, ==, 3);
593 }
594 
595 static void
test_percent(void)596 test_percent (void)
597 {
598   gchar buf[128];
599   gint res;
600 
601   res = g_snprintf (buf, 128, "%%");
602   g_assert_cmpint (res, ==, 1);
603   g_assert_cmpstr (buf, ==, "%");
604 }
605 
606 static void
test_positional_params(void)607 test_positional_params (void)
608 {
609   gchar buf[128];
610   gint res;
611 
612   res = g_snprintf (buf, 128, "%2$c %1$c", 'b', 'a');
613   g_assert_cmpint (res, ==, 3);
614   g_assert_cmpstr (buf, ==, "a b");
615 
616   res = g_snprintf (buf, 128, "%1$*2$.*3$s", "abc", 5, 2);
617   g_assert_cmpint (res, ==, 5);
618   g_assert_cmpstr (buf, ==, "   ab");
619 
620   res = g_snprintf (buf, 128, "%1$s%1$s", "abc");
621   g_assert_cmpint (res, ==, 6);
622   g_assert_cmpstr (buf, ==, "abcabc");
623 }
624 
625 static void
test_positional_params2(void)626 test_positional_params2 (void)
627 {
628   if (g_test_subprocess ())
629     {
630       gint res;
631 
632       res = g_printf ("%2$c %1$c\n", 'b', 'a');
633       g_assert_cmpint (res, ==, 4);
634 
635       res = g_printf ("%1$*2$.*3$s\n", "abc", 5, 2);
636       g_assert_cmpint (res, ==, 6);
637 
638       res = g_printf ("%1$s%1$s\n", "abc");
639       g_assert_cmpint (res, ==, 7);
640       return;
641     }
642   g_test_trap_subprocess (NULL, 0, 0);
643   g_test_trap_assert_passed ();
644   g_test_trap_assert_stdout ("a b\n   ab\nabcabc\n");
645 }
646 
647 static void
test_positional_params3(void)648 test_positional_params3 (void)
649 {
650   gchar buf[128];
651   gint res;
652 
653   res = g_sprintf (buf, "%2$c %1$c", 'b', 'a');
654   g_assert_cmpint (res, ==, 3);
655   g_assert_cmpstr (buf, ==, "a b");
656 
657   res = g_sprintf (buf, "%1$*2$.*3$s", "abc", 5, 2);
658   g_assert_cmpint (res, ==, 5);
659   g_assert_cmpstr (buf, ==, "   ab");
660 
661   res = g_sprintf (buf, "%1$s%1$s", "abc");
662   g_assert_cmpint (res, ==, 6);
663   g_assert_cmpstr (buf, ==, "abcabc");
664 }
665 
666 static void
test_percent2(void)667 test_percent2 (void)
668 {
669   if (g_test_subprocess ())
670     {
671       gint res;
672 
673       res = g_printf ("%%");
674       g_assert_cmpint (res, ==, 1);
675       return;
676     }
677   g_test_trap_subprocess (NULL, 0, 0);
678   g_test_trap_assert_passed ();
679   g_test_trap_assert_stdout ("*%*");
680 }
681 
682 static void
test_64bit(void)683 test_64bit (void)
684 {
685   gchar buf[128];
686   gint res;
687 
688   res = g_snprintf (buf, 128, "%" G_GINT64_FORMAT, (gint64)123456);
689   g_assert_cmpint (res, ==, 6);
690   g_assert_cmpstr (buf, ==, "123456");
691 
692   res = g_snprintf (buf, 128, "%" G_GINT64_FORMAT, (gint64)-123456);
693   g_assert_cmpint (res, ==, 7);
694   g_assert_cmpstr (buf, ==, "-123456");
695 
696   res = g_snprintf (buf, 128, "%" G_GUINT64_FORMAT, (guint64)123456);
697   g_assert_cmpint (res, ==, 6);
698   g_assert_cmpstr (buf, ==, "123456");
699 
700   res = g_snprintf (buf, 128, "%" G_GINT64_MODIFIER "o", (gint64)123456);
701   g_assert_cmpint (res, ==, 6);
702   g_assert_cmpstr (buf, ==, "361100");
703 
704   res = g_snprintf (buf, 128, "%#" G_GINT64_MODIFIER "o", (gint64)123456);
705   g_assert_cmpint (res, ==, 7);
706   g_assert_cmpstr (buf, ==, "0361100");
707 
708   res = g_snprintf (buf, 128, "%" G_GINT64_MODIFIER "x", (gint64)123456);
709   g_assert_cmpint (res, ==, 5);
710   g_assert_cmpstr (buf, ==, "1e240");
711 
712   res = g_snprintf (buf, 128, "%#" G_GINT64_MODIFIER "x", (gint64)123456);
713   g_assert_cmpint (res, ==, 7);
714   g_assert_cmpstr (buf, ==, "0x1e240");
715 
716   res = g_snprintf (buf, 128, "%" 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 
776 static void
test_64bit2_base(void)777 test_64bit2_base (void)
778 {
779   gint res;
780 
781   res = g_printf ("%" G_GINT64_FORMAT "\n", (gint64)123456);
782   g_assert_cmpint (res, ==, 7);
783 
784   res = g_printf ("%" G_GINT64_FORMAT "\n", (gint64)-123456);
785   g_assert_cmpint (res, ==, 8);
786 
787   res = g_printf ("%" G_GUINT64_FORMAT "\n", (guint64)123456);
788   g_assert_cmpint (res, ==, 7);
789 
790   res = g_printf ("%" G_GINT64_MODIFIER "o\n", (gint64)123456);
791   g_assert_cmpint (res, ==, 7);
792 
793   res = g_printf ("%#" G_GINT64_MODIFIER "o\n", (gint64)123456);
794   g_assert_cmpint (res, ==, 8);
795 
796   res = g_printf ("%" G_GINT64_MODIFIER "x\n", (gint64)123456);
797   g_assert_cmpint (res, ==, 6);
798 
799   res = g_printf ("%#" G_GINT64_MODIFIER "x\n", (gint64)123456);
800   g_assert_cmpint (res, ==, 8);
801 
802   res = g_printf ("%" G_GINT64_MODIFIER "X\n", (gint64)123456);
803   g_assert_cmpint (res, ==, 6);
804 }
805 
806 #ifdef G_OS_WIN32
807 static void
test_64bit2_win32(void)808 test_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 
858 static void
test_64bit2(void)859 test_64bit2 (void)
860 {
861   g_test_trap_subprocess ("/printf/test-64bit/subprocess/base", 0, 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 
875 G_GNUC_PRINTF(1, 2)
876 static gsize
upper_bound(const gchar * format,...)877 upper_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 
889 static void
test_upper_bound(void)890 test_upper_bound (void)
891 {
892   gsize res;
893 
894   res = upper_bound ("bla %s %d: %g\n", "bla", 123, 0.123);
895   g_assert_cmpint (res, ==, 20);
896 }
897 
898 int
main(int argc,char * argv[])899 main (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, &argv, NULL);
910 
911   g_test_add_func ("/snprintf/retval-and-trunc", test_retval_and_trunc);
912   g_test_add_func ("/snprintf/%d", test_d);
913   g_test_add_func ("/snprintf/%d-invalid", test_d_invalid);
914   g_test_add_func ("/snprintf/%o", test_o);
915   g_test_add_func ("/snprintf/%u", test_u);
916   g_test_add_func ("/snprintf/%x", test_x);
917   g_test_add_func ("/snprintf/%X", test_X);
918   g_test_add_func ("/snprintf/%f", test_f);
919   g_test_add_func ("/snprintf/%e", test_e);
920   g_test_add_func ("/snprintf/%c", test_c);
921   g_test_add_func ("/snprintf/%s", test_s);
922   g_test_add_func ("/snprintf/%n", test_n);
923   g_test_add_func ("/snprintf/test-percent", test_percent);
924   g_test_add_func ("/snprintf/test-positional-params", test_positional_params);
925   g_test_add_func ("/snprintf/test-64bit", test_64bit);
926 
927   g_test_add_func ("/printf/test-percent", test_percent2);
928   g_test_add_func ("/printf/test-positional-params", test_positional_params2);
929   g_test_add_func ("/printf/test-64bit", test_64bit2);
930   g_test_add_func ("/printf/test-64bit/subprocess/base", 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 ("/sprintf/test-positional-params", test_positional_params3);
936   g_test_add_func ("/sprintf/upper-bound", test_upper_bound);
937 
938   return g_test_run();
939 }
940