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
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) \
42 ok(expect_ ##func, "unexpected call " #func "\n"); \
43 called_ ## func = TRUE; \
46 #define CHECK_EXPECT(func) \
48 CHECK_EXPECT2(func); \
49 expect_ ## func = FALSE; \
52 #define CHECK_CALLED(func) \
54 ok(called_ ## func, "expected " #func "\n"); \
55 expect_ ## func = called_ ## func = FALSE; \
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 */
91 typedef struct 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
;
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
);
173 table
._last
= (void*)0x456;
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)
188 static int CDECL
onexit_func2(void)
190 ok(g_onexit_called
== 0, "got %d\n", g_onexit_called
);
195 static void test__register_onexit_function(void)
197 MSVCRT__onexit_table_t table
;
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
);
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
);
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
;
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
);
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 */
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
);
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);
287 skip("_controlfp not supported\n");
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
;
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
);
379 ok(!lstrcmpA(ret
, "\"misc\" cmd"), "ret = %s\n", ret
);
383 for(len
= strlen(path
); len
>0; len
--)
384 if(path
[len
-1]=='\\' || path
[len
-1]=='/') break;
385 if(len
) name
= path
+len
;
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");
402 win_skip("ucrtbase.dll not available\n");
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");
433 static void test__sopen_dispatch(void)
438 tempf
= _tempnam(".", "wne");
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
);
447 p__set_invalid_parameter_handler(global_invalid_parameter_handler
);
449 SET_EXPECT(global_invalid_parameter_handler
);
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
);
461 p__set_invalid_parameter_handler(NULL
);
466 static void test__sopen_s(void)
471 tempf
= _tempnam(".", "wne");
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
);
480 /* _open() does not validate pmode */
481 fd
= _open(tempf
, _O_CREAT
, 0xff);
482 ok(fd
> 0, "got fd %d\n", fd
);
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
);
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
);
500 static void test_lldiv(void)
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)
513 for(c
= 0; c
<= 0xff; c
++) {
514 if(c
== '\t' || c
== ' ') {
516 ok(!p__isctype(c
, _BLANK
), "tab shouldn't be blank\n");
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
);
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) {
531 todo_wine
ok(!p__iswctype_l(c
, _BLANK
, NULL
), "tab shouldn't be blank\n");
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
);
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
));
554 static void test_math_errors(void)
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},
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},
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},
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},
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},
625 {"sinh", INFINITY
, -1, -1},
626 {"sqrt", -INFINITY
, EDOM
, _DOMAIN
},
627 {"sqrt", -1, EDOM
, _DOMAIN
},
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},
636 {"tanh", INFINITY
, -1, -1},
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},
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);
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
);
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
);
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
);
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
);
758 arg_c
= winetest_get_mainargs(&arg_v
);
760 test__get_narrow_winmain_command_line(NULL
);
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();