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:
FPMatcher(T expectedValue)39 FPMatcher(T expectedValue) : expected(expectedValue) {}
40
match(T actualValue)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
explainError(testutils::StreamWrapper & stream)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>
getMatcher(T expectedValue)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