[Clang] ensure mangled names are valid identifiers before being suggested in ifunc...
[llvm-project.git] / libc / test / UnitTest / ErrnoSetterMatcher.h
bloba895c5044b0ad163ef6d61398c3142e194d8293a
1 //===-- ErrnoSetterMatcher.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 //===----------------------------------------------------------------------===//
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/config.h"
16 #include "src/__support/macros/properties/architectures.h"
17 #include "src/errno/libc_errno.h"
18 #include "test/UnitTest/Test.h"
20 namespace LIBC_NAMESPACE_DECL {
21 namespace testing {
23 namespace internal {
25 enum class CompareAction { EQ = 0, GE, GT, LE, LT, NE };
27 constexpr const char *CompareMessage[] = {
28 "equal to", "greater than or equal to",
29 "greater than", "less than or equal to",
30 "less than", "not equal to"};
32 template <typename T> struct Comparator {
33 CompareAction cmp;
34 T expected;
35 bool compare(T actual) {
36 switch (cmp) {
37 case CompareAction::EQ:
38 return actual == expected;
39 case CompareAction::NE:
40 return actual != expected;
41 case CompareAction::GE:
42 return actual >= expected;
43 case CompareAction::GT:
44 return actual > expected;
45 case CompareAction::LE:
46 return actual <= expected;
47 case CompareAction::LT:
48 return actual < expected;
50 __builtin_unreachable();
53 // The NVPTX backend cannot handle circular dependencies on global variables.
54 // We provide a constant dummy implementation to prevent this from occurring.
55 #ifdef LIBC_TARGET_ARCH_IS_NVPTX
56 constexpr const char *str() { return ""; }
57 #else
58 const char *str() { return CompareMessage[static_cast<int>(cmp)]; }
59 #endif
62 template <typename T> class ErrnoSetterMatcher : public Matcher<T> {
63 Comparator<T> return_cmp;
64 Comparator<int> errno_cmp;
65 T actual_return;
66 int actual_errno;
68 // Even though this is a errno matcher primarily, it has to cater to platforms
69 // which do not have an errno. This predicate checks if errno matching is to
70 // be skipped.
71 static constexpr bool ignore_errno() {
72 #ifdef LIBC_TARGET_ARCH_IS_GPU
73 return true;
74 #else
75 return false;
76 #endif
79 public:
80 ErrnoSetterMatcher(Comparator<T> rcmp) : return_cmp(rcmp) {}
81 ErrnoSetterMatcher(Comparator<T> rcmp, Comparator<int> ecmp)
82 : return_cmp(rcmp), errno_cmp(ecmp) {}
84 ErrnoSetterMatcher<T> with_errno(Comparator<int> ecmp) {
85 errno_cmp = ecmp;
86 return *this;
89 void explainError() override {
90 if (!return_cmp.compare(actual_return)) {
91 if constexpr (cpp::is_floating_point_v<T>) {
92 tlog << "Expected return value to be " << return_cmp.str() << ": "
93 << str(fputil::FPBits<T>(return_cmp.expected)) << '\n'
94 << " But got: "
95 << str(fputil::FPBits<T>(actual_return)) << '\n';
96 } else {
97 tlog << "Expected return value to be " << return_cmp.str() << " "
98 << return_cmp.expected << " but got " << actual_return << ".\n";
102 if constexpr (!ignore_errno()) {
103 if (!errno_cmp.compare(actual_errno)) {
104 tlog << "Expected errno to be " << errno_cmp.str() << " \""
105 << get_error_string(errno_cmp.expected) << "\" but got \""
106 << get_error_string(actual_errno) << "\".\n";
111 bool match(T got) {
112 actual_return = got;
113 actual_errno = LIBC_NAMESPACE::libc_errno;
114 LIBC_NAMESPACE::libc_errno = 0;
115 if constexpr (ignore_errno())
116 return return_cmp.compare(actual_return);
117 else
118 return return_cmp.compare(actual_return) &&
119 errno_cmp.compare(actual_errno);
123 } // namespace internal
125 namespace ErrnoSetterMatcher {
127 template <typename T> internal::Comparator<T> LT(T val) {
128 return internal::Comparator<T>{internal::CompareAction::LT, val};
131 template <typename T> internal::Comparator<T> LE(T val) {
132 return internal::Comparator<T>{internal::CompareAction::LE, val};
135 template <typename T> internal::Comparator<T> GT(T val) {
136 return internal::Comparator<T>{internal::CompareAction::GT, val};
139 template <typename T> internal::Comparator<T> GE(T val) {
140 return internal::Comparator<T>{internal::CompareAction::GE, val};
143 template <typename T> internal::Comparator<T> EQ(T val) {
144 return internal::Comparator<T>{internal::CompareAction::EQ, val};
147 template <typename T> internal::Comparator<T> NE(T val) {
148 return internal::Comparator<T>{internal::CompareAction::NE, val};
151 template <typename RetT = int>
152 static internal::ErrnoSetterMatcher<RetT> Succeeds(RetT ExpectedReturn = 0,
153 int ExpectedErrno = 0) {
154 return internal::ErrnoSetterMatcher<RetT>(EQ(ExpectedReturn),
155 EQ(ExpectedErrno));
158 template <typename RetT = int>
159 static internal::ErrnoSetterMatcher<RetT> Fails(int ExpectedErrno,
160 RetT ExpectedReturn = -1) {
161 return internal::ErrnoSetterMatcher<RetT>(EQ(ExpectedReturn),
162 EQ(ExpectedErrno));
165 template <typename RetT = int> class ErrnoSetterMatcherBuilder {
166 public:
167 template <typename T> using Cmp = internal::Comparator<T>;
168 ErrnoSetterMatcherBuilder(Cmp<RetT> cmp) : return_cmp(cmp) {}
170 internal::ErrnoSetterMatcher<RetT> with_errno(Cmp<int> cmp) {
171 return internal::ErrnoSetterMatcher<RetT>(return_cmp, cmp);
174 private:
175 Cmp<RetT> return_cmp;
178 template <typename RetT>
179 static ErrnoSetterMatcherBuilder<RetT> returns(internal::Comparator<RetT> cmp) {
180 return ErrnoSetterMatcherBuilder<RetT>(cmp);
183 } // namespace ErrnoSetterMatcher
185 } // namespace testing
186 } // namespace LIBC_NAMESPACE_DECL
188 #endif // LLVM_LIBC_TEST_ERRNOSETTERMATCHER_H