1 #include <catch2/catch.hpp>
2 #include <rapidcheck/catch.h>
3
4 #include <algorithm>
5
6 #include "util/Generators.h"
7
8 using namespace rc;
9 using namespace rc::detail;
10
11 namespace {
12
stringContains(const std::string & str,const std::string & substr)13 bool stringContains(const std::string &str, const std::string &substr) {
14 return str.find(substr) != std::string::npos;
15 }
16
descriptionContains(const CaseResult & result,const std::string & substr)17 bool descriptionContains(const CaseResult &result, const std::string &substr) {
18 return stringContains(result.description, substr);
19 }
20
21 } // namespace
22
23 TEST_CASE("makeMessage") {
24 SECTION("message contains assertion") {
25 REQUIRE(stringContains(makeMessage("", 0, "ASSERT_IT(foo)", ""),
26 "ASSERT_IT(foo)"));
27 }
28
29 SECTION("message contains extra") {
30 REQUIRE(
31 stringContains(makeMessage("", 0, "", "foo bar baz"), "foo bar baz"));
32 }
33
34 SECTION("message is only two lines if extra is empty") {
35 const auto msg = makeMessage("foo.cpp", 0, "foo", "");
36 REQUIRE(std::count(begin(msg), end(msg), '\n') == 1);
37 }
38
39 SECTION("message contains file and line") {
40 REQUIRE(
41 stringContains(makeMessage("foo.cpp", 1337, "", ""), "foo.cpp:1337"));
42 }
43 }
44
45 TEST_CASE("makeExpressionMessage") {
46 SECTION("message contains assertion") {
47 REQUIRE(stringContains(makeExpressionMessage("", 0, "ASSERT_IT(foo)", ""),
48 "ASSERT_IT(foo)"));
49 }
50
51 SECTION("message contains expansion") {
52 REQUIRE(
53 stringContains(makeExpressionMessage("", 0, "", "a == b"), "a == b"));
54 }
55
56 SECTION("message contains file and line") {
57 REQUIRE(stringContains(makeExpressionMessage("foo.cpp", 1337, "", ""),
58 "foo.cpp:1337"));
59 }
60 }
61
62 TEST_CASE("makeUnthrownExceptionMessage") {
63 SECTION("message contains assertion") {
64 REQUIRE(
65 stringContains(makeUnthrownExceptionMessage("", 0, "ASSERT_IT(foo)"),
66 "ASSERT_IT(foo)"));
67 }
68
69 SECTION("message contains file and line") {
70 REQUIRE(stringContains(makeUnthrownExceptionMessage("foo.cpp", 1337, ""),
71 "foo.cpp:1337"));
72 }
73 }
74
75 TEST_CASE("makeWrongExceptionMessage") {
76 SECTION("message contains assertion") {
77 REQUIRE(
78 stringContains(makeWrongExceptionMessage("", 0, "ASSERT_IT(foo)", ""),
79 "ASSERT_IT(foo)"));
80 }
81
82 SECTION("message contains expected exception") {
83 REQUIRE(
84 stringContains(makeWrongExceptionMessage("", 0, "", "std::exception"),
85 "std::exception"));
86 }
87
88 SECTION("message contains file and line") {
89 REQUIRE(stringContains(makeWrongExceptionMessage("foo.cpp", 1337, "", ""),
90 "foo.cpp:1337"));
91 }
92 }
93
94 TEST_CASE("doAssert") {
95 SECTION("does nothing if expression equals expected result") {
96 doAssert(
97 RC_INTERNAL_CAPTURE(true), true, CaseResult::Type::Failure, "", 0, "");
98 }
99
100 prop(
101 "throws CaseResult of given type if expression does not equal expected "
102 "result",
__anoneeb93ac80202(CaseResult::Type type) 103 [](CaseResult::Type type) {
104 try {
105 doAssert(RC_INTERNAL_CAPTURE(true), false, type, "", 0, "");
106 } catch (const CaseResult &result) {
107 RC_SUCCEED_IF(result.type == type);
108 }
109 RC_FAIL("Did not throw");
110 });
111 }
112
113 TEST_CASE("assertions") {
114 // We want to test that we never evaluate expression components more than once
115 // so we pass x++ as a component to test for that.
116 int x = 0;
117
118 SECTION("RC_ASSERT") {
119 SECTION("does not throw if expression is true") { RC_ASSERT(100 == 100); }
120
121 SECTION("when false, throws Failure with relevant info") {
122 try {
123 RC_ASSERT(x++ == 100);
124 FAIL("Never threw");
125 } catch (const CaseResult &result) {
126 REQUIRE(result.type == CaseResult::Type::Failure);
127 REQUIRE(descriptionContains(result, "0 == 100"));
128 REQUIRE(descriptionContains(result, "RC_ASSERT(x++ == 100)"));
129 }
130 }
131 }
132
133 SECTION("RC_ASSERT_THROWS") {
134 SECTION("does not throw if expression throws") {
135 RC_ASSERT_THROWS(throw 0);
136 }
137
138 SECTION("throws Failure with relevant info when expression does not throw") {
139 try {
140 RC_ASSERT_THROWS(x++);
141 FAIL("Never threw");
142 } catch (const CaseResult &result) {
143 REQUIRE(result.type == CaseResult::Type::Failure);
144 REQUIRE(descriptionContains(result, "RC_ASSERT_THROWS(x++)"));
145 }
146 }
147 }
148
149 SECTION("RC_ASSERT_THROWS_AS") {
150 SECTION(
151 "does not throw if expression throws exception matching given type") {
152 // Intentionally different but matching types
153 RC_ASSERT_THROWS_AS(throw std::runtime_error("foo"), std::exception);
154 }
155
156 SECTION(
157 "throws Failure with releveant info if expression throws exception "
158 "that does not match the provided type") {
159 try {
160 RC_ASSERT_THROWS_AS(throw x++, CaseResult);
161 FAIL("Never threw");
162 } catch (const CaseResult &result) {
163 REQUIRE(result.type == CaseResult::Type::Failure);
164 REQUIRE(descriptionContains(result, "RC_ASSERT_THROWS_AS(throw x++, CaseResult)"));
165 REQUIRE(descriptionContains(result, "did not match CaseResult"));
166 }
167 }
168
169 SECTION(
170 "throws Failure with relevant info when expression does not throw") {
171 try {
172 RC_ASSERT_THROWS_AS(x++, int);
173 FAIL("Never threw");
174 } catch (const CaseResult &result) {
175 REQUIRE(result.type == CaseResult::Type::Failure);
176 REQUIRE(descriptionContains(result, "RC_ASSERT_THROWS_AS(x++, int)"));
177 }
178 }
179 }
180
181 SECTION("RC_ASSERT_FALSE") {
182 SECTION("does not throw if expression is false") {
183 RC_ASSERT_FALSE(100 == 101);
184 }
185
186 SECTION("when true, throws Failure with relevant info") {
187 try {
188 RC_ASSERT_FALSE(x++ == 0);
189 FAIL("Never threw");
190 } catch (const CaseResult &result) {
191 REQUIRE(result.type == CaseResult::Type::Failure);
192 REQUIRE(descriptionContains(result, "0 == 0"));
193 REQUIRE(descriptionContains(result, "RC_ASSERT_FALSE(x++ == 0)"));
194 }
195 }
196 }
197
198 SECTION("RC_FAIL") {
199 SECTION("throws Failure with message") {
200 try {
201 RC_FAIL("foo bar baz");
202 FAIL("Never threw");
203 } catch (const CaseResult &result) {
204 REQUIRE(result.type == CaseResult::Type::Failure);
205 REQUIRE(descriptionContains(result, "RC_FAIL(\"foo bar baz\")"));
206 }
207 }
208
209 SECTION("throws Failure with macro name only if no message") {
210 try {
211 RC_FAIL();
212 FAIL("Never threw");
213 } catch (const CaseResult &result) {
214 REQUIRE(result.type == CaseResult::Type::Failure);
215 REQUIRE(descriptionContains(result, "RC_FAIL()"));
216 }
217 }
218
219 SECTION("message is only two lines if no arguments") {
220 try {
221 RC_FAIL();
222 FAIL("Never threw");
223 } catch (const CaseResult &result) {
224 REQUIRE(std::count(begin(result.description),
225 end(result.description),
226 '\n') == 1);
227 }
228 }
229 }
230
231 SECTION("RC_SUCCEED_IF") {
232 SECTION("does not throw if expression is false") {
233 RC_SUCCEED_IF(100 == 101);
234 }
235
236 SECTION("when true, throws Success with relevant info") {
237 try {
238 RC_SUCCEED_IF(x++ == 0);
239 FAIL("Never threw");
240 } catch (const CaseResult &result) {
241 REQUIRE(result.type == CaseResult::Type::Success);
242 REQUIRE(descriptionContains(result, "0 == 0"));
243 REQUIRE(descriptionContains(result, "RC_SUCCEED_IF(x++ == 0)"));
244 }
245 }
246 }
247
248 SECTION("RC_SUCCEED") {
249 SECTION("throws Success with message") {
250 try {
251 RC_SUCCEED("foo bar baz");
252 FAIL("Never threw");
253 } catch (const CaseResult &result) {
254 REQUIRE(result.type == CaseResult::Type::Success);
255 REQUIRE(descriptionContains(result, "RC_SUCCEED(\"foo bar baz\")"));
256 }
257 }
258
259 SECTION("throws Success with macro name only if no message") {
260 try {
261 RC_SUCCEED();
262 FAIL("Never threw");
263 } catch (const CaseResult &result) {
264 REQUIRE(result.type == CaseResult::Type::Success);
265 REQUIRE(descriptionContains(result, "RC_SUCCEED()"));
266 }
267 }
268
269 SECTION("message is only two lines if no arguments") {
270 try {
271 RC_SUCCEED();
272 FAIL("Never threw");
273 } catch (const CaseResult &result) {
274 REQUIRE(std::count(begin(result.description),
275 end(result.description),
276 '\n') == 1);
277 }
278 }
279 }
280
281 SECTION("RC_PRE") {
282 SECTION("does not throw if expression is true") { RC_PRE(100 == 100); }
283
284 SECTION("when false, throws Discard with relevant info") {
285 try {
286 RC_PRE(x++ == 100);
287 FAIL("Never threw");
288 } catch (const CaseResult &result) {
289 REQUIRE(result.type == CaseResult::Type::Discard);
290 REQUIRE(descriptionContains(result, "0 == 100"));
291 REQUIRE(descriptionContains(result, "RC_PRE(x++ == 100)"));
292 }
293 }
294 }
295
296 SECTION("RC_DISCARD") {
297 SECTION("throws Discard with message") {
298 try {
299 RC_DISCARD("foo bar baz");
300 FAIL("Never threw");
301 } catch (const CaseResult &result) {
302 REQUIRE(result.type == CaseResult::Type::Discard);
303 REQUIRE(descriptionContains(result, "RC_DISCARD(\"foo bar baz\")"));
304 }
305 }
306
307 SECTION("throws Discard with macro name only if no message") {
308 try {
309 RC_DISCARD();
310 FAIL("Never threw");
311 } catch (const CaseResult &result) {
312 REQUIRE(result.type == CaseResult::Type::Discard);
313 REQUIRE(descriptionContains(result, "RC_DISCARD()"));
314 }
315 }
316
317 SECTION("message is only two lines if no arguments") {
318 try {
319 RC_DISCARD();
320 FAIL("Never threw");
321 } catch (const CaseResult &result) {
322 REQUIRE(std::count(begin(result.description),
323 end(result.description),
324 '\n') == 1);
325 }
326 }
327 }
328 }
329