2 * Conformance tests for *printf functions.
4 * Copyright 2002 Uwe Bonnes
5 * Copyright 2004 Aneurin Price
6 * Copyright 2005 Mike McCormack
7 * Copyright 2015 Martin Storsjo
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/test.h"
33 #define DEFINE_EXPECT(func) \
34 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
36 #define SET_EXPECT(func) \
37 expect_ ## func = TRUE
39 #define CHECK_EXPECT2(func) \
41 ok(expect_ ##func, "unexpected call " #func "\n"); \
42 called_ ## func = TRUE; \
45 #define CHECK_EXPECT(func) \
47 CHECK_EXPECT2(func); \
48 expect_ ## func = FALSE; \
51 #define CHECK_CALLED(func) \
53 ok(called_ ## func, "expected " #func "\n"); \
54 expect_ ## func = called_ ## func = FALSE; \
57 DEFINE_EXPECT(invalid_parameter_handler
);
59 /* make sure we use the correct errno */
61 #define errno (*p_errno())
63 #define UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION (0x0001)
64 #define UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR (0x0002)
65 #define UCRTBASE_PRINTF_LEGACY_WIDE_SPECIFIERS (0x0004)
66 #define UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY (0x0008)
67 #define UCRTBASE_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS (0x0010)
69 static inline float __port_infinity(void)
71 static const unsigned __inf_bytes
= 0x7f800000;
72 return *(const float *)&__inf_bytes
;
74 #define INFINITY __port_infinity()
76 static inline float __port_nan(void)
78 static const unsigned __nan_bytes
= 0x7fc00000;
79 return *(const float *)&__nan_bytes
;
81 #define NAN __port_nan()
83 static inline float __port_ind(void)
85 static const unsigned __ind_bytes
= 0xffc00000;
86 return *(const float *)&__ind_bytes
;
88 #define IND __port_ind()
90 static int (__cdecl
*p_vfprintf
)(unsigned __int64 options
, FILE *file
, const char *format
,
91 void *locale
, __ms_va_list valist
);
92 static int (__cdecl
*p_vfwprintf
)(unsigned __int64 options
, FILE *file
, const wchar_t *format
,
93 void *locale
, __ms_va_list valist
);
94 static int (__cdecl
*p_vsprintf
)(unsigned __int64 options
, char *str
, size_t len
, const char *format
,
95 void *locale
, __ms_va_list valist
);
96 static int (__cdecl
*p_vsnprintf_s
)(unsigned __int64 options
, char *str
, size_t sizeOfBuffer
, size_t count
, const char *format
,
97 void *locale
, __ms_va_list valist
);
98 static int (__cdecl
*p_vsprintf_s
)(unsigned __int64 options
, char *str
, size_t count
, const char *format
,
99 void *locale
, __ms_va_list valist
);
100 static int (__cdecl
*p_vswprintf
)(unsigned __int64 options
, wchar_t *str
, size_t len
, const wchar_t *format
,
101 void *locale
, __ms_va_list valist
);
102 static int (__cdecl
*p_vsnwprintf_s
)(unsigned __int64 options
, WCHAR
*str
, size_t sizeOfBuffer
, size_t count
, const WCHAR
*format
,
103 void *locale
, __ms_va_list valist
);
105 static FILE *(__cdecl
*p_fopen
)(const char *name
, const char *mode
);
106 static int (__cdecl
*p_fclose
)(FILE *file
);
107 static long (__cdecl
*p_ftell
)(FILE *file
);
108 static char *(__cdecl
*p_fgets
)(char *str
, int size
, FILE *file
);
109 static wchar_t *(__cdecl
*p_fgetws
)(wchar_t *str
, int size
, FILE *file
);
111 static _invalid_parameter_handler (__cdecl
*p_set_invalid_parameter_handler
)(_invalid_parameter_handler
);
112 static int* (__cdecl
*p_errno
)(void);
114 static void __cdecl
test_invalid_parameter_handler(const wchar_t *expression
,
115 const wchar_t *function
, const wchar_t *file
,
116 unsigned line
, uintptr_t arg
)
118 CHECK_EXPECT(invalid_parameter_handler
);
119 ok(expression
== NULL
, "expression is not NULL\n");
120 ok(function
== NULL
, "function is not NULL\n");
121 ok(file
== NULL
, "file is not NULL\n");
122 ok(line
== 0, "line = %u\n", line
);
123 ok(arg
== 0, "arg = %lx\n", (UINT_PTR
)arg
);
126 static BOOL
init( void )
128 HMODULE hmod
= LoadLibraryA("ucrtbase.dll");
132 win_skip("ucrtbase.dll not installed\n");
136 p_vfprintf
= (void *)GetProcAddress(hmod
, "__stdio_common_vfprintf");
137 p_vfwprintf
= (void *)GetProcAddress(hmod
, "__stdio_common_vfwprintf");
138 p_vsprintf
= (void *)GetProcAddress(hmod
, "__stdio_common_vsprintf");
139 p_vsnprintf_s
= (void *)GetProcAddress(hmod
, "__stdio_common_vsnprintf_s");
140 p_vsnwprintf_s
= (void *)GetProcAddress(hmod
, "__stdio_common_vsnwprintf_s");
141 p_vsprintf_s
= (void *)GetProcAddress(hmod
, "__stdio_common_vsprintf_s");
142 p_vswprintf
= (void *)GetProcAddress(hmod
, "__stdio_common_vswprintf");
144 p_fopen
= (void *)GetProcAddress(hmod
, "fopen");
145 p_fclose
= (void *)GetProcAddress(hmod
, "fclose");
146 p_ftell
= (void *)GetProcAddress(hmod
, "ftell");
147 p_fgets
= (void *)GetProcAddress(hmod
, "fgets");
148 p_fgetws
= (void *)GetProcAddress(hmod
, "fgetws");
150 p_set_invalid_parameter_handler
= (void *)GetProcAddress(hmod
, "_set_invalid_parameter_handler");
151 p_errno
= (void *)GetProcAddress(hmod
, "_errno");
155 static int WINAPIV
vsprintf_wrapper(unsigned __int64 options
, char *str
,
156 size_t len
, const char *format
, ...)
160 __ms_va_start(valist
, format
);
161 ret
= p_vsprintf(options
, str
, len
, format
, NULL
, valist
);
166 static void test_snprintf (void)
168 const char *tests
[] = {"short", "justfit", "justfits", "muchlonger"};
170 const int bufsiz
= sizeof buffer
;
173 /* Legacy _snprintf style termination */
174 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
175 const char *fmt
= tests
[i
];
176 const int expect
= strlen(fmt
) > bufsiz
? -1 : strlen(fmt
);
177 const int n
= vsprintf_wrapper (UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
, buffer
, bufsiz
, fmt
);
178 const int valid
= n
< 0 ? bufsiz
: (n
== bufsiz
? n
: n
+1);
180 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
182 ok (!memcmp (fmt
, buffer
, valid
),
183 "\"%s\": rendered \"%.*s\"\n", fmt
, valid
, buffer
);
186 /* C99 snprintf style termination */
187 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
188 const char *fmt
= tests
[i
];
189 const int expect
= strlen(fmt
);
190 const int n
= vsprintf_wrapper (UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR
, buffer
, bufsiz
, fmt
);
191 const int valid
= n
>= bufsiz
? bufsiz
- 1 : n
< 0 ? 0 : n
;
193 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
195 ok (!memcmp (fmt
, buffer
, valid
),
196 "\"%s\": rendered \"%.*s\"\n", fmt
, valid
, buffer
);
197 ok (buffer
[valid
] == '\0',
198 "\"%s\": Missing null termination (ret %d) - is %d\n", fmt
, n
, buffer
[valid
]);
201 /* swprintf style termination */
202 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
203 const char *fmt
= tests
[i
];
204 const int expect
= strlen(fmt
) >= bufsiz
? -2 : strlen(fmt
);
205 const int n
= vsprintf_wrapper (0, buffer
, bufsiz
, fmt
);
206 const int valid
= n
< 0 ? bufsiz
- 1 : n
;
208 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
210 ok (!memcmp (fmt
, buffer
, valid
),
211 "\"%s\": rendered \"%.*s\"\n", fmt
, valid
, buffer
);
212 ok (buffer
[valid
] == '\0',
213 "\"%s\": Missing null termination (ret %d) - is %d\n", fmt
, n
, buffer
[valid
]);
216 ok (vsprintf_wrapper (UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR
, NULL
, 0, "abcd") == 4,
217 "Failure to snprintf to NULL\n");
218 ok (vsprintf_wrapper (UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
, NULL
, 0, "abcd") == 4,
219 "Failure to snprintf to NULL\n");
220 ok (vsprintf_wrapper (0, NULL
, 0, "abcd") == 4,
221 "Failure to snprintf to NULL\n");
224 static int WINAPIV
vswprintf_wrapper(unsigned __int64 options
, wchar_t *str
,
225 size_t len
, const wchar_t *format
, ...)
229 __ms_va_start(valist
, format
);
230 ret
= p_vswprintf(options
, str
, len
, format
, NULL
, valist
);
235 static void test_swprintf (void)
237 const wchar_t str_short
[] = {'s','h','o','r','t',0};
238 const wchar_t str_justfit
[] = {'j','u','s','t','f','i','t',0};
239 const wchar_t str_justfits
[] = {'j','u','s','t','f','i','t','s',0};
240 const wchar_t str_muchlonger
[] = {'m','u','c','h','l','o','n','g','e','r',0};
241 const wchar_t *tests
[] = {str_short
, str_justfit
, str_justfits
, str_muchlonger
};
244 char narrow
[8], narrow_fmt
[16];
245 const int bufsiz
= ARRAY_SIZE(buffer
);
248 /* Legacy _snprintf style termination */
249 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
250 const wchar_t *fmt
= tests
[i
];
251 const int expect
= wcslen(fmt
) > bufsiz
? -1 : wcslen(fmt
);
252 const int n
= vswprintf_wrapper (UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
, buffer
, bufsiz
, fmt
);
253 const int valid
= n
< 0 ? bufsiz
: (n
== bufsiz
? n
: n
+1);
255 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
256 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
257 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
258 narrow_fmt
, expect
, n
);
259 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
260 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
263 /* C99 snprintf style termination */
264 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
265 const wchar_t *fmt
= tests
[i
];
266 const int expect
= wcslen(fmt
);
267 const int n
= vswprintf_wrapper (UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR
, buffer
, bufsiz
, fmt
);
268 const int valid
= n
>= bufsiz
? bufsiz
- 1 : n
< 0 ? 0 : n
;
270 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
271 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
272 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
273 narrow_fmt
, expect
, n
);
274 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
275 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
276 ok (buffer
[valid
] == '\0',
277 "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt
, n
, buffer
[valid
]);
280 /* swprintf style termination */
281 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
282 const wchar_t *fmt
= tests
[i
];
283 const int expect
= wcslen(fmt
) >= bufsiz
? -2 : wcslen(fmt
);
284 const int n
= vswprintf_wrapper (0, buffer
, bufsiz
, fmt
);
285 const int valid
= n
< 0 ? bufsiz
- 1 : n
;
287 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
288 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
289 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
290 narrow_fmt
, expect
, n
);
291 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
292 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
293 ok (buffer
[valid
] == '\0',
294 "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt
, n
, buffer
[valid
]);
297 ok (vswprintf_wrapper (UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR
, NULL
, 0, str_short
) == 5,
298 "Failure to swprintf to NULL\n");
299 ok (vswprintf_wrapper (UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
, NULL
, 0, str_short
) == 5,
300 "Failure to swprintf to NULL\n");
301 ok (vswprintf_wrapper (0, NULL
, 0, str_short
) == 5,
302 "Failure to swprintf to NULL\n");
305 static int WINAPIV
vfprintf_wrapper(FILE *file
,
306 const char *format
, ...)
310 __ms_va_start(valist
, format
);
311 ret
= p_vfprintf(0, file
, format
, NULL
, valist
);
316 static void test_fprintf(void)
318 static const char file_name
[] = "fprintf.tst";
320 FILE *fp
= p_fopen(file_name
, "wb");
324 ret
= vfprintf_wrapper(fp
, "simple test\n");
325 ok(ret
== 12, "ret = %d\n", ret
);
327 ok(ret
== 12, "ftell returned %d\n", ret
);
329 ret
= vfprintf_wrapper(fp
, "contains%cnull\n", '\0');
330 ok(ret
== 14, "ret = %d\n", ret
);
332 ok(ret
== 26, "ftell returned %d\n", ret
);
336 fp
= p_fopen(file_name
, "rb");
337 p_fgets(buf
, sizeof(buf
), fp
);
339 ok(ret
== 12, "ftell returned %d\n", ret
);
340 ok(!strcmp(buf
, "simple test\n"), "buf = %s\n", buf
);
342 p_fgets(buf
, sizeof(buf
), fp
);
344 ok(ret
== 26, "ret = %d\n", ret
);
345 ok(!memcmp(buf
, "contains\0null\n", 14), "buf = %s\n", buf
);
349 fp
= p_fopen(file_name
, "wt");
351 ret
= vfprintf_wrapper(fp
, "simple test\n");
352 ok(ret
== 12, "ret = %d\n", ret
);
354 ok(ret
== 13, "ftell returned %d\n", ret
);
356 ret
= vfprintf_wrapper(fp
, "contains%cnull\n", '\0');
357 ok(ret
== 14, "ret = %d\n", ret
);
359 ok(ret
== 28, "ftell returned %d\n", ret
);
363 fp
= p_fopen(file_name
, "rb");
364 p_fgets(buf
, sizeof(buf
), fp
);
366 ok(ret
== 13, "ftell returned %d\n", ret
);
367 ok(!strcmp(buf
, "simple test\r\n"), "buf = %s\n", buf
);
369 p_fgets(buf
, sizeof(buf
), fp
);
371 ok(ret
== 28, "ret = %d\n", ret
);
372 ok(!memcmp(buf
, "contains\0null\r\n", 15), "buf = %s\n", buf
);
378 static int WINAPIV
vfwprintf_wrapper(FILE *file
,
379 const wchar_t *format
, ...)
383 __ms_va_start(valist
, format
);
384 ret
= p_vfwprintf(0, file
, format
, NULL
, valist
);
389 static void test_fwprintf(void)
391 static const char file_name
[] = "fprintf.tst";
392 static const WCHAR simple
[] = {'s','i','m','p','l','e',' ','t','e','s','t','\n',0};
393 static const WCHAR cont_fmt
[] = {'c','o','n','t','a','i','n','s','%','c','n','u','l','l','\n',0};
394 static const WCHAR cont
[] = {'c','o','n','t','a','i','n','s','\0','n','u','l','l','\n',0};
396 FILE *fp
= p_fopen(file_name
, "wb");
401 ret
= vfwprintf_wrapper(fp
, simple
);
402 ok(ret
== 12, "ret = %d\n", ret
);
404 ok(ret
== 24, "ftell returned %d\n", ret
);
406 ret
= vfwprintf_wrapper(fp
, cont_fmt
, '\0');
407 ok(ret
== 14, "ret = %d\n", ret
);
409 ok(ret
== 52, "ftell returned %d\n", ret
);
413 fp
= p_fopen(file_name
, "rb");
414 p_fgetws(bufw
, ARRAY_SIZE(bufw
), fp
);
416 ok(ret
== 24, "ftell returned %d\n", ret
);
417 ok(!wcscmp(bufw
, simple
), "buf = %s\n", wine_dbgstr_w(bufw
));
419 p_fgetws(bufw
, ARRAY_SIZE(bufw
), fp
);
421 ok(ret
== 52, "ret = %d\n", ret
);
422 ok(!memcmp(bufw
, cont
, 28), "buf = %s\n", wine_dbgstr_w(bufw
));
426 fp
= p_fopen(file_name
, "wt");
428 ret
= vfwprintf_wrapper(fp
, simple
);
429 ok(ret
== 12, "ret = %d\n", ret
);
431 ok(ret
== 13, "ftell returned %d\n", ret
);
433 ret
= vfwprintf_wrapper(fp
, cont_fmt
, '\0');
434 ok(ret
== 14, "ret = %d\n", ret
);
436 ok(ret
== 28, "ftell returned %d\n", ret
);
440 fp
= p_fopen(file_name
, "rb");
441 p_fgets(bufa
, sizeof(bufa
), fp
);
443 ok(ret
== 13, "ftell returned %d\n", ret
);
444 ok(!strcmp(bufa
, "simple test\r\n"), "buf = %s\n", bufa
);
446 p_fgets(bufa
, sizeof(bufa
), fp
);
448 ok(ret
== 28, "ret = %d\n", ret
);
449 ok(!memcmp(bufa
, "contains\0null\r\n", 15), "buf = %s\n", bufa
);
454 ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler
) == NULL
,
455 "Invalid parameter handler was already set\n");
459 SET_EXPECT(invalid_parameter_handler
);
460 ret
= vfwprintf_wrapper(fp
, NULL
);
461 ok(errno
== EINVAL
, "expected errno EINVAL, got %d\n", errno
);
462 ok(ret
== -1, "expected ret -1, got %d\n", ret
);
463 CHECK_CALLED(invalid_parameter_handler
);
467 SET_EXPECT(invalid_parameter_handler
);
468 ret
= vfwprintf_wrapper(NULL
, simple
);
469 ok(errno
== EINVAL
, "expected errno EINVAL, got %d\n", errno
);
470 ok(ret
== -1, "expected ret -1, got %d\n", ret
);
471 CHECK_CALLED(invalid_parameter_handler
);
473 /* format using % with NULL arglist*/
474 /* crashes on Windows */
475 /* ret = p_vfwprintf(0, fp, cont_fmt, NULL, NULL); */
477 ok(p_set_invalid_parameter_handler(NULL
) == test_invalid_parameter_handler
,
478 "Cannot reset invalid parameter handler\n");
481 static int WINAPIV
_vsnprintf_s_wrapper(char *str
, size_t sizeOfBuffer
,
482 size_t count
, const char *format
, ...)
486 __ms_va_start(valist
, format
);
487 ret
= p_vsnprintf_s(0, str
, sizeOfBuffer
, count
, format
, NULL
, valist
);
492 static void test_vsnprintf_s(void)
494 const char format
[] = "AB%uC";
495 const char out7
[] = "AB123C";
496 const char out6
[] = "AB123";
497 const char out2
[] = "A";
498 const char out1
[] = "";
499 char buffer
[14] = { 0 };
505 got
= _vsnprintf_s_wrapper(buffer
, 14, _TRUNCATE
, format
, 123);
506 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
507 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
509 got
= _vsnprintf_s_wrapper(buffer
, 12, _TRUNCATE
, format
, 123);
510 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
511 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
513 got
= _vsnprintf_s_wrapper(buffer
, 7, _TRUNCATE
, format
, 123);
514 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
515 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
517 /* Not enough room. */
520 got
= _vsnprintf_s_wrapper(buffer
, 6, _TRUNCATE
, format
, 123);
521 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
522 ok( !strcmp(out6
, buffer
), "buffer wrong, got=%s\n", buffer
);
524 got
= _vsnprintf_s_wrapper(buffer
, 2, _TRUNCATE
, format
, 123);
525 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
526 ok( !strcmp(out2
, buffer
), "buffer wrong, got=%s\n", buffer
);
528 got
= _vsnprintf_s_wrapper(buffer
, 1, _TRUNCATE
, format
, 123);
529 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
530 ok( !strcmp(out1
, buffer
), "buffer wrong, got=%s\n", buffer
);
533 static int WINAPIV
_vsnwprintf_s_wrapper(WCHAR
*str
, size_t sizeOfBuffer
,
534 size_t count
, const WCHAR
*format
, ...)
538 __ms_va_start(valist
, format
);
539 ret
= p_vsnwprintf_s(0, str
, sizeOfBuffer
, count
, format
, NULL
, valist
);
544 static void test_vsnwprintf_s(void)
546 const WCHAR format
[] = {'A','B','%','u','C',0};
547 const WCHAR out7
[] = {'A','B','1','2','3','C',0};
548 const WCHAR out6
[] = {'A','B','1','2','3',0};
549 const WCHAR out2
[] = {'A',0};
550 const WCHAR out1
[] = {0};
551 WCHAR buffer
[14] = { 0 };
555 exp
= lstrlenW(out7
);
557 got
= _vsnwprintf_s_wrapper(buffer
, 14, _TRUNCATE
, format
, 123);
558 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
559 ok( !lstrcmpW(out7
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
561 got
= _vsnwprintf_s_wrapper(buffer
, 12, _TRUNCATE
, format
, 123);
562 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
563 ok( !lstrcmpW(out7
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
565 got
= _vsnwprintf_s_wrapper(buffer
, 7, _TRUNCATE
, format
, 123);
566 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
567 ok( !lstrcmpW(out7
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
569 /* Not enough room. */
572 got
= _vsnwprintf_s_wrapper(buffer
, 6, _TRUNCATE
, format
, 123);
573 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
574 ok( !lstrcmpW(out6
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
576 got
= _vsnwprintf_s_wrapper(buffer
, 2, _TRUNCATE
, format
, 123);
577 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
578 ok( !lstrcmpW(out2
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
580 got
= _vsnwprintf_s_wrapper(buffer
, 1, _TRUNCATE
, format
, 123);
581 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
582 ok( !lstrcmpW(out1
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
585 static void test_printf_legacy_wide(void)
587 const wchar_t wide
[] = {'A','B','C','D',0};
588 const char narrow
[] = "abcd";
589 const char out
[] = "abcd ABCD";
590 /* The legacy wide flag doesn't affect narrow printfs, so the same
591 * format should behave the same both with and without the flag. */
592 const char narrow_fmt
[] = "%s %ls";
593 /* The standard behaviour is to use the same format as for the narrow
594 * case, while the legacy case has got a different meaning for %s. */
595 const wchar_t std_wide_fmt
[] = {'%','s',' ','%','l','s',0};
596 const wchar_t legacy_wide_fmt
[] = {'%','h','s',' ','%','s',0};
600 vsprintf_wrapper(0, buffer
, sizeof(buffer
), narrow_fmt
, narrow
, wide
);
601 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
602 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_WIDE_SPECIFIERS
, buffer
, sizeof(buffer
), narrow_fmt
, narrow
, wide
);
603 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
605 vswprintf_wrapper(0, wbuffer
, sizeof(wbuffer
), std_wide_fmt
, narrow
, wide
);
606 WideCharToMultiByte(CP_ACP
, 0, wbuffer
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
607 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
608 vswprintf_wrapper(UCRTBASE_PRINTF_LEGACY_WIDE_SPECIFIERS
, wbuffer
, sizeof(wbuffer
), legacy_wide_fmt
, narrow
, wide
);
609 WideCharToMultiByte(CP_ACP
, 0, wbuffer
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
610 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
613 static void test_printf_legacy_msvcrt(void)
617 /* In standard mode, %F is a float format conversion, while it is a
618 * length modifier in legacy msvcrt mode. In legacy mode, N is also
619 * a length modifier. */
620 vsprintf_wrapper(0, buf
, sizeof(buf
), "%F", 1.23);
621 ok(!strcmp(buf
, "1.230000"), "buf = %s\n", buf
);
622 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%Fd %Nd", 123, 456);
623 ok(!strcmp(buf
, "123 456"), "buf = %s\n", buf
);
625 vsprintf_wrapper(0, buf
, sizeof(buf
), "%f %F %f %e %E %g %G", INFINITY
, INFINITY
, -INFINITY
, INFINITY
, INFINITY
, INFINITY
, INFINITY
);
626 ok(!strcmp(buf
, "inf INF -inf inf INF inf INF"), "buf = %s\n", buf
);
627 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%f", INFINITY
);
628 ok(!strcmp(buf
, "1.#INF00"), "buf = %s\n", buf
);
629 vsprintf_wrapper(0, buf
, sizeof(buf
), "%f %F", NAN
, NAN
);
630 ok(!strcmp(buf
, "nan NAN"), "buf = %s\n", buf
);
631 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%f", NAN
);
632 ok(!strcmp(buf
, "1.#QNAN0"), "buf = %s\n", buf
);
633 vsprintf_wrapper(0, buf
, sizeof(buf
), "%f %F", IND
, IND
);
634 ok(!strcmp(buf
, "-nan(ind) -NAN(IND)"), "buf = %s\n", buf
);
635 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%f", IND
);
636 ok(!strcmp(buf
, "-1.#IND00"), "buf = %s\n", buf
);
639 static void test_printf_legacy_three_digit_exp(void)
643 vsprintf_wrapper(0, buf
, sizeof(buf
), "%E", 1.23);
644 ok(!strcmp(buf
, "1.230000E+00"), "buf = %s\n", buf
);
645 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS
, buf
, sizeof(buf
), "%E", 1.23);
646 ok(!strcmp(buf
, "1.230000E+000"), "buf = %s\n", buf
);
647 vsprintf_wrapper(0, buf
, sizeof(buf
), "%E", 1.23e+123);
648 ok(!strcmp(buf
, "1.230000E+123"), "buf = %s\n", buf
);
651 static void test_printf_c99(void)
655 /* The msvcrt compatibility flag doesn't affect whether 'z' is interpreted
656 * as size_t size for integers. */
657 if (sizeof(void*) == 8) {
658 vsprintf_wrapper(0, buf
, sizeof(buf
), "%zx %d",
659 (size_t) 0x12345678123456, 1);
660 ok(!strcmp(buf
, "12345678123456 1"), "buf = %s\n", buf
);
661 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
,
662 buf
, sizeof(buf
), "%zx %d", (size_t) 0x12345678123456, 1);
663 ok(!strcmp(buf
, "12345678123456 1"), "buf = %s\n", buf
);
665 vsprintf_wrapper(0, buf
, sizeof(buf
), "%zx %d",
666 (size_t) 0x123456, 1);
667 ok(!strcmp(buf
, "123456 1"), "buf = %s\n", buf
);
668 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
,
669 buf
, sizeof(buf
), "%zx %d", (size_t) 0x123456, 1);
670 ok(!strcmp(buf
, "123456 1"), "buf = %s\n", buf
);
674 static void test_printf_natural_string(void)
676 const wchar_t wide
[] = {'A','B','C','D',0};
677 const char narrow
[] = "abcd";
678 const char narrow_fmt
[] = "%s %Ts";
679 const char narrow_out
[] = "abcd abcd";
680 const wchar_t wide_fmt
[] = {'%','s',' ','%','T','s',0};
681 const wchar_t wide_out
[] = {'a','b','c','d',' ','A','B','C','D',0};
685 vsprintf_wrapper(0, buffer
, sizeof(buffer
), narrow_fmt
, narrow
, narrow
);
686 ok(!strcmp(buffer
, narrow_out
), "buffer wrong, got=%s\n", buffer
);
688 vswprintf_wrapper(0, wbuffer
, sizeof(wbuffer
), wide_fmt
, narrow
, wide
);
689 ok(!lstrcmpW(wbuffer
, wide_out
), "buffer wrong, got=%s\n", wine_dbgstr_w(wbuffer
));
702 test_printf_legacy_wide();
703 test_printf_legacy_msvcrt();
704 test_printf_legacy_three_digit_exp();
706 test_printf_natural_string();