msvcrt/tests: Move function pointer initialization code in printf.c into separate...
[wine] / dlls / msvcrt / tests / printf.c
1 /*
2  * Conformance tests for *printf functions.
3  *
4  * Copyright 2002 Uwe Bonnes
5  * Copyright 2004 Aneurin Price
6  * Copyright 2005 Mike McCormack
7  *
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.
12  *
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.
17  *
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
21  */
22
23 /* With Visual Studio >= 2005,  swprintf() takes an extra parameter unless
24  * the following macro is defined.
25  */
26 #define _CRT_NON_CONFORMING_SWPRINTFS
27  
28 #include <stdio.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winnls.h"
33
34 #include "wine/test.h"
35
36 static int (__cdecl *p__vscprintf)(const char *format, __ms_va_list valist);
37 static int (__cdecl *p__vscwprintf)(const wchar_t *format, __ms_va_list valist);
38 static int (__cdecl *p__vsnwprintf_s)(wchar_t *str, size_t sizeOfBuffer,
39                                       size_t count, const wchar_t *format,
40                                       __ms_va_list valist);
41
42 static void init( void )
43 {
44     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
45
46     p__vscprintf = (void *)GetProcAddress(hmod, "_vscprintf");
47     p__vscwprintf = (void *)GetProcAddress(hmod, "_vscwprintf");
48     p__vsnwprintf_s = (void *)GetProcAddress(hmod, "_vsnwprintf_s");
49 }
50
51 static void test_sprintf( void )
52 {
53     char buffer[100];
54     const char *format;
55     double pnumber=789456123;
56     int x, r;
57     WCHAR wide[] = { 'w','i','d','e',0};
58
59     format = "%+#23.15e";
60     r = sprintf(buffer,format,pnumber);
61     ok(!strcmp(buffer,"+7.894561230000000e+008"),"+#23.15e failed: '%s'\n", buffer);
62     ok( r==23, "return count wrong\n");
63
64     format = "%-#23.15e";
65     r = sprintf(buffer,format,pnumber);
66     ok(!strcmp(buffer,"7.894561230000000e+008 "),"-#23.15e failed: '%s'\n", buffer);
67     ok( r==23, "return count wrong\n");
68
69     format = "%#23.15e";
70     r = sprintf(buffer,format,pnumber);
71     ok(!strcmp(buffer," 7.894561230000000e+008"),"#23.15e failed: '%s'\n", buffer);
72     ok( r==23, "return count wrong\n");
73
74     format = "%#1.1g";
75     r = sprintf(buffer,format,pnumber);
76     ok(!strcmp(buffer,"8.e+008"),"#1.1g failed: '%s'\n", buffer);
77     ok( r==7, "return count wrong\n");
78
79     format = "%I64d";
80     r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
81     ok(!strcmp(buffer,"-8589934591"),"Problem with long long\n");
82     ok( r==11, "return count wrong\n");
83
84     format = "%+8I64d";
85     r = sprintf(buffer,format,(LONGLONG)100);
86     ok(!strcmp(buffer,"    +100") && r==8,"+8I64d failed: '%s'\n", buffer);
87
88     format = "%+.8I64d";
89     r = sprintf(buffer,format,(LONGLONG)100);
90     ok(!strcmp(buffer,"+00000100") && r==9,"+.8I64d failed: '%s'\n", buffer);
91
92     format = "%+10.8I64d";
93     r = sprintf(buffer,format,(LONGLONG)100);
94     ok(!strcmp(buffer," +00000100") && r==10,"+10.8I64d failed: '%s'\n", buffer);
95     format = "%_1I64d";
96     r = sprintf(buffer,format,(LONGLONG)100);
97     ok(!strcmp(buffer,"_1I64d") && r==6,"_1I64d failed\n");
98
99     format = "%-1.5I64d";
100     r = sprintf(buffer,format,(LONGLONG)-100);
101     ok(!strcmp(buffer,"-00100") && r==6,"-1.5I64d failed: '%s'\n", buffer);
102
103     format = "%5I64d";
104     r = sprintf(buffer,format,(LONGLONG)100);
105     ok(!strcmp(buffer,"  100") && r==5,"5I64d failed: '%s'\n", buffer);
106
107     format = "%5I64d";
108     r = sprintf(buffer,format,(LONGLONG)-100);
109     ok(!strcmp(buffer," -100") && r==5,"5I64d failed: '%s'\n", buffer);
110
111     format = "%-5I64d";
112     r = sprintf(buffer,format,(LONGLONG)100);
113     ok(!strcmp(buffer,"100  ") && r==5,"-5I64d failed: '%s'\n", buffer);
114
115     format = "%-5I64d";
116     r = sprintf(buffer,format,(LONGLONG)-100);
117     ok(!strcmp(buffer,"-100 ") && r==5,"-5I64d failed: '%s'\n", buffer);
118
119     format = "%-.5I64d";
120     r = sprintf(buffer,format,(LONGLONG)100);
121     ok(!strcmp(buffer,"00100") && r==5,"-.5I64d failed: '%s'\n", buffer);
122
123     format = "%-.5I64d";
124     r = sprintf(buffer,format,(LONGLONG)-100);
125     ok(!strcmp(buffer,"-00100") && r==6,"-.5I64d failed: '%s'\n", buffer);
126
127     format = "%-8.5I64d";
128     r = sprintf(buffer,format,(LONGLONG)100);
129     ok(!strcmp(buffer,"00100   ") && r==8,"-8.5I64d failed: '%s'\n", buffer);
130
131     format = "%-8.5I64d";
132     r = sprintf(buffer,format,(LONGLONG)-100);
133     ok(!strcmp(buffer,"-00100  ") && r==8,"-8.5I64d failed: '%s'\n", buffer);
134
135     format = "%05I64d";
136     r = sprintf(buffer,format,(LONGLONG)100);
137     ok(!strcmp(buffer,"00100") && r==5,"05I64d failed: '%s'\n", buffer);
138
139     format = "%05I64d";
140     r = sprintf(buffer,format,(LONGLONG)-100);
141     ok(!strcmp(buffer,"-0100") && r==5,"05I64d failed: '%s'\n", buffer);
142
143     format = "% I64d";
144     r = sprintf(buffer,format,(LONGLONG)100);
145     ok(!strcmp(buffer," 100") && r==4,"' I64d' failed: '%s'\n", buffer);
146
147     format = "% I64d";
148     r = sprintf(buffer,format,(LONGLONG)-100);
149     ok(!strcmp(buffer,"-100") && r==4,"' I64d' failed: '%s'\n", buffer);
150
151     format = "% 5I64d";
152     r = sprintf(buffer,format,(LONGLONG)100);
153     ok(!strcmp(buffer,"  100") && r==5,"' 5I64d' failed: '%s'\n", buffer);
154
155     format = "% 5I64d";
156     r = sprintf(buffer,format,(LONGLONG)-100);
157     ok(!strcmp(buffer," -100") && r==5,"' 5I64d' failed: '%s'\n", buffer);
158
159     format = "% .5I64d";
160     r = sprintf(buffer,format,(LONGLONG)100);
161     ok(!strcmp(buffer," 00100") && r==6,"' .5I64d' failed: '%s'\n", buffer);
162
163     format = "% .5I64d";
164     r = sprintf(buffer,format,(LONGLONG)-100);
165     ok(!strcmp(buffer,"-00100") && r==6,"' .5I64d' failed: '%s'\n", buffer);
166
167     format = "% 8.5I64d";
168     r = sprintf(buffer,format,(LONGLONG)100);
169     ok(!strcmp(buffer,"   00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer);
170
171     format = "% 8.5I64d";
172     r = sprintf(buffer,format,(LONGLONG)-100);
173     ok(!strcmp(buffer,"  -00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer);
174
175     format = "%.0I64d";
176     r = sprintf(buffer,format,(LONGLONG)0);
177     ok(r==0,".0I64d failed: '%s'\n", buffer);
178
179     format = "%#+21.18I64x";
180     r = sprintf(buffer,format,(LONGLONG)-100);
181     ok(!strcmp(buffer," 0x00ffffffffffffff9c") && r==21,"#+21.18I64x failed: '%s'\n", buffer);
182
183     format = "%#.25I64o";
184     r = sprintf(buffer,format,(LONGLONG)-100);
185     ok(!strcmp(buffer,"0001777777777777777777634") && r==25,"#.25I64o failed: '%s'\n", buffer);
186
187     format = "%#+24.20I64o";
188     r = sprintf(buffer,format,(LONGLONG)-100);
189     ok(!strcmp(buffer," 01777777777777777777634") && r==24,"#+24.20I64o failed: '%s'\n", buffer);
190
191     format = "%#+18.21I64X";
192     r = sprintf(buffer,format,(LONGLONG)-100);
193     ok(!strcmp(buffer,"0X00000FFFFFFFFFFFFFF9C") && r==23,"#+18.21I64X failed: '%s '\n", buffer);
194
195     format = "%#+20.24I64o";
196     r = sprintf(buffer,format,(LONGLONG)-100);
197     ok(!strcmp(buffer,"001777777777777777777634") && r==24,"#+20.24I64o failed: '%s'\n", buffer);
198
199     format = "%#+25.22I64u";
200     r = sprintf(buffer,format,(LONGLONG)-1);
201     ok(!strcmp(buffer,"   0018446744073709551615") && r==25,"#+25.22I64u conversion failed: '%s'\n", buffer);
202
203     format = "%#+25.22I64u";
204     r = sprintf(buffer,format,(LONGLONG)-1);
205     ok(!strcmp(buffer,"   0018446744073709551615") && r==25,"#+25.22I64u failed: '%s'\n", buffer);
206
207     format = "%#+30.25I64u";
208     r = sprintf(buffer,format,(LONGLONG)-1);
209     ok(!strcmp(buffer,"     0000018446744073709551615") && r==30,"#+30.25I64u failed: '%s'\n", buffer);
210
211     format = "%+#25.22I64d";
212     r = sprintf(buffer,format,(LONGLONG)-1);
213     ok(!strcmp(buffer,"  -0000000000000000000001") && r==25,"+#25.22I64d failed: '%s'\n", buffer);
214
215     format = "%#-8.5I64o";
216     r = sprintf(buffer,format,(LONGLONG)100);
217     ok(!strcmp(buffer,"00144   ") && r==8,"-8.5I64o failed: '%s'\n", buffer);
218
219     format = "%#-+ 08.5I64d";
220     r = sprintf(buffer,format,(LONGLONG)100);
221     ok(!strcmp(buffer,"+00100  ") && r==8,"'#-+ 08.5I64d failed: '%s'\n", buffer);
222
223     format = "%#-+ 08.5I64d";
224     r = sprintf(buffer,format,(LONGLONG)100);
225     ok(!strcmp(buffer,"+00100  ") && r==8,"#-+ 08.5I64d failed: '%s'\n", buffer);
226
227     format = "%.80I64d";
228     r = sprintf(buffer,format,(LONGLONG)1);
229     ok(r==80,"%s format failed\n", format);
230
231     format = "% .80I64d";
232     r = sprintf(buffer,format,(LONGLONG)1);
233     ok(r==81,"%s format failed\n", format);
234
235     format = "% .80d";
236     r = sprintf(buffer,format,1);
237     ok(r==81,"%s format failed\n", format);
238
239     format = "%lld";
240     r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
241     ok( r == 1 || r == 11, "return count wrong %d\n", r);
242     if (r == 11)  /* %ll works on Vista */
243         ok(!strcmp(buffer, "-8589934591"), "Problem with \"ll\" interpretation '%s'\n", buffer);
244     else
245         ok(!strcmp(buffer, "1"), "Problem with \"ll\" interpretation '%s'\n", buffer);
246
247     format = "%I";
248     r = sprintf(buffer,format,1);
249     ok(!strcmp(buffer, "I"), "Problem with \"I\" interpretation\n");
250     ok( r==1, "return count wrong\n");
251
252     format = "%I0d";
253     r = sprintf(buffer,format,1);
254     ok(!strcmp(buffer,"I0d"),"I0d failed\n");
255     ok( r==3, "return count wrong\n");
256
257     format = "%I32d";
258     r = sprintf(buffer,format,1);
259     if (r == 1)
260     {
261         ok(!strcmp(buffer,"1"),"I32d failed, got '%s'\n",buffer);
262     }
263     else
264     {
265         /* Older versions don't grok I32 format */
266         ok(r == 4 && !strcmp(buffer,"I32d"),"I32d failed, got '%s',%d\n",buffer,r);
267     }
268
269     format = "%I64D";
270     r = sprintf(buffer,format,(LONGLONG)-1);
271     ok(!strcmp(buffer,"D"),"I64D failed: %s\n",buffer);
272     ok( r==1, "return count wrong\n");
273
274     format = "% d";
275     r = sprintf(buffer,format,1);
276     ok(!strcmp(buffer, " 1"),"Problem with sign place-holder: '%s'\n",buffer);
277     ok( r==2, "return count wrong\n");
278
279     format = "%+ d";
280     r = sprintf(buffer,format,1);
281     ok(!strcmp(buffer, "+1"),"Problem with sign flags: '%s'\n",buffer);
282     ok( r==2, "return count wrong\n");
283
284     format = "%S";
285     r = sprintf(buffer,format,wide);
286     ok(!strcmp(buffer,"wide"),"Problem with wide string format\n");
287     ok( r==4, "return count wrong\n");
288
289     format = "%04c";
290     r = sprintf(buffer,format,'1');
291     ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer);
292     ok( r==4, "return count wrong\n");
293
294     format = "%-04c";
295     r = sprintf(buffer,format,'1');
296     ok(!strcmp(buffer,"1   "),"Character zero-padded and/or not left-adjusted \"%s\"\n",buffer);
297     ok( r==4, "return count wrong\n");
298
299     if (sizeof(void *) == 8)
300     {
301         format = "%p";
302         r = sprintf(buffer,format,(void *)57);
303         ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
304         ok( r==16, "return count wrong\n");
305
306         format = "%#020p";
307         r = sprintf(buffer,format,(void *)57);
308         ok(!strcmp(buffer,"  0X0000000000000039"),"Pointer formatted incorrectly\n");
309         ok( r==20, "return count wrong\n");
310
311         format = "%Fp";
312         r = sprintf(buffer,format,(void *)57);
313         ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
314         ok( r==16, "return count wrong\n");
315
316         format = "%#-020p";
317         r = sprintf(buffer,format,(void *)57);
318         ok(!strcmp(buffer,"0X0000000000000039  "),"Pointer formatted incorrectly\n");
319         ok( r==20, "return count wrong\n");
320     }
321     else
322     {
323         format = "%p";
324         r = sprintf(buffer,format,(void *)57);
325         ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
326         ok( r==8, "return count wrong\n");
327
328         format = "%#012p";
329         r = sprintf(buffer,format,(void *)57);
330         ok(!strcmp(buffer,"  0X00000039"),"Pointer formatted incorrectly\n");
331         ok( r==12, "return count wrong\n");
332
333         format = "%Fp";
334         r = sprintf(buffer,format,(void *)57);
335         ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
336         ok( r==8, "return count wrong\n");
337
338         format = "%#-012p";
339         r = sprintf(buffer,format,(void *)57);
340         ok(!strcmp(buffer,"0X00000039  "),"Pointer formatted incorrectly\n");
341         ok( r==12, "return count wrong\n");
342     }
343
344     format = "%04s";
345     r = sprintf(buffer,format,"foo");
346     ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer);
347     ok( r==4, "return count wrong\n");
348
349     format = "%.1s";
350     r = sprintf(buffer,format,"foo");
351     ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer);
352     ok( r==1, "return count wrong\n");
353
354     format = "%.*s";
355     r = sprintf(buffer,format,1,"foo");
356     ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer);
357     ok( r==1, "return count wrong\n");
358
359     format = "%*s";
360     r = sprintf(buffer,format,-5,"foo");
361     ok(!strcmp(buffer,"foo  "),"Negative field width ignored \"%s\"\n",buffer);
362     ok( r==5, "return count wrong\n");
363
364     format = "hello";
365     r = sprintf(buffer, format);
366     ok(!strcmp(buffer,"hello"), "failed\n");
367     ok( r==5, "return count wrong\n");
368
369     format = "%ws";
370     r = sprintf(buffer, format, wide);
371     ok(!strcmp(buffer,"wide"), "failed\n");
372     ok( r==4, "return count wrong\n");
373
374     format = "%-10ws";
375     r = sprintf(buffer, format, wide );
376     ok(!strcmp(buffer,"wide      "), "failed\n");
377     ok( r==10, "return count wrong\n");
378
379     format = "%10ws";
380     r = sprintf(buffer, format, wide );
381     ok(!strcmp(buffer,"      wide"), "failed\n");
382     ok( r==10, "return count wrong\n");
383
384     format = "%#+ -03whlls";
385     r = sprintf(buffer, format, wide );
386     ok(!strcmp(buffer,"wide"), "failed\n");
387     ok( r==4, "return count wrong\n");
388
389     format = "%w0s";
390     r = sprintf(buffer, format, wide );
391     ok(!strcmp(buffer,"0s"), "failed\n");
392     ok( r==2, "return count wrong\n");
393
394     format = "%w-s";
395     r = sprintf(buffer, format, wide );
396     ok(!strcmp(buffer,"-s"), "failed\n");
397     ok( r==2, "return count wrong\n");
398
399     format = "%ls";
400     r = sprintf(buffer, format, wide );
401     ok(!strcmp(buffer,"wide"), "failed\n");
402     ok( r==4, "return count wrong\n");
403
404     format = "%Ls";
405     r = sprintf(buffer, format, "not wide" );
406     ok(!strcmp(buffer,"not wide"), "failed\n");
407     ok( r==8, "return count wrong\n");
408
409     format = "%b";
410     r = sprintf(buffer, format);
411     ok(!strcmp(buffer,"b"), "failed\n");
412     ok( r==1, "return count wrong\n");
413
414     format = "%3c";
415     r = sprintf(buffer, format,'a');
416     ok(!strcmp(buffer,"  a"), "failed\n");
417     ok( r==3, "return count wrong\n");
418
419     format = "%3d";
420     r = sprintf(buffer, format,1234);
421     ok(!strcmp(buffer,"1234"), "failed\n");
422     ok( r==4, "return count wrong\n");
423
424     format = "%3h";
425     r = sprintf(buffer, format);
426     ok(!strcmp(buffer,""), "failed\n");
427     ok( r==0, "return count wrong\n");
428
429     format = "%j%k%m%q%r%t%v%y%z";
430     r = sprintf(buffer, format);
431     ok(!strcmp(buffer,"jkmqrtvyz"), "failed\n");
432     ok( r==9, "return count wrong\n");
433
434     format = "asdf%n";
435     x = 0;
436     r = sprintf(buffer, format, &x );
437     if (r == -1)
438     {
439         /* %n format is disabled by default on vista */
440         /* FIXME: should test with _set_printf_count_output */
441         ok(x == 0, "should not write to x: %d\n", x);
442     }
443     else
444     {
445         ok(x == 4, "should write to x: %d\n", x);
446         ok(!strcmp(buffer,"asdf"), "failed\n");
447         ok( r==4, "return count wrong: %d\n", r);
448     }
449
450     format = "%-1d";
451     r = sprintf(buffer, format,2);
452     ok(!strcmp(buffer,"2"), "failed\n");
453     ok( r==1, "return count wrong\n");
454
455     format = "%2.4f";
456     r = sprintf(buffer, format,8.6);
457     ok(!strcmp(buffer,"8.6000"), "failed\n");
458     ok( r==6, "return count wrong\n");
459
460     format = "%0f";
461     r = sprintf(buffer, format,0.6);
462     ok(!strcmp(buffer,"0.600000"), "failed\n");
463     ok( r==8, "return count wrong\n");
464
465     format = "%.0f";
466     r = sprintf(buffer, format,0.6);
467     ok(!strcmp(buffer,"1"), "failed\n");
468     ok( r==1, "return count wrong\n");
469
470     format = "%2.4e";
471     r = sprintf(buffer, format,8.6);
472     ok(!strcmp(buffer,"8.6000e+000"), "failed\n");
473     ok( r==11, "return count wrong\n");
474
475     format = "%2.4g";
476     r = sprintf(buffer, format,8.6);
477     ok(!strcmp(buffer,"8.6"), "failed\n");
478     ok( r==3, "return count wrong\n");
479
480     format = "%-i";
481     r = sprintf(buffer, format,-1);
482     ok(!strcmp(buffer,"-1"), "failed\n");
483     ok( r==2, "return count wrong\n");
484
485     format = "%-i";
486     r = sprintf(buffer, format,1);
487     ok(!strcmp(buffer,"1"), "failed\n");
488     ok( r==1, "return count wrong\n");
489
490     format = "%+i";
491     r = sprintf(buffer, format,1);
492     ok(!strcmp(buffer,"+1"), "failed\n");
493     ok( r==2, "return count wrong\n");
494
495     format = "%o";
496     r = sprintf(buffer, format,10);
497     ok(!strcmp(buffer,"12"), "failed\n");
498     ok( r==2, "return count wrong\n");
499
500     format = "%p";
501     r = sprintf(buffer, format,0);
502     if (sizeof(void *) == 8)
503     {
504         ok(!strcmp(buffer,"0000000000000000"), "failed\n");
505         ok( r==16, "return count wrong\n");
506     }
507     else
508     {
509         ok(!strcmp(buffer,"00000000"), "failed\n");
510         ok( r==8, "return count wrong\n");
511     }
512
513     format = "%s";
514     r = sprintf(buffer, format,0);
515     ok(!strcmp(buffer,"(null)"), "failed\n");
516     ok( r==6, "return count wrong\n");
517
518     format = "%s";
519     r = sprintf(buffer, format,"%%%%");
520     ok(!strcmp(buffer,"%%%%"), "failed\n");
521     ok( r==4, "return count wrong\n");
522
523     format = "%u";
524     r = sprintf(buffer, format,-1);
525     ok(!strcmp(buffer,"4294967295"), "failed\n");
526     ok( r==10, "return count wrong\n");
527
528     format = "%w";
529     r = sprintf(buffer, format,-1);
530     ok(!strcmp(buffer,""), "failed\n");
531     ok( r==0, "return count wrong\n");
532
533     format = "%h";
534     r = sprintf(buffer, format,-1);
535     ok(!strcmp(buffer,""), "failed\n");
536     ok( r==0, "return count wrong\n");
537
538     format = "%z";
539     r = sprintf(buffer, format,-1);
540     ok(!strcmp(buffer,"z"), "failed\n");
541     ok( r==1, "return count wrong\n");
542
543     format = "%j";
544     r = sprintf(buffer, format,-1);
545     ok(!strcmp(buffer,"j"), "failed\n");
546     ok( r==1, "return count wrong\n");
547
548     format = "%F";
549     r = sprintf(buffer, format,-1);
550     ok(!strcmp(buffer,""), "failed\n");
551     ok( r==0, "return count wrong\n");
552
553     format = "%H";
554     r = sprintf(buffer, format,-1);
555     ok(!strcmp(buffer,"H"), "failed\n");
556     ok( r==1, "return count wrong\n");
557
558     format = "x%cx";
559     r = sprintf(buffer, format, 0x100+'X');
560     ok(!strcmp(buffer,"xXx"), "failed\n");
561     ok( r==3, "return count wrong\n");
562
563     format = "%%0";
564     r = sprintf(buffer, format);
565     ok(!strcmp(buffer,"%0"), "failed: \"%s\"\n", buffer);
566     ok( r==2, "return count wrong\n");
567 }
568
569 static void test_swprintf( void )
570 {
571     wchar_t buffer[100];
572     const wchar_t I64d[] = {'%','I','6','4','d',0};
573     double pnumber=789456123;
574     const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0};
575     const wchar_t e008[] = {'e','+','0','0','8',0};
576     const wchar_t string_w[] = {'s','t','r','i','n','g',0};
577     const char string[] = "string";
578     const wchar_t S[]={'%','S',0};
579     const wchar_t hs[] = {'%', 'h', 's', 0};
580
581     swprintf(buffer,TwentyThreePoint15e,pnumber);
582     ok(wcsstr(buffer,e008) != 0,"Sprintf different\n");
583     swprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff);
584       ok(wcslen(buffer) == 11,"Problem with long long\n");
585     swprintf(buffer,S,string);
586       ok(wcslen(buffer) == 6,"Problem with \"%%S\" interpretation\n");
587    swprintf(buffer, hs, string);
588    ok( wcscmp(string_w,buffer) == 0, "swprintf failed with %%hs\n");
589 }
590
591 static void test_snprintf (void)
592 {
593     struct snprintf_test {
594         const char *format;
595         int expected;
596     };
597     /* Pre-2.1 libc behaviour, not C99 compliant. */
598     const struct snprintf_test tests[] = {{"short", 5},
599                                           {"justfit", 7},
600                                           {"justfits", 8},
601                                           {"muchlonger", -1}};
602     char buffer[8];
603     const int bufsiz = sizeof buffer;
604     unsigned int i;
605
606     for (i = 0; i < sizeof tests / sizeof tests[0]; i++) {
607         const char *fmt  = tests[i].format;
608         const int expect = tests[i].expected;
609         const int n      = _snprintf (buffer, bufsiz, fmt);
610         const int valid  = n < 0 ? bufsiz : (n == bufsiz ? n : n+1);
611
612         ok (n == expect, "\"%s\": expected %d, returned %d\n",
613             fmt, expect, n);
614         ok (!memcmp (fmt, buffer, valid),
615             "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer);
616     };
617 }
618
619 static void test_fcvt(void)
620 {
621     char *str;
622     int dec=100, sign=100;
623     
624     /* Numbers less than 1.0 with different precisions */
625     str = _fcvt(0.0001, 1, &dec, &sign );
626     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
627     ok( -3 == dec, "dec wrong %d\n", dec);
628     ok( 0 == sign, "sign wrong\n");
629
630     str = _fcvt(0.0001, -10, &dec, &sign );
631     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
632     ok( -3 == dec, "dec wrong %d\n", dec);
633     ok( 0 == sign, "sign wrong\n");
634
635     str = _fcvt(0.0001, 10, &dec, &sign );
636     ok( 0 == strcmp(str,"1000000"), "bad return '%s'\n", str);
637     ok( -3 == dec, "dec wrong %d\n", dec);
638     ok( 0 == sign, "sign wrong\n");
639
640     /* Basic sign test */
641     str = _fcvt(-111.0001, 5, &dec, &sign );
642     ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
643     ok( 3 == dec, "dec wrong %d\n", dec);
644     ok( 1 == sign, "sign wrong\n");
645
646     str = _fcvt(111.0001, 5, &dec, &sign );
647     ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
648     ok( 3 == dec, "dec wrong\n");
649     ok( 0 == sign, "sign wrong\n");
650
651     /* 0.0 with different precisions */
652     str = _fcvt(0.0, 5, &dec, &sign );
653     ok( 0 == strcmp(str,"00000"), "bad return '%s'\n", str);
654     ok( 0 == dec, "dec wrong %d\n", dec);
655     ok( 0 == sign, "sign wrong\n");
656
657     str = _fcvt(0.0, 0, &dec, &sign );
658     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
659     ok( 0 == dec, "dec wrong %d\n", dec);
660     ok( 0 == sign, "sign wrong\n");
661
662     str = _fcvt(0.0, -1, &dec, &sign );
663     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
664     ok( 0 == dec, "dec wrong %d\n", dec);
665     ok( 0 == sign, "sign wrong\n");
666
667     /* Numbers > 1.0 with 0 or -ve precision */
668     str = _fcvt(-123.0001, 0, &dec, &sign );
669     ok( 0 == strcmp(str,"123"), "bad return '%s'\n", str);
670     ok( 3 == dec, "dec wrong %d\n", dec);
671     ok( 1 == sign, "sign wrong\n");
672
673     str = _fcvt(-123.0001, -1, &dec, &sign );
674     ok( 0 == strcmp(str,"12"), "bad return '%s'\n", str);
675     ok( 3 == dec, "dec wrong %d\n", dec);
676     ok( 1 == sign, "sign wrong\n");
677
678     str = _fcvt(-123.0001, -2, &dec, &sign );
679     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
680     ok( 3 == dec, "dec wrong %d\n", dec);
681     ok( 1 == sign, "sign wrong\n");
682
683     str = _fcvt(-123.0001, -3, &dec, &sign );
684     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
685     ok( 3 == dec, "dec wrong %d\n", dec);
686     ok( 1 == sign, "sign wrong\n");
687
688     /* Numbers > 1.0, but with rounding at the point of precision */
689     str = _fcvt(99.99, 1, &dec, &sign );
690     ok( 0 == strcmp(str,"1000"), "bad return '%s'\n", str);
691     ok( 3 == dec, "dec wrong %d\n", dec);
692     ok( 0 == sign, "sign wrong\n");
693
694     /* Numbers < 1.0 where rounding occurs at the point of precision */
695     str = _fcvt(0.00636, 2, &dec, &sign );
696     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
697     ok( -1 == dec, "dec wrong %d\n", dec);
698     ok( 0 == sign, "sign wrong\n");
699
700     str = _fcvt(0.00636, 3, &dec, &sign );
701     ok( 0 == strcmp(str,"6"), "bad return '%s'\n", str);
702     ok( -2 == dec, "dec wrong %d\n", dec);
703     ok( 0 == sign, "sign wrong\n");
704
705     str = _fcvt(0.09999999996, 2, &dec, &sign );
706     ok( 0 == strcmp(str,"10"), "bad return '%s'\n", str);
707     ok( 0 == dec, "dec wrong %d\n", dec);
708     ok( 0 == sign, "sign wrong\n");
709
710     str = _fcvt(0.6, 0, &dec, &sign );
711     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
712     ok( 1 == dec, "dec wrong %d\n", dec);
713     ok( 0 == sign, "sign wrong\n");
714 }
715
716 static struct {
717     double value;
718     int nrdigits;
719     const char *expstr_e;
720     const char *expstr_f;
721     int expdecpt_e;
722     int expdecpt_f;
723     int expsign;
724 } test_cvt_testcases[] = {
725     {          45.0,   2,        "45",           "4500",          2,      2,      0 },
726     /* Numbers less than 1.0 with different precisions */
727     {        0.0001,   1,         "1",               "",         -3,     -3,     0 },
728     {        0.0001, -10,          "",               "",         -3,     -3,     0 },
729     {        0.0001,  10,"1000000000",        "1000000",         -3,     -3,     0 },
730     /* Basic sign test */
731     {     -111.0001,   5,     "11100",       "11100010",          3,      3,     1 },
732     {      111.0001,   5,     "11100",       "11100010",          3,      3,     0 },
733     /* big numbers with low precision */
734     {        3333.3,   2,        "33",         "333330",          4,      4,     0 },
735     {999999999999.9,   3,       "100","999999999999900",         13,     12,     0 },
736     /* 0.0 with different precisions */
737     {           0.0,   5,     "00000",          "00000",          0,      0,     0 },
738     {           0.0,   0,          "",               "",          0,      0,     0 },
739     {           0.0,  -1,          "",               "",          0,      0,     0 },
740     /* Numbers > 1.0 with 0 or -ve precision */
741     {     -123.0001,   0,          "",            "123",          3,      3,     1 },
742     {     -123.0001,  -1,          "",             "12",          3,      3,     1 },
743     {     -123.0001,  -2,          "",              "1",          3,      3,     1 },
744     {     -123.0001,  -3,          "",               "",          3,      3,     1 },
745     /* Numbers > 1.0, but with rounding at the point of precision */
746     {         99.99,   1,         "1",           "1000",          3,      3,     0 },
747     /* Numbers < 1.0 where rounding occurs at the point of precision */
748     {        0.0063,   2,        "63",              "1",         -2,     -1,     0 },
749     {        0.0063,   3,        "630",             "6",         -2,     -2,     0 },
750     { 0.09999999996,   2,        "10",             "10",          0,      0,     0 },
751     {           0.6,   1,         "6",              "6",          0,      0,     0 },
752     {           0.6,   0,          "",              "1",          1,      1,     0 },
753     {           0.4,   0,          "",               "",          0,      0,     0 },
754     {          0.49,   0,          "",               "",          0,      0,     0 },
755     {          0.51,   0,          "",              "1",          1,      1,     0 },
756     /* ask ridiculous amunt of precision, ruin formatting this table */
757     {           1.0,  30, "100000000000000000000000000000",
758                       "1000000000000000000000000000000",          1,      1,      0},
759     {           123456789012345678901.0,  30, "123456789012345680000000000000",
760                       "123456789012345680000000000000000000000000000000000",         21,    21,      0},
761     /* end marker */
762     { 0, 0, "END"}
763 };
764
765 static void test_xcvt(void)
766 {
767     char *str;
768     int i, decpt, sign;
769     for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
770         decpt = sign = 100;
771         str = _ecvt( test_cvt_testcases[i].value,
772                 test_cvt_testcases[i].nrdigits,
773                 &decpt,
774                 &sign);
775         ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15),
776                "_ecvt() bad return, got \n'%s' expected \n'%s'\n", str,
777               test_cvt_testcases[i].expstr_e);
778         ok( decpt == test_cvt_testcases[i].expdecpt_e,
779                 "_ecvt() decimal point wrong, got %d expected %d\n", decpt,
780                 test_cvt_testcases[i].expdecpt_e);
781     }
782     for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
783         decpt = sign = 100;
784         str = _fcvt( test_cvt_testcases[i].value,
785                 test_cvt_testcases[i].nrdigits,
786                 &decpt,
787                 &sign);
788         ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15),
789                "_fcvt() bad return, got \n'%s' expected \n'%s'\n", str,
790               test_cvt_testcases[i].expstr_f);
791         ok( decpt == test_cvt_testcases[i].expdecpt_f,
792                 "_fcvt() decimal point wrong, got %d expected %d\n", decpt,
793                 test_cvt_testcases[i].expdecpt_f);
794         ok( sign == test_cvt_testcases[i].expsign,
795                 "_ecvt() sign wrong, got %d expected %d\n", sign,
796                 test_cvt_testcases[i].expsign);
797     }
798 }
799
800 static int __cdecl _vsnwprintf_wrapper(wchar_t *str, size_t len, const wchar_t *format, ...)
801 {
802     int ret;
803     __ms_va_list valist;
804     __ms_va_start(valist, format);
805     ret = _vsnwprintf(str, len, format, valist);
806     __ms_va_end(valist);
807     return ret;
808 }
809
810 static void test_vsnwprintf(void)
811 {
812     const wchar_t format[] = {'%','w','s','%','w','s','%','w','s',0};
813     const wchar_t one[]    = {'o','n','e',0};
814     const wchar_t two[]    = {'t','w','o',0};
815     const wchar_t three[]  = {'t','h','r','e','e',0};
816
817     int ret;
818     wchar_t str[32];
819     char buf[32];
820
821     ret = _vsnwprintf_wrapper( str, sizeof(str)/sizeof(str[0]), format, one, two, three );
822
823     ok( ret == 11, "got %d expected 11\n", ret );
824     WideCharToMultiByte( CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL );
825     ok( !strcmp(buf, "onetwothree"), "got %s expected 'onetwothree'\n", buf );
826 }
827
828 static int __cdecl _vscprintf_wrapper(const char *format, ...)
829 {
830     int ret;
831     __ms_va_list valist;
832     __ms_va_start(valist, format);
833     ret = p__vscprintf(format, valist);
834     __ms_va_end(valist);
835     return ret;
836 }
837
838 static void test_vscprintf(void)
839 {
840     int ret;
841
842     if (!p__vscprintf)
843     {
844        win_skip("_vscprintf not available\n");
845        return;
846     }
847
848     ret = _vscprintf_wrapper( "%s %d", "number", 1 );
849     ok( ret == 8, "got %d expected 8\n", ret );
850 }
851
852 static int __cdecl _vscwprintf_wrapper(const wchar_t *format, ...)
853 {
854     int ret;
855     __ms_va_list valist;
856     __ms_va_start(valist, format);
857     ret = p__vscwprintf(format, valist);
858     __ms_va_end(valist);
859     return ret;
860 }
861
862 static void test_vscwprintf(void)
863 {
864     const wchar_t format[] = {'%','s',' ','%','d',0};
865     const wchar_t number[] = {'n','u','m','b','e','r',0};
866
867     int ret;
868
869     if (!p__vscwprintf)
870     {
871         win_skip("_vscwprintf not available\n");
872         return;
873     }
874
875     ret = _vscwprintf_wrapper( format, number, 1 );
876     ok( ret == 8, "got %d expected 8\n", ret );
877 }
878
879 static int __cdecl _vsnwprintf_s_wrapper(wchar_t *str, size_t sizeOfBuffer,
880                                  size_t count, const wchar_t *format, ...)
881 {
882     int ret;
883     __ms_va_list valist;
884     __ms_va_start(valist, format);
885     ret = p__vsnwprintf_s(str, sizeOfBuffer, count, format, valist);
886     __ms_va_end(valist);
887     return ret;
888 }
889
890 static void test_vsnwprintf_s(void)
891 {
892     const wchar_t format[] = { 'A','B','%','u','C',0 };
893     const wchar_t out7[] = { 'A','B','1','2','3','C',0 };
894     const wchar_t out6[] = { 'A','B','1','2','3',0 };
895     const wchar_t out2[] = { 'A',0 };
896     const wchar_t out1[] = { 0 };
897     wchar_t buffer[14] = { 0 };
898     int exp, got;
899
900     if (!p__vsnwprintf_s)
901     {
902         win_skip("_vsnwprintf_s not available\n");
903         return;
904     }
905
906     /* Enough room. */
907     exp = wcslen(out7);
908
909     got = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, format, 123);
910     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
911     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
912
913     got = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, format, 123);
914     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
915     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
916
917     got = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, format, 123);
918     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
919     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
920
921     /* Not enough room. */
922     exp = -1;
923
924     got = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, format, 123);
925     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
926     ok( !wcscmp(out6, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
927
928     got = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, format, 123);
929     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
930     ok( !wcscmp(out2, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
931
932     got = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, format, 123);
933     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
934     ok( !wcscmp(out1, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
935 }
936
937 START_TEST(printf)
938 {
939     init();
940
941     test_sprintf();
942     test_swprintf();
943     test_snprintf();
944     test_fcvt();
945     test_xcvt();
946     test_vsnwprintf();
947     test_vscprintf();
948     test_vscwprintf();
949     test_vsnwprintf_s();
950 }