brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.8 KiB · 1e10629 Raw
106 lines · c
1//===-- FEnvSafeTest.h -----------------------------------------*- C++ -*-===//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-exception6//7//===---------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_TEST_UNITTEST_FPENVSAFE_H10#define LLVM_LIBC_TEST_UNITTEST_FPENVSAFE_H11 12#include "hdr/types/fenv_t.h"13#include "src/__support/CPP/utility.h"14#include "src/__support/macros/config.h"15#include "test/UnitTest/ErrnoCheckingTest.h"16#include "test/UnitTest/Test.h"17 18namespace LIBC_NAMESPACE_DECL {19namespace testing {20 21// This provides a test fixture (or base class for other test fixtures) that22// asserts that each test does not leave the FPU state represented by `fenv_t`23// (aka `FPState`) perturbed from its initial state.24class FEnvSafeTest : public ErrnoCheckingTest {25public:26  void TearDown() override;27 28protected:29  // This is an RAII type where `PreserveFEnv preserve{this};` will sample the30  // `fenv_t` state and restore it when `preserve` goes out of scope.31  class PreserveFEnv {32    fenv_t before;33    FEnvSafeTest &test;34 35  public:36    explicit PreserveFEnv(FEnvSafeTest *self) : test{*self} {37      test.get_fenv(before);38    }39 40    // Cause test expectation failures if the current state doesn't match what41    // was captured in the constructor.42    void check();43 44    // Restore the state captured in the constructor.45    void restore() { test.set_fenv(before); }46 47    ~PreserveFEnv() { restore(); }48  };49 50  // This is an RAII type where `CheckFEnv check{this};` will sample the51  // `fenv_t` state and require it be the same when `check` goes out of scope.52  struct CheckFEnv : public PreserveFEnv {53    using PreserveFEnv::PreserveFEnv;54 55    ~CheckFEnv() { check(); }56  };57 58  // This calls callable() and returns its value, but has EXPECT_* failures if59  // the `fenv_t` state is not preserved by the call.60  template <typename T> decltype(auto) check_fenv_preserved(T &&callable) {61    CheckFEnv check{this};62    return cpp::forward<T>(callable)();63  }64 65  // This calls callable() and returns its value, but saves and restores the66  // `fenv_t` state around the call.67  template <typename T>68  auto with_fenv_preserved(T &&callable)69      -> decltype(cpp::forward<decltype(callable)>(callable)()) {70    PreserveFEnv preserve{this};71    return cpp::forward<T>(callable)();72  }73 74  // A test can call these to indicate it will or won't change `fenv_t` state.75  void will_change_fenv() { should_be_unchanged = false; }76  void will_not_change_fenv() { should_be_unchanged = true; }77 78  // This explicitly resets back to the "before" state captured in SetUp().79  // TearDown() always does this, but should_be_unchanged controls whether80  // it also causes test failures if a test fails to restore it.81  void restore_fenv() { check.restore(); }82 83private:84  void get_fenv(fenv_t &fenv);85  void set_fenv(const fenv_t &fenv);86  void expect_fenv_eq(const fenv_t &before_fenv, const fenv_t &after_fenv);87 88  CheckFEnv check{this};89 90  // TODO: Many tests fail if this is true. It needs to be figured out whether91  // the state should be preserved by each library function under test, and92  // separately whether each test itself should preserve the state.  It93  // probably isn't important that tests be explicitly written to preserve the94  // state, as the fixture can (and does) reset it--the next test can rely on95  // getting "normal" ambient state initially.  For library functions that96  // should preserve the state, that should be checked after each call, not97  // just after the whole test.  So they can use check_fenv_preserved or98  // with_fenv_preserved as appropriate.99  bool should_be_unchanged = false;100};101 102} // namespace testing103} // namespace LIBC_NAMESPACE_DECL104 105#endif // LLVM_LIBC_TEST_UNITTEST_FPENVSAFE_H106