janitorial: Remove remaining NULL checks before free() (found by Smatch).
[wine] / dlls / oleaut32 / tests / varformat.c
1 /*
2  * VARFORMAT test program
3  *
4  * Copyright 1998 Jean-Claude Cote
5  * Copyright 2006 Google (Benjamin Arai)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26 #include <time.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winsock.h"
31 #include "wine/test.h"
32 #include "winuser.h"
33 #include "wingdi.h"
34 #include "winnls.h"
35 #include "winerror.h"
36 #include "winnt.h"
37
38 #include "wtypes.h"
39 #include "oleauto.h"
40
41 static HMODULE hOleaut32;
42
43 static HRESULT (WINAPI *pVarFormatNumber)(LPVARIANT,int,int,int,int,ULONG,BSTR*);
44 static HRESULT (WINAPI *pVarFormat)(LPVARIANT,LPOLESTR,int,int,ULONG,BSTR*);
45
46 /* Have I8/UI8 data type? */
47 #define HAVE_OLEAUT32_I8      HAVE_FUNC(VarI8FromI1)
48
49 /* Is a given function exported from oleaut32? */
50 #define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
51
52 /* Get a conversion function ptr, return if function not available */
53 #define CHECKPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func); \
54   if (!p##func) { trace("function " # func " not available, not testing it\n"); return; }
55
56 static inline int strcmpW( const WCHAR *str1, const WCHAR *str2 )
57 {
58     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
59     return *str1 - *str2;
60 }
61
62 #define FMT_NUMBER(vt,val) \
63   VariantInit(&v); V_VT(&v) = vt; val(&v) = 1; \
64   hres = pVarFormatNumber(&v,2,0,0,0,0,&str); \
65   ok(hres == S_OK, "VarFormatNumber (vt %d): returned %8lx\n", vt, hres); \
66   if (hres == S_OK) \
67     ok(str && strcmpW(str,szResult1) == 0, \
68        "VarFormatNumber (vt %d): string different\n", vt)
69
70 static void test_VarFormatNumber(void)
71 {
72   static const WCHAR szSrc1[] = { '1','\0' };
73   static const WCHAR szResult1[] = { '1','.','0','0','\0' };
74   static const WCHAR szSrc2[] = { '-','1','\0' };
75   static const WCHAR szResult2[] = { '(','1','.','0','0',')','\0' };
76   char buff[8];
77   HRESULT hres;
78   VARIANT v;
79   BSTR str = NULL;
80
81   CHECKPTR(VarFormatNumber);
82
83   GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buff, sizeof(buff)/sizeof(char));
84   if (buff[0] != '.' || buff[1])
85   {
86     trace("Skipping VarFormatNumber tests as decimal separator is '%s'\n", buff);
87     return;
88   }
89
90   FMT_NUMBER(VT_I1, V_I1);
91   FMT_NUMBER(VT_UI1, V_UI1);
92   FMT_NUMBER(VT_I2, V_I2);
93   FMT_NUMBER(VT_UI2, V_UI2);
94   FMT_NUMBER(VT_I4, V_I4);
95   FMT_NUMBER(VT_UI4, V_UI4);
96   if (HAVE_OLEAUT32_I8)
97   {
98     FMT_NUMBER(VT_I8, V_I8);
99     FMT_NUMBER(VT_UI8, V_UI8);
100   }
101   FMT_NUMBER(VT_R4, V_R4);
102   FMT_NUMBER(VT_R8, V_R8);
103   FMT_NUMBER(VT_BOOL, V_BOOL);
104
105   V_VT(&v) = VT_BSTR;
106   V_BSTR(&v) = SysAllocString(szSrc1);
107
108   hres = pVarFormatNumber(&v,2,0,0,0,0,&str);
109   ok(hres == S_OK, "VarFormatNumber (bstr): returned %8lx\n", hres);
110   if (hres == S_OK)
111     ok(str && strcmpW(str, szResult1) == 0, "VarFormatNumber (bstr): string different\n");
112   SysFreeString(V_BSTR(&v));
113   SysFreeString(str);
114
115   V_BSTR(&v) = SysAllocString(szSrc2);
116   hres = pVarFormatNumber(&v,2,0,-1,0,0,&str);
117   ok(hres == S_OK, "VarFormatNumber (bstr): returned %8lx\n", hres);
118   if (hres == S_OK)
119     ok(str && strcmpW(str, szResult2) == 0, "VarFormatNumber (-bstr): string different\n");
120   SysFreeString(V_BSTR(&v));
121   SysFreeString(str);
122 }
123
124 #define SIGNED_VTBITS (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8|VTBIT_R4|VTBIT_R8)
125
126 static const char *szVarFmtFail = "VT %d|0x%04x Format %s: expected 0x%08lx, '%s', got 0x%08lx, '%s'\n";
127 #define VARFMT(vt,v,val,fmt,ret,str) do { \
128   if (out) SysFreeString(out); out = NULL; \
129   V_VT(&in) = (vt); v(&in) = val; \
130   if (fmt) MultiByteToWideChar(CP_ACP, 0, fmt, -1, buffW, sizeof(buffW)/sizeof(WCHAR)); \
131   hres = pVarFormat(&in,fmt ? buffW : NULL,fd,fw,flags,&out); \
132   if (SUCCEEDED(hres)) WideCharToMultiByte(CP_ACP, 0, out, -1, buff, sizeof(buff),0,0); \
133   else buff[0] = '\0'; \
134   ok(hres == ret && (FAILED(ret) || !strcmp(buff, str)), \
135      szVarFmtFail, \
136      (vt)&VT_TYPEMASK,(vt)&~VT_TYPEMASK,fmt?fmt:"<null>",ret,str,hres,buff); \
137   } while(0)
138
139 typedef struct tagFMTRES
140 {
141   LPCSTR fmt;
142   LPCSTR one_res;
143   LPCSTR zero_res;
144 } FMTRES;
145
146 static const FMTRES VarFormat_results[] =
147 {
148   { NULL, "1", "0" },
149   { "", "1", "0" },
150   { "General Number", "1", "0" },
151   { "Percent", "100.00%", "0.00%" },
152   { "Standard", "1.00", "0.00" },
153   { "Scientific","1.00E+00", "0.00E+00" },
154   { "True/False", "True", "False" },
155   { "On/Off", "On", "Off" },
156   { "Yes/No", "Yes", "No" },
157   { "#", "1", "" },
158   { "##", "1", "" },
159   { "#.#", "1.", "." },
160   { "0", "1", "0" },
161   { "00", "01", "00" },
162   { "0.0", "1.0", "0.0" },
163   { "00\\c\\o\\p\\y", "01copy","00copy" },
164   { "\"pos\";\"neg\"", "pos", "pos" },
165   { "\"pos\";\"neg\";\"zero\"","pos", "zero" }
166 };
167
168 typedef struct tagFMTDATERES
169 {
170   DATE   val;
171   LPCSTR fmt;
172   LPCSTR res;
173 } FMTDATERES;
174
175 static const FMTDATERES VarFormat_date_results[] =
176 {
177   { 0.0, "w", "7" },
178   { 0.0, "w", "6" },
179   { 0.0, "w", "5" },
180   { 0.0, "w", "4" },
181   { 0.0, "w", "3" },
182   { 0.0, "w", "2" },
183   { 0.0, "w", "1" }, /* First 7 entries must remain in this order! */
184   { 2.525, "am/pm", "pm" },
185   { 2.525, "AM/PM", "PM" },
186   { 2.525, "A/P", "P" },
187   { 2.525, "a/p", "p" },
188   { 2.525, "q", "1" },
189   { 2.525, "d", "1" },
190   { 2.525, "dd", "01" },
191   { 2.525, "ddd", "Mon" },
192   { 2.525, "dddd", "Monday" },
193   { 2.525, "mmm", "Jan" },
194   { 2.525, "mmmm", "January" },
195   { 2.525, "y", "1" },
196   { 2.525, "yy", "00" },
197   { 2.525, "yyy", "001" },
198   { 2.525, "yyyy", "1900" },
199   { 2.525, "dd mm yyyy hh:mm:ss", "01 01 1900 12:36:00" },
200   { 2.525, "dd mm yyyy mm", "01 01 1900 01" },
201   { 2.525, "dd mm yyyy :mm", "01 01 1900 :01" },
202   { 2.525, "dd mm yyyy hh:mm", "01 01 1900 12:36" },
203   { 2.525, "mm mm", "01 01" },
204   { 2.525, "mm :mm:ss", "01 :01:00" },
205   { 2.525, "mm :ss:mm", "01 :00:01" },
206   { 2.525, "hh:mm :ss:mm", "12:36 :00:01" },
207   { 2.525, "hh:dd :mm:mm", "12:01 :01:01" },
208   { 2.525, "dd:hh :mm:mm", "01:12 :36:01" },
209   { 2.525, "hh :mm:mm", "12 :36:01" },
210   { 2.525, "dd :mm:mm", "01 :01:01" },
211   { 2.525, "dd :mm:nn", "01 :01:36" },
212   { 2.725, "hh:nn:ss A/P", "05:24:00 P" }
213 };
214
215 #define VNUMFMT(vt,v) \
216   for (i = 0; i < sizeof(VarFormat_results)/sizeof(FMTRES); i++) \
217   { \
218     VARFMT(vt,v,1,VarFormat_results[i].fmt,S_OK,VarFormat_results[i].one_res); \
219     VARFMT(vt,v,0,VarFormat_results[i].fmt,S_OK,VarFormat_results[i].zero_res); \
220   } \
221   if ((1 << vt) & SIGNED_VTBITS) \
222   { \
223     VARFMT(vt,v,-1,"\"pos\";\"neg\"",S_OK,"neg"); \
224     VARFMT(vt,v,-1,"\"pos\";\"neg\";\"zero\"",S_OK,"neg"); \
225   }
226
227 static void test_VarFormat(void)
228 {
229   static const WCHAR szTesting[] = { 't','e','s','t','i','n','g','\0' };
230   size_t i;
231   WCHAR buffW[256];
232   char buff[256];
233   VARIANT in;
234   VARIANT_BOOL bTrue = VARIANT_TRUE, bFalse = VARIANT_FALSE;
235   int fd = 0, fw = 0;
236   ULONG flags = 0;
237   BSTR bstrin, out = NULL;
238   HRESULT hres;
239
240   CHECKPTR(VarFormat);
241
242   if (PRIMARYLANGID(LANGIDFROMLCID(GetUserDefaultLCID())) != LANG_ENGLISH)
243   {
244     trace("Skipping VarFormat tests for non english language\n");
245     return;
246   }
247   GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, buff, sizeof(buff)/sizeof(char));
248   if (buff[0] != '.' || buff[1])
249   {
250     trace("Skipping VarFormat tests as decimal separator is '%s'\n", buff);
251     return;
252   }
253   GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_IDIGITS, buff, sizeof(buff)/sizeof(char));
254   if (buff[0] != '2' || buff[1])
255   {
256     trace("Skipping VarFormat tests as decimal places is '%s'\n", buff);
257     return;
258   }
259
260   VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"True/False",S_OK,"True");
261   VARFMT(VT_BOOL,V_BOOL,VARIANT_FALSE,"True/False",S_OK,"False");
262
263   VNUMFMT(VT_I1,V_I1);
264   VNUMFMT(VT_I2,V_I2);
265   VNUMFMT(VT_I4,V_I4);
266   if (HAVE_OLEAUT32_I8)
267   {
268     VNUMFMT(VT_I8,V_I8);
269   }
270   VNUMFMT(VT_INT,V_INT);
271   VNUMFMT(VT_UI1,V_UI1);
272   VNUMFMT(VT_UI2,V_UI2);
273   VNUMFMT(VT_UI4,V_UI4);
274   if (HAVE_OLEAUT32_I8)
275   {
276     VNUMFMT(VT_UI8,V_UI8);
277   }
278   VNUMFMT(VT_UINT,V_UINT);
279   VNUMFMT(VT_R4,V_R4);
280   VNUMFMT(VT_R8,V_R8);
281
282   /* Reference types are dereferenced */
283   VARFMT(VT_BOOL|VT_BYREF,V_BOOLREF,&bTrue,"True/False",S_OK,"True");
284   VARFMT(VT_BOOL|VT_BYREF,V_BOOLREF,&bFalse,"True/False",S_OK,"False");
285
286   /* Dates */
287   for (i = 0; i < sizeof(VarFormat_date_results)/sizeof(FMTDATERES); i++)
288   {
289     if (i < 7)
290       fd = i + 1; /* Test first day */
291     else
292       fd = 0;
293     VARFMT(VT_DATE,V_DATE,VarFormat_date_results[i].val,
294            VarFormat_date_results[i].fmt,S_OK,
295            VarFormat_date_results[i].res);
296   }
297
298   /* Strings */
299   bstrin = SysAllocString(szTesting);
300   VARFMT(VT_BSTR,V_BSTR,bstrin,"",S_OK,"testing");
301   VARFMT(VT_BSTR,V_BSTR,bstrin,"@",S_OK,"testing");
302   VARFMT(VT_BSTR,V_BSTR,bstrin,"&",S_OK,"testing");
303   VARFMT(VT_BSTR,V_BSTR,bstrin,"\\x@\\x@",S_OK,"xtxesting");
304   VARFMT(VT_BSTR,V_BSTR,bstrin,"\\x&\\x&",S_OK,"xtxesting");
305   VARFMT(VT_BSTR,V_BSTR,bstrin,"@\\x",S_OK,"txesting");
306   VARFMT(VT_BSTR,V_BSTR,bstrin,"@@@@@@@@",S_OK," testing");
307   VARFMT(VT_BSTR,V_BSTR,bstrin,"@\\x@@@@@@@",S_OK," xtesting");
308   VARFMT(VT_BSTR,V_BSTR,bstrin,"&&&&&&&&",S_OK,"testing");
309   VARFMT(VT_BSTR,V_BSTR,bstrin,"!&&&&&&&",S_OK,"testing");
310   VARFMT(VT_BSTR,V_BSTR,bstrin,"&&&&&&&!",S_OK,"testing");
311   VARFMT(VT_BSTR,V_BSTR,bstrin,">&&",S_OK,"TESTING");
312   VARFMT(VT_BSTR,V_BSTR,bstrin,"<&&",S_OK,"testing");
313   VARFMT(VT_BSTR,V_BSTR,bstrin,"<&>&",S_OK,"testing");
314   SysFreeString(bstrin);
315   /* Numeric values are converted to strings then output */
316   VARFMT(VT_I1,V_I1,1,"<&>&",S_OK,"1");
317
318   /* Number formats */
319   VARFMT(VT_I4,V_I4,1,"#00000000",S_OK,"00000001");
320   VARFMT(VT_I4,V_I4,1,"000###",S_OK,"000001");
321   VARFMT(VT_I4,V_I4,1,"#00##00#0",S_OK,"00000001");
322   VARFMT(VT_I4,V_I4,1,"1#####0000",S_OK,"10001");
323   todo_wine {
324   VARFMT(VT_I4,V_I4,100000,"#,###,###,###",S_OK,"100,000");
325   }
326   VARFMT(VT_R8,V_R8,1.23456789,"0#.0#0#0#0#0",S_OK,"01.234567890");
327   VARFMT(VT_R8,V_R8,1.2,"0#.0#0#0#0#0",S_OK,"01.200000000");
328   VARFMT(VT_R8,V_R8,9.87654321,"#0.#0#0#0#0#",S_OK,"9.87654321");
329   VARFMT(VT_R8,V_R8,9.8,"#0.#0#0#0#0#",S_OK,"9.80000000");
330   VARFMT(VT_R8,V_R8,0.00000008,"#0.#0#0#0#0#0",S_OK,"0.0000000800");
331   VARFMT(VT_R8,V_R8,0.00010705,"#0.##########",S_OK,"0.00010705");
332   VARFMT(VT_I4,V_I4,17,"#0",S_OK,"17");
333   VARFMT(VT_I4,V_I4,4711,"#0",S_OK,"4711");
334   VARFMT(VT_I4,V_I4,17,"#00",S_OK,"17");
335   VARFMT(VT_I4,V_I4,100,"0##",S_OK,"100");
336   VARFMT(VT_I4,V_I4,17,"#000",S_OK,"017");
337   VARFMT(VT_I4,V_I4,17,"#0.00",S_OK,"17.00");
338   VARFMT(VT_I4,V_I4,17,"#0000.00",S_OK,"0017.00");
339   VARFMT(VT_I4,V_I4,17,"#.00",S_OK,"17.00");
340   VARFMT(VT_R8,V_R8,1.7,"#.00",S_OK,"1.70");
341   VARFMT(VT_R8,V_R8,.17,"#.00",S_OK,".17");
342   VARFMT(VT_I4,V_I4,17,"#3",S_OK,"173");
343   VARFMT(VT_I4,V_I4,17,"#33",S_OK,"1733");
344   VARFMT(VT_I4,V_I4,17,"#3.33",S_OK,"173.33");
345   VARFMT(VT_I4,V_I4,17,"#3333.33",S_OK,"173333.33");
346   VARFMT(VT_I4,V_I4,17,"#.33",S_OK,"17.33");
347   VARFMT(VT_R8,V_R8,.17,"#.33",S_OK,".33");
348   VARFMT(VT_R8,V_R8,1.7,"0.0000E-000",S_OK,"1.7000E000");
349   VARFMT(VT_R8,V_R8,1.7,"0.0000e-1",S_OK,"1.7000e01");
350   VARFMT(VT_R8,V_R8,86.936849,"#0.000000000000e-000",S_OK,"86.936849000000e000");
351   VARFMT(VT_R8,V_R8,1.7,"#0",S_OK,"2");
352   VARFMT(VT_R8,V_R8,1.7,"#.33",S_OK,"2.33");
353   VARFMT(VT_R8,V_R8,1.7,"#3",S_OK,"23");
354   VARFMT(VT_R8,V_R8,1.73245,"0.0000E+000",S_OK,"1.7325E+000");
355   VARFMT(VT_R8,V_R8,9.9999999,"#0.000000",S_OK,"10.000000");
356   VARFMT(VT_R8,V_R8,1.7,"0.0000e+0#",S_OK,"1.7000e+0");
357   VARFMT(VT_R8,V_R8,100.0001e+0,"0.0000E+0",S_OK,"1.0000E+2");
358   VARFMT(VT_R8,V_R8,1000001,"0.0000e+1",S_OK,"1.0000e+61");
359   VARFMT(VT_R8,V_R8,100.0001e+25,"0.0000e+0",S_OK,"1.0000e+27");
360   VARFMT(VT_R8,V_R8,450.0001e+43,"#000.0000e+0",S_OK,"4500.0010e+42");
361   VARFMT(VT_R8,V_R8,0.0001e-11,"##00.0000e-0",S_OK,"1000.0000e-18");
362   VARFMT(VT_R8,V_R8,0.0317e-11,"0000.0000e-0",S_OK,"3170.0000e-16");
363   VARFMT(VT_R8,V_R8,0.0021e-11,"00##.0000e-0",S_OK,"2100.0000e-17");
364   VARFMT(VT_R8,V_R8,1.0001e-27,"##00.0000e-0",S_OK,"1000.1000e-30");
365   VARFMT(VT_R8,V_R8,47.11,".0000E+0",S_OK,".4711E+2");
366   VARFMT(VT_R8,V_R8,3.0401e-13,"#####.####e-0%",S_OK,"30401.e-15%");
367
368
369   /* 'out' is not cleared */
370   out = (BSTR)0x1;
371   pVarFormat(&in,NULL,fd,fw,flags,&out); /* Would crash if out is cleared */
372   out = NULL;
373
374   /* VT_NULL */
375   V_VT(&in) = VT_NULL;
376   hres = pVarFormat(&in,NULL,fd,fw,0,&out);
377   ok(hres == S_OK, "VarFormat failed with 0x%08lx\n", hres);
378   ok(out == NULL, "expected NULL formatted string\n");
379
380   /* Invalid args */
381   hres = pVarFormat(&in,NULL,fd,fw,flags,NULL);
382   ok(hres == E_INVALIDARG, "Null out: expected E_INVALIDARG, got 0x%08lx\n", hres);
383   hres = pVarFormat(NULL,NULL,fd,fw,flags,&out);
384   ok(hres == E_INVALIDARG, "Null in: expected E_INVALIDARG, got 0x%08lx\n", hres);
385   fd = -1;
386   VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
387   fd = 8;
388   VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
389   fd = 0; fw = -1;
390   VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
391   fw = 4;
392   VARFMT(VT_BOOL,V_BOOL,VARIANT_TRUE,"",E_INVALIDARG,"");
393 }
394
395 START_TEST(varformat)
396 {
397   hOleaut32 = LoadLibraryA("oleaut32.dll");
398
399   test_VarFormatNumber();
400   test_VarFormat();
401 }