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 UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION (0x0001)
34 #define UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR (0x0002)
35 #define UCRTBASE_PRINTF_LEGACY_WIDE_SPECIFIERS (0x0004)
36 #define UCRTBASE_PRINTF_LEGACY_MSVCRT_COMPATIBILITY (0x0008)
37 #define UCRTBASE_PRINTF_LEGACY_THREE_DIGIT_EXPONENTS (0x0010)
39 static int (__cdecl
*p_vfprintf
)(unsigned __int64 options
, FILE *file
, const char *format
,
40 void *locale
, __ms_va_list valist
);
41 static int (__cdecl
*p_vsprintf
)(unsigned __int64 options
, char *str
, size_t len
, const char *format
,
42 void *locale
, __ms_va_list valist
);
43 static int (__cdecl
*p_vsnprintf_s
)(unsigned __int64 options
, char *str
, size_t sizeOfBuffer
, size_t count
, const char *format
,
44 void *locale
, __ms_va_list valist
);
45 static int (__cdecl
*p_vsprintf_s
)(unsigned __int64 options
, char *str
, size_t count
, const char *format
,
46 void *locale
, __ms_va_list valist
);
47 static int (__cdecl
*p_vswprintf
)(unsigned __int64 options
, wchar_t *str
, size_t len
, const wchar_t *format
,
48 void *locale
, __ms_va_list valist
);
50 static FILE *(__cdecl
*p_fopen
)(const char *name
, const char *mode
);
51 static int (__cdecl
*p_fclose
)(FILE *file
);
52 static long (__cdecl
*p_ftell
)(FILE *file
);
53 static char *(__cdecl
*p_fgets
)(char *str
, int size
, FILE *file
);
55 static BOOL
init( void )
57 HMODULE hmod
= LoadLibraryA("ucrtbase.dll");
61 win_skip("ucrtbase.dll not installed\n");
65 p_vfprintf
= (void *)GetProcAddress(hmod
, "__stdio_common_vfprintf");
66 p_vsprintf
= (void *)GetProcAddress(hmod
, "__stdio_common_vsprintf");
67 p_vsnprintf_s
= (void *)GetProcAddress(hmod
, "__stdio_common_vsnprintf_s");
68 p_vsprintf_s
= (void *)GetProcAddress(hmod
, "__stdio_common_vsprintf_s");
69 p_vswprintf
= (void *)GetProcAddress(hmod
, "__stdio_common_vswprintf");
71 p_fopen
= (void *)GetProcAddress(hmod
, "fopen");
72 p_fclose
= (void *)GetProcAddress(hmod
, "fclose");
73 p_ftell
= (void *)GetProcAddress(hmod
, "ftell");
74 p_fgets
= (void *)GetProcAddress(hmod
, "fgets");
78 static int __cdecl
vsprintf_wrapper(unsigned __int64 options
, char *str
,
79 size_t len
, const char *format
, ...)
83 __ms_va_start(valist
, format
);
84 ret
= p_vsprintf(options
, str
, len
, format
, NULL
, valist
);
89 static void test_snprintf (void)
91 const char *tests
[] = {"short", "justfit", "justfits", "muchlonger"};
93 const int bufsiz
= sizeof buffer
;
96 /* Legacy _snprintf style termination */
97 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
98 const char *fmt
= tests
[i
];
99 const int expect
= strlen(fmt
) > bufsiz
? -1 : strlen(fmt
);
100 const int n
= vsprintf_wrapper (UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
, buffer
, bufsiz
, fmt
);
101 const int valid
= n
< 0 ? bufsiz
: (n
== bufsiz
? n
: n
+1);
103 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
105 ok (!memcmp (fmt
, buffer
, valid
),
106 "\"%s\": rendered \"%.*s\"\n", fmt
, valid
, buffer
);
109 /* C99 snprintf style termination */
110 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
111 const char *fmt
= tests
[i
];
112 const int expect
= strlen(fmt
);
113 const int n
= vsprintf_wrapper (UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR
, buffer
, bufsiz
, fmt
);
114 const int valid
= n
>= bufsiz
? bufsiz
- 1 : n
< 0 ? 0 : n
;
116 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
118 ok (!memcmp (fmt
, buffer
, valid
),
119 "\"%s\": rendered \"%.*s\"\n", fmt
, valid
, buffer
);
120 ok (buffer
[valid
] == '\0',
121 "\"%s\": Missing null termination (ret %d) - is %d\n", fmt
, n
, buffer
[valid
]);
124 /* swprintf style termination */
125 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
126 const char *fmt
= tests
[i
];
127 const int expect
= strlen(fmt
) >= bufsiz
? -2 : strlen(fmt
);
128 const int n
= vsprintf_wrapper (0, buffer
, bufsiz
, fmt
);
129 const int valid
= n
< 0 ? bufsiz
- 1 : n
;
131 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
133 ok (!memcmp (fmt
, buffer
, valid
),
134 "\"%s\": rendered \"%.*s\"\n", fmt
, valid
, buffer
);
135 ok (buffer
[valid
] == '\0',
136 "\"%s\": Missing null termination (ret %d) - is %d\n", fmt
, n
, buffer
[valid
]);
140 static int __cdecl
vswprintf_wrapper(unsigned __int64 options
, wchar_t *str
,
141 size_t len
, const wchar_t *format
, ...)
145 __ms_va_start(valist
, format
);
146 ret
= p_vswprintf(options
, str
, len
, format
, NULL
, valist
);
151 static void test_swprintf (void)
153 const wchar_t str_short
[] = {'s','h','o','r','t',0};
154 const wchar_t str_justfit
[] = {'j','u','s','t','f','i','t',0};
155 const wchar_t str_justfits
[] = {'j','u','s','t','f','i','t','s',0};
156 const wchar_t str_muchlonger
[] = {'m','u','c','h','l','o','n','g','e','r',0};
157 const wchar_t *tests
[] = {str_short
, str_justfit
, str_justfits
, str_muchlonger
};
160 char narrow
[8], narrow_fmt
[16];
161 const int bufsiz
= sizeof buffer
/ sizeof buffer
[0];
164 /* Legacy _snprintf style termination */
165 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
166 const wchar_t *fmt
= tests
[i
];
167 const int expect
= wcslen(fmt
) > bufsiz
? -1 : wcslen(fmt
);
168 const int n
= vswprintf_wrapper (UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
, buffer
, bufsiz
, fmt
);
169 const int valid
= n
< 0 ? bufsiz
: (n
== bufsiz
? n
: n
+1);
171 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
172 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
173 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
174 narrow_fmt
, expect
, n
);
175 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
176 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
179 /* C99 snprintf style termination */
180 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
181 const wchar_t *fmt
= tests
[i
];
182 const int expect
= wcslen(fmt
);
183 const int n
= vswprintf_wrapper (UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR
, buffer
, bufsiz
, fmt
);
184 const int valid
= n
>= bufsiz
? bufsiz
- 1 : n
< 0 ? 0 : n
;
186 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
187 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
188 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
189 narrow_fmt
, expect
, n
);
190 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
191 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
192 ok (buffer
[valid
] == '\0',
193 "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt
, n
, buffer
[valid
]);
196 /* swprintf style termination */
197 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
198 const wchar_t *fmt
= tests
[i
];
199 const int expect
= wcslen(fmt
) >= bufsiz
? -2 : wcslen(fmt
);
200 const int n
= vswprintf_wrapper (0, buffer
, bufsiz
, fmt
);
201 const int valid
= n
< 0 ? bufsiz
- 1 : n
;
203 WideCharToMultiByte (CP_ACP
, 0, buffer
, -1, narrow
, sizeof(narrow
), NULL
, NULL
);
204 WideCharToMultiByte (CP_ACP
, 0, fmt
, -1, narrow_fmt
, sizeof(narrow_fmt
), NULL
, NULL
);
205 ok (n
== expect
, "\"%s\": expected %d, returned %d\n",
206 narrow_fmt
, expect
, n
);
207 ok (!memcmp (fmt
, buffer
, valid
* sizeof(wchar_t)),
208 "\"%s\": rendered \"%.*s\"\n", narrow_fmt
, valid
, narrow
);
209 ok (buffer
[valid
] == '\0',
210 "\"%s\": Missing null termination (ret %d) - is %d\n", narrow_fmt
, n
, buffer
[valid
]);
214 static int __cdecl
vfprintf_wrapper(FILE *file
,
215 const char *format
, ...)
219 __ms_va_start(valist
, format
);
220 ret
= p_vfprintf(0, file
, format
, NULL
, valist
);
225 static void test_fprintf(void)
227 static const char file_name
[] = "fprintf.tst";
229 FILE *fp
= p_fopen(file_name
, "wb");
233 ret
= vfprintf_wrapper(fp
, "simple test\n");
234 ok(ret
== 12, "ret = %d\n", ret
);
236 ok(ret
== 12, "ftell returned %d\n", ret
);
238 ret
= vfprintf_wrapper(fp
, "contains%cnull\n", '\0');
239 ok(ret
== 14, "ret = %d\n", ret
);
241 ok(ret
== 26, "ftell returned %d\n", ret
);
245 fp
= p_fopen(file_name
, "rb");
246 p_fgets(buf
, sizeof(buf
), fp
);
248 ok(ret
== 12, "ftell returned %d\n", ret
);
249 ok(!strcmp(buf
, "simple test\n"), "buf = %s\n", buf
);
251 p_fgets(buf
, sizeof(buf
), fp
);
253 ok(ret
== 26, "ret = %d\n", ret
);
254 ok(!memcmp(buf
, "contains\0null\n", 14), "buf = %s\n", buf
);
258 fp
= p_fopen(file_name
, "wt");
260 ret
= vfprintf_wrapper(fp
, "simple test\n");
261 ok(ret
== 12, "ret = %d\n", ret
);
263 ok(ret
== 13, "ftell returned %d\n", ret
);
265 ret
= vfprintf_wrapper(fp
, "contains%cnull\n", '\0');
266 ok(ret
== 14, "ret = %d\n", ret
);
268 ok(ret
== 28, "ftell returned %d\n", ret
);
272 fp
= p_fopen(file_name
, "rb");
273 p_fgets(buf
, sizeof(buf
), fp
);
275 ok(ret
== 13, "ftell returned %d\n", ret
);
276 ok(!strcmp(buf
, "simple test\r\n"), "buf = %s\n", buf
);
278 p_fgets(buf
, sizeof(buf
), fp
);
280 ok(ret
== 28, "ret = %d\n", ret
);
281 ok(!memcmp(buf
, "contains\0null\r\n", 15), "buf = %s\n", buf
);
287 static int __cdecl
_vsnprintf_s_wrapper(char *str
, size_t sizeOfBuffer
,
288 size_t count
, const char *format
, ...)
292 __ms_va_start(valist
, format
);
293 ret
= p_vsnprintf_s(0, str
, sizeOfBuffer
, count
, format
, NULL
, valist
);
298 static void test_vsnprintf_s(void)
300 const char format
[] = "AB%uC";
301 const char out7
[] = "AB123C";
302 const char out6
[] = "AB123";
303 const char out2
[] = "A";
304 const char out1
[] = "";
305 char buffer
[14] = { 0 };
311 got
= _vsnprintf_s_wrapper(buffer
, 14, _TRUNCATE
, format
, 123);
312 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
313 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
315 got
= _vsnprintf_s_wrapper(buffer
, 12, _TRUNCATE
, format
, 123);
316 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
317 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
319 got
= _vsnprintf_s_wrapper(buffer
, 7, _TRUNCATE
, format
, 123);
320 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
321 ok( !strcmp(out7
, buffer
), "buffer wrong, got=%s\n", buffer
);
323 /* Not enough room. */
326 got
= _vsnprintf_s_wrapper(buffer
, 6, _TRUNCATE
, format
, 123);
327 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
328 ok( !strcmp(out6
, buffer
), "buffer wrong, got=%s\n", buffer
);
330 got
= _vsnprintf_s_wrapper(buffer
, 2, _TRUNCATE
, format
, 123);
331 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
332 ok( !strcmp(out2
, buffer
), "buffer wrong, got=%s\n", buffer
);
334 got
= _vsnprintf_s_wrapper(buffer
, 1, _TRUNCATE
, format
, 123);
335 ok( exp
== got
, "length wrong, expect=%d, got=%d\n", exp
, got
);
336 ok( !strcmp(out1
, buffer
), "buffer wrong, got=%s\n", buffer
);