1*71db0c75SAndroid Build Coastguard Worker //===-- ErrnoSetterMatcher.h ------------------------------------*- C++ -*-===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker
9*71db0c75SAndroid Build Coastguard Worker #ifndef LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H
10*71db0c75SAndroid Build Coastguard Worker #define LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H
11*71db0c75SAndroid Build Coastguard Worker
12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/FPBits.h"
13*71db0c75SAndroid Build Coastguard Worker #include "src/__support/FPUtil/fpbits_str.h"
14*71db0c75SAndroid Build Coastguard Worker #include "src/__support/StringUtil/error_to_string.h"
15*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h"
16*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/properties/architectures.h"
17*71db0c75SAndroid Build Coastguard Worker #include "src/errno/libc_errno.h"
18*71db0c75SAndroid Build Coastguard Worker #include "test/UnitTest/Test.h"
19*71db0c75SAndroid Build Coastguard Worker
20*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
21*71db0c75SAndroid Build Coastguard Worker namespace testing {
22*71db0c75SAndroid Build Coastguard Worker
23*71db0c75SAndroid Build Coastguard Worker namespace internal {
24*71db0c75SAndroid Build Coastguard Worker
25*71db0c75SAndroid Build Coastguard Worker enum class CompareAction { EQ = 0, GE, GT, LE, LT, NE };
26*71db0c75SAndroid Build Coastguard Worker
27*71db0c75SAndroid Build Coastguard Worker constexpr const char *CompareMessage[] = {
28*71db0c75SAndroid Build Coastguard Worker "equal to", "greater than or equal to",
29*71db0c75SAndroid Build Coastguard Worker "greater than", "less than or equal to",
30*71db0c75SAndroid Build Coastguard Worker "less than", "not equal to"};
31*71db0c75SAndroid Build Coastguard Worker
32*71db0c75SAndroid Build Coastguard Worker template <typename T> struct Comparator {
33*71db0c75SAndroid Build Coastguard Worker CompareAction cmp;
34*71db0c75SAndroid Build Coastguard Worker T expected;
compareComparator35*71db0c75SAndroid Build Coastguard Worker bool compare(T actual) {
36*71db0c75SAndroid Build Coastguard Worker switch (cmp) {
37*71db0c75SAndroid Build Coastguard Worker case CompareAction::EQ:
38*71db0c75SAndroid Build Coastguard Worker return actual == expected;
39*71db0c75SAndroid Build Coastguard Worker case CompareAction::NE:
40*71db0c75SAndroid Build Coastguard Worker return actual != expected;
41*71db0c75SAndroid Build Coastguard Worker case CompareAction::GE:
42*71db0c75SAndroid Build Coastguard Worker return actual >= expected;
43*71db0c75SAndroid Build Coastguard Worker case CompareAction::GT:
44*71db0c75SAndroid Build Coastguard Worker return actual > expected;
45*71db0c75SAndroid Build Coastguard Worker case CompareAction::LE:
46*71db0c75SAndroid Build Coastguard Worker return actual <= expected;
47*71db0c75SAndroid Build Coastguard Worker case CompareAction::LT:
48*71db0c75SAndroid Build Coastguard Worker return actual < expected;
49*71db0c75SAndroid Build Coastguard Worker }
50*71db0c75SAndroid Build Coastguard Worker __builtin_unreachable();
51*71db0c75SAndroid Build Coastguard Worker }
52*71db0c75SAndroid Build Coastguard Worker
53*71db0c75SAndroid Build Coastguard Worker // The NVPTX backend cannot handle circular dependencies on global variables.
54*71db0c75SAndroid Build Coastguard Worker // We provide a constant dummy implementation to prevent this from occurring.
55*71db0c75SAndroid Build Coastguard Worker #ifdef LIBC_TARGET_ARCH_IS_NVPTX
strComparator56*71db0c75SAndroid Build Coastguard Worker constexpr const char *str() { return ""; }
57*71db0c75SAndroid Build Coastguard Worker #else
strComparator58*71db0c75SAndroid Build Coastguard Worker const char *str() { return CompareMessage[static_cast<int>(cmp)]; }
59*71db0c75SAndroid Build Coastguard Worker #endif
60*71db0c75SAndroid Build Coastguard Worker };
61*71db0c75SAndroid Build Coastguard Worker
62*71db0c75SAndroid Build Coastguard Worker template <typename T> class ErrnoSetterMatcher : public Matcher<T> {
63*71db0c75SAndroid Build Coastguard Worker Comparator<T> return_cmp;
64*71db0c75SAndroid Build Coastguard Worker Comparator<int> errno_cmp;
65*71db0c75SAndroid Build Coastguard Worker T actual_return;
66*71db0c75SAndroid Build Coastguard Worker int actual_errno;
67*71db0c75SAndroid Build Coastguard Worker
68*71db0c75SAndroid Build Coastguard Worker // Even though this is a errno matcher primarily, it has to cater to platforms
69*71db0c75SAndroid Build Coastguard Worker // which do not have an errno. This predicate checks if errno matching is to
70*71db0c75SAndroid Build Coastguard Worker // be skipped.
ignore_errno()71*71db0c75SAndroid Build Coastguard Worker static constexpr bool ignore_errno() {
72*71db0c75SAndroid Build Coastguard Worker #ifdef LIBC_TARGET_ARCH_IS_GPU
73*71db0c75SAndroid Build Coastguard Worker return true;
74*71db0c75SAndroid Build Coastguard Worker #else
75*71db0c75SAndroid Build Coastguard Worker return false;
76*71db0c75SAndroid Build Coastguard Worker #endif
77*71db0c75SAndroid Build Coastguard Worker }
78*71db0c75SAndroid Build Coastguard Worker
79*71db0c75SAndroid Build Coastguard Worker public:
ErrnoSetterMatcher(Comparator<T> rcmp)80*71db0c75SAndroid Build Coastguard Worker ErrnoSetterMatcher(Comparator<T> rcmp) : return_cmp(rcmp) {}
ErrnoSetterMatcher(Comparator<T> rcmp,Comparator<int> ecmp)81*71db0c75SAndroid Build Coastguard Worker ErrnoSetterMatcher(Comparator<T> rcmp, Comparator<int> ecmp)
82*71db0c75SAndroid Build Coastguard Worker : return_cmp(rcmp), errno_cmp(ecmp) {}
83*71db0c75SAndroid Build Coastguard Worker
with_errno(Comparator<int> ecmp)84*71db0c75SAndroid Build Coastguard Worker ErrnoSetterMatcher<T> with_errno(Comparator<int> ecmp) {
85*71db0c75SAndroid Build Coastguard Worker errno_cmp = ecmp;
86*71db0c75SAndroid Build Coastguard Worker return *this;
87*71db0c75SAndroid Build Coastguard Worker }
88*71db0c75SAndroid Build Coastguard Worker
explainError()89*71db0c75SAndroid Build Coastguard Worker void explainError() override {
90*71db0c75SAndroid Build Coastguard Worker if (!return_cmp.compare(actual_return)) {
91*71db0c75SAndroid Build Coastguard Worker if constexpr (cpp::is_floating_point_v<T>) {
92*71db0c75SAndroid Build Coastguard Worker tlog << "Expected return value to be " << return_cmp.str() << ": "
93*71db0c75SAndroid Build Coastguard Worker << str(fputil::FPBits<T>(return_cmp.expected)) << '\n'
94*71db0c75SAndroid Build Coastguard Worker << " But got: "
95*71db0c75SAndroid Build Coastguard Worker << str(fputil::FPBits<T>(actual_return)) << '\n';
96*71db0c75SAndroid Build Coastguard Worker } else {
97*71db0c75SAndroid Build Coastguard Worker tlog << "Expected return value to be " << return_cmp.str() << " "
98*71db0c75SAndroid Build Coastguard Worker << return_cmp.expected << " but got " << actual_return << ".\n";
99*71db0c75SAndroid Build Coastguard Worker }
100*71db0c75SAndroid Build Coastguard Worker }
101*71db0c75SAndroid Build Coastguard Worker
102*71db0c75SAndroid Build Coastguard Worker if constexpr (!ignore_errno()) {
103*71db0c75SAndroid Build Coastguard Worker if (!errno_cmp.compare(actual_errno)) {
104*71db0c75SAndroid Build Coastguard Worker tlog << "Expected errno to be " << errno_cmp.str() << " \""
105*71db0c75SAndroid Build Coastguard Worker << get_error_string(errno_cmp.expected) << "\" but got \""
106*71db0c75SAndroid Build Coastguard Worker << get_error_string(actual_errno) << "\".\n";
107*71db0c75SAndroid Build Coastguard Worker }
108*71db0c75SAndroid Build Coastguard Worker }
109*71db0c75SAndroid Build Coastguard Worker }
110*71db0c75SAndroid Build Coastguard Worker
match(T got)111*71db0c75SAndroid Build Coastguard Worker bool match(T got) {
112*71db0c75SAndroid Build Coastguard Worker actual_return = got;
113*71db0c75SAndroid Build Coastguard Worker actual_errno = LIBC_NAMESPACE::libc_errno;
114*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::libc_errno = 0;
115*71db0c75SAndroid Build Coastguard Worker if constexpr (ignore_errno())
116*71db0c75SAndroid Build Coastguard Worker return return_cmp.compare(actual_return);
117*71db0c75SAndroid Build Coastguard Worker else
118*71db0c75SAndroid Build Coastguard Worker return return_cmp.compare(actual_return) &&
119*71db0c75SAndroid Build Coastguard Worker errno_cmp.compare(actual_errno);
120*71db0c75SAndroid Build Coastguard Worker }
121*71db0c75SAndroid Build Coastguard Worker };
122*71db0c75SAndroid Build Coastguard Worker
123*71db0c75SAndroid Build Coastguard Worker } // namespace internal
124*71db0c75SAndroid Build Coastguard Worker
125*71db0c75SAndroid Build Coastguard Worker namespace ErrnoSetterMatcher {
126*71db0c75SAndroid Build Coastguard Worker
LT(T val)127*71db0c75SAndroid Build Coastguard Worker template <typename T> internal::Comparator<T> LT(T val) {
128*71db0c75SAndroid Build Coastguard Worker return internal::Comparator<T>{internal::CompareAction::LT, val};
129*71db0c75SAndroid Build Coastguard Worker }
130*71db0c75SAndroid Build Coastguard Worker
LE(T val)131*71db0c75SAndroid Build Coastguard Worker template <typename T> internal::Comparator<T> LE(T val) {
132*71db0c75SAndroid Build Coastguard Worker return internal::Comparator<T>{internal::CompareAction::LE, val};
133*71db0c75SAndroid Build Coastguard Worker }
134*71db0c75SAndroid Build Coastguard Worker
GT(T val)135*71db0c75SAndroid Build Coastguard Worker template <typename T> internal::Comparator<T> GT(T val) {
136*71db0c75SAndroid Build Coastguard Worker return internal::Comparator<T>{internal::CompareAction::GT, val};
137*71db0c75SAndroid Build Coastguard Worker }
138*71db0c75SAndroid Build Coastguard Worker
GE(T val)139*71db0c75SAndroid Build Coastguard Worker template <typename T> internal::Comparator<T> GE(T val) {
140*71db0c75SAndroid Build Coastguard Worker return internal::Comparator<T>{internal::CompareAction::GE, val};
141*71db0c75SAndroid Build Coastguard Worker }
142*71db0c75SAndroid Build Coastguard Worker
EQ(T val)143*71db0c75SAndroid Build Coastguard Worker template <typename T> internal::Comparator<T> EQ(T val) {
144*71db0c75SAndroid Build Coastguard Worker return internal::Comparator<T>{internal::CompareAction::EQ, val};
145*71db0c75SAndroid Build Coastguard Worker }
146*71db0c75SAndroid Build Coastguard Worker
NE(T val)147*71db0c75SAndroid Build Coastguard Worker template <typename T> internal::Comparator<T> NE(T val) {
148*71db0c75SAndroid Build Coastguard Worker return internal::Comparator<T>{internal::CompareAction::NE, val};
149*71db0c75SAndroid Build Coastguard Worker }
150*71db0c75SAndroid Build Coastguard Worker
151*71db0c75SAndroid Build Coastguard Worker template <typename RetT = int>
152*71db0c75SAndroid Build Coastguard Worker static internal::ErrnoSetterMatcher<RetT> Succeeds(RetT ExpectedReturn = 0,
153*71db0c75SAndroid Build Coastguard Worker int ExpectedErrno = 0) {
154*71db0c75SAndroid Build Coastguard Worker return internal::ErrnoSetterMatcher<RetT>(EQ(ExpectedReturn),
155*71db0c75SAndroid Build Coastguard Worker EQ(ExpectedErrno));
156*71db0c75SAndroid Build Coastguard Worker }
157*71db0c75SAndroid Build Coastguard Worker
158*71db0c75SAndroid Build Coastguard Worker template <typename RetT = int>
159*71db0c75SAndroid Build Coastguard Worker static internal::ErrnoSetterMatcher<RetT> Fails(int ExpectedErrno,
160*71db0c75SAndroid Build Coastguard Worker RetT ExpectedReturn = -1) {
161*71db0c75SAndroid Build Coastguard Worker return internal::ErrnoSetterMatcher<RetT>(EQ(ExpectedReturn),
162*71db0c75SAndroid Build Coastguard Worker EQ(ExpectedErrno));
163*71db0c75SAndroid Build Coastguard Worker }
164*71db0c75SAndroid Build Coastguard Worker
165*71db0c75SAndroid Build Coastguard Worker template <typename RetT = int> class ErrnoSetterMatcherBuilder {
166*71db0c75SAndroid Build Coastguard Worker public:
167*71db0c75SAndroid Build Coastguard Worker template <typename T> using Cmp = internal::Comparator<T>;
ErrnoSetterMatcherBuilder(Cmp<RetT> cmp)168*71db0c75SAndroid Build Coastguard Worker ErrnoSetterMatcherBuilder(Cmp<RetT> cmp) : return_cmp(cmp) {}
169*71db0c75SAndroid Build Coastguard Worker
with_errno(Cmp<int> cmp)170*71db0c75SAndroid Build Coastguard Worker internal::ErrnoSetterMatcher<RetT> with_errno(Cmp<int> cmp) {
171*71db0c75SAndroid Build Coastguard Worker return internal::ErrnoSetterMatcher<RetT>(return_cmp, cmp);
172*71db0c75SAndroid Build Coastguard Worker }
173*71db0c75SAndroid Build Coastguard Worker
174*71db0c75SAndroid Build Coastguard Worker private:
175*71db0c75SAndroid Build Coastguard Worker Cmp<RetT> return_cmp;
176*71db0c75SAndroid Build Coastguard Worker };
177*71db0c75SAndroid Build Coastguard Worker
178*71db0c75SAndroid Build Coastguard Worker template <typename RetT>
returns(internal::Comparator<RetT> cmp)179*71db0c75SAndroid Build Coastguard Worker static ErrnoSetterMatcherBuilder<RetT> returns(internal::Comparator<RetT> cmp) {
180*71db0c75SAndroid Build Coastguard Worker return ErrnoSetterMatcherBuilder<RetT>(cmp);
181*71db0c75SAndroid Build Coastguard Worker }
182*71db0c75SAndroid Build Coastguard Worker
183*71db0c75SAndroid Build Coastguard Worker } // namespace ErrnoSetterMatcher
184*71db0c75SAndroid Build Coastguard Worker
185*71db0c75SAndroid Build Coastguard Worker } // namespace testing
186*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
187*71db0c75SAndroid Build Coastguard Worker
188*71db0c75SAndroid Build Coastguard Worker #endif // LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H
189