1 /*
2 * Unit tests for locale functions
3 *
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
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 * NOTES
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
26 */
27
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31
32 #include "wine/test.h"
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "winnls.h"
37
38 static inline unsigned int strlenW( const WCHAR *str )
39 {
40 const WCHAR *s = str;
41 while (*s) s++;
42 return s - str;
43 }
44
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
46 {
47 if (n <= 0) return 0;
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
49 return *str1 - *str2;
50 }
51
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
53 {
54 do { if (*str == ch) return (WCHAR *)str; } while (*str++);
55 return NULL;
56 }
57
58 static inline int isdigitW( WCHAR wc )
59 {
60 WORD type;
61 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
62 return type & C1_DIGIT;
63 }
64
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32;
67 static WORD enumCount;
68
69 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
70 DWORD, LONG_PTR);
71 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
72 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
73 LGRPID, DWORD, LONG_PTR);
74 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
75 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
76 DWORD, LONG_PTR);
77 static EnumUILanguagesAFn pEnumUILanguagesA;
78
79 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
80 static FoldStringAFn pFoldStringA;
81 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
82 static FoldStringWFn pFoldStringW;
83
84 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
85 static IsValidLanguageGroupFn pIsValidLanguageGroup;
86
87 static void InitFunctionPointers(void)
88 {
89 hKernel32 = GetModuleHandleA("kernel32");
90 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
91 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
92 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
93 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
94 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
95 pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
96 }
97
98 #define eq(received, expected, label, type) \
99 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
100 (label), (received), (expected))
101
102 #define BUFFER_SIZE 128
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
104
105 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (int)(len), ret)
106 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
107 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError())
108 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
109 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError())
110 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
111 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
112 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
113 GetLastError() == ERROR_INVALID_PARAMETER, \
114 "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
115 #define EXPECT_LASTERROR_0 ok(GetLastError() == 0, \
116 "Expected GetLastError() == 0, got %d\n", GetLastError())
117 #define EXPECT_VALID ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError())
118
119 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
120 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
121 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
122 "Expected '%s', got '%s'\n", Expected, buffer)
123
124 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
125 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
126 SetLastError(0); buffer[0] = '\0'
127 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
128 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
129 #define EXPECT_FALSE ok(FALSE == ret, "Expected return value FALSE, got TRUE\n")
130 #define EXPECT_TRUE ok(FALSE != ret, "Expected return value TRUE, got FALSE\n")
131
132 #define NUO LOCALE_NOUSEROVERRIDE
133
134 static void test_GetLocaleInfoA(void)
135 {
136 int ret;
137 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
138 char buffer[BUFFER_SIZE];
139
140 ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
141
142 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
143 * partially fill the buffer even if it is too short. See bug 637.
144 */
145 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
146 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
147 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
148
149 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
150 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
151 EXPECT_BUFFER; EXPECT_LEN(0);
152 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
153
154 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
155 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
156 EXPECT_VALID; EXPECT_LEN(7);
157 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
158 }
159
160 static void test_GetTimeFormatA(void)
161 {
162 int ret;
163 SYSTEMTIME curtime;
164 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
165 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
166
167 memset(&curtime, 2, sizeof(SYSTEMTIME));
168 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
169 SetLastError(0xdeadbeef);
170 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
171 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
172
173 curtime.wHour = 8;
174 curtime.wMinute = 56;
175 curtime.wSecond = 13;
176 curtime.wMilliseconds = 22;
177 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
178 SetLastError(0xdeadbeef);
179 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
180 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
181
182 /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
183 SetLastError(0xdeadbeef);
184 ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
185 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
186
187 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
188 SetLastError(0xdeadbeef);
189 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
190 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
191
192 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
193 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
194 EXPECT_VALID; EXPECT_LENA;
195
196 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
197 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
198 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
199
200 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
201 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
202 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
203
204 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
205 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
206 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
207
208 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
209 strcpy(Expected, "8:56 AM");
210 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
211 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
212
213 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
214 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
215 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
216
217 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
218 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
219 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
220
221 STRINGSA("t/tt", "A/AM"); /* AM time marker */
222 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
223 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
224
225 curtime.wHour = 13;
226 STRINGSA("t/tt", "P/PM"); /* PM time marker */
227 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
228 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
229
230 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
231 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
232 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
233
234 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
235 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
236 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
237
238 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
239 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
240 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
241
242 curtime.wHour = 14; /* change this to 14 or 2pm */
243 curtime.wMinute = 5;
244 curtime.wSecond = 3;
245 STRINGSA("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
246 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
247 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
248
249 curtime.wHour = 0;
250 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
251 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
252 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
253
254 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
255 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
256 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
257
258 /* try to convert formatting strings with more than two letters
259 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
260 * NOTE: We expect any letter for which there is an upper case value
261 * we should see a replacement. For letters that DO NOT have
262 * upper case values we should see NO REPLACEMENT.
263 */
264 curtime.wHour = 8;
265 curtime.wMinute = 56;
266 curtime.wSecond = 13;
267 curtime.wMilliseconds = 22;
268 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
269 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
270 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
271 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
272
273 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
274 strcpy(buffer, "text");
275 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
276 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
277
278 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
279 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
280 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
281 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
282
283 STRINGSA("'''", "'"); /* invalid quoted string */
284 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
285 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
286
287 /* test that msdn suggested single quotation usage works as expected */
288 STRINGSA("''''", "'"); /* single quote mark */
289 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
290 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
291
292 STRINGSA("''HHHHHH", "08"); /* Normal use */
293 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
294 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
295
296 /* and test for normal use of the single quotation mark */
297 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
298 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
299 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
300
301 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
302 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
303 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
304
305 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
306 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
307 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
308
309 curtime.wHour = 25;
310 STRINGSA("'123'tt", ""); /* Invalid time */
311 SetLastError(0xdeadbeef);
312 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
313 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
314
315 curtime.wHour = 12;
316 curtime.wMonth = 60; /* Invalid */
317 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
318 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
319 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
320 }
321
322 static void test_GetDateFormatA(void)
323 {
324 int ret;
325 SYSTEMTIME curtime;
326 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
327 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
328
329 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
330 STRINGSA("ddd',' MMM dd yy","");
331 SetLastError(0xdeadbeef);
332 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
333 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
334
335 curtime.wYear = 2002;
336 curtime.wMonth = 5;
337 curtime.wDay = 4;
338 curtime.wDayOfWeek = 3;
339 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
340 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
341 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
342
343 /* Same as above but with LOCALE_NOUSEROVERRIDE */
344 STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
345 SetLastError(0xdeadbeef);
346 ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
347 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
348
349 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
350 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
351 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
352
353 curtime.wHour = 36; /* Invalid */
354 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
355 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
356 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
357
358 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
359 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
360 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
361
362 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
363 SetLastError(0xdeadbeef);
364 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
365 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
366
367 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
368 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
369 EXPECT_VALID; EXPECT_LENA;
370 if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
371 ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
372
373 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
374 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
375 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
376
377 /* test for expected DATE_YEARMONTH behavior with null format */
378 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
379 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
380 SetLastError(0xdeadbeef);
381 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
382 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
383
384 /* Test that using invalid DATE_* flags results in the correct error */
385 /* and return values */
386 STRINGSA("m/d/y", ""); /* Invalid flags */
387 SetLastError(0xdeadbeef);
388 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
389 &curtime, input, buffer, COUNTOF(buffer));
390 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
391 }
392
393 static void test_GetDateFormatW(void)
394 {
395 int ret;
396 SYSTEMTIME curtime;
397 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
398 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
399
400 STRINGSW("",""); /* If flags is not zero then format must be NULL */
401 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
402 input, buffer, COUNTOF(buffer));
403 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
404 return;
405 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
406
407 STRINGSW("",""); /* NULL buffer, len > 0 */
408 SetLastError(0xdeadbeef);
409 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
410 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
411
412 STRINGSW("",""); /* NULL buffer, len == 0 */
413 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
414 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
415
416 curtime.wYear = 2002;
417 curtime.wMonth = 10;
418 curtime.wDay = 23;
419 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
420 curtime.wHour = 65432; /* Invalid */
421 curtime.wMinute = 34512; /* Invalid */
422 curtime.wSecond = 65535; /* Invalid */
423 curtime.wMilliseconds = 12345;
424 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
425 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
426 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
427
428 /* Limit tests */
429
430 curtime.wYear = 1601;
431 curtime.wMonth = 1;
432 curtime.wDay = 1;
433 curtime.wDayOfWeek = 0; /* Irrelevant */
434 curtime.wHour = 0;
435 curtime.wMinute = 0;
436 curtime.wSecond = 0;
437 curtime.wMilliseconds = 0;
438 STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
439 SetLastError(0xdeadbeef);
440 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
441 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
442
443 curtime.wYear = 1600;
444 curtime.wMonth = 12;
445 curtime.wDay = 31;
446 curtime.wDayOfWeek = 0; /* Irrelevant */
447 curtime.wHour = 23;
448 curtime.wMinute = 59;
449 curtime.wSecond = 59;
450 curtime.wMilliseconds = 999;
451 STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
452 SetLastError(0xdeadbeef);
453 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
454 EXPECT_INVALID;
455 }
456
457
458 #define CY_POS_LEFT 0
459 #define CY_POS_RIGHT 1
460 #define CY_POS_LEFT_SPACE 2
461 #define CY_POS_RIGHT_SPACE 3
462
463 static void test_GetCurrencyFormatA(void)
464 {
465 static char szDot[] = { '.', '\0' };
466 static char szComma[] = { ',', '\0' };
467 static char szDollar[] = { '$', '\0' };
468 int ret;
469 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
470 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
471 CURRENCYFMTA format;
472
473 memset(&format, 0, sizeof(format));
474
475 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
476 SetLastError(0xdeadbeef);
477 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
478 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
479
480 STRINGSA("23,53",""); /* Invalid character --> Error */
481 SetLastError(0xdeadbeef);
482 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
483 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
484
485 STRINGSA("--",""); /* Double '-' --> Error */
486 SetLastError(0xdeadbeef);
487 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
488 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
489
490 STRINGSA("0-",""); /* Trailing '-' --> Error */
491 SetLastError(0xdeadbeef);
492 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
493 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
494
495 STRINGSA("0..",""); /* Double '.' --> Error */
496 SetLastError(0xdeadbeef);
497 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
498 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
499
500 STRINGSA(" 0.1",""); /* Leading space --> Error */
501 SetLastError(0xdeadbeef);
502 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
503 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
504
505 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
506 SetLastError(0xdeadbeef);
507 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
508 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
509
510 STRINGSA("2353",""); /* Format and flags given --> Error */
511 SetLastError(0xdeadbeef);
512 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
513 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
514
515 STRINGSA("2353",""); /* Invalid format --> Error */
516 SetLastError(0xdeadbeef);
517 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
518 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
519
520 STRINGSA("2353","$2,353.00"); /* Valid number */
521 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
522 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
523
524 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
525 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
526 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
527
528 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
529 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
530 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
531
532 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
533 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
534 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
535
536 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
537 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
538 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
539
540 format.NumDigits = 0; /* No decimal separator */
541 format.LeadingZero = 0;
542 format.Grouping = 0; /* No grouping char */
543 format.NegativeOrder = 0;
544 format.PositiveOrder = CY_POS_LEFT;
545 format.lpDecimalSep = szDot;
546 format.lpThousandSep = szComma;
547 format.lpCurrencySymbol = szDollar;
548
549 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
550 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
551 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
552
553 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
554 STRINGSA("2353","$2353.0");
555 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
556 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
557
558 format.Grouping = 2; /* Group by 100's */
559 STRINGSA("2353","$23,53.0");
560 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
561 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
562
563 format.LeadingZero = 1; /* Always provide leading zero */
564 STRINGSA(".5","$0.5");
565 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
566 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
567
568 format.PositiveOrder = CY_POS_RIGHT;
569 STRINGSA("1","1.0$");
570 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
571 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
572
573 format.PositiveOrder = CY_POS_LEFT_SPACE;
574 STRINGSA("1","$ 1.0");
575 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
576 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
577
578 format.PositiveOrder = CY_POS_RIGHT_SPACE;
579 STRINGSA("1","1.0 $");
580 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
581 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
582
583 format.NegativeOrder = 0;
584 STRINGSA("-1","($1.0)");
585 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
586 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
587
588 format.NegativeOrder = 1;
589 STRINGSA("-1","-$1.0");
590 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
591 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
592
593 format.NegativeOrder = 2;
594 STRINGSA("-1","$-1.0");
595 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
596 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
597
598 format.NegativeOrder = 3;
599 STRINGSA("-1","$1.0-");
600 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
601 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
602
603 format.NegativeOrder = 4;
604 STRINGSA("-1","(1.0$)");
605 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
606 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
607
608 format.NegativeOrder = 5;
609 STRINGSA("-1","-1.0$");
610 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
611 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
612
613 format.NegativeOrder = 6;
614 STRINGSA("-1","1.0-$");
615 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
616 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
617
618 format.NegativeOrder = 7;
619 STRINGSA("-1","1.0$-");
620 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
621 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
622
623 format.NegativeOrder = 8;
624 STRINGSA("-1","-1.0 $");
625 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
626 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
627
628 format.NegativeOrder = 9;
629 STRINGSA("-1","-$ 1.0");
630 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
631 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
632
633 format.NegativeOrder = 10;
634 STRINGSA("-1","1.0 $-");
635 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
636 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
637
638 format.NegativeOrder = 11;
639 STRINGSA("-1","$ 1.0-");
640 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
641 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
642
643 format.NegativeOrder = 12;
644 STRINGSA("-1","$ -1.0");
645 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
646 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
647
648 format.NegativeOrder = 13;
649 STRINGSA("-1","1.0- $");
650 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
651 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
652
653 format.NegativeOrder = 14;
654 STRINGSA("-1","($ 1.0)");
655 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
656 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
657
658 format.NegativeOrder = 15;
659 STRINGSA("-1","(1.0 $)");
660 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
661 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
662 }
663
664 #define NEG_PARENS 0 /* "(1.1)" */
665 #define NEG_LEFT 1 /* "-1.1" */
666 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
667 #define NEG_RIGHT 3 /* "1.1-" */