1 //===-- Unittests for fegetenv and fesetenv -------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "src/fenv/fegetenv.h"
10 #include "src/fenv/fegetround.h"
11 #include "src/fenv/fesetenv.h"
12 #include "src/fenv/fesetround.h"
13 
14 #include "src/__support/FPUtil/FEnvImpl.h"
15 #include "utils/UnitTest/Test.h"
16 
17 #include <fenv.h>
18 
TEST(LlvmLibcFenvTest,GetEnvAndSetEnv)19 TEST(LlvmLibcFenvTest, GetEnvAndSetEnv) {
20   // We will disable all exceptions to prevent invocation of the exception
21   // handler.
22   __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT);
23 
24   int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
25                    FE_UNDERFLOW};
26 
27   for (int e : excepts) {
28     __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
29 
30     // Save the cleared environment.
31     fenv_t env;
32     ASSERT_EQ(__llvm_libc::fegetenv(&env), 0);
33 
34     __llvm_libc::fputil::raise_except(e);
35     // Make sure that the exception is raised.
36     ASSERT_NE(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
37 
38     ASSERT_EQ(__llvm_libc::fesetenv(&env), 0);
39     ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
40   }
41 }
42 
TEST(LlvmLibcFenvTest,Set_FE_DFL_ENV)43 TEST(LlvmLibcFenvTest, Set_FE_DFL_ENV) {
44   // We will disable all exceptions to prevent invocation of the exception
45   // handler.
46   __llvm_libc::fputil::disable_except(FE_ALL_EXCEPT);
47 
48   int excepts[] = {FE_DIVBYZERO, FE_INVALID, FE_INEXACT, FE_OVERFLOW,
49                    FE_UNDERFLOW};
50 
51   for (int e : excepts) {
52     __llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
53 
54     // Save the cleared environment.
55     fenv_t env;
56     ASSERT_EQ(__llvm_libc::fegetenv(&env), 0);
57 
58     __llvm_libc::fputil::raise_except(e);
59     // Make sure that the exception is raised.
60     ASSERT_NE(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
61 
62     ASSERT_EQ(__llvm_libc::fesetenv(FE_DFL_ENV), 0);
63     // Setting the default env should clear all exceptions.
64     ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT) & e, 0);
65   }
66 
67   ASSERT_EQ(__llvm_libc::fesetround(FE_DOWNWARD), 0);
68   ASSERT_EQ(__llvm_libc::fesetenv(FE_DFL_ENV), 0);
69   // Setting the default env should set rounding mode to FE_TONEAREST.
70   int rm = __llvm_libc::fegetround();
71   EXPECT_EQ(rm, FE_TONEAREST);
72 }
73 
74 #ifdef _WIN32
TEST(LlvmLibcFenvTest,Windows_Set_Get_Test)75 TEST(LlvmLibcFenvTest, Windows_Set_Get_Test) {
76   // If a valid fenv_t is written, then reading it back out should be identical.
77   fenv_t setEnv = {0x7e00053e, 0x0f00000f};
78   fenv_t getEnv;
79   ASSERT_EQ(__llvm_libc::fesetenv(&setEnv), 0);
80   ASSERT_EQ(__llvm_libc::fegetenv(&getEnv), 0);
81 
82   ASSERT_EQ(setEnv._Fe_ctl, getEnv._Fe_ctl);
83   ASSERT_EQ(setEnv._Fe_stat, getEnv._Fe_stat);
84 }
85 #endif
86