msvcr100: Use LC_TIME code page when converting strftime data.
[wine.git] / dlls / ucrtbase / tests / misc.c
blob5fcec2e2bb5dc363348a5d162c2f73073c32fe61
1 /*
2 * Copyright 2016 Nikolay Sivov for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <wchar.h>
23 #include <stdio.h>
24 #include <math.h>
25 #include <float.h>
26 #include <io.h>
27 #include <sys/stat.h>
28 #include <share.h>
29 #include <fcntl.h>
30 #include <time.h>
31 #include <direct.h>
32 #include <locale.h>
33 #include <process.h>
34 #include <fenv.h>
35 #include <malloc.h>
37 #include <windef.h>
38 #include <winbase.h>
39 #include "wine/test.h"
41 #define DEFINE_EXPECT(func) \
42 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
44 #define SET_EXPECT(func) \
45 expect_ ## func = TRUE
47 #define CHECK_EXPECT2(func) \
48 do { \
49 ok(expect_ ##func, "unexpected call " #func "\n"); \
50 called_ ## func = TRUE; \
51 }while(0)
53 #define CHECK_EXPECT(func) \
54 do { \
55 CHECK_EXPECT2(func); \
56 expect_ ## func = FALSE; \
57 }while(0)
59 #define CHECK_CALLED(func) \
60 do { \
61 ok(called_ ## func, "expected " #func "\n"); \
62 expect_ ## func = called_ ## func = FALSE; \
63 }while(0)
65 static inline double __port_min_pos_double(void)
67 static const UINT64 __min_pos_double = 0x10000000000000;
68 return *(const double *)&__min_pos_double;
71 static inline double __port_max_double(void)
73 static const UINT64 __max_double = 0x7FEFFFFFFFFFFFFF;
74 return *(const double *)&__max_double;
77 DEFINE_EXPECT(global_invalid_parameter_handler);
78 DEFINE_EXPECT(thread_invalid_parameter_handler);
80 typedef struct {
81 const char *short_wday[7];
82 const char *wday[7];
83 const char *short_mon[12];
84 const char *mon[12];
85 const char *am;
86 const char *pm;
87 const char *short_date;
88 const char *date;
89 const char *time;
90 int unk;
91 int refcount;
92 const wchar_t *short_wdayW[7];
93 const wchar_t *wdayW[7];
94 const wchar_t *short_monW[12];
95 const wchar_t *monW[12];
96 const wchar_t *amW;
97 const wchar_t *pmW;
98 const wchar_t *short_dateW;
99 const wchar_t *dateW;
100 const wchar_t *timeW;
101 const wchar_t *locnameW;
102 } __lc_time_data;
104 typedef void (__cdecl *_se_translator_function)(unsigned int code, struct _EXCEPTION_POINTERS *info);
106 static LONGLONG crt_init_end;
108 _ACRTIMP int __cdecl _o__initialize_onexit_table(_onexit_table_t *table);
109 _ACRTIMP int __cdecl _o__register_onexit_function(_onexit_table_t *table, _onexit_t func);
110 _ACRTIMP int __cdecl _o__execute_onexit_table(_onexit_table_t *table);
111 _ACRTIMP void *__cdecl _o_malloc(size_t);
112 _se_translator_function __cdecl _set_se_translator(_se_translator_function func);
113 void** __cdecl __current_exception(void);
114 int* __cdecl __processing_throw(void);
116 static void test__initialize_onexit_table(void)
118 _onexit_table_t table, table2;
119 int ret;
121 ret = _initialize_onexit_table(NULL);
122 ok(ret == -1, "got %d\n", ret);
124 memset(&table, 0, sizeof(table));
125 ret = _initialize_onexit_table(&table);
126 ok(ret == 0, "got %d\n", ret);
127 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
128 table._first, table._last, table._end);
130 memset(&table2, 0, sizeof(table2));
131 ret = _initialize_onexit_table(&table2);
132 ok(ret == 0, "got %d\n", ret);
133 ok(table2._first == table._first, "got %p, %p\n", table2._first, table._first);
134 ok(table2._last == table._last, "got %p, %p\n", table2._last, table._last);
135 ok(table2._end == table._end, "got %p, %p\n", table2._end, table._end);
137 memset(&table2, 0, sizeof(table2));
138 ret = _o__initialize_onexit_table(&table2);
139 ok(ret == 0, "got %d\n", ret);
140 ok(table2._first == table._first, "got %p, %p\n", table2._first, table._first);
141 ok(table2._last == table._last, "got %p, %p\n", table2._last, table._last);
142 ok(table2._end == table._end, "got %p, %p\n", table2._end, table._end);
144 /* uninitialized table */
145 table._first = table._last = table._end = (void*)0x123;
146 ret = _initialize_onexit_table(&table);
147 ok(ret == 0, "got %d\n", ret);
148 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
149 table._first, table._last, table._end);
150 ok(table._first != (void*)0x123, "got %p\n", table._first);
152 table._first = (void*)0x123;
153 table._last = (void*)0x456;
154 table._end = (void*)0x123;
155 ret = _initialize_onexit_table(&table);
156 ok(ret == 0, "got %d\n", ret);
157 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
158 table._first, table._last, table._end);
159 ok(table._first != (void*)0x123, "got %p\n", table._first);
161 table._first = (void*)0x123;
162 table._last = (void*)0x456;
163 table._end = (void*)0x789;
164 ret = _initialize_onexit_table(&table);
165 ok(ret == 0, "got %d\n", ret);
166 ok(table._first == (void*)0x123, "got %p\n", table._first);
167 ok(table._last == (void*)0x456, "got %p\n", table._last);
168 ok(table._end == (void*)0x789, "got %p\n", table._end);
170 table._first = NULL;
171 table._last = (void*)0x456;
172 table._end = NULL;
173 ret = _initialize_onexit_table(&table);
174 ok(ret == 0, "got %d\n", ret);
175 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
176 table._first, table._last, table._end);
179 static int g_onexit_called;
180 static int CDECL onexit_func(void)
182 g_onexit_called++;
183 return 0;
186 static int CDECL onexit_func2(void)
188 ok(g_onexit_called == 0, "got %d\n", g_onexit_called);
189 g_onexit_called++;
190 return 0;
193 static void test__register_onexit_function(void)
195 _onexit_table_t table;
196 _PVFV *f;
197 int ret;
199 memset(&table, 0, sizeof(table));
200 ret = _initialize_onexit_table(&table);
201 ok(ret == 0, "got %d\n", ret);
203 ret = _register_onexit_function(NULL, NULL);
204 ok(ret == -1, "got %d\n", ret);
206 ret = _register_onexit_function(NULL, onexit_func);
207 ok(ret == -1, "got %d\n", ret);
209 f = table._last;
210 ret = _register_onexit_function(&table, NULL);
211 ok(ret == 0, "got %d\n", ret);
212 ok(f != table._last, "got %p, initial %p\n", table._last, f);
214 ret = _register_onexit_function(&table, onexit_func);
215 ok(ret == 0, "got %d\n", ret);
217 f = table._last;
218 ret = _register_onexit_function(&table, onexit_func);
219 ok(ret == 0, "got %d\n", ret);
220 ok(f != table._last, "got %p, initial %p\n", table._last, f);
222 f = table._last;
223 ret = _o__register_onexit_function(&table, NULL);
224 ok(ret == 0, "got %d\n", ret);
225 ok(f != table._last, "got %p, initial %p\n", table._last, f);
227 f = table._last;
228 ret = _o__register_onexit_function(&table, onexit_func);
229 ok(ret == 0, "got %d\n", ret);
230 ok(f != table._last, "got %p, initial %p\n", table._last, f);
232 ret = _execute_onexit_table(&table);
233 ok(ret == 0, "got %d\n", ret);
236 static void test__execute_onexit_table(void)
238 _onexit_table_t table;
239 int ret;
241 ret = _execute_onexit_table(NULL);
242 ok(ret == -1, "got %d\n", ret);
244 memset(&table, 0, sizeof(table));
245 ret = _initialize_onexit_table(&table);
246 ok(ret == 0, "got %d\n", ret);
248 /* execute empty table */
249 ret = _execute_onexit_table(&table);
250 ok(ret == 0, "got %d\n", ret);
252 /* same function registered multiple times */
253 ret = _register_onexit_function(&table, onexit_func);
254 ok(ret == 0, "got %d\n", ret);
256 ret = _register_onexit_function(&table, NULL);
257 ok(ret == 0, "got %d\n", ret);
259 ret = _register_onexit_function(&table, onexit_func);
260 ok(ret == 0, "got %d\n", ret);
262 ret = _o__register_onexit_function(&table, onexit_func);
263 ok(ret == 0, "got %d\n", ret);
265 ok(table._first != table._end, "got %p, %p\n", table._first, table._end);
266 g_onexit_called = 0;
267 ret = _execute_onexit_table(&table);
268 ok(ret == 0, "got %d\n", ret);
269 ok(g_onexit_called == 3, "got %d\n", g_onexit_called);
270 ok(table._first == table._end, "got %p, %p\n", table._first, table._end);
272 ret = _register_onexit_function(&table, onexit_func);
273 ok(ret == 0, "got %d\n", ret);
275 ret = _register_onexit_function(&table, NULL);
276 ok(ret == 0, "got %d\n", ret);
278 ret = _register_onexit_function(&table, onexit_func);
279 ok(ret == 0, "got %d\n", ret);
281 ret = _o__register_onexit_function(&table, onexit_func);
282 ok(ret == 0, "got %d\n", ret);
284 ok(table._first != table._end, "got %p, %p\n", table._first, table._end);
285 g_onexit_called = 0;
286 ret = _o__execute_onexit_table(&table);
287 ok(ret == 0, "got %d\n", ret);
288 ok(g_onexit_called == 3, "got %d\n", g_onexit_called);
289 ok(table._first == table._end, "got %p, %p\n", table._first, table._end);
291 /* execute again, table is already empty */
292 g_onexit_called = 0;
293 ret = _execute_onexit_table(&table);
294 ok(ret == 0, "got %d\n", ret);
295 ok(g_onexit_called == 0, "got %d\n", g_onexit_called);
297 /* check call order */
298 memset(&table, 0, sizeof(table));
299 ret = _initialize_onexit_table(&table);
300 ok(ret == 0, "got %d\n", ret);
302 ret = _register_onexit_function(&table, onexit_func);
303 ok(ret == 0, "got %d\n", ret);
305 ret = _register_onexit_function(&table, onexit_func2);
306 ok(ret == 0, "got %d\n", ret);
308 g_onexit_called = 0;
309 ret = _execute_onexit_table(&table);
310 ok(ret == 0, "got %d\n", ret);
311 ok(g_onexit_called == 2, "got %d\n", g_onexit_called);
314 static void test___fpe_flt_rounds(void)
316 unsigned int cfp = _controlfp(0, 0);
317 int ret;
319 if(!cfp) {
320 skip("_controlfp not supported\n");
321 return;
324 ok((_controlfp(_RC_NEAR, _RC_CHOP) & _RC_CHOP) == _RC_NEAR, "_controlfp(_RC_NEAR, _RC_CHOP) failed\n");
325 ret = __fpe_flt_rounds();
326 ok(ret == 1, "__fpe_flt_rounds returned %d\n", ret);
328 ok((_controlfp(_RC_UP, _RC_CHOP) & _RC_CHOP) == _RC_UP, "_controlfp(_RC_UP, _RC_CHOP) failed\n");
329 ret = __fpe_flt_rounds();
330 ok(ret == 2 || broken(ret == 3) /* w1064v1507 */, "__fpe_flt_rounds returned %d\n", ret);
332 ok((_controlfp(_RC_DOWN, _RC_CHOP) & _RC_CHOP) == _RC_DOWN, "_controlfp(_RC_DOWN, _RC_CHOP) failed\n");
333 ret = __fpe_flt_rounds();
334 ok(ret == 3 || broken(ret == 2) /* w1064v1507 */, "__fpe_flt_rounds returned %d\n", ret);
336 ok((_controlfp(_RC_CHOP, _RC_CHOP) & _RC_CHOP) == _RC_CHOP, "_controlfp(_RC_CHOP, _RC_CHOP) failed\n");
337 ret = __fpe_flt_rounds();
338 ok(ret == 0, "__fpe_flt_rounds returned %d\n", ret);
340 _controlfp(cfp, _MCW_EM | _MCW_RC | _MCW_PC);
343 static void test__control87_2(void)
345 #ifdef __i386__
346 unsigned int x86_cw_init, sse2_cw_init, x86_cw, sse2_cw, r;
348 r = __control87_2(0, 0, &x86_cw_init, &sse2_cw_init);
349 ok(r == 1, "__control87_2 returned %d\n", r);
351 r = __control87_2(0, _EM_INVALID, &x86_cw, NULL);
352 ok(r == 1, "__control87_2 returned %d\n", r);
353 ok(x86_cw == (x86_cw_init & ~_EM_INVALID), "x86_cw = %x, x86_cw_init = %x\n", x86_cw, x86_cw_init);
355 r = __control87_2(0, 0, &x86_cw, &sse2_cw);
356 ok(r == 1, "__control87_2 returned %d\n", r);
357 ok(x86_cw == (x86_cw_init & ~_EM_INVALID), "x86_cw = %x, x86_cw_init = %x\n", x86_cw, x86_cw_init);
358 ok(sse2_cw == sse2_cw_init, "sse2_cw = %x, sse2_cw_init = %x\n", sse2_cw, sse2_cw_init);
360 r = _control87(0, 0);
361 ok(r == (x86_cw | sse2_cw | _EM_AMBIGUOUS), "r = %x, expected %x\n",
362 r, x86_cw | sse2_cw | _EM_AMBIGUOUS);
364 _control87(x86_cw_init, ~0);
365 #endif
368 static void __cdecl global_invalid_parameter_handler(
369 const wchar_t *expression, const wchar_t *function,
370 const wchar_t *file, unsigned line, uintptr_t arg)
372 CHECK_EXPECT2(global_invalid_parameter_handler);
375 static void __cdecl thread_invalid_parameter_handler(
376 const wchar_t *expression, const wchar_t *function,
377 const wchar_t *file, unsigned line, uintptr_t arg)
379 CHECK_EXPECT(thread_invalid_parameter_handler);
382 static void test_invalid_parameter_handler(void)
384 _invalid_parameter_handler ret;
386 ret = _get_invalid_parameter_handler();
387 ok(!ret, "ret != NULL\n");
389 ret = _get_thread_local_invalid_parameter_handler();
390 ok(!ret, "ret != NULL\n");
392 ret = _set_thread_local_invalid_parameter_handler(thread_invalid_parameter_handler);
393 ok(!ret, "ret != NULL\n");
395 ret = _get_thread_local_invalid_parameter_handler();
396 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
398 ret = _get_invalid_parameter_handler();
399 ok(!ret, "ret != NULL\n");
401 ret = _set_invalid_parameter_handler(global_invalid_parameter_handler);
402 ok(!ret, "ret != NULL\n");
404 ret = _get_invalid_parameter_handler();
405 ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret);
407 ret = _get_thread_local_invalid_parameter_handler();
408 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
410 SET_EXPECT(thread_invalid_parameter_handler);
411 _ltoa_s(0, NULL, 0, 0);
412 CHECK_CALLED(thread_invalid_parameter_handler);
414 ret = _set_thread_local_invalid_parameter_handler(NULL);
415 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
417 SET_EXPECT(global_invalid_parameter_handler);
418 _ltoa_s(0, NULL, 0, 0);
419 CHECK_CALLED(global_invalid_parameter_handler);
421 ret = _set_invalid_parameter_handler(NULL);
422 ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret);
424 ret = _set_invalid_parameter_handler(global_invalid_parameter_handler);
425 ok(!ret, "ret != NULL\n");
428 static void test__get_narrow_winmain_command_line(char *path)
430 PROCESS_INFORMATION proc;
431 STARTUPINFOA startup;
432 char cmd[MAX_PATH+32];
433 char *ret, *cmdline, *name;
434 int len;
436 ret = _get_narrow_winmain_command_line();
437 cmdline = GetCommandLineA();
438 len = strlen(cmdline);
439 ok(ret>cmdline && ret<cmdline+len, "ret = %p, cmdline = %p (len = %d)\n", ret, cmdline, len);
441 if(!path) {
442 ok(!lstrcmpA(ret, "\"misc\" cmd"), "ret = %s\n", ret);
443 return;
446 for(len = strlen(path); len>0; len--)
447 if(path[len-1]=='\\' || path[len-1]=='/') break;
448 if(len) name = path+len;
449 else name = path;
451 sprintf(cmd, "\"\"%c\"\"\"%s\" \t \"misc\" cmd", name[0], name+1);
452 memset(&startup, 0, sizeof(startup));
453 startup.cb = sizeof(startup);
454 CreateProcessA(path, cmd, NULL, NULL, TRUE,
455 CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS,
456 NULL, NULL, &startup, &proc);
457 wait_child_process(proc.hProcess);
458 CloseHandle(proc.hProcess);
459 CloseHandle(proc.hThread);
462 static void test__sopen_dispatch(void)
464 int ret, fd;
465 char *tempf;
467 tempf = _tempnam(".", "wne");
469 fd = 0;
470 ret = _sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 0);
471 ok(!ret, "got %d\n", ret);
472 ok(fd > 0, "got fd %d\n", fd);
473 _close(fd);
474 unlink(tempf);
476 SET_EXPECT(global_invalid_parameter_handler);
477 fd = 0;
478 ret = _sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 1);
479 ok(ret == EINVAL, "got %d\n", ret);
480 ok(fd == -1, "got fd %d\n", fd);
481 CHECK_CALLED(global_invalid_parameter_handler);
482 if (fd > 0)
484 _close(fd);
485 unlink(tempf);
488 free(tempf);
491 static void test__sopen_s(void)
493 int ret, fd;
494 char *tempf;
496 tempf = _tempnam(".", "wne");
498 fd = 0;
499 ret = _sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0);
500 ok(!ret, "got %d\n", ret);
501 ok(fd > 0, "got fd %d\n", fd);
502 _close(fd);
503 unlink(tempf);
505 /* _open() does not validate pmode */
506 fd = _open(tempf, _O_CREAT, 0xff);
507 ok(fd > 0, "got fd %d\n", fd);
508 _close(fd);
509 unlink(tempf);
511 /* _sopen_s() invokes invalid parameter handler on invalid pmode */
512 SET_EXPECT(global_invalid_parameter_handler);
513 fd = 0;
514 ret = _sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0xff);
515 ok(ret == EINVAL, "got %d\n", ret);
516 ok(fd == -1, "got fd %d\n", fd);
517 CHECK_CALLED(global_invalid_parameter_handler);
519 free(tempf);
522 static void test_lldiv(void)
524 lldiv_t r;
526 r = lldiv(((LONGLONG)0x111 << 32) + 0x222, (LONGLONG)1 << 32);
527 ok(r.quot == 0x111, "quot = %s\n", wine_dbgstr_longlong(r.quot));
528 ok(r.rem == 0x222, "rem = %s\n", wine_dbgstr_longlong(r.rem));
530 r = lldiv(((LONGLONG)0x69CF0012 << 32) + 0x0033E78A, 0x30);
531 ok(r.quot == ((LONGLONG)0x02345000 << 32) + 0x600114D2, "quot = %s\n", wine_dbgstr_longlong(r.quot));
532 ok(r.rem == 0x2A, "rem = %s\n", wine_dbgstr_longlong(r.rem));
534 r = lldiv(((LONGLONG)0x243A5678 << 32) + 0x9ABCDEF0, (LONGLONG)0x12 << 48);
535 ok(r.quot == 0x0203, "quot = %s\n", wine_dbgstr_longlong(r.quot));
536 ok(r.rem == ((LONGLONG)0x00045678 << 32) + 0x9ABCDEF0, "rem = %s\n", wine_dbgstr_longlong(r.rem));
539 static void test_isblank(void)
541 int c;
543 for(c = 0; c <= 0xff; c++) {
544 if(c == '\t' || c == ' ') {
545 if(c == '\t')
546 ok(!_isctype(c, _BLANK), "tab shouldn't be blank\n");
547 else
548 ok(_isctype(c, _BLANK), "space should be blank\n");
549 ok(isblank(c), "%d should be blank\n", c);
550 ok(_isblank_l(c, NULL), "%d should be blank\n", c);
551 } else {
552 ok(!_isctype(c, _BLANK), "%d shouldn't be blank\n", c);
553 ok(!isblank(c), "%d shouldn't be blank\n", c);
554 ok(!_isblank_l(c, NULL), "%d shouldn't be blank\n", c);
558 for(c = 0; c <= 0xffff; c++) {
559 if(c == '\t' || c == ' ' || c == 0x3000 || c == 0xfeff) {
560 if(c == '\t')
561 ok(!_iswctype_l(c, _BLANK, NULL), "tab shouldn't be blank\n");
562 else
563 ok(_iswctype_l(c, _BLANK, NULL), "%d should be blank\n", c);
564 ok(iswblank(c), "%d should be blank\n", c);
565 ok(_iswblank_l(c, NULL), "%d should be blank\n", c);
566 } else {
567 ok(!_iswctype_l(c, _BLANK, NULL), "%d shouldn't be blank\n", c);
568 ok(!iswblank(c), "%d shouldn't be blank\n", c);
569 ok(!_iswblank_l(c, NULL), "%d shouldn't be blank\n", c);
574 static struct _exception exception;
576 static int CDECL matherr_callback(struct _exception *e)
578 exception = *e;
580 if (!strcmp(e->name, "acos") && e->arg1 == 2)
581 e->retval = -1;
582 return 0;
585 static void test_math_errors(void)
587 const struct {
588 char func[16];
589 double x;
590 int error;
591 int exception;
592 } testsd[] = {
593 {"_logb", -INFINITY, -1, -1},
594 {"_logb", -1, -1, -1},
595 {"_logb", 0, ERANGE, _SING},
596 {"_logb", INFINITY, -1, -1},
597 {"acos", -INFINITY, EDOM, _DOMAIN},
598 {"acos", -2, EDOM, _DOMAIN},
599 {"acos", -1, -1, -1},
600 {"acos", 1, -1, -1},
601 {"acos", 2, EDOM, _DOMAIN},
602 {"acos", INFINITY, EDOM, _DOMAIN},
603 {"acosh", -INFINITY, EDOM, -1},
604 {"acosh", 0, EDOM, -1},
605 {"acosh", 1, -1, -1},
606 {"acosh", INFINITY, -1, -1},
607 {"asin", -INFINITY, EDOM, _DOMAIN},
608 {"asin", -2, EDOM, _DOMAIN},
609 {"asin", -1, -1, -1},
610 {"asin", 1, -1, -1},
611 {"asin", 2, EDOM, _DOMAIN},
612 {"asin", INFINITY, EDOM, _DOMAIN},
613 {"asinh", -INFINITY, -1, -1},
614 {"asinh", INFINITY, -1, -1},
615 {"atan", -INFINITY, -1, -1},
616 {"atan", 0, -1, -1},
617 {"atan", INFINITY, -1, -1},
618 {"atanh", -INFINITY, EDOM, -1},
619 {"atanh", -2, EDOM, -1},
620 {"atanh", -1, ERANGE, -1},
621 {"atanh", 1, ERANGE, -1},
622 {"atanh", 2, EDOM, -1},
623 {"atanh", INFINITY, EDOM, -1},
624 {"cos", -INFINITY, EDOM, _DOMAIN},
625 {"cos", INFINITY, EDOM, _DOMAIN},
626 {"cosh", -INFINITY, -1, -1},
627 {"cosh", 0, -1, -1},
628 {"cosh", INFINITY, -1, -1},
629 {"exp", -INFINITY, -1, -1},
630 {"exp", -1e100, -1, _UNDERFLOW},
631 {"exp", 1e100, ERANGE, _OVERFLOW},
632 {"exp", INFINITY, -1, -1},
633 {"exp2", -INFINITY, -1, -1},
634 {"exp2", -1e100, -1, -1},
635 {"exp2", 1e100, ERANGE, -1},
636 {"exp2", INFINITY, -1, -1},
637 {"expm1", -INFINITY, -1, -1},
638 {"expm1", INFINITY, -1, -1},
639 {"log", -INFINITY, EDOM, _DOMAIN},
640 {"log", -1, EDOM, _DOMAIN},
641 {"log", 0, ERANGE, _SING},
642 {"log", INFINITY, -1, -1},
643 {"log10", -INFINITY, EDOM, _DOMAIN},
644 {"log10", -1, EDOM, _DOMAIN},
645 {"log10", 0, ERANGE, _SING},
646 {"log10", INFINITY, -1, -1},
647 {"log1p", -INFINITY, EDOM, -1},
648 {"log1p", -2, EDOM, -1},
649 {"log1p", -1, ERANGE, -1},
650 {"log1p", INFINITY, -1, -1},
651 {"log2", INFINITY, -1, -1},
652 {"sin", -INFINITY, EDOM, _DOMAIN},
653 {"sin", INFINITY, EDOM, _DOMAIN},
654 {"sinh", -INFINITY, -1, -1},
655 {"sinh", 0, -1, -1},
656 {"sinh", INFINITY, -1, -1},
657 {"sqrt", -INFINITY, EDOM, _DOMAIN},
658 {"sqrt", -1, EDOM, _DOMAIN},
659 {"sqrt", 0, -1, -1},
660 {"sqrt", INFINITY, -1, -1},
661 {"tan", -INFINITY, EDOM, _DOMAIN},
662 {"tan", -M_PI_2, -1, -1},
663 {"tan", M_PI_2, -1, -1},
664 {"tan", INFINITY, EDOM, _DOMAIN},
665 {"tanh", -INFINITY, -1, -1},
666 {"tanh", 0, -1, -1},
667 {"tanh", INFINITY, -1, -1},
669 const struct {
670 char func[16];
671 double a;
672 double b;
673 int error;
674 int exception;
675 } tests2d[] = {
676 {"atan2", -INFINITY, 0, -1, -1},
677 {"atan2", 0, 0, -1, -1},
678 {"atan2", INFINITY, 0, -1, -1},
679 {"atan2", 0, -INFINITY, -1, -1},
680 {"atan2", 0, INFINITY, -1, -1},
681 {"pow", -INFINITY, -2, -1, -1},
682 {"pow", -INFINITY, -1, -1, -1},
683 {"pow", -INFINITY, 0, -1, -1},
684 {"pow", -INFINITY, 1, -1, -1},
685 {"pow", -INFINITY, 2, -1, -1},
686 {"pow", -1e100, -10, -1, _UNDERFLOW},
687 {"pow", -1e100, 10, ERANGE, _OVERFLOW},
688 {"pow", -1, 1.5, EDOM, _DOMAIN},
689 {"pow", 0, -2, ERANGE, _SING},
690 {"pow", 0, -1, ERANGE, _SING},
691 {"pow", 0.5, -INFINITY, -1, -1},
692 {"pow", 0.5, INFINITY, -1, -1},
693 {"pow", 2, -INFINITY, -1, -1},
694 {"pow", 2, -1e100, -1, _UNDERFLOW},
695 {"pow", 2, 1e100, ERANGE, _OVERFLOW},
696 {"pow", 2, INFINITY, -1, -1},
697 {"pow", 1e100, -10, -1, _UNDERFLOW},
698 {"pow", 1e100, 10, ERANGE, _OVERFLOW},
699 {"pow", INFINITY, -2, -1, -1},
700 {"pow", INFINITY, -1, -1, -1},
701 {"pow", INFINITY, 0, -1, -1},
702 {"pow", INFINITY, 1, -1, -1},
703 {"pow", INFINITY, 2, -1, -1},
705 const struct {
706 char func[16];
707 double a;
708 double b;
709 double c;
710 int error;
711 int exception;
712 } tests3d[] = {
713 /* 0 * inf --> EDOM */
714 {"fma", INFINITY, 0, 0, EDOM, -1},
715 {"fma", 0, INFINITY, 0, EDOM, -1},
716 /* inf - inf -> EDOM */
717 {"fma", INFINITY, 1, -INFINITY, EDOM, -1},
718 {"fma", -INFINITY, 1, INFINITY, EDOM, -1},
719 {"fma", 1, INFINITY, -INFINITY, EDOM, -1},
720 {"fma", 1, -INFINITY, INFINITY, EDOM, -1},
721 /* NaN */
722 {"fma", NAN, 0, 0, -1, -1},
723 {"fma", 0, NAN, 0, -1, -1},
724 {"fma", 0, 0, NAN, -1, -1},
725 /* over/underflow */
726 {"fma", __port_max_double(), __port_max_double(), __port_max_double(), -1, -1},
727 {"fma", __port_min_pos_double(), __port_min_pos_double(), 1, -1, -1},
729 const struct {
730 char func[16];
731 double a;
732 long b;
733 int error;
734 int exception;
735 } testsdl[] = {
736 {"_scalb", -INFINITY, 1, -1, -1},
737 {"_scalb", -1e100, 1, -1, -1},
738 {"_scalb", 0, 1, -1, -1},
739 {"_scalb", 1e100, 1, -1, -1},
740 {"_scalb", INFINITY, 1, -1, -1},
741 {"_scalb", 1, 1e9, ERANGE, _OVERFLOW},
742 {"ldexp", -INFINITY, 1, -1, -1},
743 {"ldexp", -1e100, 1, -1, -1},
744 {"ldexp", 0, 1, -1, -1},
745 {"ldexp", 1e100, 1, -1, -1},
746 {"ldexp", INFINITY, 1, -1, -1},
747 {"ldexp", 1, -1e9, -1, _UNDERFLOW},
748 {"ldexp", 1, 1e9, ERANGE, _OVERFLOW},
750 double (CDECL *p_funcd)(double);
751 double (CDECL *p_func2d)(double, double);
752 double (CDECL *p_func3d)(double, double, double);
753 double (CDECL *p_funcdl)(double, long);
754 HMODULE module;
755 double d;
756 int i;
758 __setusermatherr(matherr_callback);
759 module = GetModuleHandleW(L"ucrtbase.dll");
761 /* necessary so that exp(1e100)==INFINITY on glibc, we can remove this if we change our implementation */
762 fesetround(FE_TONEAREST);
764 for(i = 0; i < ARRAY_SIZE(testsd); i++) {
765 p_funcd = (void*)GetProcAddress(module, testsd[i].func);
766 errno = -1;
767 exception.type = -1;
768 p_funcd(testsd[i].x);
769 ok(errno == testsd[i].error,
770 "%s(%f) got errno %d\n", testsd[i].func, testsd[i].x, errno);
771 ok(exception.type == testsd[i].exception,
772 "%s(%f) got exception type %d\n", testsd[i].func, testsd[i].x, exception.type);
773 if(exception.type == -1) continue;
774 ok(exception.arg1 == testsd[i].x,
775 "%s(%f) got exception arg1 %f\n", testsd[i].func, testsd[i].x, exception.arg1);
778 for(i = 0; i < ARRAY_SIZE(tests2d); i++) {
779 p_func2d = (void*)GetProcAddress(module, tests2d[i].func);
780 errno = -1;
781 exception.type = -1;
782 p_func2d(tests2d[i].a, tests2d[i].b);
783 ok(errno == tests2d[i].error,
784 "%s(%f, %f) got errno %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, errno);
785 ok(exception.type == tests2d[i].exception,
786 "%s(%f, %f) got exception type %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.type);
787 if(exception.type == -1) continue;
788 ok(exception.arg1 == tests2d[i].a,
789 "%s(%f, %f) got exception arg1 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg1);
790 ok(exception.arg2 == tests2d[i].b,
791 "%s(%f, %f) got exception arg2 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg2);
794 for(i = 0; i < ARRAY_SIZE(tests3d); i++) {
795 p_func3d = (void*)GetProcAddress(module, tests3d[i].func);
796 errno = -1;
797 exception.type = -1;
798 p_func3d(tests3d[i].a, tests3d[i].b, tests3d[i].c);
799 ok(errno == tests3d[i].error,
800 "%s(%f, %f, %f) got errno %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, errno);
801 ok(exception.type == tests3d[i].exception,
802 "%s(%f, %f, %f) got exception type %d\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.type);
803 if(exception.type == -1) continue;
804 ok(exception.arg1 == tests3d[i].a,
805 "%s(%f, %f, %f) got exception arg1 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg1);
806 ok(exception.arg2 == tests3d[i].b,
807 "%s(%f, %f, %f) got exception arg2 %f\n", tests3d[i].func, tests3d[i].a, tests3d[i].b, tests3d[i].c, exception.arg2);
810 for(i = 0; i < ARRAY_SIZE(testsdl); i++) {
811 p_funcdl = (void*)GetProcAddress(module, testsdl[i].func);
812 errno = -1;
813 exception.type = -1;
814 p_funcdl(testsdl[i].a, testsdl[i].b);
815 ok(errno == testsdl[i].error,
816 "%s(%f, %ld) got errno %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, errno);
817 ok(exception.type == testsdl[i].exception,
818 "%s(%f, %ld) got exception type %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.type);
819 if(exception.type == -1) continue;
820 ok(exception.arg1 == testsdl[i].a,
821 "%s(%f, %ld) got exception arg1 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg1);
822 ok(exception.arg2 == testsdl[i].b,
823 "%s(%f, %ld) got exception arg2 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg2);
826 d = acos(2.0);
827 ok(d == -1.0, "failed to change log10 return value: %e\n", d);
830 static void test_asctime(void)
832 const struct tm epoch = { 0, 0, 0, 1, 0, 70, 4, 0, 0 };
833 char *ret;
835 ret = asctime(&epoch);
836 ok(!strcmp(ret, "Thu Jan 1 00:00:00 1970\n"), "asctime returned %s\n", ret);
839 static void test_strftime(void)
841 const struct {
842 const char *format;
843 const char *ret;
844 struct tm tm;
845 BOOL todo_value;
846 BOOL todo_handler;
847 } tests[] = {
848 {"%C", "", { 0, 0, 0, 1, 0, -2000, 4, 0, 0 }},
849 {"%C", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }},
850 {"%C", "00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }},
851 {"%C", "18", { 0, 0, 0, 1, 0, -1, 4, 0, 0 }},
852 {"%C", "19", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
853 {"%C", "99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }},
854 {"%C", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }},
855 {"%d", "", { 0, 0, 0, 0, 0, 70, 4, 0, 0 }},
856 {"%d", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
857 {"%d", "31", { 0, 0, 0, 31, 0, 70, 4, 0, 0 }},
858 {"%d", "", { 0, 0, 0, 32, 0, 70, 4, 0, 0 }},
859 {"%D", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }},
860 {"%D", "01/01/00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }},
861 {"%D", "01/01/99", { 0, 0, 0, 1, 0, -1, 4, 0, 0 }},
862 {"%D", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
863 {"%D", "01/01/99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }},
864 {"%D", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }},
865 {"%#D", "1/1/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
866 {"%e", "", { 0, 0, 0, 0, 0, 70, 4, 0, 0 }},
867 {"%e", " 1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
868 {"%e", "31", { 0, 0, 0, 31, 0, 70, 4, 0, 0 }},
869 {"%e", "", { 0, 0, 0, 32, 0, 70, 4, 0, 0 }},
870 {"%#e", "1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
871 {"%F", "1970-01-01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
872 {"%#F", "1970-1-1", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
873 {"%R", "00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
874 {"%#R", "0:0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
875 {"%T", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
876 {"%#T", "0:0:0", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
877 {"%u", "", { 0, 0, 0, 1, 0, 117, -1, 0, 0 }},
878 {"%u", "7", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }},
879 {"%u", "1", { 0, 0, 0, 1, 0, 117, 1, 0, 0 }},
880 {"%u", "6", { 0, 0, 0, 1, 0, 117, 6, 0, 0 }},
881 {"%u", "", { 0, 0, 0, 1, 0, 117, 7, 0, 0 }},
882 {"%h", "Jan", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
883 {"%I", "", { 0, 0, -1, 1, 0, 70, 4, 0, 0 }},
884 {"%I", "12", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
885 {"%I", "01", { 0, 0, 1, 1, 0, 70, 4, 0, 0 }},
886 {"%I", "11", { 0, 0, 11, 1, 0, 70, 4, 0, 0 }},
887 {"%I", "12", { 0, 0, 12, 1, 0, 70, 4, 0, 0 }},
888 {"%I", "01", { 0, 0, 13, 1, 0, 70, 4, 0, 0 }},
889 {"%I", "11", { 0, 0, 23, 1, 0, 70, 4, 0, 0 }},
890 {"%I", "", { 0, 0, 24, 1, 0, 70, 4, 0, 0 }},
891 {"%n", "\n", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
892 {"%r", "12:00:00 AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
893 {"%r", "02:00:00 PM", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }},
894 {"%#r", "12:0:0 AM", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
895 {"%#r", "2:0:0 PM", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }},
896 {"%t", "\t", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
897 {"%g", "", { 0, 0, 0, 1, 0, -1901, 4, 0, 0 }},
898 {"%g", "", { 0, 0, 0, 1, 0, -1901, 3, 364, 0 }},
899 {"%g", "00", { 0, 0, 0, 1, 0, -1900, 4, 0, 0 }},
900 {"%g", "70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
901 {"%g", "71", { 0, 0, 0, 2, 0, 72, 0, 1, 0 }},
902 {"%g", "72", { 0, 0, 0, 3, 0, 72, 1, 2, 0 }},
903 {"%g", "16", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }},
904 {"%g", "99", { 0, 0, 0, 1, 0, 8099, 4, 0, 0 }},
905 {"%g", "00", { 0, 0, 0, 1, 0, 8099, 3, 364, 0 }},
906 {"%g", "", { 0, 0, 0, 1, 0, 8100, 0, 0, 0 }},
907 {"%g", "", { 0, 0, 0, 1, 0, 8100, 4, 0, 0 }},
908 {"%G", "1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
909 {"%G", "1971", { 0, 0, 0, 2, 0, 72, 0, 1, 0 }},
910 {"%G", "1972", { 0, 0, 0, 3, 0, 72, 1, 2, 0 }},
911 {"%G", "2016", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }},
912 {"%V", "01", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
913 {"%V", "52", { 0, 0, 0, 1, 0, 117, 0, 0, 0 }},
914 {"%V", "53", { 0, 0, 14, 1, 0, 121, 6, 0, 0 }},
915 {"%y", "", { 0, 0, 0, 0, 0, -1901, 0, 0, 0 }},
916 {"%y", "00", { 0, 0, 0, 0, 0, -1900, 0, 0, 0 }},
917 {"%y", "99", { 0, 0, 0, 0, 0, 8099, 0, 0, 0 }},
918 {"%y", "", { 0, 0, 0, 0, 0, 8100, 0, 0, 0 }},
919 {"%c", "Thu Jan 1 00:00:00 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
920 {"%c", "Thu Feb 30 00:00:00 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
921 {"%#c", "Thursday, January 01, 1970 00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
922 {"%#c", "Thursday, February 30, 1970 00:00:00", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
923 {"%x", "01/01/70", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
924 {"%x", "02/30/70", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
925 {"%#x", "Thursday, January 01, 1970", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
926 {"%#x", "Thursday, February 30, 1970", { 0, 0, 0, 30, 1, 70, 4, 0, 0 }},
927 {"%#x", "", { 0, 0, 0, 30, 1, 70, 7, 0, 0 }},
928 {"%#x", "", { 0, 0, 0, 30, 12, 70, 4, 0, 0 }},
929 {"%X", "00:00:00", { 0, 0, 0, 1, 0, 70, 4, 0, 0 }},
930 {"%X", "14:00:00", { 0, 0, 14, 1, 0, 70, 4, 0, 0 }},
931 {"%X", "23:59:60", { 60, 59, 23, 1, 0, 70, 4, 0, 0 }},
934 const struct {
935 const char *format;
936 const char *ret;
937 const wchar_t *short_date;
938 const wchar_t *date;
939 const wchar_t *time;
940 struct tm tm;
941 BOOL todo;
942 } tests_td[] = {
943 { "%c", "x z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
944 { "%#c", "y z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
945 { "%X", "M1", 0, 0, L"MMM", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
946 { "%X", "1", 0, 0, L"h", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
947 { "%X", "01", 0, 0, L"hh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
948 { "%X", "h01", 0, 0, L"hhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
949 { "%X", "hh01", 0, 0, L"hhhh", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
950 { "%X", "1", 0, 0, L"H", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
951 { "%X", "01", 0, 0, L"HH", { 0, 0, 1, 1, 0, 70, 0, 0, 0 }},
952 { "%X", "H13", 0, 0, L"HHH", { 0, 0, 13, 1, 0, 70, 0, 0, 0 }},
953 { "%X", "0", 0, 0, L"m", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
954 { "%X", "00", 0, 0, L"mm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
955 { "%X", "m00", 0, 0, L"mmm", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
956 { "%X", "0", 0, 0, L"s", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
957 { "%X", "00", 0, 0, L"ss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
958 { "%X", "s00", 0, 0, L"sss", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
959 { "%X", "T", 0, 0, L"t", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
960 { "%X", "TAM", 0, 0, L"tt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
961 { "%X", "TAM", 0, 0, L"ttttttttt", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
962 { "%X", "TAM", 0, 0, L"a", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
963 { "%X", "TAM", 0, 0, L"aaaaa", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
964 { "%X", "TAM", 0, 0, L"A", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
965 { "%X", "TAM", 0, 0, L"AAAAA", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
966 { "%x", "1", L"d", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
967 { "%x", "01", L"dd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
968 { "%x", "D1", L"ddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
969 { "%x", "Day1", L"dddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
970 { "%x", "dDay1", L"ddddd", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
971 { "%x", "1", L"M", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
972 { "%x", "01", L"MM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
973 { "%x", "M1", L"MMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
974 { "%x", "Mon1", L"MMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
975 { "%x", "MMon1", L"MMMMM", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
976 { "%x", "y", L"y", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
977 { "%x", "70", L"yy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
978 { "%x", "y70", L"yyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
979 { "%x", "1970", L"yyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
980 { "%x", "y1970", L"yyyyy", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
981 { "%x", "ggggggggggg", L"ggggggggggg", 0, 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
982 { "%#x", "1", 0, L"d", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
983 { "%#x", "01", 0, L"dd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
984 { "%#x", "D1", 0, L"ddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
985 { "%#x", "Day1", 0, L"dddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
986 { "%#x", "dDay1", 0, L"ddddd", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
987 { "%#x", "1", 0, L"M", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
988 { "%#x", "01", 0, L"MM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
989 { "%#x", "M1", 0, L"MMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
990 { "%#x", "Mon1", 0, L"MMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
991 { "%#x", "MMon1", 0, L"MMMMM", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
992 { "%#x", "y", 0, L"y", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
993 { "%#x", "70", 0, L"yy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
994 { "%#x", "y70", 0, L"yyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
995 { "%#x", "1970", 0, L"yyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
996 { "%#x", "y1970", 0, L"yyyyy", 0, { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
997 { "%r", "z", L"x", L"y", L"z", { 0, 0, 0, 1, 0, 70, 0, 0, 0 }},
1000 const struct {
1001 int year;
1002 int yday;
1003 const char *ret[7];
1004 } tests_yweek[] = {
1005 { 100, 0, { "99 52", "00 01", "00 01", "00 01", "00 01", "99 53", "99 52" }},
1006 { 100, 1, { "99 52", "00 01", "00 01", "00 01", "00 01", "00 01", "99 53" }},
1007 { 100, 2, { "99 53", "00 01", "00 01", "00 01", "00 01", "00 01", "00 01" }},
1008 { 100, 3, { "00 01", "00 01", "00 01", "00 01", "00 01", "00 01", "00 01" }},
1009 { 100, 4, { "00 01", "00 02", "00 01", "00 01", "00 01", "00 01", "00 01" }},
1010 { 100, 5, { "00 01", "00 02", "00 02", "00 01", "00 01", "00 01", "00 01" }},
1011 { 100, 6, { "00 01", "00 02", "00 02", "00 02", "00 01", "00 01", "00 01" }},
1012 { 100, 358, { "00 51", "00 52", "00 52", "00 52", "00 52", "00 52", "00 51" }},
1013 { 100, 359, { "00 51", "00 52", "00 52", "00 52", "00 52", "00 52", "00 52" }},
1014 { 100, 360, { "00 52", "00 52", "00 52", "00 52", "00 52", "00 52", "00 52" }},
1015 { 100, 361, { "00 52", "00 53", "00 52", "00 52", "00 52", "00 52", "00 52" }},
1016 { 100, 362, { "00 52", "00 53", "00 53", "00 52", "00 52", "00 52", "00 52" }},
1017 { 100, 363, { "00 52", "01 01", "00 53", "00 53", "00 52", "00 52", "00 52" }},
1018 { 100, 364, { "00 52", "01 01", "01 01", "00 53", "00 53", "00 52", "00 52" }},
1019 { 100, 365, { "00 52", "01 01", "01 01", "01 01", "00 53", "00 53", "00 52" }},
1020 { 101, 0, { "00 52", "01 01", "01 01", "01 01", "01 01", "00 53", "00 53" }},
1021 { 101, 1, { "00 53", "01 01", "01 01", "01 01", "01 01", "01 01", "00 53" }},
1022 { 101, 2, { "00 53", "01 01", "01 01", "01 01", "01 01", "01 01", "01 01" }},
1023 { 101, 3, { "01 01", "01 01", "01 01", "01 01", "01 01", "01 01", "01 01" }},
1024 { 101, 4, { "01 01", "01 02", "01 01", "01 01", "01 01", "01 01", "01 01" }},
1025 { 101, 5, { "01 01", "01 02", "01 02", "01 01", "01 01", "01 01", "01 01" }},
1026 { 101, 6, { "01 01", "01 02", "01 02", "01 02", "01 01", "01 01", "01 01" }},
1027 { 101, 358, { "01 51", "01 52", "01 52", "01 52", "01 52", "01 52", "01 51" }},
1028 { 101, 359, { "01 51", "01 52", "01 52", "01 52", "01 52", "01 52", "01 52" }},
1029 { 101, 360, { "01 52", "01 52", "01 52", "01 52", "01 52", "01 52", "01 52" }},
1030 { 101, 361, { "01 52", "01 53", "01 52", "01 52", "01 52", "01 52", "01 52" }},
1031 { 101, 362, { "01 52", "02 01", "01 53", "01 52", "01 52", "01 52", "01 52" }},
1032 { 101, 363, { "01 52", "02 01", "02 01", "01 53", "01 52", "01 52", "01 52" }},
1033 { 101, 364, { "01 52", "02 01", "02 01", "02 01", "01 53", "01 52", "01 52" }},
1036 __lc_time_data time_data = {
1037 { "d1", "d2", "d3", "d4", "d5", "d6", "d7" },
1038 { "day1", "day2", "day3", "day4", "day5", "day6", "day7" },
1039 { "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9", "m10", "m11", "m12" },
1040 { "mon1", "mon2", "mon3", "mon4", "mon5", "mon6", "mon7", "mon8", "mon9", "mon10", "mon11", "mon12" },
1041 "tam", "tpm", 0, 0, 0, 1, 0,
1042 { L"D1", L"D2", L"D3", L"D4", L"D5", L"D6", L"D7" },
1043 { L"Day1", L"Day2", L"Day3", L"Day4", L"Day5", L"Day6", L"Day7" },
1044 { L"M1", L"M2", L"M3", L"M4", L"M5", L"M6", L"M7", L"M8", L"M9", L"M10", L"M11", L"M12" },
1045 { L"Mon1", L"Mon2", L"Mon3", L"Mon4", L"Mon5", L"Mon6", L"Mon7", L"Mon8", L"Mon9", L"Mon10", L"Mon11", L"Mon12" },
1046 L"TAM", L"TPM"
1049 const struct tm epoch = { 0, 0, 0, 1, 0, 70, 4, 0, 0 };
1050 struct tm tm_yweek = { 0, 0, 0, 1, 0, 70, 0, 0, 0 };
1051 char buf[256];
1052 int i, ret=0;
1054 for (i=0; i<ARRAY_SIZE(tests); i++)
1056 todo_wine_if(tests[i].todo_handler) {
1057 if (!tests[i].ret[0])
1058 SET_EXPECT(global_invalid_parameter_handler);
1059 ret = strftime(buf, sizeof(buf), tests[i].format, &tests[i].tm);
1060 if (!tests[i].ret[0])
1061 CHECK_CALLED(global_invalid_parameter_handler);
1064 todo_wine_if(tests[i].todo_value) {
1065 ok(ret == strlen(tests[i].ret), "%d) ret = %d\n", i, ret);
1066 ok(!strcmp(buf, tests[i].ret), "%d) buf = \"%s\", expected \"%s\"\n",
1067 i, buf, tests[i].ret);
1071 ret = strftime(buf, sizeof(buf), "%z", &epoch);
1072 ok(ret == 5, "expected 5, got %d\n", ret);
1073 ok((buf[0] == '+' || buf[0] == '-') &&
1074 isdigit(buf[1]) && isdigit(buf[2]) &&
1075 isdigit(buf[3]) && isdigit(buf[4]), "got %s\n", buf);
1077 for (i=0; i<ARRAY_SIZE(tests_td); i++)
1079 time_data.short_dateW = tests_td[i].short_date;
1080 time_data.dateW = tests_td[i].date;
1081 time_data.timeW = tests_td[i].time;
1082 ret = _Strftime(buf, sizeof(buf), tests_td[i].format, &tests_td[i].tm, &time_data);
1083 ok(ret == strlen(buf), "%d) ret = %d\n", i, ret);
1084 todo_wine_if(tests_td[i].todo) {
1085 ok(!strcmp(buf, tests_td[i].ret), "%d) buf = \"%s\", expected \"%s\"\n",
1086 i, buf, tests_td[i].ret);
1090 for (i=0; i<ARRAY_SIZE(tests_yweek); i++)
1092 int j;
1093 tm_yweek.tm_year = tests_yweek[i].year;
1094 tm_yweek.tm_yday = tests_yweek[i].yday;
1095 for (j=0; j<7; j++)
1097 tm_yweek.tm_wday = j;
1098 strftime(buf, sizeof(buf), "%g %V", &tm_yweek);
1099 ok(!strcmp(buf, tests_yweek[i].ret[j]), "%d,%d) buf = \"%s\", expected \"%s\"\n",
1100 i, j, buf, tests_yweek[i].ret[j]);
1104 if(!setlocale(LC_ALL, "fr-FR")) {
1105 win_skip("fr-FR locale not available\n");
1106 return;
1108 ret = strftime(buf, sizeof(buf), "%c", &epoch);
1109 ok(ret == 19, "ret = %d\n", ret);
1110 ok(!strcmp(buf, "01/01/1970 00:00:00"), "buf = \"%s\", expected \"%s\"\n", buf, "01/01/1970 00:00:00");
1111 ret = strftime(buf, sizeof(buf), "%r", &epoch);
1112 ok(ret == 8, "ret = %d\n", ret);
1113 ok(!strcmp(buf, "00:00:00"), "buf = \"%s\", expected \"%s\"\n", buf, "00:00:00");
1114 setlocale(LC_ALL, "C");
1116 if(!setlocale(LC_TIME, "Japanese_Japan.932")) {
1117 win_skip("Japanese_Japan.932 locale not available\n");
1118 return;
1120 ret = strftime(buf, sizeof(buf), "%a", &epoch);
1121 ok(ret == 2 || broken(ret == 1), "ret = %d\n", ret);
1122 ok(!strcmp(buf, "\x96\xd8"), "buf = %s, expected \"\\x96\\xd8\"\n", wine_dbgstr_an(buf, 2));
1123 setlocale(LC_ALL, "C");
1126 static LONG* get_failures_counter(HANDLE *map)
1128 *map = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
1129 0, sizeof(LONG), "winetest_failures_counter");
1130 return MapViewOfFile(*map, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LONG));
1133 static void free_failures_counter(LONG *mem, HANDLE map)
1135 UnmapViewOfFile(mem);
1136 CloseHandle(map);
1139 static void set_failures_counter(LONG add)
1141 HANDLE failures_map;
1142 LONG *failures;
1144 failures = get_failures_counter(&failures_map);
1145 *failures = add;
1146 free_failures_counter(failures, failures_map);
1149 static void test_exit(const char *argv0)
1151 PROCESS_INFORMATION proc;
1152 STARTUPINFOA startup = {0};
1153 char path[MAX_PATH];
1154 HANDLE failures_map, exit_event, quick_exit_event;
1155 LONG *failures;
1156 DWORD ret;
1158 exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event");
1159 quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event");
1161 failures = get_failures_counter(&failures_map);
1162 sprintf(path, "%s misc exit", argv0);
1163 startup.cb = sizeof(startup);
1164 CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc);
1165 ret = WaitForSingleObject(proc.hProcess, INFINITE);
1166 ok(ret == WAIT_OBJECT_0, "child process wait failed\n");
1167 GetExitCodeProcess(proc.hProcess, &ret);
1168 ok(ret == 1, "child process exited with code %d\n", ret);
1169 CloseHandle(proc.hProcess);
1170 CloseHandle(proc.hThread);
1171 ok(!*failures, "%d tests failed in child process\n", *failures);
1172 free_failures_counter(failures, failures_map);
1175 ret = WaitForSingleObject(exit_event, 0);
1176 ok(ret == WAIT_OBJECT_0, "exit_event was not set (%x)\n", ret);
1177 ret = WaitForSingleObject(quick_exit_event, 0);
1178 ok(ret == WAIT_TIMEOUT, "quick_exit_event should not have be set (%x)\n", ret);
1180 CloseHandle(exit_event);
1181 CloseHandle(quick_exit_event);
1184 static int atexit_called;
1186 static void CDECL at_exit_func1(void)
1188 HANDLE exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event");
1190 ok(exit_event != NULL, "CreateEvent failed: %d\n", GetLastError());
1191 ok(atexit_called == 1, "atexit_called = %d\n", atexit_called);
1192 atexit_called++;
1193 SetEvent(exit_event);
1194 CloseHandle(exit_event);
1195 set_failures_counter(winetest_get_failures());
1198 static void CDECL at_exit_func2(void)
1200 ok(!atexit_called, "atexit_called = %d\n", atexit_called);
1201 atexit_called++;
1202 set_failures_counter(winetest_get_failures());
1205 static int atquick_exit_called;
1207 static void CDECL at_quick_exit_func1(void)
1209 HANDLE quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event");
1211 ok(quick_exit_event != NULL, "CreateEvent failed: %d\n", GetLastError());
1212 ok(atquick_exit_called == 1, "atquick_exit_called = %d\n", atquick_exit_called);
1213 atquick_exit_called++;
1214 SetEvent(quick_exit_event);
1215 CloseHandle(quick_exit_event);
1216 set_failures_counter(winetest_get_failures());
1219 static void CDECL at_quick_exit_func2(void)
1221 ok(!atquick_exit_called, "atquick_exit_called = %d\n", atquick_exit_called);
1222 atquick_exit_called++;
1223 set_failures_counter(winetest_get_failures());
1226 static void test_call_exit(void)
1228 ok(!_crt_atexit(at_exit_func1), "_crt_atexit failed\n");
1229 ok(!_crt_atexit(at_exit_func2), "_crt_atexit failed\n");
1231 ok(!_crt_at_quick_exit(at_quick_exit_func1), "_crt_at_quick_exit failed\n");
1232 ok(!_crt_at_quick_exit(at_quick_exit_func2), "_crt_at_quick_exit failed\n");
1234 set_failures_counter(winetest_get_failures());
1235 exit(1);
1238 static void test_call_quick_exit(void)
1240 ok(!_crt_atexit(at_exit_func1), "_crt_atexit failed\n");
1241 ok(!_crt_atexit(at_exit_func2), "_crt_atexit failed\n");
1243 ok(!_crt_at_quick_exit(at_quick_exit_func1), "_crt_at_quick_exit failed\n");
1244 ok(!_crt_at_quick_exit(at_quick_exit_func2), "_crt_at_quick_exit failed\n");
1246 set_failures_counter(winetest_get_failures());
1247 quick_exit(2);
1250 static void test_quick_exit(const char *argv0)
1252 PROCESS_INFORMATION proc;
1253 STARTUPINFOA startup = {0};
1254 char path[MAX_PATH];
1255 HANDLE failures_map, exit_event, quick_exit_event;
1256 LONG *failures;
1257 DWORD ret;
1259 exit_event = CreateEventA(NULL, FALSE, FALSE, "exit_event");
1260 quick_exit_event = CreateEventA(NULL, FALSE, FALSE, "quick_exit_event");
1262 failures = get_failures_counter(&failures_map);
1263 sprintf(path, "%s misc quick_exit", argv0);
1264 startup.cb = sizeof(startup);
1265 CreateProcessA(NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &proc);
1266 ret = WaitForSingleObject(proc.hProcess, INFINITE);
1267 ok(ret == WAIT_OBJECT_0, "child process wait failed\n");
1268 GetExitCodeProcess(proc.hProcess, &ret);
1269 ok(ret == 2, "child process exited with code %d\n", ret);
1270 CloseHandle(proc.hProcess);
1271 CloseHandle(proc.hThread);
1272 ok(!*failures, "%d tests failed in child process\n", *failures);
1273 free_failures_counter(failures, failures_map);
1275 ret = WaitForSingleObject(quick_exit_event, 0);
1276 ok(ret == WAIT_OBJECT_0, "quick_exit_event was not set (%x)\n", ret);
1277 ret = WaitForSingleObject(exit_event, 0);
1278 ok(ret == WAIT_TIMEOUT, "exit_event should not have be set (%x)\n", ret);
1280 CloseHandle(exit_event);
1281 CloseHandle(quick_exit_event);
1284 static void test__stat32(void)
1286 static const char test_file[] = "\\stat_file.tst";
1287 static const char test_dir[] = "\\stat_dir.tst";
1289 char path[2*MAX_PATH];
1290 struct _stat32 buf;
1291 int fd, ret;
1292 DWORD len;
1294 len = GetTempPathA(MAX_PATH, path);
1295 ok(len, "GetTempPathA failed\n");
1297 ret = _stat32("c:", &buf);
1298 ok(ret == -1, "_stat32('c:') returned %d\n", ret);
1299 ret = _stat32("c:\\", &buf);
1300 ok(!ret, "_stat32('c:\\') returned %d\n", ret);
1302 memcpy(path+len, test_file, sizeof(test_file));
1303 if((fd = open(path, O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE)) >= 0)
1305 ret = _stat32(path, &buf);
1306 ok(!ret, "_stat32('%s') returned %d\n", path, ret);
1307 strcat(path, "\\");
1308 ret = _stat32(path, &buf);
1309 todo_wine ok(ret, "_stat32('%s') returned %d\n", path, ret);
1310 close(fd);
1311 remove(path);
1314 memcpy(path+len, test_dir, sizeof(test_dir));
1315 if(!mkdir(path))
1317 ret = _stat32(path, &buf);
1318 ok(!ret, "_stat32('%s') returned %d\n", path, ret);
1319 strcat(path, "\\");
1320 ret = _stat32(path, &buf);
1321 ok(!ret, "_stat32('%s') returned %d\n", path, ret);
1322 rmdir(path);
1326 static void test__o_malloc(void)
1328 void *m;
1329 size_t s;
1331 m = _o_malloc(1);
1332 ok(m != NULL, "p__o_malloc(1) returned NULL\n");
1334 s = _msize(m);
1335 ok(s == 1, "_msize returned %d\n", (int)s);
1337 free(m);
1340 static void test_clock(void)
1342 static const int thresh = 100, max_load_delay = 1000;
1343 int c, expect_min;
1344 FILETIME cur;
1346 GetSystemTimeAsFileTime(&cur);
1347 c = clock();
1349 expect_min = (((LONGLONG)cur.dwHighDateTime << 32) + cur.dwLowDateTime - crt_init_end) / 10000;
1350 ok(c >= expect_min - thresh && c < expect_min + max_load_delay, "clock() = %d, expected range [%d, %d]\n",
1351 c, expect_min - thresh, expect_min + max_load_delay);
1354 static void __cdecl se_translator(unsigned int u, EXCEPTION_POINTERS *ep)
1358 static void test_thread_storage(void)
1360 void **current_exception;
1361 void *processing_throw;
1363 _set_se_translator(se_translator);
1364 current_exception = __current_exception();
1365 processing_throw = __processing_throw();
1367 ok(current_exception+2 == processing_throw,
1368 "current_exception = %p, processing_throw = %p\n",
1369 current_exception, processing_throw);
1370 ok(current_exception[-2] == se_translator,
1371 "can't find se_translator in thread storage\n");
1374 START_TEST(misc)
1376 int arg_c;
1377 char** arg_v;
1378 FILETIME cur;
1380 GetSystemTimeAsFileTime(&cur);
1381 crt_init_end = ((LONGLONG)cur.dwHighDateTime << 32) + cur.dwLowDateTime;
1383 arg_c = winetest_get_mainargs(&arg_v);
1384 if(arg_c == 3) {
1385 if(!strcmp(arg_v[2], "cmd"))
1386 test__get_narrow_winmain_command_line(NULL);
1387 else if(!strcmp(arg_v[2], "exit"))
1388 test_call_exit();
1389 else if(!strcmp(arg_v[2], "quick_exit"))
1390 test_call_quick_exit();
1391 return;
1394 test_invalid_parameter_handler();
1395 test__initialize_onexit_table();
1396 test__register_onexit_function();
1397 test__execute_onexit_table();
1398 test___fpe_flt_rounds();
1399 test__control87_2();
1400 test__get_narrow_winmain_command_line(arg_v[0]);
1401 test__sopen_dispatch();
1402 test__sopen_s();
1403 test_lldiv();
1404 test_isblank();
1405 test_math_errors();
1406 test_asctime();
1407 test_strftime();
1408 test_exit(arg_v[0]);
1409 test_quick_exit(arg_v[0]);
1410 test__stat32();
1411 test__o_malloc();
1412 test_clock();
1413 test_thread_storage();