@micro-os-plus/micro-test-plus 2.1.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,132 @@
1
+ /*
2
+ * This file is part of the µOS++ distribution.
3
+ * (https://github.com/micro-os-plus/)
4
+ * Copyright (c) 2021 Liviu Ionescu.
5
+ *
6
+ * Permission to use, copy, modify, and/or distribute this software
7
+ * for any purpose is hereby granted, under the terms of the MIT license.
8
+ *
9
+ * If a copy of the license was not distributed with this file, it can
10
+ * be obtained from <https://opensource.org/licenses/MIT/>.
11
+ *
12
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
13
+ * released under the terms of the Boost Version 1.0 Software License,
14
+ * which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
15
+ */
16
+
17
+ #ifndef MICRO_TEST_PLUS_TEST_RUNNER_H_
18
+ #define MICRO_TEST_PLUS_TEST_RUNNER_H_
19
+
20
+ // ----------------------------------------------------------------------------
21
+
22
+ #ifdef __cplusplus
23
+
24
+ // ----------------------------------------------------------------------------
25
+
26
+ #include <functional>
27
+
28
+ // ----------------------------------------------------------------------------
29
+
30
+ #if defined(__GNUC__)
31
+ #pragma GCC diagnostic push
32
+ #pragma GCC diagnostic ignored "-Wpadded"
33
+ #if defined(__clang__)
34
+ #pragma clang diagnostic ignored "-Wc++98-compat"
35
+ #endif
36
+ #endif
37
+
38
+ namespace micro_os_plus::micro_test_plus
39
+ {
40
+ // --------------------------------------------------------------------------
41
+
42
+ class test_suite_base;
43
+
44
+ // --------------------------------------------------------------------------
45
+
46
+ /**
47
+ * @brief The test runner. It maintaines a list of test suites which
48
+ * automatically register themselves in their constructors.
49
+ */
50
+ class test_runner
51
+ {
52
+ public:
53
+ test_runner ();
54
+
55
+ // The rule of five.
56
+ test_runner (const test_runner&) = delete;
57
+ test_runner (test_runner&&) = delete;
58
+ test_runner&
59
+ operator= (const test_runner&)
60
+ = delete;
61
+ test_runner&
62
+ operator= (test_runner&&)
63
+ = delete;
64
+
65
+ ~test_runner () = default;
66
+
67
+ /**
68
+ * @brief Pass the main arguments explicitly, if the default
69
+ * contructor was used.
70
+ */
71
+ void
72
+ initialize (int argc, char* argv[], const char* name);
73
+
74
+ /**
75
+ * @brief Return 0 if the all tests were successful, 1 otherwise.
76
+ */
77
+ int
78
+ exit_code (void);
79
+
80
+ /**
81
+ * @brief Called by test suite constructors to register them
82
+ * to the runner.
83
+ */
84
+ void
85
+ register_test_suite (test_suite_base* suite);
86
+
87
+ constexpr const char*
88
+ name (void)
89
+ {
90
+ return default_suite_name_;
91
+ }
92
+
93
+ [[noreturn]] void
94
+ abort (void);
95
+
96
+ protected:
97
+ int argc_ = 0;
98
+ char** argv_ = nullptr;
99
+
100
+ const char* default_suite_name_ = "Test";
101
+
102
+ /**
103
+ * @brief Pointer to the default test suite which groups
104
+ * the main tests.
105
+ */
106
+ test_suite_base* default_test_suite_;
107
+
108
+ /**
109
+ * @brief Pointer to array of registered test suites.
110
+ * Statically initialised to zero as BSS, such that
111
+ * test suites defined as static objects in different
112
+ * compilation units can be automatically executed.
113
+ */
114
+ std::vector<test_suite_base*>* suites_;
115
+ };
116
+
117
+ // --------------------------------------------------------------------------
118
+ } // namespace micro_os_plus::micro_test_plus
119
+
120
+ #if defined(__GNUC__)
121
+ #pragma GCC diagnostic pop
122
+ #endif
123
+
124
+ // ----------------------------------------------------------------------------
125
+
126
+ #endif // __cplusplus
127
+
128
+ // ----------------------------------------------------------------------------
129
+
130
+ #endif // MICRO_TEST_PLUS_TEST_RUNNER_H_
131
+
132
+ // ----------------------------------------------------------------------------
@@ -0,0 +1,241 @@
1
+ /*
2
+ * This file is part of the µOS++ distribution.
3
+ * (https://github.com/micro-os-plus/)
4
+ * Copyright (c) 2021 Liviu Ionescu.
5
+ *
6
+ * Permission to use, copy, modify, and/or distribute this software
7
+ * for any purpose is hereby granted, under the terms of the MIT license.
8
+ *
9
+ * If a copy of the license was not distributed with this file, it can
10
+ * be obtained from <https://opensource.org/licenses/MIT/>.
11
+ *
12
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
13
+ * released under the terms of the Boost Version 1.0 Software License,
14
+ * which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
15
+ */
16
+
17
+ #ifndef MICRO_TEST_PLUS_TEST_SUITE_H_
18
+ #define MICRO_TEST_PLUS_TEST_SUITE_H_
19
+
20
+ // ----------------------------------------------------------------------------
21
+
22
+ #ifdef __cplusplus
23
+
24
+ // ----------------------------------------------------------------------------
25
+
26
+ #include <functional>
27
+
28
+ // ----------------------------------------------------------------------------
29
+
30
+ #if defined(__GNUC__)
31
+ #pragma GCC diagnostic push
32
+ #pragma GCC diagnostic ignored "-Wpadded"
33
+ #if !defined(__clang__) // GCC only
34
+ #pragma GCC diagnostic ignored "-Wsuggest-final-types"
35
+ #pragma GCC diagnostic ignored "-Wsuggest-final-methods"
36
+ #endif
37
+ #if defined(__clang__)
38
+ #pragma clang diagnostic ignored "-Wc++98-compat"
39
+ #endif
40
+ #endif
41
+
42
+ namespace micro_os_plus::micro_test_plus
43
+ {
44
+ // --------------------------------------------------------------------------
45
+
46
+ /**
47
+ * @brief Test suites are classes that represent a named group of
48
+ * test cases which self registers to the runner.
49
+ */
50
+ class test_suite_base
51
+ {
52
+ public:
53
+ /**
54
+ * @brief Construct the default suite used in main().
55
+ */
56
+ test_suite_base (const char* name);
57
+
58
+ // The rule of five.
59
+ test_suite_base (const test_suite_base&) = delete;
60
+ test_suite_base (test_suite_base&&) = delete;
61
+ test_suite_base&
62
+ operator= (const test_suite_base&)
63
+ = delete;
64
+ test_suite_base&
65
+ operator= (test_suite_base&&)
66
+ = delete;
67
+
68
+ virtual ~test_suite_base ();
69
+
70
+ /**
71
+ * @brief Run the sequence of test cases in the suite.
72
+ */
73
+ virtual void
74
+ run (void);
75
+
76
+ /**
77
+ * @brief Mark the begining of a named test case.
78
+ */
79
+ void
80
+ begin_test_case (const char* name);
81
+
82
+ /**
83
+ * @brief Mark the end of a test case.
84
+ */
85
+ void
86
+ end_test_case (void);
87
+
88
+ /**
89
+ * @brief Get the suite name.
90
+ */
91
+ [[nodiscard]] constexpr const char*
92
+ name ()
93
+ {
94
+ return name_;
95
+ }
96
+
97
+ /**
98
+ * @brief Count one more passed test condition.
99
+ */
100
+ void
101
+ increment_successful (void);
102
+
103
+ /**
104
+ * @brief Count one more failed test condition.
105
+ */
106
+ void
107
+ increment_failed (void);
108
+
109
+ /**
110
+ * @brief Get the number of conditions that passed.
111
+ */
112
+ [[nodiscard]] constexpr int
113
+ successful_checks (void)
114
+ {
115
+ return successful_checks_;
116
+ }
117
+
118
+ /**
119
+ * @brief Get the number of conditions that failed.
120
+ */
121
+ [[nodiscard]] constexpr int
122
+ failed_checks (void)
123
+ {
124
+ return failed_checks_;
125
+ }
126
+
127
+ /**
128
+ * @brief Get the number of test cases.
129
+ */
130
+ [[nodiscard]] constexpr int
131
+ test_cases (void)
132
+ {
133
+ return test_cases_;
134
+ }
135
+
136
+ /**
137
+ * @brief Begin the execution of the test suite.
138
+ */
139
+ void
140
+ begin_test_suite (void);
141
+
142
+ /**
143
+ * @brief Mark the end of the test suite.
144
+ */
145
+ void
146
+ end_test_suite (void);
147
+
148
+ /**
149
+ * @brief Get the test suite result.
150
+ */
151
+ [[nodiscard]] constexpr bool
152
+ was_successful (void)
153
+ {
154
+ // Also fail if none passed.
155
+ return (failed_checks_ == 0 && successful_checks_ != 0);
156
+ }
157
+
158
+ [[nodiscard]] constexpr bool
159
+ unused (void)
160
+ {
161
+ return (failed_checks_ == 0 && successful_checks_ == 0
162
+ && test_cases_ == 0);
163
+ }
164
+
165
+ protected:
166
+ /**
167
+ * @brief The test suite name.
168
+ */
169
+ const char* name_;
170
+
171
+ /**
172
+ * @brief The current test case name.
173
+ */
174
+ const char* test_case_name_;
175
+
176
+ /**
177
+ * @brief Count of test conditions that passed.
178
+ */
179
+ int successful_checks_ = 0;
180
+
181
+ /**
182
+ * @brief Count of test conditions that failed.
183
+ */
184
+ int failed_checks_ = 0;
185
+
186
+ /**
187
+ * @brief Count of test cases in the test suite.
188
+ */
189
+ int test_cases_ = 0;
190
+
191
+ public:
192
+ bool process_deferred_begin = true;
193
+ struct
194
+ {
195
+ int successful_checks;
196
+ int failed_checks;
197
+ } current_test_case{};
198
+ };
199
+
200
+ class test_suite : public test_suite_base
201
+ {
202
+ public:
203
+ template <typename Callable_T, typename... Args_T>
204
+ test_suite (const char* name, Callable_T&& callable,
205
+ Args_T&&... arguments);
206
+
207
+ // The rule of five.
208
+ test_suite (const test_suite&) = delete;
209
+ test_suite (test_suite&&) = delete;
210
+ test_suite&
211
+ operator= (const test_suite&)
212
+ = delete;
213
+ test_suite&
214
+ operator= (test_suite&&)
215
+ = delete;
216
+
217
+ virtual ~test_suite () override;
218
+
219
+ virtual void
220
+ run (void) override;
221
+
222
+ protected:
223
+ std::function<void (void)> callable_;
224
+ };
225
+
226
+ // --------------------------------------------------------------------------
227
+ } // namespace micro_os_plus::micro_test_plus
228
+
229
+ #if defined(__GNUC__)
230
+ #pragma GCC diagnostic pop
231
+ #endif
232
+
233
+ // ----------------------------------------------------------------------------
234
+
235
+ #endif // __cplusplus
236
+
237
+ // ----------------------------------------------------------------------------
238
+
239
+ #endif // MICRO_TEST_PLUS_TEST_SUITE_H_
240
+
241
+ // ----------------------------------------------------------------------------
@@ -0,0 +1,346 @@
1
+ /*
2
+ * This file is part of the µOS++ distribution.
3
+ * (https://github.com/micro-os-plus/)
4
+ * Copyright (c) 2021 Liviu Ionescu.
5
+ *
6
+ * Permission to use, copy, modify, and/or distribute this software
7
+ * for any purpose is hereby granted, under the terms of the MIT license.
8
+ *
9
+ * If a copy of the license was not distributed with this file, it can
10
+ * be obtained from <https://opensource.org/licenses/MIT/>.
11
+ *
12
+ * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
13
+ * released under the terms of the Boost Version 1.0 Software License,
14
+ * which can be obtained from <https://www.boost.org/LICENSE_1_0.txt>.
15
+ */
16
+
17
+ #ifndef MICRO_TEST_PLUS_TYPE_TRAITS_H_
18
+ #define MICRO_TEST_PLUS_TYPE_TRAITS_H_
19
+
20
+ // ----------------------------------------------------------------------------
21
+
22
+ #ifdef __cplusplus
23
+
24
+ // ----------------------------------------------------------------------------
25
+
26
+ #include "math.h"
27
+
28
+ // ----------------------------------------------------------------------------
29
+
30
+ #if defined(__GNUC__)
31
+ #pragma GCC diagnostic push
32
+ #if defined(__clang__)
33
+ #pragma clang diagnostic ignored "-Wc++98-compat"
34
+ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
35
+ #endif
36
+ #endif
37
+
38
+ namespace micro_os_plus::micro_test_plus
39
+ {
40
+ // --------------------------------------------------------------------------
41
+
42
+ /**
43
+ * @brief Local type traits. Some may have standard equivalents, but
44
+ * better keep them locally.
45
+ */
46
+ namespace type_traits
47
+ {
48
+ template <class...>
49
+ struct list
50
+ {
51
+ };
52
+
53
+ template <class T, class...>
54
+ struct identity
55
+ {
56
+ using type = T;
57
+ };
58
+
59
+ template <class T>
60
+ struct function_traits : function_traits<decltype (&T::operator())>
61
+ {
62
+ };
63
+
64
+ template <class R, class... Args_T>
65
+ struct function_traits<R (*) (Args_T...)>
66
+ {
67
+ using result_type = R;
68
+ using args = list<Args_T...>;
69
+ };
70
+
71
+ template <class R, class... Args_T>
72
+ struct function_traits<R (Args_T...)>
73
+ {
74
+ using result_type = R;
75
+ using args = list<Args_T...>;
76
+ };
77
+
78
+ template <class R, class T, class... Args_T>
79
+ struct function_traits<R (T::*) (Args_T...)>
80
+ {
81
+ using result_type = R;
82
+ using args = list<Args_T...>;
83
+ };
84
+
85
+ template <class R, class T, class... Args_T>
86
+ struct function_traits<R (T::*) (Args_T...) const>
87
+ {
88
+ using result_type = R;
89
+ using args = list<Args_T...>;
90
+ };
91
+
92
+ template <class T>
93
+ T&&
94
+ declval ();
95
+ template <class... Ts, class Expr_T>
96
+ constexpr auto
97
+ is_valid (Expr_T expr) -> decltype (expr (declval<Ts...> ()), bool ())
98
+ {
99
+ return true;
100
+ }
101
+
102
+ template <class...>
103
+ constexpr auto
104
+ is_valid (...) -> bool
105
+ {
106
+ return false;
107
+ }
108
+
109
+ template <class T>
110
+ static constexpr auto is_container_v
111
+ = is_valid<T> ([] (auto t) -> decltype (t.begin (), t.end (),
112
+ void ()) {});
113
+
114
+ template <class T>
115
+ static constexpr auto has_npos_v
116
+ = is_valid<T> ([] (auto t) -> decltype (void (t.npos)) {});
117
+
118
+ template <class T>
119
+ static constexpr auto has_value_v
120
+ = is_valid<T> ([] (auto t) -> decltype (void (t.value)) {});
121
+
122
+ template <class T>
123
+ static constexpr auto has_epsilon_v
124
+ = is_valid<T> ([] (auto t) -> decltype (void (t.epsilon)) {});
125
+
126
+ template <class T>
127
+ inline constexpr auto is_floating_point_v = false;
128
+ template <>
129
+ inline constexpr auto is_floating_point_v<float> = true;
130
+ template <>
131
+ inline constexpr auto is_floating_point_v<double> = true;
132
+ template <>
133
+ inline constexpr auto is_floating_point_v<long double> = true;
134
+
135
+ #if defined(__clang__) or defined(_MSC_VER)
136
+ template <class From, class To>
137
+ static constexpr auto is_convertible_v = __is_convertible_to(From, To);
138
+ #else
139
+ template <class From, class To>
140
+ constexpr auto
141
+ is_convertible (int) -> decltype (bool (To (declval<From> ())))
142
+ {
143
+ return true;
144
+ }
145
+ template <class...>
146
+ constexpr auto
147
+ is_convertible (...)
148
+ {
149
+ return false;
150
+ }
151
+ template <class From, class To>
152
+ constexpr auto is_convertible_v = is_convertible<From, To> (0);
153
+ #endif
154
+
155
+ template <bool>
156
+ struct requires_
157
+ {
158
+ };
159
+
160
+ template <>
161
+ struct requires_<true>
162
+ {
163
+ using type = int;
164
+ };
165
+
166
+ template <bool Cond>
167
+ using requires_t = typename requires_<Cond>::type;
168
+
169
+ /**
170
+ * @brief Empty base class of all operators.
171
+ */
172
+ struct op
173
+ {
174
+ };
175
+
176
+ /**
177
+ * @brief A generic integral constant.
178
+ * It has a getter and a '-' operator to return the negative value.
179
+ */
180
+ template <auto N>
181
+ struct integral_constant : op
182
+ {
183
+ using value_type = decltype (N);
184
+ static constexpr auto value = N;
185
+
186
+ [[nodiscard]] constexpr auto
187
+ operator- () const
188
+ {
189
+ return integral_constant<-N>{};
190
+ }
191
+
192
+ [[nodiscard]] constexpr explicit operator value_type () const
193
+ {
194
+ return N;
195
+ }
196
+
197
+ [[nodiscard]] constexpr auto
198
+ get () const
199
+ {
200
+ return N;
201
+ }
202
+ };
203
+
204
+ /**
205
+ * @brief A generic floating point constant, with custom size
206
+ * and precision.
207
+ * It has a getter and a '-' operator to return the negative value.
208
+ */
209
+ template <class T, auto N, auto D, auto Size, auto P = 1>
210
+ struct floating_point_constant : op
211
+ {
212
+ using value_type = T;
213
+
214
+ static constexpr auto epsilon = T (1) / math::pow (T (10), Size - 1);
215
+ static constexpr auto value
216
+ = T (P) * (T (N) + (T (D) / math::pow (T (10), Size)));
217
+
218
+ [[nodiscard]] constexpr auto
219
+ operator- () const
220
+ {
221
+ return floating_point_constant<T, N, D, Size, -1>{};
222
+ }
223
+
224
+ [[nodiscard]] constexpr explicit operator value_type () const
225
+ {
226
+ return value;
227
+ }
228
+
229
+ [[nodiscard]] constexpr auto
230
+ get () const
231
+ {
232
+ return value;
233
+ }
234
+ };
235
+
236
+ template <class T>
237
+ struct genuine_integral_value : op
238
+ {
239
+ using value_type = T;
240
+
241
+ constexpr genuine_integral_value (const T& _value) : value_{ _value }
242
+ {
243
+ }
244
+
245
+ [[nodiscard]] constexpr explicit operator T () const
246
+ {
247
+ return value_;
248
+ }
249
+
250
+ [[nodiscard]] constexpr decltype (auto)
251
+ get () const
252
+ {
253
+ return value_;
254
+ }
255
+
256
+ T value_{};
257
+ };
258
+
259
+ template <class T>
260
+ inline constexpr auto is_op_v = __is_base_of(type_traits::op, T);
261
+
262
+ /**
263
+ * @brief Class defining a generic value, accessible via a getter.
264
+ */
265
+ template <class T, class = int>
266
+ struct value : type_traits::op
267
+ {
268
+ using value_type = T;
269
+
270
+ constexpr value (const T& _value) : value_{ _value }
271
+ {
272
+ }
273
+
274
+ [[nodiscard]] constexpr explicit operator T () const
275
+ {
276
+ return value_;
277
+ }
278
+
279
+ [[nodiscard]] constexpr decltype (auto)
280
+ get () const
281
+ {
282
+ return value_;
283
+ }
284
+
285
+ T value_{};
286
+ };
287
+
288
+ /**
289
+ * @brief A generic value used to define floating points, which,
290
+ * in addition to the actual value, has an epsilon, to use the
291
+ * desired precision during comparisons.
292
+ * If missing, the default is 1 / (10^decimals).
293
+ */
294
+ template <class T>
295
+ struct value<T,
296
+ type_traits::requires_t<type_traits::is_floating_point_v<T>>>
297
+ : type_traits::op
298
+ {
299
+ using value_type = T;
300
+ static inline auto epsilon = T{}; // Why static?
301
+
302
+ constexpr value (const T& _value, const T precision) : value_{ _value }
303
+ {
304
+ epsilon = precision;
305
+ }
306
+
307
+ constexpr /*explicit(false)*/ value (const T& val)
308
+ : value{ val,
309
+ T (1)
310
+ / math::pow (T (10),
311
+ math::den_size<unsigned long long> (val)) }
312
+ {
313
+ }
314
+
315
+ [[nodiscard]] constexpr explicit operator T () const
316
+ {
317
+ return value_;
318
+ }
319
+
320
+ [[nodiscard]] constexpr decltype (auto)
321
+ get () const
322
+ {
323
+ return value_;
324
+ }
325
+
326
+ T value_{};
327
+ };
328
+
329
+ } // namespace type_traits
330
+
331
+ // --------------------------------------------------------------------------
332
+ } // namespace micro_os_plus::micro_test_plus
333
+
334
+ #if defined(__GNUC__)
335
+ #pragma GCC diagnostic pop
336
+ #endif
337
+
338
+ // ----------------------------------------------------------------------------
339
+
340
+ #endif // __cplusplus
341
+
342
+ // ----------------------------------------------------------------------------
343
+
344
+ #endif // MICRO_TEST_PLUS_TYPE_TRAITS_H_
345
+
346
+ // ----------------------------------------------------------------------------