1#ifndef RADARELAB_UTILS_TESTS_H
2#define RADARELAB_UTILS_TESTS_H
57struct LocationInfo :
public std::stringstream
74 std::string local_info;
76 TestStackFrame(
const char* file,
int line,
const char* call)
77 : file(file), line(line), call(call)
81 TestStackFrame(
const char* file,
int line,
const char* call,
const LocationInfo& local_info)
82 : file(file), line(line), call(call), local_info(local_info.str())
86 std::string format()
const;
88 void format(std::ostream& out)
const;
91struct TestStack :
public std::vector<TestStackFrame>
96 std::string backtrace()
const;
99 void backtrace(std::ostream& out)
const;
106struct TestFailed :
public std::exception
111 TestFailed(
const std::exception& e);
113 template<
typename ...Args>
114 TestFailed(
const std::exception& e, Args&&... args)
117 add_stack_info(std::forward<Args>(args)...);
120 TestFailed(
const std::string& message) : message(message) {}
122 template<
typename ...Args>
123 TestFailed(
const std::string& message, Args&&... args)
124 : TestFailed(message)
126 add_stack_info(std::forward<Args>(args)...);
129 const char* what()
const noexcept override {
return message.c_str(); }
131 template<
typename ...Args>
132 void add_stack_info(Args&&... args) { stack.emplace_back(std::forward<Args>(args)...); }
138struct TestSkipped :
public std::exception
143 TestSkipped(
const std::string& reason);
150#define RADARELAB_UTILS_TEST_INFO(name) \
151 radarelab::utils::tests::LocationInfo radarelab_utils_test_location_info; \
152 radarelab::utils::tests::LocationInfo& name = radarelab_utils_test_location_info
164void assert_true(
const A& actual)
167 std::stringstream ss;
168 ss <<
"actual value " << actual <<
" is not true";
172void assert_true(std::nullptr_t actual);
176void assert_false(
const A& actual)
179 std::stringstream ss;
180 ss <<
"actual value " << actual <<
" is not false";
181 throw TestFailed(ss.str());
184void assert_false(std::nullptr_t actual);
186template<
typename LIST>
187static inline void _format_list(std::ostream& o,
const LIST& list) {
190 for (
const auto& v: list)
202void assert_equal(
const std::vector<T>& actual,
const std::vector<T>& expected)
204 if (actual == expected)
return;
205 std::stringstream ss;
207 _format_list(ss, actual);
208 ss <<
" is different than the expected ";
209 _format_list(ss, expected);
214void assert_equal(
const std::vector<T>& actual,
const std::initializer_list<T>& expected)
216 if (actual == expected)
return;
217 std::stringstream ss;
219 _format_list(ss, actual);
220 ss <<
" is different than the expected ";
221 _format_list(ss, expected);
229template<
typename A,
typename E>
230void assert_equal(
const A& actual,
const E& expected)
232 if (actual == expected)
return;
233 std::stringstream ss;
234 ss <<
"value '" << actual <<
"' is different than the expected '" << expected <<
"'";
242template<
typename A,
typename E>
243void assert_not_equal(
const A& actual,
const E& expected)
245 if (actual != expected)
return;
246 std::stringstream ss;
247 ss <<
"value '" << actual <<
"' is not different than the expected '" << expected <<
"'";
252template<
typename A,
typename E>
253void assert_less(
const A& actual,
const E& expected)
255 if (actual < expected)
return;
256 std::stringstream ss;
257 ss <<
"value '" << actual <<
"' is not less than the expected '" << expected <<
"'";
262template<
typename A,
typename E>
263void assert_less_equal(
const A& actual,
const E& expected)
265 if (actual <= expected)
return;
266 std::stringstream ss;
267 ss <<
"value '" << actual <<
"' is not less than or equals to the expected '" << expected <<
"'";
272template<
typename A,
typename E>
273void assert_greater(
const A& actual,
const E& expected)
275 if (actual > expected)
return;
276 std::stringstream ss;
277 ss <<
"value '" << actual <<
"' is not greater than the expected '" << expected <<
"'";
282template<
typename A,
typename E>
283void assert_greater_equal(
const A& actual,
const E& expected)
285 if (actual >= expected)
return;
286 std::stringstream ss;
287 ss <<
"value '" << actual <<
"' is not greater than or equals to the expected '" << expected <<
"'";
292void assert_startswith(
const std::string& actual,
const std::string& expected);
295void assert_endswith(
const std::string& actual,
const std::string& expected);
298void assert_contains(
const std::string& actual,
const std::string& expected);
301void assert_not_contains(
const std::string& actual,
const std::string& expected);
309void assert_re_matches(
const std::string& actual,
const std::string& expected);
317void assert_not_re_matches(
const std::string& actual,
const std::string& expected);
324 Actual(
const A& actual) : _actual(actual) {}
327 void istrue()
const { assert_true(_actual); }
328 void isfalse()
const { assert_false(_actual); }
329 template<
typename E>
void operator==(
const E& expected)
const { assert_equal(_actual, expected); }
330 template<
typename E>
void operator!=(
const E& expected)
const { assert_not_equal(_actual, expected); }
331 template<
typename E>
void operator<(
const E& expected)
const {
return assert_less(_actual, expected); }
332 template<
typename E>
void operator<=(
const E& expected)
const {
return assert_less_equal(_actual, expected); }
333 template<
typename E>
void operator>(
const E& expected)
const {
return assert_greater(_actual, expected); }
334 template<
typename E>
void operator>=(
const E& expected)
const {
return assert_greater_equal(_actual, expected); }
340 ActualCString(
const char* s) : _actual(s) {}
342 void istrue()
const {
return assert_true(_actual); }
343 void isfalse()
const {
return assert_false(_actual); }
344 void operator==(
const char* expected)
const;
345 void operator==(
const std::string& expected)
const;
346 void operator!=(
const char* expected)
const;
347 void operator!=(
const std::string& expected)
const;
348 void operator<(
const std::string& expected)
const;
349 void operator<=(
const std::string& expected)
const;
350 void operator>(
const std::string& expected)
const;
351 void operator>=(
const std::string& expected)
const;
352 void startswith(
const std::string& expected)
const;
353 void endswith(
const std::string& expected)
const;
354 void contains(
const std::string& expected)
const;
355 void not_contains(
const std::string& expected)
const;
356 void matches(
const std::string& re)
const;
357 void not_matches(
const std::string& re)
const;
360struct ActualStdString :
public Actual<std::string>
362 ActualStdString(
const std::string& s) : Actual<std::string>(s) {}
364 using Actual<std::string>::operator==;
365 void operator==(
const std::vector<uint8_t>& expected)
const;
366 using Actual<std::string>::operator!=;
367 void operator!=(
const std::vector<uint8_t>& expected)
const;
368 void startswith(
const std::string& expected)
const;
369 void endswith(
const std::string& expected)
const;
370 void contains(
const std::string& expected)
const;
371 void not_contains(
const std::string& expected)
const;
372 void matches(
const std::string& re)
const;
373 void not_matches(
const std::string& re)
const;
376struct ActualDouble :
public Actual<double>
378 using Actual::Actual;
380 void almost_equal(
double expected,
unsigned places)
const;
381 void not_almost_equal(
double expected,
unsigned places)
const;
385inline Actual<A> actual(
const A& actual) {
return Actual<A>(actual); }
386inline ActualCString actual(
const char* actual) {
return ActualCString(actual); }
387inline ActualCString actual(
char* actual) {
return ActualCString(actual); }
388inline ActualStdString actual(
const std::string& actual) {
return ActualStdString(actual); }
389inline ActualStdString actual(
const std::vector<uint8_t>& actual) {
return ActualStdString(std::string(actual.begin(), actual.end())); }
390inline ActualDouble actual(
double actual) {
return ActualDouble(actual); }
392struct ActualFunction :
public Actual<std::function<void()>>
394 using Actual::Actual;
396 void throws(
const std::string& what_match)
const;
399inline ActualFunction actual_function(std::function<
void()> actual) {
return ActualFunction(actual); }
401struct ActualFile :
public Actual<std::string>
403 using Actual::Actual;
406 void not_exists()
const;
407 void startswith(
const std::string& data)
const;
409 void not_empty()
const;
410 void contents_equal(
const std::string& data)
const;
411 void contents_equal(
const std::vector<uint8_t>& data)
const;
412 void contents_equal(
const std::initializer_list<std::string>& lines)
const;
413 void contents_match(
const std::string& data_re)
const;
414 void contents_match(
const std::initializer_list<std::string>& lines_re)
const;
417inline ActualFile actual_file(
const std::string& pathname) {
return ActualFile(pathname); }
426#define wassert(...) \
429 } catch (radarelab::utils::tests::TestFailed& e) { \
430 e.add_stack_info(__FILE__, __LINE__, #__VA_ARGS__, radarelab_utils_test_location_info); \
432 } catch (std::exception& e) { \
433 throw radarelab::utils::tests::TestFailed(e, __FILE__, __LINE__, #__VA_ARGS__, radarelab_utils_test_location_info); \
437#define wassert_true(...) wassert(actual(__VA_ARGS__).istrue())
440#define wassert_false(...) wassert(actual(__VA_ARGS__).isfalse())
447#define wassert_throws(exc, ...) \
450 wfail_test(#__VA_ARGS__ " did not throw " #exc); \
451 } catch (TestFailed& e) { \
455 } catch (std::exception& e) { \
456 std::string msg(#__VA_ARGS__ " did not throw " #exc " but threw "); \
457 msg += typeid(e).name(); \
469#define wcallchecked(func) \
472 } catch (radarelab::utils::tests::TestFailed& e) { \
473 e.add_stack_info(__FILE__, __LINE__, #func, radarelab_utils_test_location_info); \
475 } catch (std::exception& e) { \
476 throw radarelab::utils::tests::TestFailed(e, __FILE__, __LINE__, #func, radarelab_utils_test_location_info); \
482#define wfail_test(msg) wassert(throw radarelab::utils::tests::TestFailed((msg)))
510 TestMethod(
const std::string&
name)
534 TestCase(
const std::string&
name);
535 virtual ~TestCase() {}
607 template<
typename ...Args>
617 template<
typename ...Args>
643 void test_teardown() {}
646template<
typename Fixture,
typename... Args>
647static inline Fixture* fixture_factory(Args... args)
655template<
typename FIXTURE>
656class FixtureTestCase :
public TestCase
659 typedef FIXTURE Fixture;
661 Fixture* fixture =
nullptr;
662 std::function<Fixture*()> make_fixture;
664 template<
typename... Args>
665 FixtureTestCase(
const std::string&
name, Args... args)
668 make_fixture = std::bind(fixture_factory<FIXTURE, Args...>, args...);
674 fixture = make_fixture();
687 if (fixture) fixture->test_setup();
692 if (fixture) fixture->test_teardown();
700 template<
typename ...Args>
710 template<
typename ...Args>
void method_teardown(TestMethodResult &mr) override
Clean up after the test method is run.
void teardown() override
Clean up after the test case is run.
TestMethod & add_method(const std::string &name, const std::string &doc, std::function< void(FIXTURE &)> test_function)
Register a new test method that takes a reference to the fixture as argument, including documentation...
void setup() override
Set up the test case before it is run.
TestMethod & add_method(const std::string &name, std::function< void(FIXTURE &)> test_function)
Register a new test method that takes a reference to the fixture as argument.
void method_setup(TestMethodResult &mr) override
Set up before the test method is run.
Base class for test fixtures.
std::ostream & operator()()
Clear the current information and return the output stream to which new information can be sent.
Add information to the test backtrace for the tests run in the current scope.
Result of running a whole test case.
std::vector< TestMethod > methods
All registered test methods.
bool tests_registered
Set to true the first time register_tests_once is run.
virtual void teardown()
Clean up after the test case is run.
virtual void setup()
Set up the test case before it is run.
virtual void register_tests()=0
This will be called before running the test case, to populate it with its test methods.
TestMethod & add_method(const std::string &name, const std::string &doc, std::function< void()> test_function)
Register a new test method, including documentation.
void register_tests_once()
Idempotent wrapper for register_tests()
virtual void method_setup(TestMethodResult &)
Set up before the test method is run.
virtual TestCaseResult run_tests(TestController &controller)
Call setup(), run all the tests that have been registered, then call teardown().
std::string name
Name of the test case.
TestMethod & add_method(const std::string &name)
Register a new test method, with the actual test function to be added later.
virtual void method_teardown(TestMethodResult &)
Clean up after the test method is run.
virtual TestMethodResult run_test(TestController &controller, TestMethod &method)
Run a test method.
TestMethod & add_method(const std::string &name, std::function< void()> test_function)
Register a new test method.
Test case collecting several test methods, and self-registering with the singleton instance of TestRe...
Abstract interface for the objects that supervise test execution.
Exception thrown when a test assertion fails, normally by Location::fail_test.
Result of running a test method.
std::string doc
Documentation attached to this test method.
std::string name
Name of the test method.
std::function< void()> test_function
Main body of the test method.