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