libGimbal 0.2.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_test_macros.h
Go to the documentation of this file.
1/*! \file
2 * \brief Unit testing macro utilities
3 * \ingroup testing
4 *
5 * \todo
6 * - need to make an actual exported set of C
7 * functions as the top-level entry-point into
8 * GBL_TEST_COMPARE(), so that language bindings
9 * without macros can use the test framework.
10 *
11 * \author Falco Girgis
12 */
13#ifndef GIMBAL_TEST_MACROS_H
14#define GIMBAL_TEST_MACROS_H
15
16#include "../preprocessor/gimbal_macro_utils.h"
18#include <stdint.h>
19#include <inttypes.h>
20
21#ifdef __cplusplus
22# include <concepts>
23#endif
24
25#define GBL_TEST_VERIFY(expr) GBL_CTX_VERIFY_EXPRESSION(expr)
26
27/// \cond
28GBL_INLINE const char* GBL_TEST_COMPARE_FMT_DFLT_ (void) { return "Values differed"; }
29GBL_INLINE const char* GBL_TEST_COMPARE_FMT_CHAR_ (void) { return "Values differed [actual: %c, expected: %c]"; }
30GBL_INLINE const char* GBL_TEST_COMPARE_FMT_INT_ (void) { return "Values differed [actual: %d, expected: %d]"; }
31GBL_INLINE const char* GBL_TEST_COMPARE_FMT_UINT_ (void) { return "Values differed [actual: %u, expected: %u]"; }
32GBL_INLINE const char* GBL_TEST_COMPARE_FMT_LINT_ (void) { return "Values differed [actual: %" PRId64 ", expected: %" PRId64 "]"; }
33GBL_INLINE const char* GBL_TEST_COMPARE_FMT_LUINT_(void) { return "Values differed [actual: %" PRIu64 ", expected: %" PRIu64 "]"; }
34GBL_INLINE const char* GBL_TEST_COMPARE_FMT_STR_ (void) { return "Values differed [actual: %s, expected: %s]"; }
35GBL_INLINE const char* GBL_TEST_COMPARE_FMT_FLT_ (void) { return "Values differed [actual: %f, expected: %f]"; }
36GBL_INLINE const char* GBL_TEST_COMPARE_FMT_PTR_ (void) { return "Values differed [actual: %p, expected: %p]"; }
37
38#ifndef __cplusplus
39# define GBL_TEST_COMPARE_FMT_TABLE_ (
40 GBL_TEST_COMPARE_FMT_PTR_,
41 (
42 (char, GBL_TEST_COMPARE_FMT_CHAR_),
43 (int16_t, GBL_TEST_COMPARE_FMT_INT_),
44 (int32_t, GBL_TEST_COMPARE_FMT_INT_),
45 (int64_t, GBL_TEST_COMPARE_FMT_LINT_),
46 (uint8_t, GBL_TEST_COMPARE_FMT_UINT_),
47 (uint16_t, GBL_TEST_COMPARE_FMT_UINT_),
48 (uint32_t, GBL_TEST_COMPARE_FMT_UINT_),
49 (uint64_t, GBL_TEST_COMPARE_FMT_LUINT_),
50 (const char*, GBL_TEST_COMPARE_FMT_STR_),
51 (char*, GBL_TEST_COMPARE_FMT_STR_),
52 (float, GBL_TEST_COMPARE_FMT_FLT_),
53 (double, GBL_TEST_COMPARE_FMT_FLT_),
54 (const void*, GBL_TEST_COMPARE_FMT_PTR_)
55 )
56 )
57
58# define GBL_TEST_COMPARE_FMT_(value) GBL_META_GENERIC_MACRO_GENERATE(GBL_TEST_COMPARE_FMT_TABLE_, value)()
59#else
60
61inline constexpr const char* GBL_TEST_COMPARE_FMT_(char) { return "Values differed [actual: %c, expected: %c]"; }
62inline constexpr const char* GBL_TEST_COMPARE_FMT_(short) { return "Values differed [actual: %d, expected: %d]"; }
63inline constexpr const char* GBL_TEST_COMPARE_FMT_(unsigned short) { return "Values differed [actual: %u, expected: %u]"; }
64inline constexpr const char* GBL_TEST_COMPARE_FMT_(int) { return "Values differed [actual: %d, expected: %d]"; }
65inline constexpr const char* GBL_TEST_COMPARE_FMT_(unsigned) { return "Values differed [actual: %u, expected: %u]"; }
66inline constexpr const char* GBL_TEST_COMPARE_FMT_(long) { return "Values differed [actual: %ld, expected: %ld]"; }
67inline constexpr const char* GBL_TEST_COMPARE_FMT_(unsigned long) { return "Values differed [actual: %lu, expected: %lu]"; }
68inline constexpr const char* GBL_TEST_COMPARE_FMT_(long long) { return "Values differed [actual: %lld, expected: %lld]"; }
69inline constexpr const char* GBL_TEST_COMPARE_FMT_(unsigned long long) { return "Values differed [actual: %llu, expected: %llu]"; }
70inline constexpr const char* GBL_TEST_COMPARE_FMT_(const char*) { return "Values differed [actual: %s, expected: %s]"; }
71inline constexpr const char* GBL_TEST_COMPARE_FMT_(float) { return "Values differed [actual: %f, expected: %f]"; }
72inline constexpr const char* GBL_TEST_COMPARE_FMT_(double) { return "Values differed [actual: %f, expected: %f]"; }
73inline constexpr const char* GBL_TEST_COMPARE_FMT_(auto*) { return "Values differed [actual: %p, expected: %p]"; }
74inline constexpr const char* GBL_TEST_COMPARE_FMT_(auto) { return "Values differed"; }
75
76#endif
77
78
79GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_UINTPTR_(uintptr_t actual, uintptr_t expected) { return actual == expected; }
80GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_PTR_ (const void* pActual, const void* pExpected) { return pActual == pExpected; }
81GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_UINT32_ (uint32_t actual, uint32_t expected) { return actual == expected; }
82GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_UINT64_ (uint64_t actual, uint64_t expected) { return actual == expected; }
83GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_INT32_ (int32_t actual, int32_t expected) { return actual == expected; }
84GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_INT64_ (int64_t actual, int64_t expected) { return actual == expected; }
85GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_FLT_ (float actual, float expected) { return fabsf(actual - expected) < FLT_EPSILON; }
86GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_DBL_ (double actual, double expected) { return fabs(actual - expected) < DBL_EPSILON; }
87GBL_INLINE GblBool GBL_TEST_COMPARE_CMP_STR_ (const char* pActual, const char* pExpected) { return pActual == pExpected ||
88 (pActual && pExpected &&
89 strcmp(pActual, pExpected) == 0); }
90
91#ifndef __cplusplus
92#if defined(GBL_DREAMCAST) || defined(GBL_GAMECUBE)
93# define GBL_TEST_CMP_PLATFORM_ENTRIES()
94 (size_t , GBL_TEST_COMPARE_CMP_UINT32_),
95 (int, GBL_TEST_COMPARE_CMP_INT32_),
96#elif defined(GBL_PSP)
97# define GBL_TEST_CMP_PLATFORM_ENTRIES()
98 (size_t , GBL_TEST_COMPARE_CMP_UINT32_),
99 (int, GBL_TEST_COMPARE_CMP_INT32_),
100#elif (defined(__APPLE__) && defined(GBL_64BIT))
101# define GBL_TEST_CMP_PLATFORM_ENTRIES()
102 (size_t , GBL_TEST_COMPARE_CMP_UINT64_),
103 (long, GBL_TEST_COMPARE_CMP_INT64_),
104#elif defined(__EMSCRIPTEN__)
105# define GBL_TEST_CMP_PLATFORM_ENTRIES()
106 (size_t , GBL_TEST_COMPARE_CMP_UINT64_),
107 (int8_t, GBL_TEST_COMPARE_CMP_UINT32_),
108# else
109# define GBL_TEST_CMP_PLATFORM_ENTRIES()
110# endif
111
112# define GBL_TEST_COMPARE_CMP_TABLE_ (
113 GBL_TEST_COMPARE_CMP_PTR_,
114 (
115 (char, GBL_TEST_COMPARE_CMP_INT32_),
116 (int16_t, GBL_TEST_COMPARE_CMP_INT32_),
117 (int32_t, GBL_TEST_COMPARE_CMP_INT32_),
118 (int64_t, GBL_TEST_COMPARE_CMP_INT64_),
119 (uint8_t, GBL_TEST_COMPARE_CMP_UINT32_),
120 (uint16_t, GBL_TEST_COMPARE_CMP_UINT32_),
121 (uint32_t, GBL_TEST_COMPARE_CMP_UINT32_),
122 (uint64_t, GBL_TEST_COMPARE_CMP_UINT64_),
123 GBL_TEST_CMP_PLATFORM_ENTRIES()
124 (const char*, GBL_TEST_COMPARE_CMP_STR_),
125 (char*, GBL_TEST_COMPARE_CMP_STR_),
126 (float, GBL_TEST_COMPARE_CMP_FLT_),
127 (double, GBL_TEST_COMPARE_CMP_DBL_),
128 (const void*, GBL_TEST_COMPARE_CMP_PTR_)
129 )
130 )
131
132# define GBL_TEST_COMPARE_CMP_(actual, expected) GBL_META_GENERIC_MACRO_GENERATE(GBL_TEST_COMPARE_CMP_TABLE_, actual)(actual, expected)
133
134#else
135inline constexpr GblBool GBL_TEST_COMPARE_CMP_(auto actual, auto expected) noexcept {
136 if constexpr(std::floating_point<decltype(actual)> || std::floating_point<decltype(expected)>) {
137 constexpr double epsilon = std::is_same_v<float, decltype(actual)> ? FLT_EPSILON : DBL_EPSILON;
138 return abs(static_cast<double>(actual) - static_cast<double>(expected)) < epsilon;
139 }
140 else if constexpr(std::convertible_to<decltype(actual), decltype(expected)>)
141 return static_cast<decltype(expected)>(actual) == expected;
142 else if constexpr(std::convertible_to<decltype(expected), decltype(actual)>)
143 return actual == static_cast<decltype(actual)>(expected);
144 else static_assert("Incompatible types!");
145}
146
147inline GblBool GBL_TEST_COMPARE_CMP_(const char* pActual, const char *pExpected) noexcept {
148 return GBL_TEST_COMPARE_CMP_STR_(pActual, pExpected);
149}
150
151#endif
152/// \endcond
153
154#define GBL_TEST_COMPARE(actual, expected) GBL_CTX_VERIFY_EXPRESSION(GBL_TEST_COMPARE_CMP_(actual, expected),
155 GBL_TEST_COMPARE_FMT_(actual),
156 actual, expected)
157
158#define GBL_TEST_COMPARE_INT(actual, expected) GBL_CTX_VERIFY_EXPRESSION(actual == expected,
159 "Values differed [expected: %d, actual: %d]",
160 actual, expected)
161
162#define GBL_TEST_COMPARE_UINT(actual, expected) GBL_CTX_VERIFY_EXPRESSION(actual == expected,
163 "Values differed [expected: %u, actual: %u]",
164 actual, expected)
165
166#define GBL_TEST_COMPARE_STRING(actual, expected) GBL_CTX_VERIFY_EXPRESSION(strcmp(actual, expected) == 0,
167 "Values differed [expected: %s, actual: %s]",
168 actual, expected)
169
170#define GBL_TEST_COMPARE_FLOAT(actual, expected) GBL_CTX_VERIFY_EXPRESSION(fabsf((actual) - (expected)) < FLT_EPSILON,
171 "Values differed [expected: %f, actual: %f]",
172 actual, expected)
173
174#define GBL_TEST_COMPARE_DOUBLE(actual, expected) GBL_CTX_VERIFY_EXPRESSION(fabs((actual) - (expected)) < DBL_EPSILON,
175 "Values differed [expected: %f, actual: %f]",
176 actual, expected)
177
178#define GBL_TEST_COMPARE_POINTER(actual, expected) GBL_CTX_VERIFY_EXPRESSION(actual == expected,
179 "Values differed [exptected: %p, actual: %p]",
180 actual, expected)
181
182typedef enum GBL_TEST_ERROR_COMPARISON {
183 GBL_TEST_ERROR_ABSOLUTE,
184 GBL_TEST_ERROR_RELATIVE,
185 GBL_TEST_ERROR_FUZZY
186} GBL_TEST_ERROR_COMPARISON;
187
188#define GBL_TEST_ERROR(actual, precise, epsilon, cmp)
190 double relative = gblRelativeError((actual), (precise));
191 double absolute = gblAbsoluteError((actual), (precise));
192 if(((cmp) == GBL_TEST_ERROR_ABSOLUTE && absolute > (epsilon)) ||
193 ((cmp) == GBL_TEST_ERROR_RELATIVE && relative > (epsilon)) ||
194 (absolute > (epsilon) && relative > (epsilon)))
195 GBL_TEST_FAIL("(actual == %.9f) != (expected == %.9f)\n"
196 "\t ERROR: Rel == %.9f, Abs == %.9f, Max == %.9f",
197 (actual), (precise), relative, absolute, (epsilon));
199
200
201#define GBL_TEST_CALL GBL_CTX_VERIFY_CALL
202
203//! Reports an enum value to a registered result group, with an optional formatted message.
204#define GBL_TEST_CUSTOM(...) GBL_TEST_CUSTOM_(__VA_ARGS__, NULL)
205
206#define GBL_TEST_CUSTOM_(name, enumType, expression, ...)
208 const GblEnum gblTestCustomValue_ = (expression);
209 GBL_CTX_VERIFY_CALL(GblTestScenario_reportResult(
210 GBL_TEST_SCENARIO(GBL_CTX_CONTEXT()), (name), (enumType),
211 gblTestCustomValue_, __VA_ARGS__));
213
214#define GBL_TEST_SKIP(reason) GBL_CTX_VERIFY(GBL_FALSE,
215 GBL_RESULT_SKIPPED,
216 reason)
217
218#define GBL_TEST_FAIL(...) GBL_CTX_VERIFY(GBL_FALSE,
220 __VA_ARGS__)
221
222#define GBL_TEST_EXPECT_ERROR()
224 GBL_CTX_VERIFY(!GBL_CONFIG_ASSERT_ERROR_ENABLED,
225 GBL_RESULT_SKIPPED,
226 "Skipping test case due to GBL_CONFIG_ASSERT_ERROR_ENABLED.");
227 GblTestScenario* pScenario = GBL_TEST_SCENARIO(GBL_CTX_CONTEXT());
228 if(pScenario) GblTestScenario_expectError(pScenario);
230
231
232#ifndef GBL_SELF_TYPE_NAME
233# define GBL_SELF_TYPE_NAME pSelf
234#endif
235
236#ifndef GBL_TEST_SUITE_CONTEXT_NAME
237# define GBL_TEST_SUITE_CONTEXT_NAME pCtx
238#endif
239
240#ifndef GBL_SELF_TYPE_PRIVATE_NAME
241# define GBL_SELF_TYPE_PRIVATE_NAME pFixture
242#endif
243
244#ifndef GBL_SELF_TYPE_PRIVATE
245# define GBL_SELF_TYPE_PRIVATE GBL_GLUE(GBL_SELF_TYPE, _)
246#endif
247
248#define GBL_TEST_CASE(name)
249 static GBL_RESULT GBL_GLUE(GBL_GLUE(GBL_GLUE(GBL_SELF_TYPE, _), name), _)
250 (GblTestSuite* GBL_SELF_TYPE_NAME,
251 GblContext* GBL_TEST_SUITE_CONTEXT_NAME) {
255 GBL_PRIVATE(GBL_SELF_TYPE, pSelf);
259
260#define GBL_TEST_CASE_END
261 GBL_CTX_END(); }
262
263#define GBL_TEST_FIXTURE_TYPE
265
266#define GBL_TEST_FIXTURE
268 typedef struct GBL_TEST_FIXTURE_TYPE GblTestFixture;
270
271#ifdef __cplusplus
272# define GBL_TEST_REGISTER(...)
273 extern "C" GBL_TEST_REGISTER_(__VA_ARGS__)
274#else
275# define GBL_TEST_REGISTER(...)
276 GBL_TEST_REGISTER_(__VA_ARGS__)
277#endif
278
279#define GBL_TEST_REGISTER_(...)
280 GBL_EXPORT GblType GBL_GLUE(GBL_GLUE(GBL_SELF_TYPE, _), type)(void) GBL_NOEXCEPT {
281 static GblType type = GBL_INVALID_TYPE;
282 const static GblTestCase cases[] = {
283 GBL_TUPLE_FOREACH(GBL_TEST_CASE_PAIR, GBL_GLUE(GBL_SELF_TYPE,_), (__VA_ARGS__))
284 { NULL, NULL }
285 };
286 const static GblTestSuiteVTable vTable = {
287 .pFnSuiteInit = GBL_GLUE(GBL_GLUE(GBL_GLUE(GBL_SELF_TYPE, _), init), _),
288 .pFnSuiteFinal = GBL_GLUE(GBL_GLUE(GBL_GLUE(GBL_SELF_TYPE, _), final), _),
289 .pCases = cases
290 };
291 if(type == GBL_INVALID_TYPE) {
292 GBL_CTX_BEGIN(NULL);
293 type = GblTestSuite_register(GblQuark_internStatic(GBL_STRINGIFY(GBL_SELF_TYPE)),
294 &vTable,
295 sizeof(GBL_SELF_TYPE),
296 sizeof(GBL_SELF_TYPE_PRIVATE),
297 GBL_TYPE_FLAGS_NONE);
300 }
301 return type; \
302}
303
304#define GBL_TEST_CASE_PAIR(suiteName, caseName)
305 { GBL_STRINGIFY(caseName), GBL_GLUE(GBL_GLUE(suiteName, caseName), _) },
306
307#define GBL_TEST_INIT() GBL_TEST_CASE(init)
308#define GBL_TEST_FINAL() GBL_TEST_CASE(final)
309#define GBL_TEST_INIT_NONE
312#define GBL_TEST_FINAL_NONE
315#define GBL_TEST_FIXTURE_NONE
316 GBL_TEST_FIXTURE { uintptr_t compat; };
317#define GBL_TEST_INIT_END GBL_TEST_CASE_END
318#define GBL_TEST_FINAL_END GBL_TEST_CASE_END
319
320#endif // GIMBAL_TEST_MACROS_H
#define GBL_NOEXCEPT
#define GBL_INLINE
#define GBL_CTX_VERIFY_CALL(...)
Definition gimbal_ctx.h:541
#define GBL_CTX_END_BLOCK()
Definition gimbal_ctx.h:569
#define GBL_CTX_VERIFY_LAST_RECORD()
Definition gimbal_ctx.h:162
#define GBL_CTX_BEGIN(...)
Definition gimbal_ctx.h:563
#define GBL_CTX_VERIFY_EXPRESSION(...)
Definition gimbal_ctx.h:113
#define GBL_CTX_END()
Definition gimbal_ctx.h:576
#define GBL_CTX_VERIFY(...)
Definition gimbal_ctx.h:99
#define GBL_CTX_CONTEXT()
Definition gimbal_ctx.h:25
#define GBL_UNUSED(...)
#define GBL_EXPORT
#define GBL_DECLARE_STRUCT(S)
#define GBL_STRINGIFY(a)
#define GBL_GLUE(A, B)
#define GBL_TUPLE_FOREACH(MACRO_, DATA_, TUPLE_)
#define GBL_STMT_START
#define GBL_STMT_END
#define GBL_RESULT_ERROR(value)
#define GBL_TEST_FIXTURE_TYPE
#define GBL_TEST_INIT()
#define GBL_SELF_TYPE_PRIVATE
#define GBL_TEST_CASE(name)
#define GBL_TEST_CASE_PAIR(suiteName, caseName)
#define GBL_TEST_REGISTER_(...)
#define GBL_SELF_TYPE_PRIVATE_NAME
#define GBL_TEST_CASE_END
#define GBL_SELF_TYPE_NAME
#define GBL_TEST_FAIL(...)
#define GBL_TEST_FIXTURE
#define GBL_TEST_FINAL()
#define GBL_TEST_CUSTOM_(name, enumType, expression,...)
#define GBL_TEST_SUITE_CONTEXT_NAME
#define GBL_TEST_SCENARIO(self)
Casts a GblInstance to a GblTestScenario.
#define GBL_INVALID_TYPE
GblType UUID of the invalid type.
Definition gimbal_type.h:31
#define GBL_FALSE
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)