msvcrt/tests: Use wide-char string literals.
[wine.git] / dlls / msvcrt / tests / printf.c
blob8960671f23ee4575f219cb787288ce8253d73286
1 /*
2 * Conformance tests for *printf functions.
4 * Copyright 2002 Uwe Bonnes
5 * Copyright 2004 Aneurin Price
6 * Copyright 2005 Mike McCormack
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* With Visual Studio >= 2005, swprintf() takes an extra parameter unless
24 * the following macro is defined.
26 #define _CRT_NON_CONFORMING_SWPRINTFS
28 #include <stdio.h>
29 #include <errno.h>
30 #include <math.h>
31 #include <locale.h>
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winnls.h"
37 #include "wine/test.h"
39 static inline float __port_ind(void)
41 static const unsigned __ind_bytes = 0xffc00000;
42 return *(const float *)&__ind_bytes;
44 #define IND __port_ind()
46 static int (__cdecl *p__vscprintf)(const char *format, __ms_va_list valist);
47 static int (__cdecl *p__vscwprintf)(const wchar_t *format, __ms_va_list valist);
48 static int (__cdecl *p__vsnwprintf_s)(wchar_t *str, size_t sizeOfBuffer,
49 size_t count, const wchar_t *format,
50 __ms_va_list valist);
51 static int (__cdecl *p__ecvt_s)(char *buffer, size_t length, double number,
52 int ndigits, int *decpt, int *sign);
53 static int (__cdecl *p__fcvt_s)(char *buffer, size_t length, double number,
54 int ndigits, int *decpt, int *sign);
55 static unsigned int (__cdecl *p__get_output_format)(void);
56 static unsigned int (__cdecl *p__set_output_format)(unsigned int);
57 static int (WINAPIV *p_sprintf)(char*, ...);
58 static int (__cdecl *p__vsprintf_p)(char*, size_t, const char*, __ms_va_list);
59 static int (__cdecl *p_vswprintf)(wchar_t *str, const wchar_t *format, __ms_va_list valist);
60 static int (__cdecl *p__vswprintf)(wchar_t *str, const wchar_t *format, __ms_va_list valist);
61 static int (__cdecl *p__vswprintf_l)(wchar_t *str, const wchar_t *format,
62 void *locale, __ms_va_list valist);
63 static int (__cdecl *p__vswprintf_c)(wchar_t *str, size_t size, const wchar_t *format,
64 __ms_va_list valist);
65 static int (__cdecl *p__vswprintf_c_l)(wchar_t *str, size_t size, const wchar_t *format,
66 void *locale, __ms_va_list valist);
67 static int (__cdecl *p__vswprintf_p_l)(wchar_t *str, size_t size, const wchar_t *format,
68 void *locale, __ms_va_list valist);
70 static void init( void )
72 HMODULE hmod = GetModuleHandleA("msvcrt.dll");
74 p_sprintf = (void *)GetProcAddress(hmod, "sprintf");
75 p__vscprintf = (void *)GetProcAddress(hmod, "_vscprintf");
76 p__vscwprintf = (void *)GetProcAddress(hmod, "_vscwprintf");
77 p__vsnwprintf_s = (void *)GetProcAddress(hmod, "_vsnwprintf_s");
78 p__ecvt_s = (void *)GetProcAddress(hmod, "_ecvt_s");
79 p__fcvt_s = (void *)GetProcAddress(hmod, "_fcvt_s");
80 p__get_output_format = (void *)GetProcAddress(hmod, "_get_output_format");
81 p__set_output_format = (void *)GetProcAddress(hmod, "_set_output_format");
82 p__vsprintf_p = (void*)GetProcAddress(hmod, "_vsprintf_p");
83 p_vswprintf = (void*)GetProcAddress(hmod, "vswprintf");
84 p__vswprintf = (void*)GetProcAddress(hmod, "_vswprintf");
85 p__vswprintf_l = (void*)GetProcAddress(hmod, "_vswprintf_l");
86 p__vswprintf_c = (void*)GetProcAddress(hmod, "_vswprintf_c");
87 p__vswprintf_c_l = (void*)GetProcAddress(hmod, "_vswprintf_c_l");
88 p__vswprintf_p_l = (void*)GetProcAddress(hmod, "_vswprintf_p_l");
91 static void test_sprintf( void )
93 enum {
94 NO_ARG,
95 INT_ARG,
96 ULONGLONG_ARG,
97 DOUBLE_ARG,
98 PTR_ARG,
99 TODO_FLAG = 0x1000
102 struct {
103 const char *format;
104 const char *out;
105 const char *broken;
106 int type;
107 int arg_i;
108 ULONGLONG arg_ull;
109 double arg_d;
110 const void *arg_ptr;
111 } tests[] = {
112 { "%+#23.15e", "+7.894561230000000e+008", 0, DOUBLE_ARG, 0, 0, 789456123 },
113 { "%-#23.15e", "7.894561230000000e+008 ", 0, DOUBLE_ARG, 0, 0, 789456123 },
114 { "%#23.15e", " 7.894561230000000e+008", 0, DOUBLE_ARG, 0, 0, 789456123 },
115 { "%#1.1g", "8.e+008", 0, DOUBLE_ARG, 0, 0, 789456123 },
116 { "%I64d", "-8589934591", 0, ULONGLONG_ARG, 0, ((ULONGLONG)0xffffffff)*0xffffffff },
117 { "%+8I64d", " +100", 0, ULONGLONG_ARG, 0, 100 },
118 { "%+.8I64d", "+00000100", 0, ULONGLONG_ARG, 0, 100 },
119 { "%+10.8I64d", " +00000100", 0, ULONGLONG_ARG, 0, 100 },
120 { "%_1I64d", "_1I64d", 0, ULONGLONG_ARG, 0, 100 },
121 { "%-1.5I64d", "-00100", 0, ULONGLONG_ARG, 0, -100 },
122 { "%5I64d", " 100", 0, ULONGLONG_ARG, 0, 100 },
123 { "%5I64d", " -100", 0, ULONGLONG_ARG, 0, -100 },
124 { "%-5I64d", "100 ", 0, ULONGLONG_ARG, 0, 100 },
125 { "%-5I64d", "-100 ", 0, ULONGLONG_ARG, 0, -100 },
126 { "%-.5I64d", "00100", 0, ULONGLONG_ARG, 0, 100 },
127 { "%-.5I64d", "-00100", 0, ULONGLONG_ARG, 0, -100 },
128 { "%-8.5I64d", "00100 ", 0, ULONGLONG_ARG, 0, 100 },
129 { "%-8.5I64d", "-00100 ", 0, ULONGLONG_ARG, 0, -100 },
130 { "%05I64d", "00100", 0, ULONGLONG_ARG, 0, 100 },
131 { "%05I64d", "-0100", 0, ULONGLONG_ARG, 0, -100 },
132 { "% I64d", " 100", 0, ULONGLONG_ARG, 0, 100 },
133 { "% I64d", "-100", 0, ULONGLONG_ARG, 0, -100 },
134 { "% 5I64d", " 100", 0, ULONGLONG_ARG, 0, 100 },
135 { "% 5I64d", " -100", 0, ULONGLONG_ARG, 0, -100 },
136 { "% .5I64d", " 00100", 0, ULONGLONG_ARG, 0, 100 },
137 { "% .5I64d", "-00100", 0, ULONGLONG_ARG, 0, -100 },
138 { "% 8.5I64d", " 00100", 0, ULONGLONG_ARG, 0, 100 },
139 { "% 8.5I64d", " -00100", 0, ULONGLONG_ARG, 0, -100 },
140 { "%.0I64d", "", 0, ULONGLONG_ARG },
141 { "%#+21.18I64x", " 0x00ffffffffffffff9c", 0, ULONGLONG_ARG, 0, -100 },
142 { "%#.25I64o", "0001777777777777777777634", 0, ULONGLONG_ARG, 0, -100 },
143 { "%#+24.20I64o", " 01777777777777777777634", 0, ULONGLONG_ARG, 0, -100 },
144 { "%#+18.21I64X", "0X00000FFFFFFFFFFFFFF9C", 0, ULONGLONG_ARG, 0, -100 },
145 { "%#+20.24I64o", "001777777777777777777634", 0, ULONGLONG_ARG, 0, -100 },
146 { "%#+25.22I64u", " 0018446744073709551615", 0, ULONGLONG_ARG, 0, -1 },
147 { "%#+25.22I64u", " 0018446744073709551615", 0, ULONGLONG_ARG, 0, -1 },
148 { "%#+30.25I64u", " 0000018446744073709551615", 0, ULONGLONG_ARG, 0, -1 },
149 { "%+#25.22I64d", " -0000000000000000000001", 0, ULONGLONG_ARG, 0, -1 },
150 { "%#-8.5I64o", "00144 ", 0, ULONGLONG_ARG, 0, 100 },
151 { "%#-+ 08.5I64d", "+00100 ", 0, ULONGLONG_ARG, 0, 100 },
152 { "%.80I64d",
153 "00000000000000000000000000000000000000000000000000000000000000000000000000000001",
154 0, ULONGLONG_ARG, 0, 1 },
155 { "% .80I64d",
156 " 00000000000000000000000000000000000000000000000000000000000000000000000000000001",
157 0, ULONGLONG_ARG, 0, 1 },
158 { "% .80d",
159 " 00000000000000000000000000000000000000000000000000000000000000000000000000000001",
160 0, INT_ARG, 1 },
161 { "%I", "I", 0, INT_ARG, 1 },
162 { "%Iq", "Iq", 0, INT_ARG, 1 },
163 { "%Ihd", "Ihd", 0, INT_ARG, 1 },
164 { "%I0d", "I0d", 0, INT_ARG, 1 },
165 { "%I64D", "D", 0, ULONGLONG_ARG, 0, -1 },
166 { "%zx", "1", "zx", INT_ARG, 1 },
167 { "%z", "z", 0, INT_ARG, 1 },
168 { "%tx", "1", "tx", INT_ARG, 1 },
169 { "%t", "t", 0, INT_ARG, 1 },
170 { "% d", " 1", 0, INT_ARG, 1 },
171 { "%+ d", "+1", 0, INT_ARG, 1 },
172 { "%S", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" },
173 { "%04c", "0001", 0, INT_ARG, '1' },
174 { "%-04c", "1 ", 0, INT_ARG, '1' },
175 { "%#012x", "0x0000000001", 0, INT_ARG, 1 },
176 { "%#012x", "000000000000", 0, INT_ARG, 0 },
177 { "%#04.8x", "0x00000001", 0, INT_ARG, 1 },
178 { "%#04.8x", "00000000", 0, INT_ARG, 0 },
179 { "%#-08.2x", "0x01 ", 0, INT_ARG, 1 },
180 { "%#-08.2x", "00 ", 0, INT_ARG, 0 },
181 { "%#.0x", "0x1", 0, INT_ARG, 1 },
182 { "%#.0x", "", 0, INT_ARG, 0 },
183 { "%#08o", "00000001", 0, INT_ARG, 1 },
184 { "%#o", "01", 0, INT_ARG, 1 },
185 { "%#o", "0", 0, INT_ARG, 0 },
186 { "%04s", "0foo", 0, PTR_ARG, 0, 0, 0, "foo" },
187 { "%.1s", "f", 0, PTR_ARG, 0, 0, 0, "foo" },
188 { "hello", "hello", 0, NO_ARG },
189 { "%ws", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" },
190 { "%-10ws", "wide ", 0, PTR_ARG, 0, 0, 0, L"wide" },
191 { "%10ws", " wide", 0, PTR_ARG, 0, 0, 0, L"wide" },
192 { "%#+ -03whlls", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" },
193 { "%w0s", "0s", 0, PTR_ARG, 0, 0, 0, L"wide" },
194 { "%w-s", "-s", 0, PTR_ARG, 0, 0, 0, L"wide" },
195 { "%ls", "wide", 0, PTR_ARG, 0, 0, 0, L"wide" },
196 { "%Ls", "not wide", 0, PTR_ARG, 0, 0, 0, "not wide" },
197 { "%b", "b", 0, NO_ARG },
198 { "%3c", " a", 0, INT_ARG, 'a' },
199 { "%3d", "1234", 0, INT_ARG, 1234 },
200 { "%3h", "", 0, NO_ARG },
201 { "%k%m%q%r%t%v%y%z", "kmqrtvyz", 0, NO_ARG },
202 { "%-1d", "2", 0, INT_ARG, 2 },
203 { "%2.4f", "8.6000", 0, DOUBLE_ARG, 0, 0, 8.6 },
204 { "%0f", "0.600000", 0, DOUBLE_ARG, 0, 0, 0.6 },
205 { "%.0f", "1", 0, DOUBLE_ARG, 0, 0, 0.6 },
206 { "%2.4e", "8.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 },
207 { "% 2.4e", " 8.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 },
208 { "% 014.4e", " 008.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 },
209 { "% 2.4e", "-8.6000e+000", 0, DOUBLE_ARG, 0, 0, -8.6 },
210 { "%+2.4e", "+8.6000e+000", 0, DOUBLE_ARG, 0, 0, 8.6 },
211 { "%2.4g", "8.6", 0, DOUBLE_ARG, 0, 0, 8.6 },
212 { "%-i", "-1", 0, INT_ARG, -1 },
213 { "%-i", "1", 0, INT_ARG, 1 },
214 { "%+i", "+1", 0, INT_ARG, 1 },
215 { "%o", "12", 0, INT_ARG, 10 },
216 { "%s", "(null)", 0, PTR_ARG, 0, 0, 0, NULL },
217 { "%s", "%%%%", 0, PTR_ARG, 0, 0, 0, "%%%%" },
218 { "%u", "4294967295", 0, INT_ARG, -1 },
219 { "%w", "", 0, INT_ARG, -1 },
220 { "%h", "", 0, INT_ARG, -1 },
221 { "%j", "", "j", ULONGLONG_ARG, 0, -1 },
222 { "%jd", "-1", "jd", ULONGLONG_ARG, 0, -1 },
223 { "%F", "", 0, INT_ARG, -1 },
224 { "%N", "", 0, INT_ARG, -1 },
225 { "%H", "H", 0, INT_ARG, -1 },
226 { "x%cx", "xXx", 0, INT_ARG, 0x100+'X' },
227 { "%%0", "%0", 0, NO_ARG },
228 { "%hx", "2345", 0, INT_ARG, 0x12345 },
229 { "%hhx", "123", 0, INT_ARG, 0x123 },
230 { "%hhx", "2345", 0, INT_ARG, 0x12345 },
231 { "%lf", "-1.#IND00", 0, DOUBLE_ARG, 0, 0, IND },
232 { "%lf", "1.#QNAN0", 0, DOUBLE_ARG, 0, 0, NAN },
233 { "%lf", "1.#INF00", 0, DOUBLE_ARG, 0, 0, INFINITY },
234 { "%le", "-1.#IND00e+000", 0, DOUBLE_ARG, 0, 0, IND },
235 { "%le", "1.#QNAN0e+000", 0, DOUBLE_ARG, 0, 0, NAN },
236 { "%le", "1.#INF00e+000", 0, DOUBLE_ARG, 0, 0, INFINITY },
237 { "%lg", "-1.#IND", 0, DOUBLE_ARG, 0, 0, IND },
238 { "%lg", "1.#QNAN", 0, DOUBLE_ARG, 0, 0, NAN },
239 { "%lg", "1.#INF", 0, DOUBLE_ARG, 0, 0, INFINITY },
240 { "%010.2lf", "-000001.#J", 0, DOUBLE_ARG, 0, 0, IND },
241 { "%010.2lf", "0000001.#R", 0, DOUBLE_ARG, 0, 0, NAN },
242 { "%010.2lf", "0000001.#J", 0, DOUBLE_ARG, 0, 0, INFINITY },
243 { "%c", "a", 0, INT_ARG, 'a' },
244 { "%c", "\x82", 0, INT_ARG, 0xa082 },
245 { "%C", "a", 0, INT_ARG, 'a' },
246 { "%C", "", 0, INT_ARG, 0x3042 },
247 { "a%Cb", "ab", 0, INT_ARG, 0x3042 },
248 { "%lld", "-8589934591", "1", ULONGLONG_ARG, 0, ((ULONGLONG)0xffffffff)*0xffffffff },
249 { "%I32d", "1", "I32d", INT_ARG, 1 },
250 { "%.0f", "-2", 0, DOUBLE_ARG, 0, 0, -1.5 },
251 { "%.0f", "-1", 0, DOUBLE_ARG, 0, 0, -0.5 },
252 { "%.0f", "1", 0, DOUBLE_ARG, 0, 0, 0.5 },
253 { "%.0f", "2", 0, DOUBLE_ARG, 0, 0, 1.5 },
254 { "%.30f", "0.333333333333333310000000000000", 0, TODO_FLAG | DOUBLE_ARG, 0, 0, 1.0/3.0 },
255 { "%.30lf", "1.414213562373095100000000000000", 0, TODO_FLAG | DOUBLE_ARG, 0, 0, sqrt(2) },
258 char buffer[100];
259 int i, x, r;
261 for (i=0; i<ARRAY_SIZE(tests); i++) {
262 memset(buffer, 'x', sizeof(buffer));
263 switch(tests[i].type & 0xff) {
264 case NO_ARG:
265 r = p_sprintf(buffer, tests[i].format);
266 break;
267 case INT_ARG:
268 r = p_sprintf(buffer, tests[i].format, tests[i].arg_i);
269 break;
270 case ULONGLONG_ARG:
271 r = p_sprintf(buffer, tests[i].format, tests[i].arg_ull);
272 break;
273 case DOUBLE_ARG:
274 r = p_sprintf(buffer, tests[i].format, tests[i].arg_d);
275 break;
276 case PTR_ARG:
277 r = p_sprintf(buffer, tests[i].format, tests[i].arg_ptr);
278 break;
279 default:
280 ok(0, "tests[%d].type = %x\n", i, tests[i].type);
281 continue;
284 ok(r == strlen(buffer), "%d) r = %d, buffer = \"%s\"\n", i, r, buffer);
285 todo_wine_if(tests[i].type & TODO_FLAG)
287 ok(!strcmp(buffer, tests[i].out) ||
288 broken(tests[i].broken && !strcmp(buffer, tests[i].broken)),
289 "%d) buffer = \"%s\"\n", i, buffer);
293 if (sizeof(void *) == 8)
295 r = p_sprintf(buffer, "%p", (void *)57);
296 ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
297 ok( r==16, "return count wrong\n");
299 r = p_sprintf(buffer, "%#020p", (void *)57);
300 ok(!strcmp(buffer," 0X0000000000000039"),"Pointer formatted incorrectly\n");
301 ok( r==20, "return count wrong\n");
303 r = p_sprintf(buffer, "%Fp", (void *)57);
304 ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
305 ok( r==16, "return count wrong\n");
307 r = p_sprintf(buffer, "%Np", (void *)57);
308 ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
309 ok( r==16, "return count wrong\n");
311 r = p_sprintf(buffer, "%#-020p", (void *)57);
312 ok(!strcmp(buffer,"0X0000000000000039 "),"Pointer formatted incorrectly\n");
313 ok( r==20, "return count wrong\n");
315 r = p_sprintf(buffer, "%Ix %d", (size_t)0x12345678123456,1);
316 ok(!strcmp(buffer,"12345678123456 1"),"buffer = %s\n",buffer);
317 ok( r==16, "return count wrong\n");
319 r = p_sprintf(buffer, "%p", 0);
320 ok(!strcmp(buffer,"0000000000000000"), "failed\n");
321 ok( r==16, "return count wrong\n");
323 else
325 r = p_sprintf(buffer, "%p", (void *)57);
326 ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
327 ok( r==8, "return count wrong\n");
329 r = p_sprintf(buffer, "%#012p", (void *)57);
330 ok(!strcmp(buffer," 0X00000039"),"Pointer formatted incorrectly\n");
331 ok( r==12, "return count wrong\n");
333 r = p_sprintf(buffer, "%Fp", (void *)57);
334 ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
335 ok( r==8, "return count wrong\n");
337 r = p_sprintf(buffer, "%Np",(void *)57);
338 ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
339 ok( r==8, "return count wrong\n");
341 r = p_sprintf(buffer, "%#-012p", (void *)57);
342 ok(!strcmp(buffer,"0X00000039 "),"Pointer formatted incorrectly\n");
343 ok( r==12, "return count wrong\n");
345 r = p_sprintf(buffer, "%Ix %d", 0x123456, 1);
346 ok(!strcmp(buffer,"123456 1"),"buffer = %s\n",buffer);
347 ok( r==8, "return count wrong\n");
349 r = p_sprintf(buffer, "%p", 0);
350 ok(!strcmp(buffer,"00000000"), "failed\n");
351 ok( r==8, "return count wrong\n");
354 r = p_sprintf(buffer, "%.*s", 1, "foo");
355 ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer);
356 ok( r==1, "return count wrong\n");
358 r = p_sprintf(buffer, "%*s", -5, "foo");
359 ok(!strcmp(buffer,"foo "),"Negative field width ignored \"%s\"\n",buffer);
360 ok( r==5, "return count wrong\n");
362 x = 0;
363 r = p_sprintf(buffer, "asdf%n", &x );
364 if (r == -1)
366 /* %n format is disabled by default on vista */
367 /* FIXME: should test with _set_printf_count_output */
368 ok(x == 0, "should not write to x: %d\n", x);
370 else
372 ok(x == 4, "should write to x: %d\n", x);
373 ok(!strcmp(buffer,"asdf"), "failed\n");
374 ok( r==4, "return count wrong: %d\n", r);
377 r = p_sprintf(buffer, "%S", L"\x3042");
378 ok(r==-1 || broken(!r), "r = %d\n", r);
380 if(!setlocale(LC_ALL, "Japanese_Japan.932")) {
381 win_skip("Japanese_Japan.932 locale not available\n");
382 return;
385 r = p_sprintf(buffer, "%c", 0xa082);
386 ok(r==1, "r = %d\n", r);
387 ok(!strcmp(buffer, "\x82"), "failed: \"%s\"\n", buffer);
389 r = p_sprintf(buffer, "%C", 0x3042);
390 ok(r==2, "r = %d\n", r);
391 ok(!strcmp(buffer, "\x82\xa0"), "failed: \"%s\"\n", buffer);
393 strcpy(buffer, " string to copy");
394 r = p_sprintf(buffer, buffer+1);
395 ok(r==14, "r = %d\n", r);
396 ok(!strcmp(buffer, "string to copy"), "failed: \"%s\"\n", buffer);
398 setlocale(LC_ALL, "C");
401 static void test_swprintf( void )
403 wchar_t buffer[100];
404 double pnumber = 789456123;
405 const char string[] = "string";
407 swprintf(buffer, L"%+#23.15e", pnumber);
408 ok(wcsstr(buffer, L"e+008") != 0, "Sprintf different\n");
409 swprintf(buffer, L"%I64d", ((ULONGLONG)0xffffffff)*0xffffffff);
410 ok(wcslen(buffer) == 11, "Problem with long long\n");
411 swprintf(buffer, L"%S", string);
412 ok(wcslen(buffer) == 6, "Problem with \"%%S\" interpretation\n");
413 swprintf(buffer, L"%hs", string);
414 ok(!wcscmp(L"string", buffer), "swprintf failed with %%hs\n");
417 static void test_snprintf (void)
419 struct snprintf_test {
420 const char *format;
421 int expected;
423 /* Pre-2.1 libc behaviour, not C99 compliant. */
424 const struct snprintf_test tests[] = {{"short", 5},
425 {"justfit", 7},
426 {"justfits", 8},
427 {"muchlonger", -1}};
428 char buffer[8];
429 const int bufsiz = sizeof buffer;
430 unsigned int i;
432 for (i = 0; i < ARRAY_SIZE(tests); i++) {
433 const char *fmt = tests[i].format;
434 const int expect = tests[i].expected;
435 const int n = _snprintf (buffer, bufsiz, fmt);
436 const int valid = n < 0 ? bufsiz : (n == bufsiz ? n : n+1);
438 ok (n == expect, "\"%s\": expected %d, returned %d\n",
439 fmt, expect, n);
440 ok (!memcmp (fmt, buffer, valid),
441 "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer);
445 static void test_fprintf(void)
447 FILE *fp = fopen("fprintf.tst", "wb");
448 char buf[1024];
449 int ret;
451 ret = fprintf(fp, "simple test\n");
452 ok(ret == 12, "ret = %d\n", ret);
453 ret = ftell(fp);
454 ok(ret == 12, "ftell returned %d\n", ret);
456 ret = fprintf(fp, "contains%cnull\n", '\0');
457 ok(ret == 14, "ret = %d\n", ret);
458 ret = ftell(fp);
459 ok(ret == 26, "ftell returned %d\n", ret);
461 ret = fwprintf(fp, L"unicode\n");
462 ok(ret == 8, "ret = %d\n", ret);
463 ret = ftell(fp);
464 ok(ret == 42, "ftell returned %d\n", ret);
466 fclose(fp);
468 fp = fopen("fprintf.tst", "rb");
469 ret = fscanf(fp, "%[^\n] ", buf);
470 ok(ret == 1, "ret = %d\n", ret);
471 ret = ftell(fp);
472 ok(ret == 12, "ftell returned %d\n", ret);
473 ok(!strcmp(buf, "simple test"), "buf = %s\n", buf);
475 fgets(buf, sizeof(buf), fp);
476 ret = ftell(fp);
477 ok(ret == 26, "ret = %d\n", ret);
478 ok(!memcmp(buf, "contains\0null\n", 14), "buf = %s\n", buf);
480 memset(buf, 0, sizeof(buf));
481 fgets(buf, sizeof(buf), fp);
482 ret = ftell(fp);
483 ok(ret == 41, "ret = %d\n", ret);
484 ok(!wcscmp((wchar_t*)buf, L"unicode\n"), "buf = %s\n", wine_dbgstr_w((WCHAR*)buf));
486 fclose(fp);
488 fp = fopen("fprintf.tst", "wt");
490 ret = fprintf(fp, "simple test\n");
491 ok(ret == 12, "ret = %d\n", ret);
492 ret = ftell(fp);
493 ok(ret == 13, "ftell returned %d\n", ret);
495 ret = fprintf(fp, "contains%cnull\n", '\0');
496 ok(ret == 14, "ret = %d\n", ret);
497 ret = ftell(fp);
498 ok(ret == 28, "ftell returned %d\n", ret);
500 ret = fwprintf(fp, L"unicode\n");
501 ok(ret == 8, "ret = %d\n", ret);
502 ret = ftell(fp);
503 ok(ret == 37, "ftell returned %d\n", ret);
505 fclose(fp);
507 fp = fopen("fprintf.tst", "rb");
508 ret = fscanf(fp, "%[^\n] ", buf);
509 ok(ret == 1, "ret = %d\n", ret);
510 ret = ftell(fp);
511 ok(ret == 13, "ftell returned %d\n", ret);
512 ok(!strcmp(buf, "simple test\r"), "buf = %s\n", buf);
514 fgets(buf, sizeof(buf), fp);
515 ret = ftell(fp);
516 ok(ret == 28, "ret = %d\n", ret);
517 ok(!memcmp(buf, "contains\0null\r\n", 15), "buf = %s\n", buf);
519 fgets(buf, sizeof(buf), fp);
520 ret = ftell(fp);
521 ok(ret == 37, "ret = %d\n", ret);
522 ok(!strcmp(buf, "unicode\r\n"), "buf = %s\n", buf);
524 fclose(fp);
525 unlink("fprintf.tst");
528 static void test_fcvt(void)
530 char *str;
531 int dec=100, sign=100;
533 /* Numbers less than 1.0 with different precisions */
534 str = _fcvt(0.0001, 1, &dec, &sign );
535 ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
536 ok( -3 == dec, "dec wrong %d\n", dec);
537 ok( 0 == sign, "sign wrong\n");
539 str = _fcvt(0.0001, -10, &dec, &sign );
540 ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
541 ok( -3 == dec, "dec wrong %d\n", dec);
542 ok( 0 == sign, "sign wrong\n");
544 str = _fcvt(0.0001, 10, &dec, &sign );
545 ok( 0 == strcmp(str,"1000000"), "bad return '%s'\n", str);
546 ok( -3 == dec, "dec wrong %d\n", dec);
547 ok( 0 == sign, "sign wrong\n");
549 /* Basic sign test */
550 str = _fcvt(-111.0001, 5, &dec, &sign );
551 ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
552 ok( 3 == dec, "dec wrong %d\n", dec);
553 ok( 1 == sign, "sign wrong\n");
555 str = _fcvt(111.0001, 5, &dec, &sign );
556 ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
557 ok( 3 == dec, "dec wrong\n");
558 ok( 0 == sign, "sign wrong\n");
560 /* 0.0 with different precisions */
561 str = _fcvt(0.0, 5, &dec, &sign );
562 ok( 0 == strcmp(str,"00000"), "bad return '%s'\n", str);
563 ok( 0 == dec, "dec wrong %d\n", dec);
564 ok( 0 == sign, "sign wrong\n");
566 str = _fcvt(0.0, 0, &dec, &sign );
567 ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
568 ok( 0 == dec, "dec wrong %d\n", dec);
569 ok( 0 == sign, "sign wrong\n");
571 str = _fcvt(0.0, -1, &dec, &sign );
572 ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
573 ok( 0 == dec, "dec wrong %d\n", dec);
574 ok( 0 == sign, "sign wrong\n");
576 /* Numbers > 1.0 with 0 or -ve precision */
577 str = _fcvt(-123.0001, 0, &dec, &sign );
578 ok( 0 == strcmp(str,"123"), "bad return '%s'\n", str);
579 ok( 3 == dec, "dec wrong %d\n", dec);
580 ok( 1 == sign, "sign wrong\n");
582 str = _fcvt(-123.0001, -1, &dec, &sign );
583 ok( 0 == strcmp(str,"12"), "bad return '%s'\n", str);
584 ok( 3 == dec, "dec wrong %d\n", dec);
585 ok( 1 == sign, "sign wrong\n");
587 str = _fcvt(-123.0001, -2, &dec, &sign );
588 ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
589 ok( 3 == dec, "dec wrong %d\n", dec);
590 ok( 1 == sign, "sign wrong\n");
592 str = _fcvt(-123.0001, -3, &dec, &sign );
593 ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
594 ok( 3 == dec, "dec wrong %d\n", dec);
595 ok( 1 == sign, "sign wrong\n");
597 /* Numbers > 1.0, but with rounding at the point of precision */
598 str = _fcvt(99.99, 1, &dec, &sign );
599 ok( 0 == strcmp(str,"1000"), "bad return '%s'\n", str);
600 ok( 3 == dec, "dec wrong %d\n", dec);
601 ok( 0 == sign, "sign wrong\n");
603 /* Numbers < 1.0 where rounding occurs at the point of precision */
604 str = _fcvt(0.00636, 2, &dec, &sign );
605 ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
606 ok( -1 == dec, "dec wrong %d\n", dec);
607 ok( 0 == sign, "sign wrong\n");
609 str = _fcvt(0.00636, 3, &dec, &sign );
610 ok( 0 == strcmp(str,"6"), "bad return '%s'\n", str);
611 ok( -2 == dec, "dec wrong %d\n", dec);
612 ok( 0 == sign, "sign wrong\n");
614 str = _fcvt(0.09999999996, 2, &dec, &sign );
615 ok( 0 == strcmp(str,"10"), "bad return '%s'\n", str);
616 ok( 0 == dec, "dec wrong %d\n", dec);
617 ok( 0 == sign, "sign wrong\n");
619 str = _fcvt(0.6, 0, &dec, &sign );
620 ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
621 ok( 1 == dec, "dec wrong %d\n", dec);
622 ok( 0 == sign, "sign wrong\n");
625 /* Don't test nrdigits < 0, msvcrt on Win9x and NT4 will corrupt memory by
626 * writing outside allocated memory */
627 static struct {
628 double value;
629 int nrdigits;
630 const char *expstr_e;
631 const char *expstr_f;
632 int expdecpt_e;
633 int expdecpt_f;
634 int expsign;
635 } test_cvt_testcases[] = {
636 { 45.0, 2, "45", "4500", 2, 2, 0 },
637 /* Numbers less than 1.0 with different precisions */
638 { 0.0001, 1, "1", "", -3, -3, 0 },
639 { 0.0001, 10,"1000000000", "1000000", -3, -3, 0 },
640 /* Basic sign test */
641 { -111.0001, 5, "11100", "11100010", 3, 3, 1 },
642 { 111.0001, 5, "11100", "11100010", 3, 3, 0 },
643 /* big numbers with low precision */
644 { 3333.3, 2, "33", "333330", 4, 4, 0 },
645 {999999999999.9, 3, "100","999999999999900", 13, 12, 0 },
646 /* 0.0 with different precisions */
647 { 0.0, 5, "00000", "00000", 0, 0, 0 },
648 { 0.0, 0, "", "", 0, 0, 0 },
649 { 0.0, -1, "", "", 0, 0, 0 },
650 /* Numbers > 1.0 with 0 or -ve precision */
651 { -123.0001, 0, "", "123", 3, 3, 1 },
652 { -123.0001, -1, "", "12", 3, 3, 1 },
653 { -123.0001, -2, "", "1", 3, 3, 1 },
654 { -123.0001, -3, "", "", 3, 3, 1 },
655 /* Numbers > 1.0, but with rounding at the point of precision */
656 { 99.99, 1, "1", "1000", 3, 3, 0 },
657 /* Numbers < 1.0 where rounding occurs at the point of precision */
658 { 0.0063, 2, "63", "1", -2, -1, 0 },
659 { 0.0063, 3, "630", "6", -2, -2, 0 },
660 { 0.09999999996, 2, "10", "10", 0, 0, 0 },
661 { 0.6, 1, "6", "6", 0, 0, 0 },
662 { 0.6, 0, "", "1", 1, 1, 0 },
663 { 0.4, 0, "", "", 0, 0, 0 },
664 { 0.49, 0, "", "", 0, 0, 0 },
665 { 0.51, 0, "", "1", 1, 1, 0 },
666 /* ask for ridiculous precision, ruin formatting this table */
667 { 1.0, 30, "100000000000000000000000000000",
668 "1000000000000000000000000000000", 1, 1, 0},
669 { 123456789012345678901.0, 30, "123456789012345680000000000000",
670 "123456789012345680000000000000000000000000000000000", 21, 21, 0},
671 /* end marker */
672 { 0, 0, "END"}
675 static void test_xcvt(void)
677 char *str;
678 int i, decpt, sign, err;
680 for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
681 decpt = sign = 100;
682 str = _ecvt( test_cvt_testcases[i].value,
683 test_cvt_testcases[i].nrdigits,
684 &decpt,
685 &sign);
686 ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15),
687 "_ecvt() bad return, got \n'%s' expected \n'%s'\n", str,
688 test_cvt_testcases[i].expstr_e);
689 ok( decpt == test_cvt_testcases[i].expdecpt_e,
690 "_ecvt() decimal point wrong, got %d expected %d\n", decpt,
691 test_cvt_testcases[i].expdecpt_e);
692 ok( sign == test_cvt_testcases[i].expsign,
693 "_ecvt() sign wrong, got %d expected %d\n", sign,
694 test_cvt_testcases[i].expsign);
696 for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
697 decpt = sign = 100;
698 str = _fcvt( test_cvt_testcases[i].value,
699 test_cvt_testcases[i].nrdigits,
700 &decpt,
701 &sign);
702 ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15),
703 "_fcvt() bad return, got \n'%s' expected \n'%s'\n", str,
704 test_cvt_testcases[i].expstr_f);
705 ok( decpt == test_cvt_testcases[i].expdecpt_f,
706 "_fcvt() decimal point wrong, got %d expected %d\n", decpt,
707 test_cvt_testcases[i].expdecpt_f);
708 ok( sign == test_cvt_testcases[i].expsign,
709 "_fcvt() sign wrong, got %d expected %d\n", sign,
710 test_cvt_testcases[i].expsign);
713 if (p__ecvt_s)
715 str = malloc(1024);
716 for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
717 decpt = sign = 100;
718 err = p__ecvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign);
719 ok(err == 0, "_ecvt_s() failed with error code %d\n", err);
720 ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15),
721 "_ecvt_s() bad return, got \n'%s' expected \n'%s'\n", str,
722 test_cvt_testcases[i].expstr_e);
723 ok( decpt == test_cvt_testcases[i].expdecpt_e,
724 "_ecvt_s() decimal point wrong, got %d expected %d\n", decpt,
725 test_cvt_testcases[i].expdecpt_e);
726 ok( sign == test_cvt_testcases[i].expsign,
727 "_ecvt_s() sign wrong, got %d expected %d\n", sign,
728 test_cvt_testcases[i].expsign);
730 free(str);
732 else
733 win_skip("_ecvt_s not available\n");
735 if (p__fcvt_s)
737 int i;
739 str = malloc(1024);
741 /* invalid arguments */
742 err = p__fcvt_s(NULL, 0, 0.0, 0, &i, &i);
743 ok(err == EINVAL, "got %d, expected EINVAL\n", err);
745 err = p__fcvt_s(str, 0, 0.0, 0, &i, &i);
746 ok(err == EINVAL, "got %d, expected EINVAL\n", err);
748 str[0] = ' ';
749 str[1] = 0;
750 err = p__fcvt_s(str, -1, 0.0, 0, &i, &i);
751 ok(err == 0, "got %d, expected 0\n", err);
752 ok(str[0] == 0, "got %c, expected 0\n", str[0]);
753 ok(str[1] == 0, "got %c, expected 0\n", str[1]);
755 err = p__fcvt_s(str, 1, 0.0, 0, NULL, &i);
756 ok(err == EINVAL, "got %d, expected EINVAL\n", err);
758 err = p__fcvt_s(str, 1, 0.0, 0, &i, NULL);
759 ok(err == EINVAL, "got %d, expected EINVAL\n", err);
761 for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
762 decpt = sign = 100;
763 err = p__fcvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign);
764 ok(err == 0, "_fcvt_s() failed with error code %d\n", err);
765 ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15),
766 "_fcvt_s() bad return, got '%s' expected '%s'. test %d\n", str,
767 test_cvt_testcases[i].expstr_f, i);
768 ok( decpt == test_cvt_testcases[i].expdecpt_f,
769 "_fcvt_s() decimal point wrong, got %d expected %d\n", decpt,
770 test_cvt_testcases[i].expdecpt_f);
771 ok( sign == test_cvt_testcases[i].expsign,
772 "_fcvt_s() sign wrong, got %d expected %d\n", sign,
773 test_cvt_testcases[i].expsign);
775 free(str);
777 else
778 win_skip("_fcvt_s not available\n");
781 static int WINAPIV _vsnwprintf_wrapper(wchar_t *str, size_t len, const wchar_t *format, ...)
783 int ret;
784 __ms_va_list valist;
785 __ms_va_start(valist, format);
786 ret = _vsnwprintf(str, len, format, valist);
787 __ms_va_end(valist);
788 return ret;
791 static void test_vsnwprintf(void)
793 int ret;
794 wchar_t str[32];
795 char buf[32];
797 ret = _vsnwprintf_wrapper( str, ARRAY_SIZE(str), L"%ws%ws%ws", L"one", L"two", L"three" );
798 ok( ret == 11, "got %d expected 11\n", ret );
799 WideCharToMultiByte( CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL );
800 ok( !strcmp(buf, "onetwothree"), "got %s expected 'onetwothree'\n", buf );
802 ret = _vsnwprintf_wrapper( str, 0, L"%ws%ws%ws", L"one", L"two", L"three" );
803 ok( ret == -1, "got %d, expected -1\n", ret );
805 ret = _vsnwprintf_wrapper( NULL, 0, L"%ws%ws%ws", L"one", L"two", L"three" );
806 ok( ret == 11 || broken(ret == -1 /* Win2k */), "got %d, expected 11\n", ret );
809 static int WINAPIV vswprintf_wrapper(wchar_t *str, const wchar_t *format, ...)
811 int ret;
812 __ms_va_list valist;
813 __ms_va_start(valist, format);
814 ret = p_vswprintf(str, format, valist);
815 __ms_va_end(valist);
816 return ret;
819 static int WINAPIV _vswprintf_wrapper(wchar_t *str, const wchar_t *format, ...)
821 int ret;
822 __ms_va_list valist;
823 __ms_va_start(valist, format);
824 ret = p__vswprintf(str, format, valist);
825 __ms_va_end(valist);
826 return ret;
829 static int WINAPIV _vswprintf_l_wrapper(wchar_t *str, const wchar_t *format, void *locale, ...)
831 int ret;
832 __ms_va_list valist;
833 __ms_va_start(valist, locale);
834 ret = p__vswprintf_l(str, format, locale, valist);
835 __ms_va_end(valist);
836 return ret;
839 static int WINAPIV _vswprintf_c_wrapper(wchar_t *str, size_t size, const wchar_t *format, ...)
841 int ret;
842 __ms_va_list valist;
843 __ms_va_start(valist, format);
844 ret = p__vswprintf_c(str, size, format, valist);
845 __ms_va_end(valist);
846 return ret;
849 static int WINAPIV _vswprintf_c_l_wrapper(wchar_t *str, size_t size, const wchar_t *format, void *locale, ...)
851 int ret;
852 __ms_va_list valist;
853 __ms_va_start(valist, locale);
854 ret = p__vswprintf_c_l(str, size, format, locale, valist);
855 __ms_va_end(valist);
856 return ret;
859 static int WINAPIV _vswprintf_p_l_wrapper(wchar_t *str, size_t size, const wchar_t *format, void *locale, ...)
861 int ret;
862 __ms_va_list valist;
863 __ms_va_start(valist, locale);
864 ret = p__vswprintf_p_l(str, size, format, locale, valist);
865 __ms_va_end(valist);
866 return ret;
869 static void test_vswprintf(void)
871 wchar_t buf[20];
872 int ret;
874 if (!p_vswprintf || !p__vswprintf || !p__vswprintf_l ||!p__vswprintf_c
875 || !p__vswprintf_c_l || !p__vswprintf_p_l)
877 win_skip("_vswprintf or vswprintf not available\n");
878 return;
881 ret = vswprintf_wrapper(buf, L"%s %d", L"number", 123);
882 ok(ret == 10, "got %d, expected 10\n", ret);
883 ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf));
885 memset(buf, 0, sizeof(buf));
886 ret = _vswprintf_wrapper(buf, L"%s %d", L"number", 123);
887 ok(ret == 10, "got %d, expected 10\n", ret);
888 ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf));
890 memset(buf, 0, sizeof(buf));
891 ret = _vswprintf_l_wrapper(buf, L"%s %d", NULL, L"number", 123);
892 ok(ret == 10, "got %d, expected 10\n", ret);
893 ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf));
895 memset(buf, 0, sizeof(buf));
896 ret = _vswprintf_c_wrapper(buf, 20, L"%s %d", L"number", 123);
897 ok(ret == 10, "got %d, expected 10\n", ret);
898 ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf));
900 memset(buf, 'x', sizeof(buf));
901 ret = _vswprintf_c_wrapper(buf, 10, L"%s %d", L"number", 123);
902 ok(ret == -1, "got %d, expected -1\n", ret);
903 ok(!wcscmp(buf, L"number 12"), "buf = %s\n", wine_dbgstr_w(buf));
905 memset(buf, 0, sizeof(buf));
906 ret = _vswprintf_c_l_wrapper(buf, 20, L"%s %d", NULL, L"number", 123);
907 ok(ret == 10, "got %d, expected 10\n", ret);
908 ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf));
910 memset(buf, 0, sizeof(buf));
911 ret = _vswprintf_p_l_wrapper(buf, 20, L"%s %d", NULL, L"number", 123);
912 ok(ret == 10, "got %d, expected 10\n", ret);
913 ok(!wcscmp(buf, L"number 123"), "buf = %s\n", wine_dbgstr_w(buf));
916 static int WINAPIV _vscprintf_wrapper(const char *format, ...)
918 int ret;
919 __ms_va_list valist;
920 __ms_va_start(valist, format);
921 ret = p__vscprintf(format, valist);
922 __ms_va_end(valist);
923 return ret;
926 static void test_vscprintf(void)
928 int ret;
930 if (!p__vscprintf)
932 win_skip("_vscprintf not available\n");
933 return;
936 ret = _vscprintf_wrapper( "%s %d", "number", 1 );
937 ok( ret == 8, "got %d expected 8\n", ret );
940 static int WINAPIV _vscwprintf_wrapper(const wchar_t *format, ...)
942 int ret;
943 __ms_va_list valist;
944 __ms_va_start(valist, format);
945 ret = p__vscwprintf(format, valist);
946 __ms_va_end(valist);
947 return ret;
950 static void test_vscwprintf(void)
952 int ret;
954 if (!p__vscwprintf)
956 win_skip("_vscwprintf not available\n");
957 return;
960 ret = _vscwprintf_wrapper(L"%s %d", L"number", 1 );
961 ok( ret == 8, "got %d expected 8\n", ret );
964 static int WINAPIV _vsnwprintf_s_wrapper(wchar_t *str, size_t sizeOfBuffer,
965 size_t count, const wchar_t *format, ...)
967 int ret;
968 __ms_va_list valist;
969 __ms_va_start(valist, format);
970 ret = p__vsnwprintf_s(str, sizeOfBuffer, count, format, valist);
971 __ms_va_end(valist);
972 return ret;
975 static void test_vsnwprintf_s(void)
977 wchar_t buffer[14] = { 0 };
978 int ret;
980 if (!p__vsnwprintf_s)
982 win_skip("_vsnwprintf_s not available\n");
983 return;
986 /* Enough room. */
987 ret = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, L"AB%uC", 123);
988 ok( ret == 6, "length wrong, expect=6, got=%d\n", ret);
989 ok( !wcscmp(L"AB123C", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
991 ret = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, L"AB%uC", 123);
992 ok( ret == 6, "length wrong, expect=6, got=%d\n", ret);
993 ok( !wcscmp(L"AB123C", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
995 ret = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, L"AB%uC", 123);
996 ok( ret == 6, "length wrong, expect=6, got=%d\n", ret);
997 ok( !wcscmp(L"AB123C", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
999 /* Not enough room. */
1000 ret = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, L"AB%uC", 123);
1001 ok( ret == -1, "length wrong, expect=-1, got=%d\n", ret);
1002 ok( !wcscmp(L"AB123", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
1004 ret = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, L"AB%uC", 123);
1005 ok( ret == -1, "length wrong, expect=-1, got=%d\n", ret);
1006 ok( !wcscmp(L"A", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
1008 ret = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, L"AB%uC", 123);
1009 ok( ret == -1, "length wrong, expect=-1, got=%d\n", ret);
1010 ok( !wcscmp(L"", buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
1013 static int WINAPIV _vsprintf_p_wrapper(char *str, size_t sizeOfBuffer,
1014 const char *format, ...)
1016 int ret;
1017 __ms_va_list valist;
1018 __ms_va_start(valist, format);
1019 ret = p__vsprintf_p(str, sizeOfBuffer, format, valist);
1020 __ms_va_end(valist);
1021 return ret;
1024 static void test_vsprintf_p(void)
1026 char buf[1024];
1027 int ret;
1029 if(!p__vsprintf_p) {
1030 win_skip("vsprintf_p not available\n");
1031 return;
1034 ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%s %d", "test", 1234);
1035 ok(ret == 9, "ret = %d\n", ret);
1036 ok(!memcmp(buf, "test 1234", 10), "buf = %s\n", buf);
1038 ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%1$d", 1234, "additional param");
1039 ok(ret == 4, "ret = %d\n", ret);
1040 ok(!memcmp(buf, "1234", 5), "buf = %s\n", buf);
1042 ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%2$s %1$d", 1234, "test");
1043 ok(ret == 9, "ret = %d\n", ret);
1044 ok(!memcmp(buf, "test 1234", 10), "buf = %s\n", buf);
1046 ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%2$*3$s %2$.*1$s", 2, "test", 3);
1047 ok(ret == 7, "ret = %d\n", ret);
1048 ok(!memcmp(buf, "test te", 8), "buf = %s\n", buf);
1050 /* Following test invokes invalid parameter handler */
1051 /* ret = _vsprintf_p_wrapper(buf, sizeof(buf), "%d %1$d", 1234); */
1054 static void test__get_output_format(void)
1056 unsigned int ret;
1057 char buf[64];
1058 int c;
1060 if (!p__get_output_format || !p__set_output_format)
1062 win_skip("_get_output_format or _set_output_format is not available\n");
1063 return;
1066 ret = p__get_output_format();
1067 ok(ret == 0, "got %d\n", ret);
1069 c = p_sprintf(buf, "%E", 1.23);
1070 ok(c == 13, "c = %d\n", c);
1071 ok(!strcmp(buf, "1.230000E+000"), "buf = %s\n", buf);
1073 ret = p__set_output_format(_TWO_DIGIT_EXPONENT);
1074 ok(ret == 0, "got %d\n", ret);
1076 c = p_sprintf(buf, "%E", 1.23);
1077 ok(c == 12, "c = %d\n", c);
1078 ok(!strcmp(buf, "1.230000E+00"), "buf = %s\n", buf);
1080 ret = p__get_output_format();
1081 ok(ret == _TWO_DIGIT_EXPONENT, "got %d\n", ret);
1083 ret = p__set_output_format(_TWO_DIGIT_EXPONENT);
1084 ok(ret == _TWO_DIGIT_EXPONENT, "got %d\n", ret);
1087 START_TEST(printf)
1089 init();
1091 test_sprintf();
1092 test_swprintf();
1093 test_snprintf();
1094 test_fprintf();
1095 test_fcvt();
1096 test_xcvt();
1097 test_vsnwprintf();
1098 test_vscprintf();
1099 test_vscwprintf();
1100 test_vswprintf();
1101 test_vsnwprintf_s();
1102 test_vsprintf_p();
1103 test__get_output_format();