ZeroErr
Loading...
Searching...
No Matches
unittest.h
Go to the documentation of this file.
1#pragma once
2
3// libc++ offers compatibility-only transitive includes through C++20.
4// Suppress those while loading our explicit dependencies, then restore the
5// caller's setting. This does not change standard-library types or ABI.
6#pragma push_macro("_LIBCPP_REMOVE_TRANSITIVE_INCLUDES")
7#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
8#define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
9#endif
10
11
13#include "zeroerr/assert.h"
14
16#include <iosfwd>
17#include <functional>
18#include "zeroerr/string.h"
19#include <vector>
20
22
23#define ZEROERR_CREATE_TEST_FUNC(function, name, ...) \
24 ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH \
25 static void function(zeroerr::TestContext*); \
26 static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
27 zeroerr::TestCase(name, __FILE__, __LINE__, function, {__VA_ARGS__})); \
28 ZEROERR_SUPPRESS_COMMON_WARNINGS_POP; \
29 static void function(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))
30
31#define TEST_CASE(...) \
32 ZEROERR_EXPAND(ZEROERR_CREATE_TEST_FUNC(ZEROERR_NAMEGEN(_zeroerr_testcase), __VA_ARGS__))
33
34#define ZEROERR_CREATE_SUB_CASE(name, ...) \
35 zeroerr::SubCase(name, __FILE__, __LINE__, _ZEROERR_TEST_CONTEXT, {__VA_ARGS__}) \
36 << [=](ZEROERR_UNUSED(zeroerr::TestContext * _ZEROERR_TEST_CONTEXT)) mutable
37
38// The caller supplies the lambda body, so no diagnostic pragma may follow
39// the lambda declarator (GCC rejects it before the opening brace).
40#define SUB_CASE(...) ZEROERR_EXPAND(ZEROERR_CREATE_SUB_CASE(__VA_ARGS__))
41
42#define ZEROERR_CREATE_TEST_CLASS(fixture, classname, funcname, name, ...) \
43 class classname : public fixture { \
44 public: \
45 void funcname(zeroerr::TestContext*); \
46 }; \
47 static void ZEROERR_CAT(call_, funcname)(zeroerr::TestContext * _ZEROERR_TEST_CONTEXT) { \
48 classname instance; \
49 instance.funcname(_ZEROERR_TEST_CONTEXT); \
50 } \
51 static zeroerr::detail::regTest ZEROERR_NAMEGEN(_zeroerr_reg)( \
52 zeroerr::TestCase(name, __FILE__, __LINE__, ZEROERR_CAT(call_, funcname), \
53 {__VA_ARGS__})); \
54 inline void classname::funcname(ZEROERR_UNUSED(zeroerr::TestContext* _ZEROERR_TEST_CONTEXT))
55
56#define TEST_CASE_FIXTURE(fixture, ...) \
57 ZEROERR_EXPAND(ZEROERR_CREATE_TEST_CLASS(fixture, ZEROERR_NAMEGEN(ZEROERR_CAT(fixture, _zeroerr_class)), \
58 ZEROERR_NAMEGEN(ZEROERR_CAT(fixture, _zeroerr_test_method)), \
59 __VA_ARGS__))
60
61
62#define ZEROERR_HAVE_SAME_OUTPUT _ZEROERR_TEST_CONTEXT->save_output();
63
64#ifndef ZEROERR_DISABLE_BDD
65#define SCENARIO(...) TEST_CASE("Scenario: " __VA_ARGS__)
66#define GIVEN(...) SUB_CASE("given: " __VA_ARGS__)
67#define WHEN(...) SUB_CASE("when: " __VA_ARGS__)
68#define THEN(...) SUB_CASE("then: " __VA_ARGS__)
69#endif
70
71namespace zeroerr {
72
73class IReporter;
74struct TestCase;
75class Decorator;
76
90public:
91 unsigned passed = 0;
92 unsigned warning = 0;
93 unsigned failed = 0;
94 unsigned skipped = 0;
95 unsigned passed_as = 0;
96 unsigned warning_as = 0;
97 unsigned failed_as = 0;
98 unsigned skipped_as = 0;
99
101
103
109 int add(TestContext& local);
110
114 void reset();
115
119 void save_output();
120
126 ~TestContext() = default;
127};
128
146struct UnitTest {
153 UnitTest& parseArgs(int argc, const char** argv);
154
159 int run();
160
167 bool run_filter(const TestCase& tc);
168
169 bool silent = false;
170 bool run_bench = false;
171 bool run_fuzz = false;
172 bool list_test_cases = false;
174 bool no_color = false;
175 bool log_to_report = false;
176 bool show_help = false;
177 bool invalid_args = false;
181 // Fresh output directory for optional Clang per-test raw profiles.
183 // Run collection and analysis together, like the optional fuzz mode.
184 bool run_coverage = false;
185 std::vector<zeroerr::String> coverage_arguments;
186 struct Filters* filters = nullptr;
187};
188
198struct TestCase {
201 unsigned line;
202 std::function<void(TestContext*)> func;
203 std::vector<TestCase*> subcases;
204 std::vector<Decorator*> decorators;
210 bool operator<(const TestCase& rhs) const;
211
220
230 std::function<void(TestContext*)> func, std::vector<Decorator*> decorators)
232};
233
234
240 std::vector<Decorator*> decorators);
241 ~SubCase() = default;
243 void operator<<(std::function<void(TestContext*)> op);
244};
245
246
247template <typename T>
249 void add(T&& obj) { objects.push_back(std::forward<T>(obj)); }
250 std::vector<T> objects;
251};
252
253
266public:
267 virtual ~IReporter() = default;
268
269 virtual zeroerr::String getName() const = 0;
270
271 // There are a list of events
272 virtual void testStart() = 0;
273 virtual void testCaseStart(const TestCase& tc, std::stringbuf& sb) = 0;
274 virtual void testCaseEnd(const TestCase& tc, std::stringbuf& sb, const TestContext& ctx,
275 int type) = 0;
276 virtual void subCaseStart(const TestCase& tc, std::stringbuf& sb) = 0;
277 virtual void subCaseEnd(const TestCase& tc, std::stringbuf& sb, const TestContext& ctx,
278 int type) = 0;
279 virtual void testEnd(const TestContext& tc) = 0;
280
286 static IReporter* create(const zeroerr::String& name, UnitTest& ut);
287
289
290protected:
292};
293
297enum TestType { test_case = 1, sub_case = 1 << 1, bench = 1 << 2, fuzz_test = 1 << 3 };
298
299namespace detail {
300
305struct regTest {
306 explicit regTest(const TestCase& tc, TestType type = test_case);
307};
308
314 explicit regReporter(IReporter*);
315};
316} // namespace detail
317
318
335public:
336 CombinationalTest(std::function<void()> func) : func(func) {}
337 std::function<void()> func;
338
339 template <typename T>
340 void operator()(T& arg) {
341 arg.reset();
342 for (size_t i = 0; i < arg.size(); ++i, ++arg) {
343 func();
344 }
345 }
346
347 template <typename T, typename... Args>
348 void operator()(T& arg, Args&... args) {
349 arg.reset();
350 for (size_t i = 0; i < arg.size(); ++i, ++arg) {
351 operator()(args...);
352 }
353 }
354};
355
356
360template <typename T>
361class TestArgs {
362public:
363 TestArgs(std::initializer_list<T> args) : args(args) {}
364 std::vector<T> args;
365
366 operator T() const { return args[index]; }
368 index++;
369 return *this;
370 }
371 size_t size() const { return args.size(); }
372 void reset() { index = 0; }
373
374private:
375 int index = 0;
376};
377
378
380public:
381 // Called when the test registered, return true can block the test registering
382 virtual bool onStartup(const TestCase&) { return false; }
383
384 // Called when the test executing, return true can block the test execution
385 virtual bool onExecution(const TestCase&) { return false; }
386
387 // Called on each assertion, return true can skip the assertion
388 virtual bool onAssertion() { return false; }
389
390 // Called when the test finished, return true means the test containing changes
391 virtual bool onFinish(const TestCase&, TestContext&) { return false; }
392};
393
394Decorator* skip(bool isSkip = true);
395Decorator* timeout(float timeout = 0.1f); // in seconds
396Decorator* may_fail(bool isMayFail = true);
397Decorator* should_fail(bool isShouldFail = true);
398
399} // namespace zeroerr
400
402
403#pragma pop_macro("_LIBCPP_REMOVE_TRANSITIVE_INCLUDES")
std::function< void()> func
Definition unittest.h:337
void operator()(T &arg, Args &... args)
Definition unittest.h:348
void operator()(T &arg)
Definition unittest.h:340
CombinationalTest(std::function< void()> func)
Definition unittest.h:336
Definition unittest.h:379
virtual bool onAssertion()
Definition unittest.h:388
virtual bool onStartup(const TestCase &)
Definition unittest.h:382
virtual bool onExecution(const TestCase &)
Definition unittest.h:385
virtual bool onFinish(const TestCase &, TestContext &)
Definition unittest.h:391
IReporter is an interface that is used to report the test results. You can create a new reporter by i...
Definition unittest.h:265
virtual zeroerr::String getName() const =0
virtual void subCaseStart(const TestCase &tc, std::stringbuf &sb)=0
virtual ~IReporter()=default
virtual void testStart()=0
virtual void testCaseStart(const TestCase &tc, std::stringbuf &sb)=0
virtual void subCaseEnd(const TestCase &tc, std::stringbuf &sb, const TestContext &ctx, int type)=0
static IReporter * create(const zeroerr::String &name, UnitTest &ut)
Create the reporter object with the given name.
Definition unittest.cpp:1169
virtual void testEnd(const TestContext &tc)=0
UnitTest & ut
Definition unittest.h:291
IReporter(UnitTest &ut)
Definition unittest.h:288
virtual void testCaseEnd(const TestCase &tc, std::stringbuf &sb, const TestContext &ctx, int type)=0
Definition string.h:41
TestArgs & operator++()
Definition unittest.h:367
size_t size() const
Definition unittest.h:371
std::vector< T > args
Definition unittest.h:364
TestArgs(std::initializer_list< T > args)
Definition unittest.h:363
void reset()
Definition unittest.h:372
TestContext is a class that holds the test results and reporter context. There are 8 different matric...
Definition unittest.h:89
void reset()
Reset the matrices to 0.
Definition unittest.cpp:258
unsigned skipped
Definition unittest.h:94
unsigned failed
Definition unittest.h:93
unsigned passed
Definition unittest.h:91
Duration duration
Definition unittest.h:100
void save_output()
Save the output of the test to the correct_output_path as a golden file.
Definition unittest.cpp:238
unsigned skipped_as
Definition unittest.h:98
unsigned passed_as
Definition unittest.h:95
unsigned failed_as
Definition unittest.h:97
IReporter & reporter
Definition unittest.h:102
unsigned warning
Definition unittest.h:92
unsigned warning_as
Definition unittest.h:96
TestContext(IReporter &reporter)
Construct a new Test Context object.
Definition unittest.h:125
int add(TestContext &local)
Add the subtest results to the matrices.
Definition unittest.cpp:217
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:283
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:235
Definition assert_text.cpp:5
Decorator * should_fail(bool isShouldFail)
Definition unittest.cpp:1252
TestType
TestType is a enum describe the type of the test case.
Definition unittest.h:297
@ bench
Definition unittest.h:297
@ test_case
Definition unittest.h:297
@ fuzz_test
Definition unittest.h:297
@ sub_case
Definition unittest.h:297
Decorator * timeout(float timeout)
Definition unittest.cpp:1202
Decorator * may_fail(bool isMayFail)
Definition unittest.cpp:1246
Decorator * skip(bool isSkip)
Definition unittest.cpp:1180
Definition time.h:3
Definition unittest.cpp:300
TestContext * context
Definition unittest.h:242
SubCase(zeroerr::String name, zeroerr::String file, unsigned line, TestContext *context, std::vector< Decorator * > decorators)
Definition unittest.cpp:271
void operator<<(std::function< void(TestContext *)> op)
Definition unittest.cpp:275
~SubCase()=default
TestCase is a class that holds the test case information. There are several fields that are used to s...
Definition unittest.h:198
bool operator<(const TestCase &rhs) const
Compare the test cases.
Definition unittest.cpp:660
std::function< void(TestContext *)> func
Definition unittest.h:202
std::vector< Decorator * > decorators
Definition unittest.h:204
zeroerr::String file
Definition unittest.h:200
unsigned line
Definition unittest.h:201
zeroerr::String name
Definition unittest.h:199
std::vector< TestCase * > subcases
Definition unittest.h:203
TestCase(zeroerr::String name, zeroerr::String file, unsigned line, std::vector< Decorator * > decorators)
Construct a new Test Case object.
Definition unittest.h:218
TestCase(zeroerr::String name, zeroerr::String file, unsigned line, std::function< void(TestContext *)> func, std::vector< Decorator * > decorators)
Construct a new Test Case object.
Definition unittest.h:229
Definition unittest.h:248
std::vector< T > objects
Definition unittest.h:250
void add(T &&obj)
Definition unittest.h:249
UnitTest is a class that holds the test configuration. There are several options that can be set to c...
Definition unittest.h:146
bool show_help
Definition unittest.h:176
bool list_test_cases
Definition unittest.h:172
bool run_coverage
Definition unittest.h:184
bool run_fuzz
Definition unittest.h:171
bool invalid_args
Definition unittest.h:177
bool run_bench
Definition unittest.h:170
std::vector< zeroerr::String > coverage_arguments
Definition unittest.h:185
bool log_to_report
Definition unittest.h:175
zeroerr::String list_format
Definition unittest.h:173
bool run_filter(const TestCase &tc)
Run the test with the given filter.
Definition unittest.cpp:502
zeroerr::String reporter_name
Definition unittest.h:179
bool no_color
Definition unittest.h:174
struct Filters * filters
Definition unittest.h:186
zeroerr::String binary
Definition unittest.h:180
zeroerr::String correct_output_path
Definition unittest.h:178
UnitTest & parseArgs(int argc, const char **argv)
Parse the arguments to configure the test.
Definition unittest.cpp:331
zeroerr::String coverage_output
Definition unittest.h:182
int run()
Run the test.
Definition unittest.cpp:532
bool silent
Definition unittest.h:169
regReporter(IReporter *)
Definition unittest.cpp:699
regTest(const TestCase &tc, TestType type=test_case)
Definition unittest.cpp:687