1 //===-- TestMatchers.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIBC_UTILS_UNITTEST_FPMATCHER_H 10 #define LLVM_LIBC_UTILS_UNITTEST_FPMATCHER_H 11 12 #include "src/__support/FPUtil/FEnvImpl.h" 13 #include "src/__support/FPUtil/FPBits.h" 14 #include "utils/UnitTest/Test.h" 15 16 #include <errno.h> 17 #include <math.h> 18 19 namespace __llvm_libc { 20 namespace fputil { 21 namespace testing { 22 23 template <typename ValType, typename StreamType> 24 cpp::EnableIfType<cpp::IsFloatingPointType<ValType>::Value, void> 25 describeValue(const char *label, ValType value, StreamType &stream); 26 27 template <typename T, __llvm_libc::testing::TestCondition Condition> 28 class FPMatcher : public __llvm_libc::testing::Matcher<T> { 29 static_assert(__llvm_libc::cpp::IsFloatingPointType<T>::Value, 30 "FPMatcher can only be used with floating point values."); 31 static_assert(Condition == __llvm_libc::testing::Cond_EQ || 32 Condition == __llvm_libc::testing::Cond_NE, 33 "Unsupported FPMathcer test condition."); 34 35 T expected; 36 T actual; 37 38 public: 39 FPMatcher(T expectedValue) : expected(expectedValue) {} 40 41 bool match(T actualValue) { 42 actual = actualValue; 43 fputil::FPBits<T> actualBits(actual), expectedBits(expected); 44 if (Condition == __llvm_libc::testing::Cond_EQ) 45 return (actualBits.is_nan() && expectedBits.is_nan()) || 46 (actualBits.uintval() == expectedBits.uintval()); 47 48 // If condition == Cond_NE. 49 if (actualBits.is_nan()) 50 return !expectedBits.is_nan(); 51 return expectedBits.is_nan() || 52 (actualBits.uintval() != expectedBits.uintval()); 53 } 54 55 void explainError(testutils::StreamWrapper &stream) override { 56 describeValue("Expected floating point value: ", expected, stream); 57 describeValue(" Actual floating point value: ", actual, stream); 58 } 59 }; 60 61 template <__llvm_libc::testing::TestCondition C, typename T> 62 FPMatcher<T, C> getMatcher(T expectedValue) { 63 return FPMatcher<T, C>(expectedValue); 64 } 65 66 } // namespace testing 67 } // namespace fputil 68 } // namespace __llvm_libc 69 70 #define DECLARE_SPECIAL_CONSTANTS(T) \ 71 using FPBits = __llvm_libc::fputil::FPBits<T>; \ 72 using UIntType = typename FPBits::UIntType; \ 73 const T zero = T(FPBits::zero()); \ 74 const T neg_zero = T(FPBits::neg_zero()); \ 75 const T aNaN = T(FPBits::build_nan(1)); \ 76 const T inf = T(FPBits::inf()); \ 77 const T neg_inf = T(FPBits::neg_inf()); 78 79 #define EXPECT_FP_EQ(expected, actual) \ 80 EXPECT_THAT( \ 81 actual, \ 82 __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_EQ>( \ 83 expected)) 84 85 #define ASSERT_FP_EQ(expected, actual) \ 86 ASSERT_THAT( \ 87 actual, \ 88 __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_EQ>( \ 89 expected)) 90 91 #define EXPECT_FP_NE(expected, actual) \ 92 EXPECT_THAT( \ 93 actual, \ 94 __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_NE>( \ 95 expected)) 96 97 #define ASSERT_FP_NE(expected, actual) \ 98 ASSERT_THAT( \ 99 actual, \ 100 __llvm_libc::fputil::testing::getMatcher<__llvm_libc::testing::Cond_NE>( \ 101 expected)) 102 103 #define EXPECT_MATH_ERRNO(expected) \ 104 do { \ 105 if (math_errhandling & MATH_ERRNO) { \ 106 int actual = errno; \ 107 errno = 0; \ 108 EXPECT_EQ(actual, expected); \ 109 } \ 110 } while (0) 111 112 #define ASSERT_MATH_ERRNO(expected) \ 113 do { \ 114 if (math_errhandling & MATH_ERRNO) { \ 115 int actual = errno; \ 116 errno = 0; \ 117 ASSERT_EQ(actual, expected); \ 118 } \ 119 } while (0) 120 121 #define EXPECT_FP_EXCEPTION(expected) \ 122 do { \ 123 if (math_errhandling & MATH_ERREXCEPT) { \ 124 EXPECT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT), expected); \ 125 } \ 126 } while (0) 127 128 #define ASSERT_FP_EXCEPTION(expected) \ 129 do { \ 130 if (math_errhandling & MATH_ERREXCEPT) { \ 131 ASSERT_EQ(__llvm_libc::fputil::test_except(FE_ALL_EXCEPT), expected); \ 132 } \ 133 } while (0) 134 135 #endif // LLVM_LIBC_UTILS_UNITTEST_FPMATCHER_H 136