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