msvcrt: Set the correct error number in pow(f).
[wine.git] / dlls / ucrtbase / tests / misc.c
blobd17f2d08864132c8c4719d26ddeb35c16f16236f
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 <float.h>
25 #include <io.h>
26 #include <sys/stat.h>
27 #include <share.h>
28 #include <fcntl.h>
30 #include <windef.h>
31 #include <winbase.h>
32 #include "wine/test.h"
34 #define DEFINE_EXPECT(func) \
35 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
37 #define SET_EXPECT(func) \
38 expect_ ## func = TRUE
40 #define CHECK_EXPECT2(func) \
41 do { \
42 ok(expect_ ##func, "unexpected call " #func "\n"); \
43 called_ ## func = TRUE; \
44 }while(0)
46 #define CHECK_EXPECT(func) \
47 do { \
48 CHECK_EXPECT2(func); \
49 expect_ ## func = FALSE; \
50 }while(0)
52 #define CHECK_CALLED(func) \
53 do { \
54 ok(called_ ## func, "expected " #func "\n"); \
55 expect_ ## func = called_ ## func = FALSE; \
56 }while(0)
58 static inline float __port_infinity(void)
60 static const unsigned __inf_bytes = 0x7f800000;
61 return *(const float *)&__inf_bytes;
63 #define INFINITY __port_infinity()
65 #define M_PI_2 1.57079632679489661923
67 #define FE_TONEAREST 0
69 #define _DOMAIN 1 /* domain error in argument */
70 #define _SING 2 /* singularity */
71 #define _OVERFLOW 3 /* range overflow */
72 #define _UNDERFLOW 4 /* range underflow */
74 DEFINE_EXPECT(global_invalid_parameter_handler);
75 DEFINE_EXPECT(thread_invalid_parameter_handler);
77 typedef int (CDECL *MSVCRT__onexit_t)(void);
79 typedef struct MSVCRT__onexit_table_t
81 MSVCRT__onexit_t *_first;
82 MSVCRT__onexit_t *_last;
83 MSVCRT__onexit_t *_end;
84 } MSVCRT__onexit_table_t;
86 typedef struct MSVCRT__lldiv_t {
87 LONGLONG quot; /* quotient */
88 LONGLONG rem; /* remainder */
89 } MSVCRT_lldiv_t;
91 typedef struct MSVCRT__exception {
92 int type;
93 char* name;
94 double arg1;
95 double arg2;
96 double retval;
97 } MSVCRT__exception;
99 typedef int (CDECL *MSVCRT_matherr_func)(struct MSVCRT__exception *);
101 static HMODULE module;
103 static int (CDECL *p_initialize_onexit_table)(MSVCRT__onexit_table_t *table);
104 static int (CDECL *p_register_onexit_function)(MSVCRT__onexit_table_t *table, MSVCRT__onexit_t func);
105 static int (CDECL *p_execute_onexit_table)(MSVCRT__onexit_table_t *table);
106 static int (CDECL *p___fpe_flt_rounds)(void);
107 static unsigned int (CDECL *p__controlfp)(unsigned int, unsigned int);
108 static _invalid_parameter_handler (CDECL *p__set_invalid_parameter_handler)(_invalid_parameter_handler);
109 static _invalid_parameter_handler (CDECL *p__get_invalid_parameter_handler)(void);
110 static _invalid_parameter_handler (CDECL *p__set_thread_local_invalid_parameter_handler)(_invalid_parameter_handler);
111 static _invalid_parameter_handler (CDECL *p__get_thread_local_invalid_parameter_handler)(void);
112 static int (CDECL *p__ltoa_s)(LONG, char*, size_t, int);
113 static char* (CDECL *p__get_narrow_winmain_command_line)(void);
114 static int (CDECL *p_sopen_dispatch)(const char *, int, int, int, int *, int);
115 static int (CDECL *p_sopen_s)(int *, const char *, int, int, int);
116 static MSVCRT_lldiv_t (CDECL *p_lldiv)(LONGLONG,LONGLONG);
117 static int (CDECL *p__isctype)(int,int);
118 static int (CDECL *p_isblank)(int);
119 static int (CDECL *p__isblank_l)(int,_locale_t);
120 static int (CDECL *p__iswctype_l)(int,int,_locale_t);
121 static int (CDECL *p_iswblank)(int);
122 static int (CDECL *p__iswblank_l)(wint_t,_locale_t);
123 static int (CDECL *p_fesetround)(int);
124 static void (CDECL *p___setusermatherr)(MSVCRT_matherr_func);
125 static int* (CDECL *p_errno)(void);
127 static void test__initialize_onexit_table(void)
129 MSVCRT__onexit_table_t table, table2;
130 int ret;
132 ret = p_initialize_onexit_table(NULL);
133 ok(ret == -1, "got %d\n", ret);
135 memset(&table, 0, sizeof(table));
136 ret = p_initialize_onexit_table(&table);
137 ok(ret == 0, "got %d\n", ret);
138 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
139 table._first, table._last, table._end);
141 memset(&table2, 0, sizeof(table2));
142 ret = p_initialize_onexit_table(&table2);
143 ok(ret == 0, "got %d\n", ret);
144 ok(table2._first == table._first, "got %p, %p\n", table2._first, table._first);
146 /* uninitialized table */
147 table._first = table._last = table._end = (void*)0x123;
148 ret = p_initialize_onexit_table(&table);
149 ok(ret == 0, "got %d\n", ret);
150 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
151 table._first, table._last, table._end);
152 ok(table._first != (void*)0x123, "got %p\n", table._first);
154 table._first = (void*)0x123;
155 table._last = (void*)0x456;
156 table._end = (void*)0x123;
157 ret = p_initialize_onexit_table(&table);
158 ok(ret == 0, "got %d\n", ret);
159 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
160 table._first, table._last, table._end);
161 ok(table._first != (void*)0x123, "got %p\n", table._first);
163 table._first = (void*)0x123;
164 table._last = (void*)0x456;
165 table._end = (void*)0x789;
166 ret = p_initialize_onexit_table(&table);
167 ok(ret == 0, "got %d\n", ret);
168 ok(table._first == (void*)0x123, "got %p\n", table._first);
169 ok(table._last == (void*)0x456, "got %p\n", table._last);
170 ok(table._end == (void*)0x789, "got %p\n", table._end);
172 table._first = NULL;
173 table._last = (void*)0x456;
174 table._end = NULL;
175 ret = p_initialize_onexit_table(&table);
176 ok(ret == 0, "got %d\n", ret);
177 ok(table._first == table._last && table._first == table._end, "got first %p, last %p, end %p\n",
178 table._first, table._last, table._end);
181 static int g_onexit_called;
182 static int CDECL onexit_func(void)
184 g_onexit_called++;
185 return 0;
188 static int CDECL onexit_func2(void)
190 ok(g_onexit_called == 0, "got %d\n", g_onexit_called);
191 g_onexit_called++;
192 return 0;
195 static void test__register_onexit_function(void)
197 MSVCRT__onexit_table_t table;
198 MSVCRT__onexit_t *f;
199 int ret;
201 memset(&table, 0, sizeof(table));
202 ret = p_initialize_onexit_table(&table);
203 ok(ret == 0, "got %d\n", ret);
205 ret = p_register_onexit_function(NULL, NULL);
206 ok(ret == -1, "got %d\n", ret);
208 ret = p_register_onexit_function(NULL, onexit_func);
209 ok(ret == -1, "got %d\n", ret);
211 f = table._last;
212 ret = p_register_onexit_function(&table, NULL);
213 ok(ret == 0, "got %d\n", ret);
214 ok(f != table._last, "got %p, initial %p\n", table._last, f);
216 ret = p_register_onexit_function(&table, onexit_func);
217 ok(ret == 0, "got %d\n", ret);
219 f = table._last;
220 ret = p_register_onexit_function(&table, onexit_func);
221 ok(ret == 0, "got %d\n", ret);
222 ok(f != table._last, "got %p, initial %p\n", table._last, f);
225 static void test__execute_onexit_table(void)
227 MSVCRT__onexit_table_t table;
228 int ret;
230 ret = p_execute_onexit_table(NULL);
231 ok(ret == -1, "got %d\n", ret);
233 memset(&table, 0, sizeof(table));
234 ret = p_initialize_onexit_table(&table);
235 ok(ret == 0, "got %d\n", ret);
237 /* execute empty table */
238 ret = p_execute_onexit_table(&table);
239 ok(ret == 0, "got %d\n", ret);
241 /* same functions registered twice */
242 ret = p_register_onexit_function(&table, onexit_func);
243 ok(ret == 0, "got %d\n", ret);
245 ret = p_register_onexit_function(&table, NULL);
246 ok(ret == 0, "got %d\n", ret);
248 ret = p_register_onexit_function(&table, onexit_func);
249 ok(ret == 0, "got %d\n", ret);
251 ok(table._first != table._end, "got %p, %p\n", table._first, table._end);
252 g_onexit_called = 0;
253 ret = p_execute_onexit_table(&table);
254 ok(ret == 0, "got %d\n", ret);
255 ok(g_onexit_called == 2, "got %d\n", g_onexit_called);
256 ok(table._first == table._end, "got %p, %p\n", table._first, table._end);
258 /* execute again, table is already empty */
259 g_onexit_called = 0;
260 ret = p_execute_onexit_table(&table);
261 ok(ret == 0, "got %d\n", ret);
262 ok(g_onexit_called == 0, "got %d\n", g_onexit_called);
264 /* check call order */
265 memset(&table, 0, sizeof(table));
266 ret = p_initialize_onexit_table(&table);
267 ok(ret == 0, "got %d\n", ret);
269 ret = p_register_onexit_function(&table, onexit_func);
270 ok(ret == 0, "got %d\n", ret);
272 ret = p_register_onexit_function(&table, onexit_func2);
273 ok(ret == 0, "got %d\n", ret);
275 g_onexit_called = 0;
276 ret = p_execute_onexit_table(&table);
277 ok(ret == 0, "got %d\n", ret);
278 ok(g_onexit_called == 2, "got %d\n", g_onexit_called);
281 static void test___fpe_flt_rounds(void)
283 unsigned int cfp = p__controlfp(0, 0);
284 int ret;
286 if(!cfp) {
287 skip("_controlfp not supported\n");
288 return;
291 ok((p__controlfp(_RC_NEAR, _RC_CHOP) & _RC_CHOP) == _RC_NEAR, "_controlfp(_RC_NEAR, _RC_CHOP) failed\n");
292 ret = p___fpe_flt_rounds();
293 ok(ret == 1, "__fpe_flt_rounds returned %d\n", ret);
295 ok((p__controlfp(_RC_UP, _RC_CHOP) & _RC_CHOP) == _RC_UP, "_controlfp(_RC_UP, _RC_CHOP) failed\n");
296 ret = p___fpe_flt_rounds();
297 ok(ret == 2 + (sizeof(void*)>sizeof(int)), "__fpe_flt_rounds returned %d\n", ret);
299 ok((p__controlfp(_RC_DOWN, _RC_CHOP) & _RC_CHOP) == _RC_DOWN, "_controlfp(_RC_DOWN, _RC_CHOP) failed\n");
300 ret = p___fpe_flt_rounds();
301 ok(ret == 3 - (sizeof(void*)>sizeof(int)), "__fpe_flt_rounds returned %d\n", ret);
303 ok((p__controlfp(_RC_CHOP, _RC_CHOP) & _RC_CHOP) == _RC_CHOP, "_controlfp(_RC_CHOP, _RC_CHOP) failed\n");
304 ret = p___fpe_flt_rounds();
305 ok(ret == 0, "__fpe_flt_rounds returned %d\n", ret);
308 static void __cdecl global_invalid_parameter_handler(
309 const wchar_t *expression, const wchar_t *function,
310 const wchar_t *file, unsigned line, uintptr_t arg)
312 CHECK_EXPECT(global_invalid_parameter_handler);
315 static void __cdecl thread_invalid_parameter_handler(
316 const wchar_t *expression, const wchar_t *function,
317 const wchar_t *file, unsigned line, uintptr_t arg)
319 CHECK_EXPECT(thread_invalid_parameter_handler);
322 static void test_invalid_parameter_handler(void)
324 _invalid_parameter_handler ret;
326 ret = p__get_invalid_parameter_handler();
327 ok(!ret, "ret != NULL\n");
329 ret = p__get_thread_local_invalid_parameter_handler();
330 ok(!ret, "ret != NULL\n");
332 ret = p__set_thread_local_invalid_parameter_handler(thread_invalid_parameter_handler);
333 ok(!ret, "ret != NULL\n");
335 ret = p__get_thread_local_invalid_parameter_handler();
336 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
338 ret = p__get_invalid_parameter_handler();
339 ok(!ret, "ret != NULL\n");
341 ret = p__set_invalid_parameter_handler(global_invalid_parameter_handler);
342 ok(!ret, "ret != NULL\n");
344 ret = p__get_invalid_parameter_handler();
345 ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret);
347 ret = p__get_thread_local_invalid_parameter_handler();
348 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
350 SET_EXPECT(thread_invalid_parameter_handler);
351 p__ltoa_s(0, NULL, 0, 0);
352 CHECK_CALLED(thread_invalid_parameter_handler);
354 ret = p__set_thread_local_invalid_parameter_handler(NULL);
355 ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
357 SET_EXPECT(global_invalid_parameter_handler);
358 p__ltoa_s(0, NULL, 0, 0);
359 CHECK_CALLED(global_invalid_parameter_handler);
361 ret = p__set_invalid_parameter_handler(NULL);
362 ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret);
365 static void test__get_narrow_winmain_command_line(char *path)
367 PROCESS_INFORMATION proc;
368 STARTUPINFOA startup;
369 char cmd[MAX_PATH+32];
370 char *ret, *cmdline, *name;
371 int len;
373 ret = p__get_narrow_winmain_command_line();
374 cmdline = GetCommandLineA();
375 len = strlen(cmdline);
376 ok(ret>cmdline && ret<cmdline+len, "ret = %p, cmdline = %p (len = %d)\n", ret, cmdline, len);
378 if(!path) {
379 ok(!lstrcmpA(ret, "\"misc\" cmd"), "ret = %s\n", ret);
380 return;
383 for(len = strlen(path); len>0; len--)
384 if(path[len-1]=='\\' || path[len-1]=='/') break;
385 if(len) name = path+len;
386 else name = path;
388 sprintf(cmd, "\"\"%c\"\"\"%s\" \t \"misc\" cmd", name[0], name+1);
389 memset(&startup, 0, sizeof(startup));
390 startup.cb = sizeof(startup);
391 CreateProcessA(path, cmd, NULL, NULL, TRUE,
392 CREATE_DEFAULT_ERROR_MODE|NORMAL_PRIORITY_CLASS,
393 NULL, NULL, &startup, &proc);
394 winetest_wait_child_process(proc.hProcess);
397 static BOOL init(void)
399 module = LoadLibraryA("ucrtbase.dll");
401 if(!module) {
402 win_skip("ucrtbase.dll not available\n");
403 return FALSE;
406 p_initialize_onexit_table = (void*)GetProcAddress(module, "_initialize_onexit_table");
407 p_register_onexit_function = (void*)GetProcAddress(module, "_register_onexit_function");
408 p_execute_onexit_table = (void*)GetProcAddress(module, "_execute_onexit_table");
409 p___fpe_flt_rounds = (void*)GetProcAddress(module, "__fpe_flt_rounds");
410 p__controlfp = (void*)GetProcAddress(module, "_controlfp");
411 p__set_invalid_parameter_handler = (void*)GetProcAddress(module, "_set_invalid_parameter_handler");
412 p__get_invalid_parameter_handler = (void*)GetProcAddress(module, "_get_invalid_parameter_handler");
413 p__set_thread_local_invalid_parameter_handler = (void*)GetProcAddress(module, "_set_thread_local_invalid_parameter_handler");
414 p__get_thread_local_invalid_parameter_handler = (void*)GetProcAddress(module, "_get_thread_local_invalid_parameter_handler");
415 p__ltoa_s = (void*)GetProcAddress(module, "_ltoa_s");
416 p__get_narrow_winmain_command_line = (void*)GetProcAddress(GetModuleHandleA("ucrtbase.dll"), "_get_narrow_winmain_command_line");
417 p_sopen_dispatch = (void*)GetProcAddress(module, "_sopen_dispatch");
418 p_sopen_s = (void*)GetProcAddress(module, "_sopen_s");
419 p_lldiv = (void*)GetProcAddress(module, "lldiv");
420 p__isctype = (void*)GetProcAddress(module, "_isctype");
421 p_isblank = (void*)GetProcAddress(module, "isblank");
422 p__isblank_l = (void*)GetProcAddress(module, "_isblank_l");
423 p__iswctype_l = (void*)GetProcAddress(module, "_iswctype_l");
424 p_iswblank = (void*)GetProcAddress(module, "iswblank");
425 p__iswblank_l = (void*)GetProcAddress(module, "_iswblank_l");
426 p_fesetround = (void*)GetProcAddress(module, "fesetround");
427 p___setusermatherr = (void*)GetProcAddress(module, "__setusermatherr");
428 p_errno = (void*)GetProcAddress(module, "_errno");
430 return TRUE;
433 static void test__sopen_dispatch(void)
435 int ret, fd;
436 char *tempf;
438 tempf = _tempnam(".", "wne");
440 fd = 0;
441 ret = p_sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 0);
442 ok(!ret, "got %d\n", ret);
443 ok(fd > 0, "got fd %d\n", fd);
444 _close(fd);
445 unlink(tempf);
447 p__set_invalid_parameter_handler(global_invalid_parameter_handler);
449 SET_EXPECT(global_invalid_parameter_handler);
450 fd = 0;
451 ret = p_sopen_dispatch(tempf, _O_CREAT, _SH_DENYWR, 0xff, &fd, 1);
452 ok(ret == EINVAL, "got %d\n", ret);
453 ok(fd == -1, "got fd %d\n", fd);
454 CHECK_CALLED(global_invalid_parameter_handler);
455 if (fd > 0)
457 _close(fd);
458 unlink(tempf);
461 p__set_invalid_parameter_handler(NULL);
463 free(tempf);
466 static void test__sopen_s(void)
468 int ret, fd;
469 char *tempf;
471 tempf = _tempnam(".", "wne");
473 fd = 0;
474 ret = p_sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0);
475 ok(!ret, "got %d\n", ret);
476 ok(fd > 0, "got fd %d\n", fd);
477 _close(fd);
478 unlink(tempf);
480 /* _open() does not validate pmode */
481 fd = _open(tempf, _O_CREAT, 0xff);
482 ok(fd > 0, "got fd %d\n", fd);
483 _close(fd);
484 unlink(tempf);
486 p__set_invalid_parameter_handler(global_invalid_parameter_handler);
488 /* _sopen_s() invokes invalid parameter handler on invalid pmode */
489 SET_EXPECT(global_invalid_parameter_handler);
490 fd = 0;
491 ret = p_sopen_s(&fd, tempf, _O_CREAT, _SH_DENYWR, 0xff);
492 ok(ret == EINVAL, "got %d\n", ret);
493 ok(fd == -1, "got fd %d\n", fd);
494 CHECK_CALLED(global_invalid_parameter_handler);
495 p__set_invalid_parameter_handler(NULL);
497 free(tempf);
500 static void test_lldiv(void)
502 MSVCRT_lldiv_t r;
504 r = p_lldiv((LONGLONG)0x111 << 32 | 0x222, (LONGLONG)1 << 32);
505 ok(r.quot == 0x111, "quot = %s\n", wine_dbgstr_longlong(r.quot));
506 ok(r.rem == 0x222, "rem = %s\n", wine_dbgstr_longlong(r.rem));
509 static void test_isblank(void)
511 int c;
513 for(c = 0; c <= 0xff; c++) {
514 if(c == '\t' || c == ' ') {
515 if(c == '\t')
516 ok(!p__isctype(c, _BLANK), "tab shouldn't be blank\n");
517 else
518 ok(p__isctype(c, _BLANK), "space should be blank\n");
519 ok(p_isblank(c), "%d should be blank\n", c);
520 ok(p__isblank_l(c, NULL), "%d should be blank\n", c);
521 } else {
522 ok(!p__isctype(c, _BLANK), "%d shouldn't be blank\n", c);
523 ok(!p_isblank(c), "%d shouldn't be blank\n", c);
524 ok(!p__isblank_l(c, NULL), "%d shouldn't be blank\n", c);
528 for(c = 0; c <= 0xffff; c++) {
529 if(c == '\t' || c == ' ' || c == 0x3000 || c == 0xfeff) {
530 if(c == '\t')
531 todo_wine ok(!p__iswctype_l(c, _BLANK, NULL), "tab shouldn't be blank\n");
532 else
533 ok(p__iswctype_l(c, _BLANK, NULL), "%d should be blank\n", c);
534 ok(p_iswblank(c), "%d should be blank\n", c);
535 ok(p__iswblank_l(c, NULL), "%d should be blank\n", c);
536 } else {
537 todo_wine_if(c == 0xa0) {
538 ok(!p__iswctype_l(c, _BLANK, NULL), "%d shouldn't be blank\n", c);
539 ok(!p_iswblank(c), "%d shouldn't be blank\n", c);
540 ok(!p__iswblank_l(c, NULL), "%d shouldn't be blank\n", c);
546 static struct MSVCRT__exception exception;
548 static int CDECL matherr_callback(struct MSVCRT__exception *e)
550 memcpy(&exception, e, sizeof(MSVCRT__exception));
551 return 0;
554 static void test_math_errors(void)
556 const struct {
557 char func[16];
558 double x;
559 int error;
560 int exception;
561 } testsd[] = {
562 {"_logb", -INFINITY, -1, -1},
563 {"_logb", -1, -1, -1},
564 {"_logb", 0, ERANGE, _SING},
565 {"_logb", INFINITY, -1, -1},
566 {"acos", -INFINITY, EDOM, _DOMAIN},
567 {"acos", -2, EDOM, _DOMAIN},
568 {"acos", -1, -1, -1},
569 {"acos", 1, -1, -1},
570 {"acos", 2, EDOM, _DOMAIN},
571 {"acos", INFINITY, EDOM, _DOMAIN},
572 {"acosh", -INFINITY, EDOM, -1},
573 {"acosh", 0, EDOM, -1},
574 {"acosh", 1, -1, -1},
575 {"acosh", INFINITY, -1, -1},
576 {"asin", -INFINITY, EDOM, _DOMAIN},
577 {"asin", -2, EDOM, _DOMAIN},
578 {"asin", -1, -1, -1},
579 {"asin", 1, -1, -1},
580 {"asin", 2, EDOM, _DOMAIN},
581 {"asin", INFINITY, EDOM, _DOMAIN},
582 {"asinh", -INFINITY, -1, -1},
583 {"asinh", INFINITY, -1, -1},
584 {"atan", -INFINITY, -1, -1},
585 {"atan", 0, -1, -1},
586 {"atan", INFINITY, -1, -1},
587 {"atanh", -INFINITY, EDOM, -1},
588 {"atanh", -2, EDOM, -1},
589 {"atanh", -1, ERANGE, -1},
590 {"atanh", 1, ERANGE, -1},
591 {"atanh", 2, EDOM, -1},
592 {"atanh", INFINITY, EDOM, -1},
593 {"cos", -INFINITY, EDOM, _DOMAIN},
594 {"cos", INFINITY, EDOM, _DOMAIN},
595 {"cosh", -INFINITY, -1, -1},
596 {"cosh", 0, -1, -1},
597 {"cosh", INFINITY, -1, -1},
598 {"exp", -INFINITY, -1, -1},
599 {"exp", -1e100, -1, _UNDERFLOW},
600 {"exp", 1e100, ERANGE, _OVERFLOW},
601 {"exp", INFINITY, -1, -1},
602 {"exp2", -INFINITY, -1, -1},
603 {"exp2", -1e100, -1, -1},
604 {"exp2", 1e100, ERANGE, -1},
605 {"exp2", INFINITY, -1, -1},
606 {"expm1", -INFINITY, -1, -1},
607 {"expm1", INFINITY, -1, -1},
608 {"log", -INFINITY, EDOM, _DOMAIN},
609 {"log", -1, EDOM, _DOMAIN},
610 {"log", 0, ERANGE, _SING},
611 {"log", INFINITY, -1, -1},
612 {"log10", -INFINITY, EDOM, _DOMAIN},
613 {"log10", -1, EDOM, _DOMAIN},
614 {"log10", 0, ERANGE, _SING},
615 {"log10", INFINITY, -1, -1},
616 {"log1p", -INFINITY, EDOM, -1},
617 {"log1p", -2, EDOM, -1},
618 {"log1p", -1, ERANGE, -1},
619 {"log1p", INFINITY, -1, -1},
620 {"log2", INFINITY, -1, -1},
621 {"sin", -INFINITY, EDOM, _DOMAIN},
622 {"sin", INFINITY, EDOM, _DOMAIN},
623 {"sinh", -INFINITY, -1, -1},
624 {"sinh", 0, -1, -1},
625 {"sinh", INFINITY, -1, -1},
626 {"sqrt", -INFINITY, EDOM, _DOMAIN},
627 {"sqrt", -1, EDOM, _DOMAIN},
628 {"sqrt", 0, -1, -1},
629 {"sqrt", INFINITY, -1, -1},
630 {"tan", -INFINITY, EDOM, _DOMAIN},
631 {"tan", -M_PI_2, -1, -1},
632 {"tan", M_PI_2, -1, -1},
633 {"tan", INFINITY, EDOM, _DOMAIN},
634 {"tanh", -INFINITY, -1, -1},
635 {"tanh", 0, -1, -1},
636 {"tanh", INFINITY, -1, -1},
638 const struct {
639 char func[16];
640 double a;
641 double b;
642 int error;
643 int exception;
644 } tests2d[] = {
645 {"atan2", -INFINITY, 0, -1, -1},
646 {"atan2", 0, 0, -1, -1},
647 {"atan2", INFINITY, 0, -1, -1},
648 {"atan2", 0, -INFINITY, -1, -1},
649 {"atan2", 0, INFINITY, -1, -1},
650 {"pow", -INFINITY, -2, -1, -1},
651 {"pow", -INFINITY, -1, -1, -1},
652 {"pow", -INFINITY, 0, -1, -1},
653 {"pow", -INFINITY, 1, -1, -1},
654 {"pow", -INFINITY, 2, -1, -1},
655 {"pow", -1e100, -10, -1, _UNDERFLOW},
656 {"pow", -1e100, 10, ERANGE, _OVERFLOW},
657 {"pow", -1, 1.5, EDOM, _DOMAIN},
658 {"pow", 0, -2, ERANGE, _SING},
659 {"pow", 0, -1, ERANGE, _SING},
660 {"pow", 0.5, -INFINITY, -1, -1},
661 {"pow", 0.5, INFINITY, -1, -1},
662 {"pow", 2, -INFINITY, -1, -1},
663 {"pow", 2, -1e100, -1, _UNDERFLOW},
664 {"pow", 2, 1e100, ERANGE, _OVERFLOW},
665 {"pow", 2, INFINITY, -1, -1},
666 {"pow", 1e100, -10, -1, _UNDERFLOW},
667 {"pow", 1e100, 10, ERANGE, _OVERFLOW},
668 {"pow", INFINITY, -2, -1, -1},
669 {"pow", INFINITY, -1, -1, -1},
670 {"pow", INFINITY, 0, -1, -1},
671 {"pow", INFINITY, 1, -1, -1},
672 {"pow", INFINITY, 2, -1, -1},
674 const struct {
675 char func[16];
676 double a;
677 long b;
678 int error;
679 int exception;
680 } testsdl[] = {
681 {"_scalb", -INFINITY, 1, -1, -1},
682 {"_scalb", -1e100, 1, -1, -1},
683 {"_scalb", 1e100, 1, -1, -1},
684 {"_scalb", INFINITY, 1, -1, -1},
685 {"_scalb", 1, 1e9, ERANGE, _OVERFLOW},
686 {"ldexp", -INFINITY, 1, -1, -1},
687 {"ldexp", -1e100, 1, -1, -1},
688 {"ldexp", 1e100, 1, -1, -1},
689 {"ldexp", INFINITY, 1, -1, -1},
690 {"ldexp", 1, -1e9, -1, _UNDERFLOW},
691 {"ldexp", 1, 1e9, ERANGE, _OVERFLOW},
693 double (CDECL *p_funcd)(double);
694 double (CDECL *p_func2d)(double, double);
695 double (CDECL *p_funcdl)(double, long);
696 int i;
698 p___setusermatherr(matherr_callback);
700 /* necessary so that exp(1e100)==INFINITY on glibc, we can remove this if we change our implementation */
701 p_fesetround(FE_TONEAREST);
703 for(i = 0; i < sizeof(testsd)/sizeof(testsd[0]); i++) {
704 p_funcd = (void*)GetProcAddress(module, testsd[i].func);
705 *p_errno() = -1;
706 exception.type = -1;
707 p_funcd(testsd[i].x);
708 ok(*p_errno() == testsd[i].error,
709 "%s(%f) got errno %d\n", testsd[i].func, testsd[i].x, *p_errno());
710 ok(exception.type == testsd[i].exception,
711 "%s(%f) got exception type %d\n", testsd[i].func, testsd[i].x, exception.type);
712 if(exception.type == -1) continue;
713 ok(exception.arg1 == testsd[i].x,
714 "%s(%f) got exception arg1 %f\n", testsd[i].func, testsd[i].x, exception.arg1);
717 for(i = 0; i < sizeof(tests2d)/sizeof(tests2d[0]); i++) {
718 p_func2d = (void*)GetProcAddress(module, tests2d[i].func);
719 *p_errno() = -1;
720 exception.type = -1;
721 p_func2d(tests2d[i].a, tests2d[i].b);
722 ok(*p_errno() == tests2d[i].error,
723 "%s(%f, %f) got errno %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, *p_errno());
724 ok(exception.type == tests2d[i].exception,
725 "%s(%f, %f) got exception type %d\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.type);
726 if(exception.type == -1) continue;
727 ok(exception.arg1 == tests2d[i].a,
728 "%s(%f, %f) got exception arg1 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg1);
729 ok(exception.arg2 == tests2d[i].b,
730 "%s(%f, %f) got exception arg2 %f\n", tests2d[i].func, tests2d[i].a, tests2d[i].b, exception.arg2);
733 for(i = 0; i < sizeof(testsdl)/sizeof(testsdl[0]); i++) {
734 p_funcdl = (void*)GetProcAddress(module, testsdl[i].func);
735 *p_errno() = -1;
736 exception.type = -1;
737 p_funcdl(testsdl[i].a, testsdl[i].b);
738 ok(*p_errno() == testsdl[i].error,
739 "%s(%f, %ld) got errno %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, *p_errno());
740 ok(exception.type == testsdl[i].exception,
741 "%s(%f, %ld) got exception type %d\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.type);
742 if(exception.type == -1) continue;
743 ok(exception.arg1 == testsdl[i].a,
744 "%s(%f, %ld) got exception arg1 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg1);
745 ok(exception.arg2 == testsdl[i].b,
746 "%s(%f, %ld) got exception arg2 %f\n", testsdl[i].func, testsdl[i].a, testsdl[i].b, exception.arg2);
750 START_TEST(misc)
752 int arg_c;
753 char** arg_v;
755 if(!init())
756 return;
758 arg_c = winetest_get_mainargs(&arg_v);
759 if(arg_c == 3) {
760 test__get_narrow_winmain_command_line(NULL);
761 return;
764 test_invalid_parameter_handler();
765 test__initialize_onexit_table();
766 test__register_onexit_function();
767 test__execute_onexit_table();
768 test___fpe_flt_rounds();
769 test__get_narrow_winmain_command_line(arg_v[0]);
770 test__sopen_dispatch();
771 test__sopen_s();
772 test_lldiv();
773 test_isblank();
774 test_math_errors();