1 //===-- ErrnoSetterMatcher.h ------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H
10 #define LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H
12 #include "src/__support/FPUtil/FPBits.h"
13 #include "src/__support/FPUtil/fpbits_str.h"
14 #include "src/__support/StringUtil/error_to_string.h"
15 #include "src/__support/macros/properties/architectures.h"
16 #include "src/errno/libc_errno.h"
17 #include "test/UnitTest/Test.h"
19 namespace LIBC_NAMESPACE
{
24 enum class CompareAction
{ EQ
= 0, GE
, GT
, LE
, LT
, NE
};
26 constexpr const char *CompareMessage
[] = {
27 "equal to", "greater than or equal to",
28 "greater than", "less than or equal to",
29 "less than", "not equal to"};
31 template <typename T
> struct Comparator
{
34 bool compare(T actual
) {
36 case CompareAction::EQ
:
37 return actual
== expected
;
38 case CompareAction::NE
:
39 return actual
!= expected
;
40 case CompareAction::GE
:
41 return actual
>= expected
;
42 case CompareAction::GT
:
43 return actual
> expected
;
44 case CompareAction::LE
:
45 return actual
<= expected
;
46 case CompareAction::LT
:
47 return actual
< expected
;
49 __builtin_unreachable();
52 // The NVPTX backend cannot handle circular dependencies on global variables.
53 // We provide a constant dummy implementation to prevent this from occurring.
54 #ifdef LIBC_TARGET_ARCH_IS_NVPTX
55 constexpr const char *str() { return ""; }
57 const char *str() { return CompareMessage
[static_cast<int>(cmp
)]; }
61 template <typename T
> class ErrnoSetterMatcher
: public Matcher
<T
> {
62 Comparator
<T
> return_cmp
;
63 Comparator
<int> errno_cmp
;
67 // Even though this is a errno matcher primarily, it has to cater to platforms
68 // which do not have an errno. This predicate checks if errno matching is to
70 static constexpr bool ignore_errno() {
71 #ifdef LIBC_TARGET_ARCH_IS_GPU
79 ErrnoSetterMatcher(Comparator
<T
> rcmp
) : return_cmp(rcmp
) {}
80 ErrnoSetterMatcher(Comparator
<T
> rcmp
, Comparator
<int> ecmp
)
81 : return_cmp(rcmp
), errno_cmp(ecmp
) {}
83 ErrnoSetterMatcher
<T
> with_errno(Comparator
<int> ecmp
) {
88 void explainError() override
{
89 if (!return_cmp
.compare(actual_return
)) {
90 if constexpr (cpp::is_floating_point_v
<T
>) {
91 tlog
<< "Expected return value to be " << return_cmp
.str() << ": "
92 << str(fputil::FPBits
<T
>(return_cmp
.expected
)) << '\n'
94 << str(fputil::FPBits
<T
>(actual_return
)) << '\n';
96 tlog
<< "Expected return value to be " << return_cmp
.str() << " "
97 << return_cmp
.expected
<< " but got " << actual_return
<< ".\n";
101 if constexpr (!ignore_errno()) {
102 if (!errno_cmp
.compare(actual_errno
)) {
103 tlog
<< "Expected errno to be " << errno_cmp
.str() << " \""
104 << get_error_string(errno_cmp
.expected
) << "\" but got \""
105 << get_error_string(actual_errno
) << "\".\n";
112 actual_errno
= libc_errno
;
114 if constexpr (ignore_errno())
115 return return_cmp
.compare(actual_return
);
117 return return_cmp
.compare(actual_return
) &&
118 errno_cmp
.compare(actual_errno
);
122 } // namespace internal
124 namespace ErrnoSetterMatcher
{
126 template <typename T
> internal::Comparator
<T
> LT(T val
) {
127 return internal::Comparator
<T
>{internal::CompareAction::LT
, val
};
130 template <typename T
> internal::Comparator
<T
> LE(T val
) {
131 return internal::Comparator
<T
>{internal::CompareAction::LE
, val
};
134 template <typename T
> internal::Comparator
<T
> GT(T val
) {
135 return internal::Comparator
<T
>{internal::CompareAction::GT
, val
};
138 template <typename T
> internal::Comparator
<T
> GE(T val
) {
139 return internal::Comparator
<T
>{internal::CompareAction::GE
, val
};
142 template <typename T
> internal::Comparator
<T
> EQ(T val
) {
143 return internal::Comparator
<T
>{internal::CompareAction::EQ
, val
};
146 template <typename T
> internal::Comparator
<T
> NE(T val
) {
147 return internal::Comparator
<T
>{internal::CompareAction::NE
, val
};
150 template <typename RetT
= int>
151 static internal::ErrnoSetterMatcher
<RetT
> Succeeds(RetT ExpectedReturn
= 0,
152 int ExpectedErrno
= 0) {
153 return internal::ErrnoSetterMatcher
<RetT
>(EQ(ExpectedReturn
),
157 template <typename RetT
= int>
158 static internal::ErrnoSetterMatcher
<RetT
> Fails(int ExpectedErrno
,
159 RetT ExpectedReturn
= -1) {
160 return internal::ErrnoSetterMatcher
<RetT
>(EQ(ExpectedReturn
),
164 template <typename RetT
>
165 static internal::ErrnoSetterMatcher
<RetT
>
166 returns(internal::Comparator
<RetT
> cmp
) {
167 return internal::ErrnoSetterMatcher
<RetT
>(cmp
);
170 } // namespace ErrnoSetterMatcher
172 } // namespace testing
173 } // namespace LIBC_NAMESPACE
175 #endif // LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H