Skip to content

Commit 0a8be6c

Browse files
committed
Add Not operator for expects
1 parent a03c6c0 commit 0a8be6c

File tree

4 files changed

+124
-39
lines changed

4 files changed

+124
-39
lines changed

runner/watch-mode.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,12 @@ static std::vector<std::string> filterTestsBy(
104104
return tests_to_run;
105105
}
106106

107-
static bool isBackspace(char key)
107+
static constexpr bool isBackspace(char key)
108108
{
109109
return key == '\b' || key == '\x7f';
110110
}
111111

112-
static bool isPrintableCharacter(char key)
112+
static constexpr bool isPrintableCharacter(char key)
113113
{
114114
return key >= ' ' && key <= '~';
115115
}

src/expect.hpp

Lines changed: 86 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
#define CLIP_STRING_LENGTH 16
88

9-
#define expect(...) cest::expectFunction(__FILE__, __LINE__, __VA_ARGS__)
9+
#define expect(...) cest::expectFunction(__FILE__, ((__LINE__ - 1)), __VA_ARGS__)
1010
#define passTest() cest::forcedPass()
1111
#define failTest() cest::forcedFailure(__FILE__, __LINE__)
1212
#define Regex(x) x, std::regex(x)
@@ -45,28 +45,33 @@ namespace cest
4545
class Assertion
4646
{
4747
public:
48-
Assertion(const char *file, int line, T value)
48+
Assertion(const char *file, int line, T value, bool negated = false) : negated(false)
4949
{
5050
actual = value;
5151
assertion_file = std::string(file);
5252
assertion_line = line;
53+
54+
if (!negated)
55+
this->Not = new Assertion<T>(file, line, value, true);
56+
else
57+
this->negated = true;
5358
}
5459

5560
void toBeTruthy()
5661
{
57-
if (!actual)
62+
if (!actual ^ this->negated)
5863
throw AssertionError(assertion_file, assertion_line, "Expresion is not truthy");
5964
}
6065

6166
void toBeFalsy()
6267
{
63-
if (actual)
68+
if (actual ^ this->negated)
6469
throw AssertionError(assertion_file, assertion_line, "Expresion is not falsy");
6570
}
6671

6772
void toBe(T expected)
6873
{
69-
if (expected != actual)
74+
if ((expected != actual) ^ this->negated)
7075
{
7176

7277
std::stringstream message;
@@ -83,22 +88,23 @@ namespace cest
8388
void toEqualMemory(T expected, int64_t length)
8489
{
8590
int i;
91+
bool any_byte_differs = false;
8692

8793
for (i = 0; i < length; ++i)
94+
any_byte_differs |= expected[i] != actual[i];
95+
96+
if (any_byte_differs ^ negated)
8897
{
89-
if (expected[i] != actual[i])
90-
{
91-
std::stringstream message;
92-
message << "Memory mismatch at byte " << i << ", expected ";
93-
message << std::hex << std::uppercase << (int)expected[i] << " but was " << std::hex << std::uppercase << (int)actual[i];
94-
throw AssertionError(assertion_file, assertion_line, message.str());
95-
}
98+
std::stringstream message;
99+
message << "Memory mismatch at byte " << i << ", expected ";
100+
message << std::hex << std::uppercase << (int)expected[i] << " but was " << std::hex << std::uppercase << (int)actual[i];
101+
throw AssertionError(assertion_file, assertion_line, message.str());
96102
}
97103
}
98104

99105
void toBeNotNull()
100106
{
101-
if (actual == NULL)
107+
if ((actual == NULL) ^ negated)
102108
{
103109
std::stringstream message;
104110
message << "Expected 0x" << std::hex << std::uppercase << actual << " to be not null";
@@ -108,15 +114,18 @@ namespace cest
108114

109115
void toBeNull()
110116
{
111-
if (actual != NULL)
117+
if ((actual != NULL) ^ negated)
112118
{
113119
std::stringstream message;
114120
message << "Expected 0x" << std::hex << std::uppercase << actual << " to be null";
115121
throw AssertionError(assertion_file, assertion_line, message.str());
116122
}
117123
}
118124

125+
Assertion<T> *Not;
126+
119127
private:
128+
bool negated;
120129
T actual;
121130
std::string assertion_file;
122131
int assertion_line;
@@ -126,16 +135,21 @@ namespace cest
126135
class Assertion<double>
127136
{
128137
public:
129-
Assertion(const char *file, int line, double value)
138+
Assertion(const char *file, int line, double value, bool negated = false) : negated(false)
130139
{
131140
actual = value;
132141
assertion_file = std::string(file);
133142
assertion_line = line;
143+
144+
if (!negated)
145+
this->Not = new Assertion<double>(file, line, value, true);
146+
else
147+
this->negated = true;
134148
}
135149

136150
void toBe(double expected, double epsilon = 0.0000001)
137151
{
138-
if (fabs(actual - expected) > epsilon)
152+
if ((fabs(actual - expected) > epsilon) ^ negated)
139153
{
140154
std::stringstream message;
141155
message << "Expected " << expected << ", was " << actual;
@@ -150,7 +164,7 @@ namespace cest
150164

151165
void toBeGreaterThan(double expected)
152166
{
153-
if (actual < expected)
167+
if ((actual < expected) ^ negated)
154168
{
155169
std::stringstream message;
156170
message << "Expected " << expected << " to be greather than" << actual;
@@ -160,15 +174,18 @@ namespace cest
160174

161175
void toBeLessThan(double expected)
162176
{
163-
if (actual > expected)
177+
if ((actual > expected) ^ negated)
164178
{
165179
std::stringstream message;
166180
message << "Expected " << expected << " to be less than" << actual;
167181
throw AssertionError(assertion_file, assertion_line, message.str());
168182
}
169183
}
170184

185+
Assertion<double> *Not;
186+
171187
private:
188+
bool negated;
172189
double actual;
173190
std::string assertion_file;
174191
int assertion_line;
@@ -178,16 +195,21 @@ namespace cest
178195
class Assertion<float>
179196
{
180197
public:
181-
Assertion(const char *file, int line, float value)
198+
Assertion(const char *file, int line, float value, bool negated = false) : negated(false)
182199
{
183200
actual = value;
184201
assertion_file = std::string(file);
185202
assertion_line = line;
203+
204+
if (!negated)
205+
this->Not = new Assertion<float>(file, line, value, true);
206+
else
207+
this->negated = true;
186208
}
187209

188210
void toBe(float expected, float epsilon = 0.00001f)
189211
{
190-
if (fabs(actual - expected) > epsilon)
212+
if ((fabs(actual - expected) > epsilon) ^ negated)
191213
{
192214
std::stringstream message;
193215
message << "Expected " << expected << ", was " << actual;
@@ -202,7 +224,7 @@ namespace cest
202224

203225
void toBeGreaterThan(float expected)
204226
{
205-
if (actual < expected)
227+
if ((actual < expected) ^ negated)
206228
{
207229
std::stringstream message;
208230
message << "Expected " << expected << " to be greather than" << actual;
@@ -212,15 +234,18 @@ namespace cest
212234

213235
void toBeLessThan(float expected)
214236
{
215-
if (actual > expected)
237+
if ((actual > expected) ^ negated)
216238
{
217239
std::stringstream message;
218240
message << "Expected " << expected << " to be less than" << actual;
219241
throw AssertionError(assertion_file, assertion_line, message.str());
220242
}
221243
}
222244

245+
Assertion<float> *Not;
246+
223247
private:
248+
bool negated;
224249
float actual;
225250
std::string assertion_file;
226251
int assertion_line;
@@ -230,30 +255,43 @@ namespace cest
230255
class Assertion<std::vector<T>>
231256
{
232257
public:
233-
Assertion(const char *file, int line, std::vector<T> value)
258+
Assertion(const char *file, int line, std::vector<T> value, bool negated = false) : negated(false)
234259
{
235260
actual = value;
236261
assertion_file = std::string(file);
237262
assertion_line = line;
263+
264+
if (!negated)
265+
this->Not = new Assertion<std::vector<T>>(file, line, value, true);
266+
else
267+
this->negated = true;
238268
}
239269

240270
void toBe(std::vector<T> expected)
241271
{
242-
if (expected.size() != actual.size())
272+
if ((expected.size() != actual.size()) ^ negated)
243273
{
244274
std::stringstream message;
245275
message << "Vector sizes do not match, expected " << expected.size() << " items but had " << actual.size() << " items";
246276
throw AssertionError(assertion_file, assertion_line, message.str());
247277
}
248278

279+
bool any_item_differs = false;
280+
size_t found_difference = 0;
281+
249282
for (size_t i = 0; i < expected.size(); ++i)
250283
{
284+
any_item_differs |= expected[i] != actual[i];
285+
251286
if (expected[i] != actual[i])
252-
{
253-
std::stringstream message;
254-
message << "Vector item mismatch at position " << i << ", expected " << expected[i] << " but was " << actual[i];
255-
throw AssertionError(assertion_file, assertion_line, message.str());
256-
}
287+
found_difference = i;
288+
}
289+
290+
if (any_item_differs ^ negated)
291+
{
292+
std::stringstream message;
293+
message << "Vector item mismatch at position " << found_difference << ", expected " << expected[found_difference] << " but was " << actual[found_difference];
294+
throw AssertionError(assertion_file, assertion_line, message.str());
257295
}
258296
}
259297

@@ -275,7 +313,7 @@ namespace cest
275313
}
276314
}
277315

278-
if (!found)
316+
if (!found ^ negated)
279317
{
280318
std::stringstream message;
281319
message << "Item " << item << " not found in vector";
@@ -285,15 +323,18 @@ namespace cest
285323

286324
void toHaveLength(size_t size)
287325
{
288-
if (actual.size() != size)
326+
if ((actual.size() != size) ^ negated)
289327
{
290328
std::stringstream message;
291329
message << "Vector sizes does not match, expected " << size << " items but had " << actual.size() << " items";
292330
throw AssertionError(assertion_file, assertion_line, message.str());
293331
}
294332
}
295333

334+
Assertion<std::vector<T>> *Not;
335+
296336
private:
337+
bool negated;
297338
std::vector<T> actual;
298339
std::string assertion_file;
299340
int assertion_line;
@@ -303,16 +344,21 @@ namespace cest
303344
class Assertion<std::string>
304345
{
305346
public:
306-
Assertion(const char *file, int line, std::string value)
347+
Assertion(const char *file, int line, std::string value, bool negated = false) : negated(false)
307348
{
308349
actual = value;
309350
assertion_file = std::string(file);
310351
assertion_line = line;
352+
353+
if (!negated)
354+
this->Not = new Assertion<std::string>(file, line, value, true);
355+
else
356+
this->negated = true;
311357
}
312358

313359
void toBe(std::string expected)
314360
{
315-
if (expected != actual)
361+
if ((expected != actual) ^ negated)
316362
{
317363
std::stringstream message;
318364

@@ -338,7 +384,7 @@ namespace cest
338384

339385
void toMatch(std::string expected_string, std::regex expected)
340386
{
341-
if (!std::regex_search(actual, expected))
387+
if (!std::regex_search(actual, expected) ^ negated)
342388
{
343389
std::stringstream message;
344390
if (expected_string.size() > CLIP_STRING_LENGTH || actual.size() > CLIP_STRING_LENGTH)
@@ -363,7 +409,7 @@ namespace cest
363409

364410
void toContain(std::string expected)
365411
{
366-
if (actual.find(expected) == std::string::npos)
412+
if ((actual.find(expected) == std::string::npos) ^ negated)
367413
{
368414
std::stringstream message;
369415

@@ -384,15 +430,18 @@ namespace cest
384430

385431
void toHaveLength(size_t length)
386432
{
387-
if (actual.length() != length)
433+
if ((actual.length() != length) ^ negated)
388434
{
389435
std::stringstream message;
390436
message << "Length of \"" << actual << "\" expected to be " << length << ", was " << actual.length();
391437
throw AssertionError(assertion_file, assertion_line, message.str());
392438
}
393439
}
394440

441+
Assertion<std::string> *Not;
442+
395443
private:
444+
bool negated;
396445
std::string actual;
397446
std::string assertion_file;
398447

@@ -424,4 +473,4 @@ namespace cest
424473
{
425474
return Assertion<std::string>(file, line, (std::string)actual);
426475
}
427-
}
476+
}

0 commit comments

Comments
 (0)