libcopp 2.3.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test_manager.h
Go to the documentation of this file.
1// Copyright 2024 atframework
2
3#pragma once
4
5// Import the C++20 feature-test macros
6#ifdef __has_include
7# if __has_include(<version>)
8# include <version>
9# endif
10#elif defined(_MSC_VER) && \
11 ((defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L))
12# if _MSC_VER >= 1922
13# include <version>
14# endif
15#endif
16
17#include <stdint.h>
18#include <ctime>
19#include <string>
20#include <type_traits>
21#include <unordered_map>
22#include <unordered_set>
23#include <utility>
24#include <vector>
25
26#ifdef __cpp_impl_three_way_comparison
27# include <compare>
28#endif
29
30#ifdef __cpp_lib_string_view
31# include <string_view>
32#endif
33
34#include "cli/shell_font.h"
35
36#include "test_case_base.h"
37
38#if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1600)
39
40# define UTILS_TEST_ENV_AUTO_MAP(...) std::unordered_map<__VA_ARGS__>
41# define UTILS_TEST_ENV_AUTO_SET(...) std::unordered_set<__VA_ARGS__>
42# define UTILS_TEST_ENV_AUTO_UNORDERED 1
43#else
44
45# include <map>
46# include <set>
47# define UTILS_TEST_ENV_AUTO_MAP(...) std::map<__VA_ARGS__>
48# define UTILS_TEST_ENV_AUTO_SET(...) std::set<__VA_ARGS__>
49
50#endif
51
56 public:
60 using test_type = std::vector<std::pair<std::string, case_ptr_type> >;
61 using event_on_start_type = std::vector<std::pair<std::string, on_start_ptr_type> >;
62 using event_on_exit_type = std::vector<std::pair<std::string, on_exit_ptr_type> >;
63 using test_data_type = std::unordered_map<std::string, test_type>;
64
65 public:
67 virtual ~test_manager();
68
69 void append_test_case(const std::string &test_name, const std::string &case_name, case_ptr_type);
70 void append_event_on_start(const std::string &event_name, on_start_ptr_type);
71 void append_event_on_exit(const std::string &event_name, on_exit_ptr_type);
72
75 int run();
76
77 void set_cases(const std::vector<std::string> &case_names);
78
79 static test_manager &me();
80
81 static std::string get_expire_time(clock_t begin, clock_t end);
82
83#ifdef UTILS_TEST_MACRO_TEST_ENABLE_BOOST_TEST
84 static boost::unit_test::test_suite *&test_suit();
85#endif
86
87 template <class T>
88 struct is_numberic : std::conditional<std::is_arithmetic<T>::value || std::is_enum<T>::value, std::true_type,
89 std::false_type>::type {};
90
91 template <class TL, class TR,
92 bool has_pointer = std::is_pointer<typename std::decay<TL>::type>::value ||
93 std::is_pointer<typename std::decay<TR>::type>::value,
94 bool has_number =
96 bool all_number =
98 struct pick_param;
99
100 // compare pointer with integer
101 template <class TL, class TR>
102 struct pick_param<TL, TR, true, true, false> {
103 using value_type = uintptr_t;
104
105 template <class T>
107 return (value_type)(std::forward<T>(t));
108 }
109 };
110
111 // compare integer with integer, all converted to double/int64_t/uint64_t
112 template <class TL, class TR>
113 struct pick_param<TL, TR, false, true, true> {
115 typename std::conditional<std::is_floating_point<typename std::decay<TL>::type>::value ||
116 std::is_floating_point<typename std::decay<TR>::type>::value,
117 double,
118 typename std::conditional<std::is_unsigned<typename std::decay<TL>::type>::value &&
119 std::is_unsigned<typename std::decay<TR>::type>::value,
120 uint64_t, int64_t>::type>::type;
121
122 template <class T>
124 return static_cast<value_type>(std::forward<T>(t));
125 }
126 };
127
128 template <class TVAL, bool>
130
131#ifdef __cpp_lib_string_view
132 using string_view_type = ::std::string_view;
133#else
134 using string_view_type = ::std::string;
135#endif
136
137 template <class TVAL>
138 struct try_convert_to_string_view<TVAL, true> {
139 using value_type = typename std::conditional<std::is_same<std::nullptr_t, typename std::decay<TVAL>::type>::value,
140 std::nullptr_t, string_view_type>::type;
141 static inline value_type pick(TVAL v) { return value_type(v); }
142 };
143
144 template <bool CONVERTABLE_TO_SV>
145 struct try_convert_to_string_view<const char *, CONVERTABLE_TO_SV> {
146 using value_type = const char *;
147 static inline value_type pick(const char *v) { return v; }
148 };
149
150 template <class TVAL>
151 struct try_convert_to_string_view<TVAL, false> {
152 using value_type = TVAL;
153 static inline value_type pick(TVAL v) { return v; }
154 };
155
156 template <class TL, class TR, bool has_pointer, bool has_integer, bool all_integer>
164
165 template <class TL, bool CONVERT_TO_VOID_P = std::is_pointer<typename std::decay<TL>::type>::value ||
166 std::is_function<typename std::decay<TL>::type>::value>
168
169 template <class TL>
170 struct convert_param<TL, true> {
171 using value_type = void;
172 using type = const void *;
173 template <class TINPUT>
174 static inline const void *pick(TINPUT &&v) {
175 return reinterpret_cast<const void *>(v);
176 }
177 };
178
179 template <class TL>
180 struct convert_param<TL, false> {
181 using value_type = typename std::decay<TL>::type;
182 using type = const value_type &;
183 template <class TINPUT>
184 static inline const value_type &pick(TINPUT &&v) {
185 return v;
186 }
187 };
188
189 template <class TL>
191 return convert_param<TL>::pick(std::forward<TL>(v));
192 }
193
194 // expect functions
195 template <class TL, class TR>
196 bool expect_eq(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line) {
198 if (pp(l) == pp(r)) {
200 return true;
201 } else {
203 util::cli::shell_stream ss(std::cout);
204 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
205 << "Expected: " << lexpr << " == " << rexpr << std::endl
206 << lexpr << ": " << pick_convert_value(l) << std::endl
207 << rexpr << ": " << pick_convert_value(r) << std::endl;
208
209 return false;
210 }
211 }
212
213 template <class TL, class TR>
214 bool expect_ne(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line) {
216
217 if (pp(l) != pp(r)) {
219 return true;
220 } else {
222 util::cli::shell_stream ss(std::cout);
223 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
224 << "Expected: " << lexpr << " != " << rexpr << std::endl
225 << lexpr << ": " << pick_convert_value(l) << std::endl
226 << rexpr << ": " << pick_convert_value(r) << std::endl;
227
228 return false;
229 }
230 }
231
232 template <class TL, class TR>
233 bool expect_lt(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line) {
235
236 if (pp(l) < pp(r)) {
238 return true;
239 } else {
241 util::cli::shell_stream ss(std::cout);
242 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
243 << "Expected: " << lexpr << " < " << rexpr << std::endl
244 << lexpr << ": " << pick_convert_value(l) << std::endl
245 << rexpr << ": " << pick_convert_value(r) << std::endl;
246
247 return false;
248 }
249 }
250
251 template <class TL, class TR>
252 bool expect_le(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line) {
254
255 if (pp(l) <= pp(r)) {
257 return true;
258 } else {
260 util::cli::shell_stream ss(std::cout);
261 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
262 << "Expected: " << lexpr << " <= " << rexpr << std::endl
263 << lexpr << ": " << pick_convert_value(l) << std::endl
264 << rexpr << ": " << pick_convert_value(r) << std::endl;
265
266 return false;
267 }
268 }
269
270 template <class TL, class TR>
271 bool expect_gt(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line) {
273
274 if (pp(l) > pp(r)) {
276 return true;
277 } else {
279 util::cli::shell_stream ss(std::cout);
280 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
281 << "Expected: " << lexpr << " > " << rexpr << std::endl
282 << lexpr << ": " << pick_convert_value(l) << std::endl
283 << rexpr << ": " << pick_convert_value(r) << std::endl;
284
285 return false;
286 }
287 }
288
289 template <class TL, class TR>
290 bool expect_ge(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line) {
292
293 if (pp(l) >= pp(r)) {
295 return true;
296 } else {
298 util::cli::shell_stream ss(std::cout);
299 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
300 << "Expected: " << lexpr << " >= " << rexpr << std::endl
301 << lexpr << ": " << pick_convert_value(l) << std::endl
302 << rexpr << ": " << pick_convert_value(r) << std::endl;
303
304 return false;
305 }
306 }
307
308 template <class TL>
309 bool expect_true(TL &&l, const char *expr, const char *file, size_t line) {
310 if (!!(l)) {
312 return true;
313 } else {
315 util::cli::shell_stream ss(std::cout);
316 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
317 << "Expected true: " << expr << std::endl
318 << expr << ": " << pick_convert_value(l) << std::endl;
319
320 return false;
321 }
322 }
323
324 template <class TL>
325 bool expect_false(TL &&l, const char *expr, const char *file, size_t line) {
326 if (!(l)) {
328 return true;
329 } else {
331 util::cli::shell_stream ss(std::cout);
332 ss() << util::cli::shell_font_style::SHELL_FONT_COLOR_RED << "FAILED => " << file << ":" << line << std::endl
333 << "Expected false: " << expr << std::endl
334 << expr << ": " << pick_convert_value(l) << std::endl;
335
336 return false;
337 }
338 }
339
340 static void set_counter_ptr(int *success_counter_ptr, int *failed_counter_ptr);
341 static void inc_success_counter();
342 static void inc_failed_counter();
343
344 private:
350 std::unordered_set<std::string> run_cases_;
351 std::unordered_set<std::string> run_groups_;
352};
353
356int run_tests(int argc, char *argv[]);
static std::string get_expire_time(clock_t begin, clock_t end)
void set_cases(const std::vector< std::string > &case_names)
static test_manager & me()
void append_event_on_start(const std::string &event_name, on_start_ptr_type)
event_on_exit_type evt_on_exits_
std::vector< std::pair< std::string, case_ptr_type > > test_type
std::unordered_map< std::string, test_type > test_data_type
static void set_counter_ptr(int *success_counter_ptr, int *failed_counter_ptr)
event_on_start_type evt_on_starts_
bool expect_false(TL &&l, const char *expr, const char *file, size_t line)
test_data_type tests_
void append_event_on_exit(const std::string &event_name, on_exit_ptr_type)
bool expect_lt(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line)
virtual ~test_manager()
std::unordered_set< std::string > run_groups_
int run_event_on_start()
bool expect_eq(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line)
static void inc_failed_counter()
bool expect_ge(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line)
bool expect_true(TL &&l, const char *expr, const char *file, size_t line)
::std::string string_view_type
static void inc_success_counter()
int run_event_on_exit()
std::vector< std::pair< std::string, on_start_ptr_type > > event_on_start_type
bool expect_le(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line)
std::unordered_set< std::string > run_cases_
void append_test_case(const std::string &test_name, const std::string &case_name, case_ptr_type)
convert_param< TL >::type pick_convert_value(TL &&v)
bool expect_ne(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line)
bool expect_gt(TL &&l, TR &&r, const char *lexpr, const char *rexpr, const char *file, size_t line)
std::vector< std::pair< std::string, on_exit_ptr_type > > event_on_exit_type
static const value_type & pick(TINPUT &&v)
typename std::decay< TL >::type value_type
static const void * pick(TINPUT &&v)
typename std::conditional< std::is_floating_point< typename std::decay< TL >::type >::value||std::is_floating_point< typename std::decay< TR >::type >::value, double, typename std::conditional< std::is_unsigned< typename std::decay< TL >::type >::value &&std::is_unsigned< typename std::decay< TR >::type >::value, uint64_t, int64_t >::type >::type value_type
try_convert_to_string_view< T, std::is_convertible< T, string_view_type >::value >::value_type operator()(T &&t)
typename std::conditional< std::is_same< std::nullptr_t, typename std::decay< TVAL >::type >::value, std::nullptr_t, string_view_type >::type value_type
int run_event_on_exit()
int run_event_on_start()
int run_tests(int argc, char *argv[])