Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <gtest/gtest.h>
     18 
     19 #include "utils.h"
     20 
     21 #include <fenv.h>
     22 #include <stdint.h>
     23 
     24 static void TestRounding(float expectation1, float expectation2) {
     25   // volatile to prevent compiler optimizations.
     26   volatile float f = 1.968750f;
     27   volatile float m = 0x1.0p23f;
     28   volatile float x = f + m;
     29   ASSERT_FLOAT_EQ(expectation1, x);
     30   x -= m;
     31   ASSERT_EQ(expectation2, x);
     32 }
     33 
     34 static void DivideByZero() {
     35   // volatile to prevent compiler optimizations.
     36   volatile float zero = 0.0f;
     37   volatile float result __attribute__((unused)) = 123.0f / zero;
     38 }
     39 
     40 TEST(fenv, fesetround_fegetround_FE_TONEAREST) {
     41   fesetround(FE_TONEAREST);
     42   ASSERT_EQ(FE_TONEAREST, fegetround());
     43   TestRounding(8388610.0f, 2.0f);
     44 }
     45 
     46 TEST(fenv, fesetround_fegetround_FE_TOWARDZERO) {
     47   fesetround(FE_TOWARDZERO);
     48   ASSERT_EQ(FE_TOWARDZERO, fegetround());
     49   TestRounding(8388609.0f, 1.0f);
     50 }
     51 
     52 TEST(fenv, fesetround_fegetround_FE_UPWARD) {
     53   fesetround(FE_UPWARD);
     54   ASSERT_EQ(FE_UPWARD, fegetround());
     55   TestRounding(8388610.0f, 2.0f);
     56 }
     57 
     58 TEST(fenv, fesetround_fegetround_FE_DOWNWARD) {
     59   fesetround(FE_DOWNWARD);
     60   ASSERT_EQ(FE_DOWNWARD, fegetround());
     61   TestRounding(8388609.0f, 1.0f);
     62 }
     63 
     64 TEST(fenv, feclearexcept_fetestexcept) {
     65   // Clearing clears.
     66   feclearexcept(FE_ALL_EXCEPT);
     67   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
     68 
     69   // Dividing by zero sets FE_DIVBYZERO.
     70   DivideByZero();
     71   int raised = fetestexcept(FE_DIVBYZERO | FE_OVERFLOW);
     72   ASSERT_TRUE((raised & FE_OVERFLOW) == 0);
     73   ASSERT_TRUE((raised & FE_DIVBYZERO) != 0);
     74 
     75   // Clearing an unset bit is a no-op.
     76   feclearexcept(FE_OVERFLOW);
     77   ASSERT_TRUE((raised & FE_OVERFLOW) == 0);
     78   ASSERT_TRUE((raised & FE_DIVBYZERO) != 0);
     79 
     80   // Clearing a set bit works.
     81   feclearexcept(FE_DIVBYZERO);
     82   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
     83 }
     84 
     85 TEST(fenv, FE_DFL_ENV_macro) {
     86   ASSERT_EQ(0, fesetenv(FE_DFL_ENV));
     87 }
     88 
     89 TEST(fenv, feraiseexcept) {
     90   feclearexcept(FE_ALL_EXCEPT);
     91   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
     92 
     93   ASSERT_EQ(0, feraiseexcept(FE_DIVBYZERO | FE_OVERFLOW));
     94   ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT));
     95 }
     96 
     97 TEST(fenv, fegetenv_fesetenv) {
     98   // Set FE_OVERFLOW only.
     99   feclearexcept(FE_ALL_EXCEPT);
    100   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
    101   ASSERT_EQ(0, feraiseexcept(FE_OVERFLOW));
    102 
    103   // fegetenv (unlike feholdexcept) leaves the current state untouched...
    104   fenv_t state;
    105   ASSERT_EQ(0, fegetenv(&state));
    106   ASSERT_EQ(FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT));
    107 
    108   // Dividing by zero sets the appropriate flag...
    109   DivideByZero();
    110   ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT));
    111 
    112   // And fesetenv (unlike feupdateenv) clobbers that to return to where
    113   // we started.
    114   ASSERT_EQ(0, fesetenv(&state));
    115   ASSERT_EQ(FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT));
    116 }
    117 
    118 TEST(fenv, feholdexcept_feupdateenv) {
    119   // Set FE_OVERFLOW only.
    120   feclearexcept(FE_ALL_EXCEPT);
    121   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
    122   ASSERT_EQ(0, feraiseexcept(FE_OVERFLOW));
    123 
    124   // feholdexcept (unlike fegetenv) clears everything...
    125   fenv_t state;
    126   ASSERT_EQ(0, feholdexcept(&state));
    127   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
    128 
    129   // Dividing by zero sets the appropriate flag...
    130   DivideByZero();
    131   ASSERT_EQ(FE_DIVBYZERO, fetestexcept(FE_ALL_EXCEPT));
    132 
    133   // And feupdateenv (unlike fesetenv) merges what we started with
    134   // (FE_OVERFLOW) with what we now have (FE_DIVBYZERO).
    135   ASSERT_EQ(0, feupdateenv(&state));
    136   ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW, fetestexcept(FE_ALL_EXCEPT));
    137 }
    138 
    139 TEST(fenv, fegetexceptflag_fesetexceptflag) {
    140   // Set three flags.
    141   feclearexcept(FE_ALL_EXCEPT);
    142   ASSERT_EQ(0, feraiseexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW));
    143   ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT));
    144 
    145   fexcept_t all; // FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW
    146   fexcept_t two; // FE_OVERFLOW | FE_UNDERFLOW
    147   ASSERT_EQ(0, fegetexceptflag(&all, FE_ALL_EXCEPT));
    148   ASSERT_EQ(0, fegetexceptflag(&two, FE_OVERFLOW | FE_UNDERFLOW));
    149 
    150   // Check we can restore all.
    151   feclearexcept(FE_ALL_EXCEPT);
    152   ASSERT_EQ(0, fesetexceptflag(&all, FE_ALL_EXCEPT));
    153   ASSERT_EQ(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT));
    154 
    155   // Check that `two` only stored a subset.
    156   feclearexcept(FE_ALL_EXCEPT);
    157   ASSERT_EQ(0, fesetexceptflag(&two, FE_ALL_EXCEPT));
    158   ASSERT_EQ(FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT));
    159 
    160   // Check that we can restore a single flag.
    161   feclearexcept(FE_ALL_EXCEPT);
    162   ASSERT_EQ(0, fesetexceptflag(&all, FE_DIVBYZERO));
    163   ASSERT_EQ(FE_DIVBYZERO, fetestexcept(FE_ALL_EXCEPT));
    164 
    165   // Check that we can restore a subset of flags.
    166   feclearexcept(FE_ALL_EXCEPT);
    167   ASSERT_EQ(0, fesetexceptflag(&all, FE_OVERFLOW | FE_UNDERFLOW));
    168   ASSERT_EQ(FE_OVERFLOW | FE_UNDERFLOW, fetestexcept(FE_ALL_EXCEPT));
    169 }
    170 
    171 TEST(fenv, fedisableexcept_fegetexcept) {
    172   feclearexcept(FE_ALL_EXCEPT);
    173   ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
    174 
    175   // No SIGFPE please...
    176   ASSERT_EQ(0, fedisableexcept(FE_ALL_EXCEPT));
    177   ASSERT_EQ(0, fegetexcept());
    178   ASSERT_EQ(0, feraiseexcept(FE_INVALID));
    179   ASSERT_EQ(FE_INVALID, fetestexcept(FE_ALL_EXCEPT));
    180 }
    181 
    182 TEST(fenv, feenableexcept_fegetexcept) {
    183 #if defined(__aarch64__) || defined(__arm__)
    184   // ARM doesn't support this. They used to if you go back far enough, but it was removed in
    185   // the Cortex-A8 between r3p1 and r3p2.
    186   ASSERT_EQ(-1, feenableexcept(FE_INVALID));
    187   ASSERT_EQ(0, fegetexcept());
    188   ASSERT_EQ(-1, feenableexcept(FE_DIVBYZERO));
    189   ASSERT_EQ(0, fegetexcept());
    190   ASSERT_EQ(-1, feenableexcept(FE_OVERFLOW));
    191   ASSERT_EQ(0, fegetexcept());
    192   ASSERT_EQ(-1, feenableexcept(FE_UNDERFLOW));
    193   ASSERT_EQ(0, fegetexcept());
    194   ASSERT_EQ(-1, feenableexcept(FE_INEXACT));
    195   ASSERT_EQ(0, fegetexcept());
    196   ASSERT_EQ(-1, feenableexcept(FE_DENORMAL));
    197   ASSERT_EQ(0, fegetexcept());
    198 #else
    199   // We can't recover from SIGFPE, so sacrifice a child...
    200   pid_t pid = fork();
    201   ASSERT_NE(-1, pid) << strerror(errno);
    202 
    203   if (pid == 0) {
    204     feclearexcept(FE_ALL_EXCEPT);
    205     ASSERT_EQ(0, fetestexcept(FE_ALL_EXCEPT));
    206     ASSERT_EQ(0, feenableexcept(FE_INVALID));
    207     ASSERT_EQ(FE_INVALID, fegetexcept());
    208     ASSERT_EQ(0, feraiseexcept(FE_INVALID));
    209     _exit(123);
    210   }
    211 
    212   AssertChildExited(pid, -SIGFPE);
    213 #endif
    214 }
    215