Skip to content

Commit 23d497c

Browse files
committed
.fail[_with] and related specs
1 parent 5f4d59b commit 23d497c

File tree

4 files changed

+136
-5
lines changed

4 files changed

+136
-5
lines changed

include/expectations/expectation.hpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "matchers/be_within.hpp"
1111
#include "matchers/include.hpp"
1212
#include "matchers/equal.hpp"
13+
#include "matchers/fail.hpp"
1314

1415
namespace Expectations {
1516

@@ -102,6 +103,8 @@ class Expectation : public Child {
102103
Result to_be_null(std::string msg = "");
103104
Result to_be_true(std::string msg = "");
104105
Result to_be_false(std::string msg = "");
106+
Result to_fail(std::string msg = "");
107+
Result to_fail_with(std::string failure_message, std::string msg = "");
105108

106109
template <typename U>
107110
Result to_include(std::initializer_list<U> expected, std::string msg = "");
@@ -271,6 +274,39 @@ Matchers::BeWithin<A, E> Expectation<A>::to_be_within(E expected,
271274
return matcher;
272275
}
273276

277+
template <typename A>
278+
Result Expectation<A>::to_fail(std::string msg) {
279+
static_assert(std::is_same<A, Result>::value,
280+
"Error: to_fail must me used on an expression that "
281+
"returns a Result.");
282+
return Matchers::Fail<Result>(*this).set_message(msg).run();
283+
}
284+
285+
// template <typename A>
286+
// Result Expectation<A>::to_fail(std::string) {
287+
// static_assert(
288+
// false,
289+
// "Error: to_fail must me used on an expression that returns a Result");
290+
// return Result::failure;
291+
//}
292+
293+
template <typename A>
294+
Result Expectation<A>::to_fail_with(std::string failure_message,
295+
std::string msg) {
296+
static_assert(std::is_same<A, Result>::value,
297+
"Error: to_fail_with must be used on an expression that "
298+
"returns a Result.");
299+
return Matchers::FailWith<A>(*this, failure_message).set_message(msg).run();
300+
}
301+
//
302+
// template <typename A>
303+
// Result Expectation<A>::to_fail_with(std::string, std::string) {
304+
// static_assert(
305+
// false,
306+
// "Error: to_fail must me used on an expression that returns a Result");
307+
// return Result::failure;
308+
//}
309+
274310
template <typename A>
275311
template <class M>
276312
Result Expectation<A>::to(M matcher, std::string msg) {

include/matchers/fail.hpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef CPPSPEC_FAIL_HPP
2+
#define CPPSPEC_FAIL_HPP
3+
#include "basematcher.hpp"
4+
5+
namespace Matchers {
6+
template <typename A>
7+
class Fail : public BaseMatcher<A, void *> {
8+
public:
9+
static_assert(std::is_same<A, Result>::value,
10+
".fail must be matched against a Result.");
11+
Fail(Expectations::Expectation<A> &expectation)
12+
: BaseMatcher<A, void *>(expectation, nullptr){};
13+
typename std::enable_if<std::is_same<A, Result>::value, bool>::type match() {
14+
return not this->get_actual().get_status();
15+
}
16+
};
17+
18+
template <typename A>
19+
class FailWith : public Matchers::BaseMatcher<A, std::string> {
20+
public:
21+
FailWith(Expectations::Expectation<A> &expectation, std::string expected)
22+
: Matchers::BaseMatcher<A, std::string>(expectation, expected){};
23+
typename std::enable_if<std::is_same<A, Result>::value, bool>::type match();
24+
};
25+
26+
template <typename A>
27+
typename std::enable_if<std::is_same<A, Result>::value, bool>::type
28+
FailWith<A>::match() {
29+
static_assert(std::is_same<A, Result>::value,
30+
".fail_with must be matched against a Result.");
31+
return (not this->get_actual().get_status()) &&
32+
this->get_actual().get_message() == this->get_expected();
33+
}
34+
}
35+
36+
#endif // CPP_SPEC_FAIL_HPP

include/runnable.hpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,27 +76,49 @@ class Child {
7676

7777
class Result {
7878
bool value;
79-
std::string failure_message = "";
79+
std::string message = "";
8080
Result(){};
8181
Result(bool value, std::string failure_message = "")
82-
: value(value), failure_message(failure_message){};
82+
: value(value), message(failure_message){};
8383

8484
public:
85-
Result(Result const& copy)
86-
: value(copy.value), failure_message(copy.failure_message) {}
85+
Result(Result const& copy) : value(copy.value), message(copy.message) {}
8786
operator bool() const { return value; }
8887
static Result success;
88+
static Result success_with(std::string success_message) {
89+
return Result(true, success_message);
90+
}
8991
static Result failure;
9092
static Result failure_with(std::string failure_message) {
9193
return Result(false, failure_message);
9294
}
9395

94-
std::string get_message() { return failure_message; }
96+
std::string get_message() { return message; }
97+
const std::string get_message() const { return message; }
98+
Result& set_message(std::string message) {
99+
message = message;
100+
return *this;
101+
}
95102
bool get_status() { return value; }
103+
104+
friend std::ostream& operator<<(std::ostream& os, const Result& res);
96105
};
97106

98107
Result Result::success = Result(true);
99108
Result Result::failure = Result(false);
109+
std::ostream& operator<<(std::ostream& os, const Result& res) {
110+
std::string str;
111+
if (res) {
112+
str = "Result::success" + (not res.get_message().empty()
113+
? "(\"" + res.get_message() + "\")"
114+
: "");
115+
} else {
116+
str = "Result::failure" + (not res.get_message().empty()
117+
? "(\"" + res.get_message() + "\")"
118+
: "");
119+
}
120+
return os << str;
121+
}
100122

101123
/**
102124
* @brief Abstract base class for executable objects

spec/expectations/expectation_spec.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,43 @@ describe expectation_spec("Expectation", $ {
3535
});
3636
});
3737

38+
context(".to_fail", _ {
39+
it("is true when Result is false", _ {
40+
expect(Result::failure).to_fail();
41+
});
42+
43+
it("is false when Result is true", _ {
44+
expect(expect(Result::success).ignore().to_fail().get_status()).to_be_false();
45+
expect(expect(Result::success).ignore().to_fail()).to_fail();
46+
});
47+
});
48+
49+
context(".to_fail_with", _ {
50+
it("is true when Result is false and messages match", _ {
51+
expect(Result::failure_with("failure")).to_fail_with("failure");
52+
});
53+
54+
context("is false when Result", _ {
55+
it("is false and messages don't match", _ {
56+
expect(
57+
expect(Result::failure_with("fail")).ignore().to_fail_with("failure").get_status()
58+
).to_be_false();
59+
});
60+
61+
it("is true and messages match", _ {
62+
expect(
63+
expect(Result::success_with("failure")).ignore().to_fail_with("failure").get_status()
64+
).to_be_false();
65+
});
66+
67+
it("is true and messages don't match", _ {
68+
expect(
69+
expect(Result::success_with("fail")).ignore().to_fail_with("failure").get_status()
70+
).to_be_false();
71+
});
72+
});
73+
});
74+
3875
context(".ignore()", [=] (Description &self) {
3976
ItD i(self, _ {});
4077
#undef expect

0 commit comments

Comments
 (0)