Module: wine Branch: master Commit: 9cd51b02eebc6339c21b8ebcb9438d7d5a9d666f URL: https://source.winehq.org/git/wine.git/?a=commit;h=9cd51b02eebc6339c21b8ebcb...
Author: Piotr Caban piotr@codeweavers.com Date: Tue May 18 21:07:04 2021 +0200
ucrtbase: Copy fenv tests from msvcr120.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ucrtbase/tests/misc.c | 167 +++++++++++++++++++++++++++++++++++++++++++++ include/msvcrt/fenv.h | 1 + 2 files changed, 168 insertions(+)
diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c index 5fcec2e2bb5..aaa8ada2a8a 100644 --- a/dlls/ucrtbase/tests/misc.c +++ b/dlls/ucrtbase/tests/misc.c @@ -1371,6 +1371,172 @@ static void test_thread_storage(void) "can't find se_translator in thread storage\n"); }
+static unsigned long fenv_encode(unsigned int e) +{ + ok(!(e & ~FE_ALL_EXCEPT), "incorrect argument: %x\n", e); + +#if defined(__i386__) + return e<<24 | e<<16 | e; +#else + return e<<24 | e; +#endif +} + +static void test_fenv(void) +{ +#if defined(__i386__) || defined(__x86_64__) + static const int tests[] = { + 0, + FE_INEXACT, + FE_UNDERFLOW, + FE_OVERFLOW, + FE_DIVBYZERO, + FE_INVALID, + FE_ALL_EXCEPT, + }; + static const struct { + fexcept_t except; + unsigned int flag; + unsigned int get; + fexcept_t expect; + } tests2[] = { + /* except flag get expect */ + { 0, 0, 0, 0 }, + { FE_ALL_EXCEPT, FE_INEXACT, 0, 0 }, + { FE_ALL_EXCEPT, FE_INEXACT, FE_ALL_EXCEPT, FE_INEXACT }, + { FE_ALL_EXCEPT, FE_INEXACT, FE_INEXACT, FE_INEXACT }, + { FE_ALL_EXCEPT, FE_INEXACT, FE_OVERFLOW, 0 }, + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_ALL_EXCEPT }, + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_INEXACT, FE_INEXACT }, + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, 0, 0 }, + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, ~0, FE_ALL_EXCEPT }, + { FE_ALL_EXCEPT, FE_ALL_EXCEPT, ~FE_ALL_EXCEPT, 0 }, + { FE_INEXACT, FE_ALL_EXCEPT, FE_ALL_EXCEPT, FE_INEXACT }, + { FE_INEXACT, FE_UNDERFLOW, FE_ALL_EXCEPT, 0 }, + { FE_UNDERFLOW, FE_INEXACT, FE_ALL_EXCEPT, 0 }, + { FE_INEXACT|FE_UNDERFLOW, FE_UNDERFLOW, FE_ALL_EXCEPT, FE_UNDERFLOW }, + { FE_UNDERFLOW, FE_INEXACT|FE_UNDERFLOW, FE_ALL_EXCEPT, FE_UNDERFLOW }, + }; + fenv_t env, env2; + fexcept_t except; + int i, ret, flags; + + _clearfp(); + + ret = fegetenv(&env); + ok(!ret, "fegetenv returned %x\n", ret); + if (env._Fe_ctl >> 24 != (env._Fe_ctl & 0xff)) + { + win_skip("fenv_t format not supported (too old ucrtbase)\n"); + return; + } + fesetround(FE_UPWARD); + ok(!env._Fe_stat, "env._Fe_stat = %lx\n", env._Fe_stat); + ret = fegetenv(&env2); + ok(!ret, "fegetenv returned %x\n", ret); + ok(env._Fe_ctl != env2._Fe_ctl, "fesetround didn't change _Fe_ctl (%lx).", env._Fe_ctl); + ret = fesetenv(&env); + ok(!ret, "fesetenv returned %x\n", ret); + ret = fegetround(); + ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret); + + except = fenv_encode(FE_ALL_EXCEPT); + ret = fesetexceptflag(&except, FE_INEXACT|FE_UNDERFLOW); + ok(!ret, "fesetexceptflag returned %x\n", ret); + except = fetestexcept(FE_ALL_EXCEPT); + ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); + + ret = feclearexcept(~FE_ALL_EXCEPT); + ok(!ret, "feclearexceptflag returned %x\n", ret); + except = fetestexcept(FE_ALL_EXCEPT); + ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); + + /* no crash, but no-op */ + ret = fesetexceptflag(NULL, 0); + ok(!ret, "fesetexceptflag returned %x\n", ret); + except = fetestexcept(FE_ALL_EXCEPT); + ok(except == (FE_INEXACT|FE_UNDERFLOW), "expected %x, got %lx\n", FE_INEXACT|FE_UNDERFLOW, except); + + /* zero clears all */ + except = 0; + ret = fesetexceptflag(&except, FE_ALL_EXCEPT); + ok(!ret, "fesetexceptflag returned %x\n", ret); + except = fetestexcept(FE_ALL_EXCEPT); + ok(!except, "expected 0, got %lx\n", except); + + ret = fetestexcept(FE_ALL_EXCEPT); + ok(!ret, "fetestexcept returned %x\n", ret); + + flags = 0; + /* adding bits with flags */ + for(i=0; i<ARRAY_SIZE(tests); i++) { + except = fenv_encode(FE_ALL_EXCEPT); + ret = fesetexceptflag(&except, tests[i]); + ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); + + ret = fetestexcept(tests[i]); + ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); + + flags |= tests[i]; + ret = fetestexcept(FE_ALL_EXCEPT); + ok(ret == flags, "Test %d: expected %x, got %x\n", i, flags, ret); + + except = ~0; + ret = fegetexceptflag(&except, ~0); + ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); + ok(except == fenv_encode(flags), + "Test %d: expected %x, got %lx\n", i, flags, except); + + except = ~0; + ret = fegetexceptflag(&except, tests[i]); + ok(!ret, "Test %d: fegetexceptflag returned %x.\n", i, ret); + ok(except == fenv_encode(tests[i]), + "Test %d: expected %x, got %lx\n", i, tests[i], except); + } + + for(i=0; i<ARRAY_SIZE(tests); i++) { + ret = feclearexcept(tests[i]); + ok(!ret, "Test %d: feclearexceptflag returned %x\n", i, ret); + + flags &= ~tests[i]; + except = fetestexcept(tests[i]); + ok(!except, "Test %d: expected %x, got %lx\n", i, flags, except); + } + + except = fetestexcept(FE_ALL_EXCEPT); + ok(!except, "expected 0, got %lx\n", except); + + /* setting bits with except */ + for(i=0; i<ARRAY_SIZE(tests); i++) { + except = fenv_encode(tests[i]); + ret = fesetexceptflag(&except, FE_ALL_EXCEPT); + ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); + + ret = fetestexcept(tests[i]); + ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); + + ret = fetestexcept(FE_ALL_EXCEPT); + ok(ret == tests[i], "Test %d: expected %x, got %x\n", i, tests[i], ret); + } + + for(i=0; i<ARRAY_SIZE(tests2); i++) { + _clearfp(); + + except = fenv_encode(tests2[i].except); + ret = fesetexceptflag(&except, tests2[i].flag); + ok(!ret, "Test %d: fesetexceptflag returned %x\n", i, ret); + + ret = fetestexcept(tests2[i].get); + ok(ret == tests2[i].expect, "Test %d: expected %lx, got %x\n", i, tests2[i].expect, ret); + } + + ret = feclearexcept(FE_ALL_EXCEPT); + ok(!ret, "feclearexceptflag returned %x\n", ret); + except = fetestexcept(FE_ALL_EXCEPT); + ok(!except, "expected 0, got %lx\n", except); +#endif +} + START_TEST(misc) { int arg_c; @@ -1411,4 +1577,5 @@ START_TEST(misc) test__o_malloc(); test_clock(); test_thread_storage(); + test_fenv(); } diff --git a/include/msvcrt/fenv.h b/include/msvcrt/fenv.h index a6b53eca567..2039a1fb4c8 100644 --- a/include/msvcrt/fenv.h +++ b/include/msvcrt/fenv.h @@ -36,6 +36,7 @@ _ACRTIMP int __cdecl fegetenv(fenv_t*); _ACRTIMP int __cdecl fesetenv(const fenv_t*); _ACRTIMP int __cdecl fegetexceptflag(fexcept_t*, int); _ACRTIMP int __cdecl fegetround(void); +_ACRTIMP int __cdecl feholdexcept(fenv_t*); _ACRTIMP int __cdecl fesetround(int); _ACRTIMP int __cdecl fesetexceptflag(const fexcept_t*, int); _ACRTIMP int __cdecl feclearexcept(int);