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
< sizeof tests
/ sizeof tests
[0]; 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
< sizeof tests
/ sizeof tests
[0]; 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
< sizeof tests
/ sizeof tests
[0]; 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");
220 static int WINAPIV
vswprintf_wrapper(unsigned __int64 options
, wchar_t *str
,
221 size_t len
, const wchar_t *format
, ...)
225 __ms_va_start(valist
, format
);
226 ret
= p_vswprintf(options
, str
, len
, format
, NULL
, valist
);
231 static void test_swprintf (void)
233 const wchar_t str_short
[] = {'s','h','o','r','t',0};
234 const wchar_t str_justfit
[] = {'j','u','s','t','f','i','t',0};
235 const wchar_t str_justfits
[] = {'j','u','s','t','f','i','t','s',0};
236 const wchar_t str_muchlonger
[] = {'m','u','c','h','l','o','n','g','e','r',0};
237 const wchar_t *tests
[] = {str_short
, str_justfit
, str_justfits
, str_muchlonger
};
240 char narrow
[8], narrow_fmt
[16];
241 const int bufsiz
= sizeof buffer
/ sizeof buffer
[0];
244 /* Legacy _snprintf style termination */
245 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
246 const wchar_t *fmt
= tests
[i
];
247 const int expect
= wcslen(fmt
) > bufsiz
? -1 : wcslen(fmt
);
248 const int n
= vswprintf_wrapper (UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
, buffer
, bufsiz
, fmt
);
249 const int valid
= n
< 0 ? bufsiz
: (n
== bufsiz
? n
: n
+1);
251 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
252 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
253 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
254 narrow_fmt
, expect
, n
);
255 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
256 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
259 /* C99 snprintf style termination */
260 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
261 const wchar_t *fmt
= tests
[i
];
262 const int expect
= wcslen(fmt
);
263 const int n
= vswprintf_wrapper (UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR
, buffer
, bufsiz
, fmt
);
264 const int valid
= n
>= bufsiz
? bufsiz
- 1 : n
< 0 ? 0 : n
;
266 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
267 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
268 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
269 narrow_fmt
, expect
, n
);
270 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
271 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
272 ok (buffer
[valid
] == '\0',
273 "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt
, n
, buffer
[valid
]);
276 /* swprintf style termination */
277 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
278 const wchar_t *fmt
= tests
[i
];
279 const int expect
= wcslen(fmt
) >= bufsiz
? -2 : wcslen(fmt
);
280 const int n
= vswprintf_wrapper (0, buffer
, bufsiz
, fmt
);
281 const int valid
= n
< 0 ? bufsiz
- 1 : n
;
283 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
284 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
285 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
286 narrow_fmt
, expect
, n
);
287 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
288 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
289 ok (buffer
[valid
] == '\0',
290 "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt
, n
, buffer
[valid
]);
294 static int WINAPIV
vfprintf_wrapper(FILE *file
,
295 const char *format
, ...)
299 __ms_va_start(valist
, format
);
300 ret
= p_vfprintf(0, file
, format
, NULL
, valist
);
305 static void test_fprintf(void)
307 static const char file_name
[] = "fprintf.tst";
309 FILE *fp
= p_fopen(file_name
, "wb");
313 ret
= vfprintf_wrapper(fp
, "simple test\n");
314 ok(ret
== 12, "ret = %d\n", ret
);
316 ok(ret
== 12, "ftell returned %d\n", ret
);
318 ret
= vfprintf_wrapper(fp
, "contains%cnull\n", '\0');
319 ok(ret
== 14, "ret = %d\n", ret
);
321 ok(ret
== 26, "ftell returned %d\n", ret
);
325 fp
= p_fopen(file_name
, "rb");
326 p_fgets(buf
, sizeof(buf
), fp
);
328 ok(ret
== 12, "ftell returned %d\n", ret
);
329 ok(!strcmp(buf
, "simple test\n"), "buf = %s\n", buf
);
331 p_fgets(buf
, sizeof(buf
), fp
);
333 ok(ret
== 26, "ret = %d\n", ret
);
334 ok(!memcmp(buf
, "contains\0null\n", 14), "buf = %s\n", buf
);
338 fp
= p_fopen(file_name
, "wt");
340 ret
= vfprintf_wrapper(fp
, "simple test\n");
341 ok(ret
== 12, "ret = %d\n", ret
);
343 ok(ret
== 13, "ftell returned %d\n", ret
);
345 ret
= vfprintf_wrapper(fp
, "contains%cnull\n", '\0');
346 ok(ret
== 14, "ret = %d\n", ret
);
348 ok(ret
== 28, "ftell returned %d\n", ret
);
352 fp
= p_fopen(file_name
, "rb");
353 p_fgets(buf
, sizeof(buf
), fp
);
355 ok(ret
== 13, "ftell returned %d\n", ret
);
356 ok(!strcmp(buf
, "simple test\r\n"), "buf = %s\n", buf
);
358 p_fgets(buf
, sizeof(buf
), fp
);
360 ok(ret
== 28, "ret = %d\n", ret
);
361 ok(!memcmp(buf
, "contains\0null\r\n", 15), "buf = %s\n", buf
);
367 static int WINAPIV
vfwprintf_wrapper(FILE *file
,
368 const wchar_t *format
, ...)
372 __ms_va_start(valist
, format
);
373 ret
= p_vfwprintf(0, file
, format
, NULL
, valist
);
378 static void test_fwprintf(void)
380 static const char file_name
[] = "fprintf.tst";
381 static const WCHAR simple
[] = {'s','i','m','p','l','e',' ','t','e','s','t','\n',0};
382 static const WCHAR cont_fmt
[] = {'c','o','n','t','a','i','n','s','%','c','n','u','l','l','\n',0};
383 static const WCHAR cont
[] = {'c','o','n','t','a','i','n','s','\0','n','u','l','l','\n',0};
385 FILE *fp
= p_fopen(file_name
, "wb");
390 ret
= vfwprintf_wrapper(fp
, simple
);
391 ok(ret
== 12, "ret = %d\n", ret
);
393 ok(ret
== 24, "ftell returned %d\n", ret
);
395 ret
= vfwprintf_wrapper(fp
, cont_fmt
, '\0');
396 ok(ret
== 14, "ret = %d\n", ret
);
398 ok(ret
== 52, "ftell returned %d\n", ret
);
402 fp
= p_fopen(file_name
, "rb");
403 p_fgetws(bufw
, sizeof(bufw
)/sizeof(bufw
[0]), fp
);
405 ok(ret
== 24, "ftell returned %d\n", ret
);
406 ok(!wcscmp(bufw
, simple
), "buf = %s\n", wine_dbgstr_w(bufw
));
408 p_fgetws(bufw
, sizeof(bufw
)/sizeof(bufw
[0]), fp
);
410 ok(ret
== 52, "ret = %d\n", ret
);
411 ok(!memcmp(bufw
, cont
, 28), "buf = %s\n", wine_dbgstr_w(bufw
));
415 fp
= p_fopen(file_name
, "wt");
417 ret
= vfwprintf_wrapper(fp
, simple
);
418 ok(ret
== 12, "ret = %d\n", ret
);
420 ok(ret
== 13, "ftell returned %d\n", ret
);
422 ret
= vfwprintf_wrapper(fp
, cont_fmt
, '\0');
423 ok(ret
== 14, "ret = %d\n", ret
);
425 ok(ret
== 28, "ftell returned %d\n", ret
);
429 fp
= p_fopen(file_name
, "rb");
430 p_fgets(bufa
, sizeof(bufa
), fp
);
432 ok(ret
== 13, "ftell returned %d\n", ret
);
433 ok(!strcmp(bufa
, "simple test\r\n"), "buf = %s\n", bufa
);
435 p_fgets(bufa
, sizeof(bufa
), fp
);
437 ok(ret
== 28, "ret = %d\n", ret
);
438 ok(!memcmp(bufa
, "contains\0null\r\n", 15), "buf = %s\n", bufa
);
443 ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler
) == NULL
,
444 "Invalid parameter handler was already set\n");
448 SET_EXPECT(invalid_parameter_handler
);
449 ret
= vfwprintf_wrapper(fp
, NULL
);
450 ok(errno
== EINVAL
, "expected errno EINVAL, got %d\n", errno
);
451 ok(ret
== -1, "expected ret -1, got %d\n", ret
);
452 CHECK_CALLED(invalid_parameter_handler
);
456 SET_EXPECT(invalid_parameter_handler
);
457 ret
= vfwprintf_wrapper(NULL
, simple
);
458 ok(errno
== EINVAL
, "expected errno EINVAL, got %d\n", errno
);
459 ok(ret
== -1, "expected ret -1, got %d\n", ret
);
460 CHECK_CALLED(invalid_parameter_handler
);
462 /* format using % with NULL arglist*/
463 /* crashes on Windows */
464 /* ret = p_vfwprintf(0, fp, cont_fmt, NULL, NULL); */
466 ok(p_set_invalid_parameter_handler(NULL
) == test_invalid_parameter_handler
,
467 "Cannot reset invalid parameter handler\n");
470 static int WINAPIV
_vsnprintf_s_wrapper(char *str
, size_t sizeOfBuffer
,
471 size_t count
, const char *format
, ...)
475 __ms_va_start(valist
, format
);
476 ret
= p_vsnprintf_s(0, str
, sizeOfBuffer
, count
, format
, NULL
, valist
);
481 static void test_vsnprintf_s(void)
483 const char format
[] = "AB%uC";
484 const char out7
[] = "AB123C";
485 const char out6
[] = "AB123";
486 const char out2
[] = "A";
487 const char out1
[] = "";
488 char buffer
[14] = { 0 };
494 got
= _vsnprintf_s_wrapper(buffer
, 14, _TRUNCATE
, format
, 123);
495 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
496 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
498 got
= _vsnprintf_s_wrapper(buffer
, 12, _TRUNCATE
, format
, 123);
499 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
500 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
502 got
= _vsnprintf_s_wrapper(buffer
, 7, _TRUNCATE
, format
, 123);
503 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
504 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
506 /* Not enough room. */
509 got
= _vsnprintf_s_wrapper(buffer
, 6, _TRUNCATE
, format
, 123);
510 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
511 ok( !strcmp(out6
, buffer
), "buffer wrong, got=%s\n", buffer
);
513 got
= _vsnprintf_s_wrapper(buffer
, 2, _TRUNCATE
, format
, 123);
514 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
515 ok( !strcmp(out2
, buffer
), "buffer wrong, got=%s\n", buffer
);
517 got
= _vsnprintf_s_wrapper(buffer
, 1, _TRUNCATE
, format
, 123);
518 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
519 ok( !strcmp(out1
, buffer
), "buffer wrong, got=%s\n", buffer
);
522 static int WINAPIV
_vsnwprintf_s_wrapper(WCHAR
*str
, size_t sizeOfBuffer
,
523 size_t count
, const WCHAR
*format
, ...)
527 __ms_va_start(valist
, format
);
528 ret
= p_vsnwprintf_s(0, str
, sizeOfBuffer
, count
, format
, NULL
, valist
);
533 static void test_vsnwprintf_s(void)
535 const WCHAR format
[] = {'A','B','%','u','C',0};
536 const WCHAR out7
[] = {'A','B','1','2','3','C',0};
537 const WCHAR out6
[] = {'A','B','1','2','3',0};
538 const WCHAR out2
[] = {'A',0};
539 const WCHAR out1
[] = {0};
540 WCHAR buffer
[14] = { 0 };
544 exp
= lstrlenW(out7
);
546 got
= _vsnwprintf_s_wrapper(buffer
, 14, _TRUNCATE
, format
, 123);
547 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
548 ok( !lstrcmpW(out7
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
550 got
= _vsnwprintf_s_wrapper(buffer
, 12, _TRUNCATE
, format
, 123);
551 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
552 ok( !lstrcmpW(out7
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
554 got
= _vsnwprintf_s_wrapper(buffer
, 7, _TRUNCATE
, format
, 123);
555 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
556 ok( !lstrcmpW(out7
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
558 /* Not enough room. */
561 got
= _vsnwprintf_s_wrapper(buffer
, 6, _TRUNCATE
, format
, 123);
562 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
563 ok( !lstrcmpW(out6
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
565 got
= _vsnwprintf_s_wrapper(buffer
, 2, _TRUNCATE
, format
, 123);
566 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
567 ok( !lstrcmpW(out2
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
569 got
= _vsnwprintf_s_wrapper(buffer
, 1, _TRUNCATE
, format
, 123);
570 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
571 ok( !lstrcmpW(out1
, buffer
), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer
));
574 static void test_printf_legacy_wide(void)
576 const wchar_t wide
[] = {'A','B','C','D',0};
577 const char narrow
[] = "abcd";
578 const char out
[] = "abcd ABCD";
579 /* The legacy wide flag doesn't affect narrow printfs, so the same
580 * format should behave the same both with and without the flag. */
581 const char narrow_fmt
[] = "%s %ls";
582 /* The standard behaviour is to use the same format as for the narrow
583 * case, while the legacy case has got a different meaning for %s. */
584 const wchar_t std_wide_fmt
[] = {'%','s',' ','%','l','s',0};
585 const wchar_t legacy_wide_fmt
[] = {'%','h','s',' ','%','s',0};
589 vsprintf_wrapper(0, buffer
, sizeof(buffer
), narrow_fmt
, narrow
, wide
);
590 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
591 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_WIDE_SPECIFIERS
, buffer
, sizeof(buffer
), narrow_fmt
, narrow
, wide
);
592 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
594 vswprintf_wrapper(0, wbuffer
, sizeof(wbuffer
), std_wide_fmt
, narrow
, wide
);
595 WideCharToMultiByte(CP_ACP
, 0, wbuffer
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
596 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
597 vswprintf_wrapper(UCRTBASE_PRINTF_LEGACY_WIDE_SPECIFIERS
, wbuffer
, sizeof(wbuffer
), legacy_wide_fmt
, narrow
, wide
);
598 WideCharToMultiByte(CP_ACP
, 0, wbuffer
, -1, buffer
, sizeof(buffer
), NULL
, NULL
);
599 ok(!strcmp(buffer
, out
), "buffer wrong, got=%s\n", buffer
);
602 static void test_printf_legacy_msvcrt(void)
606 /* In standard mode, %F is a float format conversion, while it is a
607 * length modifier in legacy msvcrt mode. In legacy mode, N is also
608 * a length modifier. */
609 vsprintf_wrapper(0, buf
, sizeof(buf
), "%F", 1.23);
610 ok(!strcmp(buf
, "1.230000"), "buf = %s\n", buf
);
611 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%Fd %Nd", 123, 456);
612 ok(!strcmp(buf
, "123 456"), "buf = %s\n", buf
);
614 vsprintf_wrapper(0, buf
, sizeof(buf
), "%f %F %f %e %E %g %G", INFINITY
, INFINITY
, -INFINITY
, INFINITY
, INFINITY
, INFINITY
, INFINITY
);
615 ok(!strcmp(buf
, "inf INF -inf inf INF inf INF"), "buf = %s\n", buf
);
616 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%f", INFINITY
);
617 ok(!strcmp(buf
, "1.#INF00"), "buf = %s\n", buf
);
618 vsprintf_wrapper(0, buf
, sizeof(buf
), "%f %F", NAN
, NAN
);
619 ok(!strcmp(buf
, "nan NAN"), "buf = %s\n", buf
);
620 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%f", NAN
);
621 ok(!strcmp(buf
, "1.#QNAN0"), "buf = %s\n", buf
);
622 vsprintf_wrapper(0, buf
, sizeof(buf
), "%f %F", IND
, IND
);
623 ok(!strcmp(buf
, "-nan(ind) -NAN(IND)"), "buf = %s\n", buf
);
624 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
, buf
, sizeof(buf
), "%f", IND
);
625 ok(!strcmp(buf
, "-1.#IND00"), "buf = %s\n", buf
);
628 static void test_printf_legacy_three_digit_exp(void)
632 vsprintf_wrapper(0, buf
, sizeof(buf
), "%E", 1.23);
633 ok(!strcmp(buf
, "1.230000E+00"), "buf = %s\n", buf
);
634 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS
, buf
, sizeof(buf
), "%E", 1.23);
635 ok(!strcmp(buf
, "1.230000E+000"), "buf = %s\n", buf
);
636 vsprintf_wrapper(0, buf
, sizeof(buf
), "%E", 1.23e+123);
637 ok(!strcmp(buf
, "1.230000E+123"), "buf = %s\n", buf
);
640 static void test_printf_c99(void)
644 /* The msvcrt compatibility flag doesn't affect whether 'z' is interpreted
645 * as size_t size for integers. */
646 if (sizeof(void*) == 8) {
647 vsprintf_wrapper(0, buf
, sizeof(buf
), "%zx %d",
648 (size_t) 0x12345678123456, 1);
649 ok(!strcmp(buf
, "12345678123456 1"), "buf = %s\n", buf
);
650 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
,
651 buf
, sizeof(buf
), "%zx %d", (size_t) 0x12345678123456, 1);
652 ok(!strcmp(buf
, "12345678123456 1"), "buf = %s\n", buf
);
654 vsprintf_wrapper(0, buf
, sizeof(buf
), "%zx %d",
655 (size_t) 0x123456, 1);
656 ok(!strcmp(buf
, "123456 1"), "buf = %s\n", buf
);
657 vsprintf_wrapper(UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY
,
658 buf
, sizeof(buf
), "%zx %d", (size_t) 0x123456, 1);
659 ok(!strcmp(buf
, "123456 1"), "buf = %s\n", buf
);
663 static void test_printf_natural_string(void)
665 const wchar_t wide
[] = {'A','B','C','D',0};
666 const char narrow
[] = "abcd";
667 const char narrow_fmt
[] = "%s %Ts";
668 const char narrow_out
[] = "abcd abcd";
669 const wchar_t wide_fmt
[] = {'%','s',' ','%','T','s',0};
670 const wchar_t wide_out
[] = {'a','b','c','d',' ','A','B','C','D',0};
674 vsprintf_wrapper(0, buffer
, sizeof(buffer
), narrow_fmt
, narrow
, narrow
);
675 ok(!strcmp(buffer
, narrow_out
), "buffer wrong, got=%s\n", buffer
);
677 vswprintf_wrapper(0, wbuffer
, sizeof(wbuffer
), wide_fmt
, narrow
, wide
);
678 ok(!lstrcmpW(wbuffer
, wide_out
), "buffer wrong, got=%s\n", wine_dbgstr_w(wbuffer
));
691 test_printf_legacy_wide();
692 test_printf_legacy_msvcrt();
693 test_printf_legacy_three_digit_exp();
695 test_printf_natural_string();