Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Help/guide/tutorial/Complete/SimpleTest/SimpleTest.h
5020 views
1
#pragma once
2
3
#include <cstdio>
4
#include <map>
5
#include <string_view>
6
7
namespace SimpleTest {
8
9
using TestFunc = void (*)();
10
11
using Registry = std::map<std::string_view, TestFunc, std::less<>>;
12
inline Registry g_registry;
13
14
inline Registry& registry()
15
{
16
return g_registry;
17
}
18
19
struct failure
20
{
21
char const* file;
22
int line;
23
char const* expr;
24
};
25
26
struct Registrar
27
{
28
template <std::size_t N>
29
Registrar(char const (&name)[N], TestFunc f)
30
{
31
auto [it, inserted] =
32
registry().emplace(std::string_view{ name, N ? (N - 1) : 0 }, f);
33
if (!inserted) {
34
std::printf("[ WARN ] duplicate test name: %.*s\n",
35
int(it->first.size()), it->first.data());
36
}
37
}
38
};
39
40
inline Registry const& all()
41
{
42
return registry();
43
}
44
inline TestFunc find(std::string_view name)
45
{
46
auto it = registry().find(name);
47
return it == registry().end() ? nullptr : it->second;
48
}
49
50
}
51
52
#define SIMPLETEST_STRINGIFY(a) #a
53
#define SIMPLETEST_XSTRINGIFY(a) SIMPLETEST_STRINGIFY(a)
54
#define SIMPLETEST_CONCAT_(a, b) a##b
55
#define SIMPLETEST_CONCAT(a, b) SIMPLETEST_CONCAT_(a, b)
56
57
#define TEST(name_literal) \
58
static void SIMPLETEST_CONCAT(_simpletest_fn_, __LINE__)(); \
59
static ::SimpleTest::Registrar SIMPLETEST_CONCAT(_simpletest_reg_, \
60
__LINE__)( \
61
name_literal, &SIMPLETEST_CONCAT(_simpletest_fn_, __LINE__)); \
62
static void SIMPLETEST_CONCAT(_simpletest_fn_, __LINE__)()
63
64
// Minimal assertion
65
#define REQUIRE(expr) \
66
do { \
67
if (!(expr)) \
68
throw ::SimpleTest::failure{ __FILE__, __LINE__, #expr }; \
69
} while (0)
70
71
int main(int argc, char** argv)
72
{
73
using namespace ::SimpleTest;
74
75
std::string_view arg1 =
76
(argc >= 2) ? std::string_view{ argv[1] } : std::string_view{};
77
78
if (arg1 == "--list") {
79
bool first = true;
80
for (auto const& [name, _] : registry()) {
81
if (!first)
82
std::printf(",");
83
std::printf("%.*s", int(name.size()), name.data());
84
first = false;
85
}
86
std::printf("\n");
87
return 0;
88
}
89
90
if (arg1 == "--test") {
91
if (argc < 3) {
92
std::printf("usage: %s [--list] [--test <name>]\n", argv[0]);
93
return 2;
94
}
95
96
#ifdef SIMPLETEST_CONFIG
97
std::printf("SimpleTest built with config: " SIMPLETEST_XSTRINGIFY(
98
SIMPLETEST_CONFIG) "\n");
99
#endif
100
101
std::string_view name{ argv[2] };
102
auto it = registry().find(name);
103
if (it == registry().end()) {
104
std::printf("[ NOTFOUND ] %s\n", argv[2]);
105
return 2;
106
}
107
108
int failed = 0;
109
std::printf("[ RUN ] %.*s\n", int(it->first.size()),
110
it->first.data());
111
try {
112
it->second();
113
std::printf("[ OK] %.*s\n", int(it->first.size()),
114
it->first.data());
115
} catch (failure const& f) {
116
std::printf("[ FAILED ] %.*s at %s:%d : %s\n", int(it->first.size()),
117
it->first.data(), f.file, f.line, f.expr);
118
failed = 1;
119
} catch (...) {
120
std::printf("[ FAILED ] %.*s : unknown exception\n",
121
int(it->first.size()), it->first.data());
122
failed = 1;
123
}
124
return failed;
125
}
126
127
if (argc > 1) {
128
std::printf("usage: %s [--list] [--test <name>]\n", argv[0]);
129
return 2;
130
}
131
132
#ifdef SIMPLETEST_CONFIG
133
std::printf("SimpleTest built with config: " SIMPLETEST_XSTRINGIFY(
134
SIMPLETEST_CONFIG) "\n");
135
#endif
136
137
// Default: run all tests.
138
int failed = 0;
139
for (auto const& [name, func] : all()) {
140
std::printf("[ RUN ] %.*s\n", int(name.size()), name.data());
141
try {
142
func();
143
std::printf("[ OK ] %.*s\n", int(name.size()), name.data());
144
} catch (failure const& f) {
145
std::printf("[ FAILED ] %.*s at %s:%d : %s\n", int(name.size()),
146
name.data(), f.file, f.line, f.expr);
147
failed = 1;
148
} catch (...) {
149
std::printf("[ FAILED ] %.*s : unknown exception\n", int(name.size()),
150
name.data());
151
failed = 1;
152
}
153
}
154
return failed;
155
}
156
157