Skip to content

Commit 62a3d84

Browse files
authored
[libc][NFC] Extend ErrnoSetterMatcher to test expected inequalities. (#67153)
Before this change, ErrnoSetterMatcher only allowed testing for equality of the expected return and errno values. This change extends it to allow testing for expected inequalities of the return and errno values. The test libc.test.src.stdio.fileop_test has been updated to use the ErrnoSetterMatcher with tests for inequalities.
1 parent 3510552 commit 62a3d84

File tree

2 files changed

+118
-42
lines changed

2 files changed

+118
-42
lines changed

libc/test/UnitTest/ErrnoSetterMatcher.h

Lines changed: 94 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,42 @@ namespace testing {
2121

2222
namespace internal {
2323

24+
enum class CompareAction { EQ = 0, GE, GT, LE, LT, NE };
25+
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"};
30+
31+
template <typename T> struct Comparator {
32+
CompareAction cmp;
33+
T expected;
34+
bool compare(T actual) {
35+
switch (cmp) {
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;
48+
}
49+
__builtin_unreachable();
50+
}
51+
52+
const char *str() { return CompareMessage[static_cast<int>(cmp)]; }
53+
};
54+
2455
template <typename T> class ErrnoSetterMatcher : public Matcher<T> {
25-
T ExpectedReturn;
26-
T ActualReturn;
27-
int ExpectedErrno;
28-
int ActualErrno;
56+
Comparator<T> return_cmp;
57+
Comparator<int> errno_cmp;
58+
T actual_return;
59+
int actual_errno;
2960

3061
// Even though this is a errno matcher primarily, it has to cater to platforms
3162
// which do not have an errno. This predicate checks if errno matching is to
@@ -39,55 +70,95 @@ template <typename T> class ErrnoSetterMatcher : public Matcher<T> {
3970
}
4071

4172
public:
42-
ErrnoSetterMatcher(T ExpectedReturn, int ExpectedErrno)
43-
: ExpectedReturn(ExpectedReturn), ExpectedErrno(ExpectedErrno) {}
73+
ErrnoSetterMatcher(Comparator<T> rcmp) : return_cmp(rcmp) {}
74+
ErrnoSetterMatcher(Comparator<T> rcmp, Comparator<int> ecmp)
75+
: return_cmp(rcmp), errno_cmp(ecmp) {}
76+
77+
ErrnoSetterMatcher<T> with_errno(Comparator<int> ecmp) {
78+
errno_cmp = ecmp;
79+
return *this;
80+
}
4481

4582
void explainError() override {
46-
if (ActualReturn != ExpectedReturn) {
83+
if (!return_cmp.compare(actual_return)) {
4784
if constexpr (cpp::is_floating_point_v<T>) {
48-
tlog << "Expected return value to be: "
49-
<< str(fputil::FPBits<T>(ExpectedReturn)) << '\n';
50-
tlog << " But got: "
51-
<< str(fputil::FPBits<T>(ActualReturn)) << '\n';
85+
tlog << "Expected return value to be " << return_cmp.str() << ": "
86+
<< str(fputil::FPBits<T>(return_cmp.expected)) << '\n'
87+
<< " But got: "
88+
<< str(fputil::FPBits<T>(actual_return)) << '\n';
5289
} else {
53-
tlog << "Expected return value to be " << ExpectedReturn << " but got "
54-
<< ActualReturn << ".\n";
90+
tlog << "Expected return value to be " << return_cmp.str() << " "
91+
<< return_cmp.expected << " but got " << actual_return << ".\n";
5592
}
5693
}
5794

5895
if constexpr (!ignore_errno()) {
59-
if (ActualErrno != ExpectedErrno) {
60-
tlog << "Expected errno to be \"" << get_error_string(ExpectedErrno)
61-
<< "\" but got \"" << get_error_string(ActualErrno) << "\".\n";
96+
if (!errno_cmp.compare(actual_errno)) {
97+
tlog << "Expected errno to be " << errno_cmp.str() << " \""
98+
<< get_error_string(errno_cmp.expected) << "\" but got \""
99+
<< get_error_string(actual_errno) << "\".\n";
62100
}
63101
}
64102
}
65103

66-
bool match(T Got) {
67-
ActualReturn = Got;
68-
ActualErrno = libc_errno;
104+
bool match(T got) {
105+
actual_return = got;
106+
actual_errno = libc_errno;
69107
libc_errno = 0;
70108
if constexpr (ignore_errno())
71-
return Got == ExpectedReturn;
109+
return return_cmp.compare(actual_return);
72110
else
73-
return Got == ExpectedReturn && ActualErrno == ExpectedErrno;
111+
return return_cmp.compare(actual_return) &&
112+
errno_cmp.compare(actual_errno);
74113
}
75114
};
76115

77116
} // namespace internal
78117

79118
namespace ErrnoSetterMatcher {
80119

120+
template <typename T> internal::Comparator<T> LT(T val) {
121+
return internal::Comparator<T>{internal::CompareAction::LT, val};
122+
}
123+
124+
template <typename T> internal::Comparator<T> LE(T val) {
125+
return internal::Comparator<T>{internal::CompareAction::LE, val};
126+
}
127+
128+
template <typename T> internal::Comparator<T> GT(T val) {
129+
return internal::Comparator<T>{internal::CompareAction::GT, val};
130+
}
131+
132+
template <typename T> internal::Comparator<T> GE(T val) {
133+
return internal::Comparator<T>{internal::CompareAction::GE, val};
134+
}
135+
136+
template <typename T> internal::Comparator<T> EQ(T val) {
137+
return internal::Comparator<T>{internal::CompareAction::EQ, val};
138+
}
139+
140+
template <typename T> internal::Comparator<T> NE(T val) {
141+
return internal::Comparator<T>{internal::CompareAction::NE, val};
142+
}
143+
81144
template <typename RetT = int>
82145
static internal::ErrnoSetterMatcher<RetT> Succeeds(RetT ExpectedReturn = 0,
83146
int ExpectedErrno = 0) {
84-
return {ExpectedReturn, ExpectedErrno};
147+
return internal::ErrnoSetterMatcher<RetT>(EQ(ExpectedReturn),
148+
EQ(ExpectedErrno));
85149
}
86150

87151
template <typename RetT = int>
88152
static internal::ErrnoSetterMatcher<RetT> Fails(int ExpectedErrno,
89153
RetT ExpectedReturn = -1) {
90-
return {ExpectedReturn, ExpectedErrno};
154+
return internal::ErrnoSetterMatcher<RetT>(EQ(ExpectedReturn),
155+
EQ(ExpectedErrno));
156+
}
157+
158+
template <typename RetT>
159+
static internal::ErrnoSetterMatcher<RetT>
160+
returns(internal::Comparator<RetT> cmp) {
161+
return internal::ErrnoSetterMatcher<RetT>(cmp);
91162
}
92163

93164
} // namespace ErrnoSetterMatcher

libc/test/src/stdio/fileop_test.cpp

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@
1616
#include "src/stdio/fread.h"
1717
#include "src/stdio/fseek.h"
1818
#include "src/stdio/fwrite.h"
19+
#include "test/UnitTest/ErrnoSetterMatcher.h"
1920
#include "test/UnitTest/Test.h"
2021

2122
#include "src/errno/libc_errno.h"
2223
#include <stdio.h>
2324

25+
using __llvm_libc::testing::ErrnoSetterMatcher::EQ;
26+
using __llvm_libc::testing::ErrnoSetterMatcher::NE;
27+
using __llvm_libc::testing::ErrnoSetterMatcher::returns;
28+
2429
TEST(LlvmLibcFILETest, SimpleFileOperations) {
2530
constexpr char FILENAME[] = "testdata/simple_operations.test";
2631
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
@@ -31,9 +36,9 @@ TEST(LlvmLibcFILETest, SimpleFileOperations) {
3136

3237
// This is not a readable file.
3338
char read_data[sizeof(CONTENT)];
34-
ASSERT_EQ(__llvm_libc::fread(read_data, 1, sizeof(CONTENT), file), size_t(0));
39+
ASSERT_THAT(__llvm_libc::fread(read_data, 1, sizeof(CONTENT), file),
40+
returns(EQ(size_t(0))).with_errno(NE(0)));
3541
ASSERT_NE(__llvm_libc::ferror(file), 0);
36-
EXPECT_NE(libc_errno, 0);
3742
libc_errno = 0;
3843

3944
__llvm_libc::clearerr(file);
@@ -62,25 +67,25 @@ TEST(LlvmLibcFILETest, SimpleFileOperations) {
6267
ASSERT_NE(__llvm_libc::feof(file), 0);
6368

6469
// Should be an error to write.
65-
ASSERT_EQ(size_t(0), __llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT), file));
70+
ASSERT_THAT(__llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT), file),
71+
returns(EQ(size_t(0))).with_errno(NE(0)));
6672
ASSERT_NE(__llvm_libc::ferror(file), 0);
67-
ASSERT_NE(libc_errno, 0);
6873
libc_errno = 0;
6974

7075
__llvm_libc::clearerr(file);
7176

7277
// Should be an error to puts.
73-
ASSERT_EQ(EOF, __llvm_libc::fputs(CONTENT, file));
78+
ASSERT_THAT(__llvm_libc::fputs(CONTENT, file),
79+
returns(EQ(EOF)).with_errno(NE(0)));
7480
ASSERT_NE(__llvm_libc::ferror(file), 0);
75-
ASSERT_NE(libc_errno, 0);
7681
libc_errno = 0;
7782

7883
__llvm_libc::clearerr(file);
7984
ASSERT_EQ(__llvm_libc::ferror(file), 0);
8085

8186
libc_errno = 0;
82-
ASSERT_EQ(__llvm_libc::fwrite("nothing", 1, 1, file), size_t(0));
83-
ASSERT_NE(libc_errno, 0);
87+
ASSERT_THAT(__llvm_libc::fwrite("nothing", 1, 1, file),
88+
returns(EQ(0)).with_errno(NE(0)));
8489
libc_errno = 0;
8590

8691
ASSERT_EQ(__llvm_libc::fclose(file), 0);
@@ -97,8 +102,8 @@ TEST(LlvmLibcFILETest, SimpleFileOperations) {
97102

98103
// This is not a readable file.
99104
libc_errno = 0;
100-
ASSERT_EQ(__llvm_libc::fread(data, 1, 1, file), size_t(0));
101-
ASSERT_NE(libc_errno, 0);
105+
ASSERT_THAT(__llvm_libc::fread(data, 1, 1, file),
106+
returns(EQ(0)).with_errno(NE(0)));
102107
libc_errno = 0;
103108

104109
ASSERT_EQ(0, __llvm_libc::fclose(file));
@@ -162,22 +167,22 @@ TEST(LlvmLibcFILETest, FOpenFWriteSizeGreaterThanOne) {
162167
FILE *file = __llvm_libc::fopen(FILENAME, "w");
163168
ASSERT_FALSE(file == nullptr);
164169
ASSERT_EQ(size_t(0), __llvm_libc::fwrite(WRITE_DATA, 0, 1, file));
165-
ASSERT_EQ(WRITE_NMEMB, __llvm_libc::fwrite(WRITE_DATA, sizeof(MyStruct),
166-
WRITE_NMEMB, file));
167-
EXPECT_EQ(libc_errno, 0);
170+
ASSERT_THAT(
171+
__llvm_libc::fwrite(WRITE_DATA, sizeof(MyStruct), WRITE_NMEMB, file),
172+
returns(EQ(WRITE_NMEMB)).with_errno(EQ(0)));
168173
ASSERT_EQ(__llvm_libc::fclose(file), 0);
169174

170175
file = __llvm_libc::fopen(FILENAME, "r");
171176
ASSERT_FALSE(file == nullptr);
172177
MyStruct read_data[WRITE_NMEMB];
173178
ASSERT_EQ(size_t(0), __llvm_libc::fread(read_data, 0, 1, file));
174-
ASSERT_EQ(WRITE_NMEMB,
175-
__llvm_libc::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file));
176-
EXPECT_EQ(libc_errno, 0);
179+
ASSERT_THAT(
180+
__llvm_libc::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file),
181+
returns(EQ(WRITE_NMEMB)).with_errno(EQ(0)));
177182
// Trying to read more should fetch nothing.
178-
ASSERT_EQ(size_t(0),
179-
__llvm_libc::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file));
180-
EXPECT_EQ(libc_errno, 0);
183+
ASSERT_THAT(
184+
__llvm_libc::fread(read_data, sizeof(MyStruct), WRITE_NMEMB, file),
185+
returns(EQ(0)).with_errno(EQ(0)));
181186
EXPECT_NE(__llvm_libc::feof(file), 0);
182187
EXPECT_EQ(__llvm_libc::ferror(file), 0);
183188
ASSERT_EQ(__llvm_libc::fclose(file), 0);

0 commit comments

Comments
 (0)