fdopen: don't rewind the file after creating the FILE* handle. Added
[wine] / dlls / kernel / tests / locale.c
1 /*
2  * Very basic unit test for locale functions
3  * Test run on win2K (French)
4  *
5  * Copyright (c) 2002 YASAR Mehmet
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "wine/test.h"
23 #include "winbase.h"
24 #include "winerror.h"
25 #include "winnls.h"
26
27 #define eq(received, expected, label, type) \
28         ok((received) == (expected), "%s: got " type " instead of " type, (label),(received),(expected))
29
30 #define BUFFER_SIZE             50
31 /* Buffer used by callback function */
32 char GlobalBuffer[BUFFER_SIZE];
33 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
34
35 /* TODO :
36  * Unicode versions
37  * EnumTimeFormatsA
38  * EnumDateFormatsA
39  * LCMapStringA
40  * GetUserDefaultLangID
41  * ...
42  */
43
44 void TestGetLocaleInfoA()
45 {
46 int ret, cmp;
47 LCID lcid;
48 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE];
49
50         strcpy(Expected, "Monday");
51         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
52         ok (lcid == 0x409, "wrong LCID calculated");
53
54         /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
55          * partially fill the buffer even if it is too short. See bug 637.
56          */
57         strcpy(Expected, "xxxxx");
58         memset( buffer, 'x', sizeof(buffer) );
59         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, 0);
60         cmp = strncmp (buffer, Expected, strlen(Expected));
61         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
62         eq (ret, lstrlenA("Monday") + 1, "GetLocaleInfoA with len=0", "%d");
63
64         strcpy(Expected, "Monxx");
65         memset( buffer, 'x', sizeof(buffer) );
66         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, 3);
67         cmp = strncmp (buffer, Expected, strlen(Expected));
68         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
69         eq (ret, 0, "GetLocaleInfoA with len = 3", "%d");
70
71         strcpy(Expected, "Monday");
72         memset( buffer, 'x', sizeof(buffer) );
73         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, 10);
74         /* We check also presence of '\0' */
75         cmp = strncmp (buffer, Expected, strlen(Expected) + 1);
76         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
77         eq (ret, lstrlenA(Expected)+1, "GetLocaleInfoA with len = 10", "%d" );
78
79         /* We check the whole buffer with strncmp */
80         memset( Expected, 'x', sizeof(Expected) );
81         strcpy(Expected, "Monday");
82         memset( buffer, 'x', sizeof(buffer) );
83         ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, BUFFER_SIZE);
84         cmp = strncmp (buffer, Expected, BUFFER_SIZE);
85         ok (cmp == 0, "GetLocaleInfoA got %s instead of %s", buffer, Expected);
86         eq (ret, lstrlenA(Expected)+1, "GetLocaleInfoA with len = 10", "%d" );
87
88 }
89
90
91 void TestGetTimeFormatA()
92 {
93 int ret, error, cmp;
94 SYSTEMTIME  curtime;
95 char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
96 LCID lcid;
97
98         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
99         strcpy(format, "tt HH':'mm'@'ss");
100
101         todo_wine {
102             /* fill curtime with dummy data */
103             memset(&curtime, 2, sizeof(SYSTEMTIME));
104             ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
105             error = GetLastError ();
106             ok (ret == 0, "GetTimeFormat should fail on dummy data");
107             eq (error, ERROR_INVALID_PARAMETER, "GetTimeFormat GetLastError()", "%d");
108         }
109
110         strcpy(Expected, "AM 08:56@13");
111         curtime.wHour = 8;  curtime.wMinute = 56;
112         curtime.wSecond = 13; curtime.wMilliseconds = 22;
113         ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
114         cmp = strncmp (Expected, buffer, strlen(Expected)+1);
115         ok (cmp == 0, "GetTimeFormat got %s instead of %s", buffer, Expected);
116         eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
117
118         /* test with too small buffers */
119         SetLastError(0);
120         ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, NULL, 0);
121         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
122            "GetTimeFormat(len=0): ret=%d error=%ld\n",ret,GetLastError());
123
124         memset(buffer, 'x', sizeof(buffer));
125         ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, ret);
126         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
127            "GetTimeFormat(right size): ret=%d error=%ld\n",ret,GetLastError());
128         ok(buffer[0]!='x',"GetTimeFormat(right size): buffer=[%s]\n",buffer);
129
130         ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, 2);
131         ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
132            "GetTimeFormat(len=2): ret=%d error=%ld", ret, GetLastError());
133 }
134
135 void TestGetDateFormatA()
136 {
137 int ret, error, cmp;
138 SYSTEMTIME  curtime;
139 char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
140 LCID lcid;
141
142         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
143         strcpy(format, "ddd',' MMM dd yy");
144
145         todo_wine {
146             /* fill curtime with dummy data */
147             memset(&curtime, 2, sizeof(SYSTEMTIME));
148             memset(buffer, 'x', sizeof(buffer));
149             ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
150             error = GetLastError ();
151             ok (ret== 0, "GetDateFormat should fail on dummy data");
152             eq (error, ERROR_INVALID_PARAMETER, "GetDateFormat", "%d");
153         }
154
155         strcpy(Expected, "Sat, May 04 02");
156         memset(buffer, 'x', sizeof(buffer));
157         curtime.wYear = 2002;
158         curtime.wMonth = 5;
159         curtime.wDay = 4;
160         curtime.wDayOfWeek = 3;
161         ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
162         cmp = strncmp (Expected, buffer, strlen(Expected)+1);
163         todo_wine { ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected); }
164         eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
165
166         /* test format with "'" */
167         memset(buffer, 'x', sizeof(buffer));
168         strcpy(format, "ddd',' MMM dd ''''yy");
169         strcpy(Expected, "Sat, May 04 '02");
170         ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
171         cmp = strncmp (Expected, buffer, strlen(Expected)+1);
172         todo_wine { ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected); }
173         eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
174
175         /* test with too small buffers */
176         SetLastError(0);
177         ret = GetDateFormatA(lcid, 0, &curtime, format, NULL, 0);
178         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
179            "GetDateFormat(len=0): ret=%d error=%ld\n",ret,GetLastError());
180
181         memset(buffer, 'x', sizeof(buffer));
182         ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, ret);
183         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
184            "GetDateFormat(right size): ret=%d error=%ld\n",ret,GetLastError());
185         ok(buffer[0]!='x',"GetTimeFormat(right size): buffer=[%s]\n",buffer);
186
187         ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, 2);
188         ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
189            "GetDateFormat(len=2): ret=%d error=%ld", ret, GetLastError());
190 }
191
192 void TestGetDateFormatW()
193 {
194     int ret, error, cmp;
195     SYSTEMTIME  curtime;
196     WCHAR buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
197     LCID lcid;
198
199     lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
200
201     /* 1. Error cases */
202
203     /* 1a If flags is not zero then format must be null. */
204     ret = GetDateFormatW (LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL, format, buffer, COUNTOF(buffer));
205     if (ret==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
206         return;
207     error = ret ? 0 : GetLastError();
208     ok (ret == 0 && error == ERROR_INVALID_FLAGS, "GetDateFormatW allowed flags and format");
209
210     /* 1b The buffer can only be null if the count is zero */
211     /* For the record other bad pointers result in a page fault (Win98) */
212     ret = GetDateFormatW (LOCALE_SYSTEM_DEFAULT, 0, NULL, format, NULL, COUNTOF(buffer));
213     error = ret ? 0 : GetLastError();
214     ok (ret == 0 && error == ERROR_INVALID_PARAMETER, "GetDateFormatW did not detect null buffer pointer.");
215     ret = GetDateFormatW (LOCALE_SYSTEM_DEFAULT, 0, NULL, format, NULL, 0);
216     error = ret ? 0 : GetLastError();
217     ok (ret != 0 && error == 0, "GetDateFormatW did not permit null buffer pointer when counting.");
218
219     /* 1c An incorrect day of week is corrected. */
220     curtime.wYear = 2002;
221     curtime.wMonth = 10;
222     curtime.wDay = 23;
223     curtime.wDayOfWeek = 5; /* should be 3 - Wednesday */
224     curtime.wHour = 0;
225     curtime.wMinute = 0;
226     curtime.wSecond = 0;
227     curtime.wMilliseconds = 234;
228     MultiByteToWideChar (CP_ACP, 0, "dddd d MMMM yyyy", -1, format, COUNTOF(format));
229     ret = GetDateFormatW (lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
230     error = ret ? 0 : GetLastError();
231     MultiByteToWideChar (CP_ACP, 0, "Wednesday 23 October 2002", -1, Expected, COUNTOF(Expected));
232     cmp = ret ? lstrcmpW (buffer, Expected) : 2;
233     ok (ret == lstrlenW(Expected)+1 && error == 0 && cmp == 0, "Day of week correction failed\n");
234
235     /* 1d Invalid year, month or day results in error */
236
237     /* 1e Insufficient space results in error */
238
239     /* 2. Standard behaviour */
240     /* 1c is a reasonable test */
241
242     /* 3. Replicated undocumented behaviour */
243     /* e.g. unexepected characters are retained. */
244 }
245
246
247 void TestGetCurrencyFormat()
248 {
249 int ret, error, cmp;
250 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], format[BUFFER_SIZE];
251 LCID lcid;
252
253         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
254 #if 0
255         lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT );
256 #endif
257
258         memset( buffer, 'x', sizeof(buffer) );
259         ret = GetCurrencyFormatA(lcid, 0, "23,65", NULL, buffer, COUNTOF(buffer));
260         error = GetLastError ();
261         cmp = strncmp ("xxxx", buffer, 4);
262
263         ok (cmp == 0, "GetCurrencyFormat should fail with ','");
264         eq (ret, 0, "GetCurrencyFormat with ','", "%d");
265         eq (error, ERROR_INVALID_PARAMETER, "GetCurrencyFormat", "%d");
266
267         /* We check the whole buffer with strncmp */
268         strcpy (Expected, "$23.53");
269         strcpy (format, "23.53");
270         memset( buffer, 'x', sizeof(buffer) );
271         ret = GetCurrencyFormatA(lcid, 0, format, NULL, buffer, COUNTOF(buffer));
272         cmp = strncmp (Expected, buffer, BUFFER_SIZE);
273         ok (cmp == 0, "GetCurrencyFormatA got %s instead of %s", buffer, Expected);
274         eq (ret, lstrlenA(Expected)+1, "GetCurrencyFormatA","%d");
275
276         /* Test too small buffers */
277         SetLastError(0);
278         ret = GetCurrencyFormatA(lcid, 0, format, NULL, NULL, 0);
279         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
280        "GetCurrencyFormatA(size=0): ret=%d error=%ld", ret, GetLastError());
281
282         memset( buffer, 'x', sizeof(buffer) );
283         ret = GetCurrencyFormatA(lcid, 0, format, NULL, buffer, ret);
284         ok(strcmp(buffer,Expected)==0,
285            "GetCurrencyFormatA(right size): got [%s] instead of [%s]", buffer, Expected);
286         eq (ret, lstrlenA(Expected)+1, "GetCurrencyFormatA(right size)", "%d");
287
288         ret = GetCurrencyFormatA(lcid, 0, format, NULL, buffer, 2);
289         ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
290            "GetCurrencyFormatA(size=2): ret=%d error=%ld", ret, GetLastError());
291 }
292
293
294 void TestGetNumberFormat()
295 {
296 int ret, error, cmp;
297 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
298 LCID lcid;
299 NUMBERFMTA format;
300
301         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
302
303         memset( buffer, 'x', sizeof(buffer) );
304         ret = GetNumberFormatA(lcid, 0, "23,65", NULL, buffer, COUNTOF(buffer));
305         error = GetLastError ();
306         cmp = strncmp ("xxx", buffer, 3);
307         ok (cmp == 0, "GetNumberFormat");
308         ok (ret == 0, "GetNumberFormat should return 0");
309         eq (error, ERROR_INVALID_PARAMETER, "GetNumberFormat", "%d");
310
311         strcpy(input, "2353");
312         strcpy(Expected, "2,353.00");
313         SetLastError(0);
314         ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, 0);
315         ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
316        "GetNumberFormatA(size=0): ret=%d error=%ld", ret, GetLastError());
317
318         memset( buffer, 'x', sizeof(buffer) );
319         ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, ret);
320         ok(strcmp(buffer,Expected)==0,
321            "GetNumberFormatA(right size): got [%s] instead of [%s]", buffer, Expected);
322         eq(ret, lstrlenA(Expected)+1, "GetNumberFormat", "%d");
323
324         ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, 2);
325         ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
326            "GetNumberFormatA(size=2): ret=%d error=%ld", ret, GetLastError());
327
328         /* We check the whole buffer with strncmp */
329         memset(Expected, 'x', sizeof(Expected) );
330         strcpy(Expected, "2,353.00");
331         memset( buffer, 'x', sizeof(buffer) );
332         ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
333         cmp = strncmp (Expected, buffer, BUFFER_SIZE);
334         ok (cmp == 0, "GetNumberFormat got %s instead of %s", buffer, Expected);
335         eq (ret, lstrlenA(Expected)+1, "GetNumberFormat", "%d");
336
337         /* If the number of decimals is zero there should be no decimal
338          * separator.
339          * If the grouping size is zero there should be no grouping symbol
340          */
341         format.NumDigits = 0;
342         format.LeadingZero = 0;
343         format.Grouping = 0;
344         format.NegativeOrder = 0;
345         format.lpDecimalSep = ".";
346         format.lpThousandSep = ",";
347         strcpy (Expected, "123456789");
348         memset( buffer, 'x', sizeof(buffer) );
349         ret = GetNumberFormatA (0, 0, "123456789.0", &format, buffer, COUNTOF(buffer));
350         cmp = strncmp (Expected, buffer, sizeof(buffer));
351         ok (cmp == 0, "GetNumberFormat got %s instead of %s", buffer, Expected);
352
353 }
354
355
356 /* Callback function used by TestEnumTimeFormats */
357 BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
358 {
359         trace("%s\n", lpTimeFormatString);
360         strcpy(GlobalBuffer, lpTimeFormatString);
361 #if 0
362         return TRUE;
363 #endif
364         return FALSE;
365 }
366
367 void TestEnumTimeFormats()
368 {
369 int ret;
370 LCID lcid;
371 char Expected[BUFFER_SIZE];
372
373         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
374         memset( GlobalBuffer, 'x', sizeof(GlobalBuffer) );
375         strcpy(Expected, "h:mm:ss tt");
376         ret = EnumTimeFormatsA(EnumTimeFormatsProc, lcid, 0);
377
378         eq (ret, 1, "EnumTimeFormats should return 1", "%d");
379         ok (strncmp (GlobalBuffer, Expected, strlen(Expected)) == 0,
380                                 "EnumTimeFormats failed");
381         ok (ret == 1, "EnumTimeFormats should return 1");
382 }
383
384
385 void TestCompareStringA()
386 {
387 int ret;
388 LCID lcid;
389 char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
390
391         lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT );
392
393         strcpy(buffer1, "Salut"); strcpy(buffer2, "Salute");
394         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
395         ok (ret== 1, "CompareStringA (st1=%s str2=%s) expected result=1", buffer1, buffer2);
396
397         strcpy(buffer1, "Salut"); strcpy(buffer2, "saLuT");
398         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
399         ok (ret== 2, "CompareStringA (st1=%s str2=%s) expected result=2", buffer1, buffer2);
400
401         strcpy(buffer1, "Salut"); strcpy(buffer2, "hola");
402         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
403         ok (ret== 3, "CompareStringA (st1=%s str2=%s) expected result=3", buffer1, buffer2);
404
405         strcpy(buffer1, "héhé"); strcpy(buffer2, "hèhè");
406         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
407         ok (ret== 1, "CompareStringA (st1=%s str2=%s) expected result=1", buffer1, buffer2);
408
409         lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
410
411         strcpy(buffer1, "héhé"); strcpy(buffer2, "hèhè");
412         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
413         ok (ret== 1, "CompareStringA (st1=%s str2=%s) expected result=1", buffer1, buffer2);
414
415         ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, 0);
416         ok (ret== 3, "CompareStringA (st1=%s str2=%s) expected result=3", buffer1, buffer2);
417 }
418
419
420 START_TEST(locale)
421 {
422 #if 0
423         TestEnumTimeFormats();
424 #endif
425         TestGetLocaleInfoA();
426         TestGetTimeFormatA();
427         TestGetDateFormatA();
428         TestGetDateFormatW();
429         TestGetNumberFormat();
430         TestGetCurrencyFormat();
431         TestCompareStringA();
432 }