Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/doctest/doctest.h
9896 views
1
// ====================================================================== lgtm [cpp/missing-header-guard]
2
// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! ==
3
// ======================================================================
4
//
5
// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD
6
//
7
// Copyright (c) 2016-2023 Viktor Kirilov
8
//
9
// Distributed under the MIT Software License
10
// See accompanying file LICENSE.txt or copy at
11
// https://opensource.org/licenses/MIT
12
//
13
// The documentation can be found at the library's page:
14
// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md
15
//
16
// =================================================================================================
17
// =================================================================================================
18
// =================================================================================================
19
//
20
// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2
21
// which uses the Boost Software License - Version 1.0
22
// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt
23
//
24
// The concept of subcases (sections in Catch) and expression decomposition are from there.
25
// Some parts of the code are taken directly:
26
// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<>
27
// - the Approx() helper class for floating point comparison
28
// - colors in the console
29
// - breaking into a debugger
30
// - signal / SEH handling
31
// - timer
32
// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste)
33
//
34
// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest
35
// which uses the Boost Software License - Version 1.0
36
// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt
37
//
38
// =================================================================================================
39
// =================================================================================================
40
// =================================================================================================
41
42
#ifndef DOCTEST_LIBRARY_INCLUDED
43
#define DOCTEST_LIBRARY_INCLUDED
44
45
// =================================================================================================
46
// == VERSION ======================================================================================
47
// =================================================================================================
48
49
#define DOCTEST_VERSION_MAJOR 2
50
#define DOCTEST_VERSION_MINOR 4
51
#define DOCTEST_VERSION_PATCH 12
52
53
// util we need here
54
#define DOCTEST_TOSTR_IMPL(x) #x
55
#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
56
57
#define DOCTEST_VERSION_STR \
58
DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
59
DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
60
DOCTEST_TOSTR(DOCTEST_VERSION_PATCH)
61
62
#define DOCTEST_VERSION \
63
(DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
64
65
// =================================================================================================
66
// == COMPILER VERSION =============================================================================
67
// =================================================================================================
68
69
// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect
70
71
#ifdef _MSC_VER
72
#define DOCTEST_CPLUSPLUS _MSVC_LANG
73
#else
74
#define DOCTEST_CPLUSPLUS __cplusplus
75
#endif
76
77
#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH))
78
79
// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
80
#if defined(_MSC_VER) && defined(_MSC_FULL_VER)
81
#if _MSC_VER == _MSC_FULL_VER / 10000
82
#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000)
83
#else // MSVC
84
#define DOCTEST_MSVC \
85
DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000)
86
#endif // MSVC
87
#endif // MSVC
88
#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__)
89
#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__)
90
#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \
91
!defined(__INTEL_COMPILER)
92
#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
93
#endif // GCC
94
#if defined(__INTEL_COMPILER)
95
#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
96
#endif // ICC
97
98
#ifndef DOCTEST_MSVC
99
#define DOCTEST_MSVC 0
100
#endif // DOCTEST_MSVC
101
#ifndef DOCTEST_CLANG
102
#define DOCTEST_CLANG 0
103
#endif // DOCTEST_CLANG
104
#ifndef DOCTEST_GCC
105
#define DOCTEST_GCC 0
106
#endif // DOCTEST_GCC
107
#ifndef DOCTEST_ICC
108
#define DOCTEST_ICC 0
109
#endif // DOCTEST_ICC
110
111
// =================================================================================================
112
// == COMPILER WARNINGS HELPERS ====================================================================
113
// =================================================================================================
114
115
#if DOCTEST_CLANG && !DOCTEST_ICC
116
#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
117
#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push")
118
#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w)
119
#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop")
120
#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \
121
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w)
122
#else // DOCTEST_CLANG
123
#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
124
#define DOCTEST_CLANG_SUPPRESS_WARNING(w)
125
#define DOCTEST_CLANG_SUPPRESS_WARNING_POP
126
#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w)
127
#endif // DOCTEST_CLANG
128
129
#if DOCTEST_GCC
130
#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x)
131
#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push")
132
#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w)
133
#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop")
134
#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \
135
DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w)
136
#else // DOCTEST_GCC
137
#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH
138
#define DOCTEST_GCC_SUPPRESS_WARNING(w)
139
#define DOCTEST_GCC_SUPPRESS_WARNING_POP
140
#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w)
141
#endif // DOCTEST_GCC
142
143
#if DOCTEST_MSVC
144
#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push))
145
#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w))
146
#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop))
147
#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \
148
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w)
149
#else // DOCTEST_MSVC
150
#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
151
#define DOCTEST_MSVC_SUPPRESS_WARNING(w)
152
#define DOCTEST_MSVC_SUPPRESS_WARNING_POP
153
#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w)
154
#endif // DOCTEST_MSVC
155
156
// =================================================================================================
157
// == COMPILER WARNINGS ============================================================================
158
// =================================================================================================
159
160
// both the header and the implementation suppress all of these,
161
// so it only makes sense to aggregate them like so
162
#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \
163
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \
164
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
165
DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \
166
DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \
167
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \
168
DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \
169
DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \
170
\
171
DOCTEST_GCC_SUPPRESS_WARNING_PUSH \
172
DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \
173
DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \
174
DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \
175
DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \
176
DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \
177
DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \
178
DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \
179
DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \
180
\
181
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
182
/* these 4 also disabled globally via cmake: */ \
183
DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \
184
DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
185
DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
186
DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
187
/* common ones */ \
188
DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
189
DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
190
DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
191
DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \
192
DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
193
DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \
194
DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
195
DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
196
DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
197
DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
198
DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
199
DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
200
DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
201
DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \
202
/* static analysis */ \
203
DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
204
DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
205
DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \
206
DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \
207
DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
208
209
#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \
210
DOCTEST_CLANG_SUPPRESS_WARNING_POP \
211
DOCTEST_GCC_SUPPRESS_WARNING_POP \
212
DOCTEST_MSVC_SUPPRESS_WARNING_POP
213
214
DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
215
216
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
217
DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
218
DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
219
220
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
221
DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
222
DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
223
DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
224
225
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
226
DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
227
228
#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
229
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
230
DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \
231
DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \
232
DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \
233
DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \
234
DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \
235
DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \
236
DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \
237
DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
238
DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
239
DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
240
DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
241
DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
242
DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \
243
DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
244
DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
245
DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \
246
DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \
247
DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */
248
249
#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
250
251
// =================================================================================================
252
// == FEATURE DETECTION ============================================================================
253
// =================================================================================================
254
255
// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support
256
// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx
257
// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
258
// MSVC version table:
259
// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
260
// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022)
261
// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
262
// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
263
// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
264
// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
265
// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
266
// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
267
// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
268
// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
269
270
// Universal Windows Platform support
271
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
272
#define DOCTEST_CONFIG_NO_WINDOWS_SEH
273
#endif // WINAPI_FAMILY
274
#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
275
#define DOCTEST_CONFIG_WINDOWS_SEH
276
#endif // MSVC
277
#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH)
278
#undef DOCTEST_CONFIG_WINDOWS_SEH
279
#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH
280
281
#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \
282
!defined(__EMSCRIPTEN__) && !defined(__wasi__)
283
#define DOCTEST_CONFIG_POSIX_SIGNALS
284
#endif // _WIN32
285
#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS)
286
#undef DOCTEST_CONFIG_POSIX_SIGNALS
287
#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS
288
289
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
290
#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \
291
|| defined(__wasi__)
292
#define DOCTEST_CONFIG_NO_EXCEPTIONS
293
#endif // no exceptions
294
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
295
296
#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
297
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
298
#define DOCTEST_CONFIG_NO_EXCEPTIONS
299
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
300
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
301
302
#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS)
303
#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
304
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
305
306
#ifdef __wasi__
307
#define DOCTEST_CONFIG_NO_MULTITHREADING
308
#endif
309
310
#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT)
311
#define DOCTEST_CONFIG_IMPLEMENT
312
#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
313
314
#if defined(_WIN32) || defined(__CYGWIN__)
315
#if DOCTEST_MSVC
316
#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport)
317
#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport)
318
#else // MSVC
319
#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport))
320
#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport))
321
#endif // MSVC
322
#else // _WIN32
323
#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default")))
324
#define DOCTEST_SYMBOL_IMPORT
325
#endif // _WIN32
326
327
#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
328
#ifdef DOCTEST_CONFIG_IMPLEMENT
329
#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT
330
#else // DOCTEST_CONFIG_IMPLEMENT
331
#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT
332
#endif // DOCTEST_CONFIG_IMPLEMENT
333
#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
334
#define DOCTEST_INTERFACE
335
#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
336
337
// needed for extern template instantiations
338
// see https://github.com/fmtlib/fmt/issues/2228
339
#if DOCTEST_MSVC
340
#define DOCTEST_INTERFACE_DECL
341
#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE
342
#else // DOCTEST_MSVC
343
#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE
344
#define DOCTEST_INTERFACE_DEF
345
#endif // DOCTEST_MSVC
346
347
#define DOCTEST_EMPTY
348
349
#if DOCTEST_MSVC
350
#define DOCTEST_NOINLINE __declspec(noinline)
351
#define DOCTEST_UNUSED
352
#define DOCTEST_ALIGNMENT(x)
353
#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0)
354
#define DOCTEST_NOINLINE
355
#define DOCTEST_UNUSED
356
#define DOCTEST_ALIGNMENT(x)
357
#else
358
#define DOCTEST_NOINLINE __attribute__((noinline))
359
#define DOCTEST_UNUSED __attribute__((unused))
360
#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x)))
361
#endif
362
363
#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE
364
#define DOCTEST_INLINE_NOINLINE inline
365
#else
366
#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE
367
#endif
368
369
#ifndef DOCTEST_NORETURN
370
#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
371
#define DOCTEST_NORETURN
372
#else // DOCTEST_MSVC
373
#define DOCTEST_NORETURN [[noreturn]]
374
#endif // DOCTEST_MSVC
375
#endif // DOCTEST_NORETURN
376
377
#ifndef DOCTEST_NOEXCEPT
378
#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
379
#define DOCTEST_NOEXCEPT
380
#else // DOCTEST_MSVC
381
#define DOCTEST_NOEXCEPT noexcept
382
#endif // DOCTEST_MSVC
383
#endif // DOCTEST_NOEXCEPT
384
385
#ifndef DOCTEST_CONSTEXPR
386
#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
387
#define DOCTEST_CONSTEXPR const
388
#define DOCTEST_CONSTEXPR_FUNC inline
389
#else // DOCTEST_MSVC
390
#define DOCTEST_CONSTEXPR constexpr
391
#define DOCTEST_CONSTEXPR_FUNC constexpr
392
#endif // DOCTEST_MSVC
393
#endif // DOCTEST_CONSTEXPR
394
395
#ifndef DOCTEST_NO_SANITIZE_INTEGER
396
#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0)
397
#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
398
#else
399
#define DOCTEST_NO_SANITIZE_INTEGER
400
#endif
401
#endif // DOCTEST_NO_SANITIZE_INTEGER
402
403
// =================================================================================================
404
// == FEATURE DETECTION END ========================================================================
405
// =================================================================================================
406
407
#define DOCTEST_DECLARE_INTERFACE(name) \
408
virtual ~name(); \
409
name() = default; \
410
name(const name&) = delete; \
411
name(name&&) = delete; \
412
name& operator=(const name&) = delete; \
413
name& operator=(name&&) = delete;
414
415
#define DOCTEST_DEFINE_INTERFACE(name) \
416
name::~name() = default;
417
418
// internal macros for string concatenation and anonymous variable name generation
419
#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
420
#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
421
#ifdef __COUNTER__ // not standard and may be missing for some compilers
422
#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__)
423
#else // __COUNTER__
424
#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
425
#endif // __COUNTER__
426
427
#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
428
#define DOCTEST_REF_WRAP(x) x&
429
#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
430
#define DOCTEST_REF_WRAP(x) x
431
#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
432
433
// not using __APPLE__ because... this is how Catch does it
434
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
435
#define DOCTEST_PLATFORM_MAC
436
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
437
#define DOCTEST_PLATFORM_IPHONE
438
#elif defined(_WIN32)
439
#define DOCTEST_PLATFORM_WINDOWS
440
#elif defined(__wasi__)
441
#define DOCTEST_PLATFORM_WASI
442
#else // DOCTEST_PLATFORM
443
#define DOCTEST_PLATFORM_LINUX
444
#endif // DOCTEST_PLATFORM
445
446
namespace doctest { namespace detail {
447
static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; }
448
}}
449
450
#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \
451
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
452
static const int var = doctest::detail::consume(&var, __VA_ARGS__); \
453
DOCTEST_CLANG_SUPPRESS_WARNING_POP
454
455
#ifndef DOCTEST_BREAK_INTO_DEBUGGER
456
// should probably take a look at https://github.com/scottt/debugbreak
457
#ifdef DOCTEST_PLATFORM_LINUX
458
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
459
// Break at the location of the failing check if possible
460
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
461
#else
462
#include <signal.h>
463
#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
464
#endif
465
#elif defined(DOCTEST_PLATFORM_MAC)
466
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
467
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
468
#elif defined(__ppc__) || defined(__ppc64__)
469
// https://www.cocoawithlove.com/2008/03/break-into-debugger.html
470
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler)
471
#else
472
#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler)
473
#endif
474
#elif DOCTEST_MSVC
475
#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
476
#elif defined(__MINGW32__)
477
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls")
478
extern "C" __declspec(dllimport) void __stdcall DebugBreak();
479
DOCTEST_GCC_SUPPRESS_WARNING_POP
480
#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak()
481
#else // linux
482
#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast<void>(0))
483
#endif // linux
484
#endif // DOCTEST_BREAK_INTO_DEBUGGER
485
486
// this is kept here for backwards compatibility since the config option was changed
487
#ifdef DOCTEST_CONFIG_USE_IOSFWD
488
#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
489
#define DOCTEST_CONFIG_USE_STD_HEADERS
490
#endif
491
#endif // DOCTEST_CONFIG_USE_IOSFWD
492
493
// for clang - always include <version> or <ciso646> (which drags some std stuff)
494
// because we want to check if we are using libc++ with the _LIBCPP_VERSION macro in
495
// which case we don't want to forward declare stuff from std - for reference:
496
// https://github.com/doctest/doctest/issues/126
497
// https://github.com/doctest/doctest/issues/356
498
#if DOCTEST_CLANG
499
#if DOCTEST_CPLUSPLUS >= 201703L && __has_include(<version>)
500
#include <version>
501
#else
502
#include <ciso646>
503
#endif
504
#endif // clang
505
506
#ifdef _LIBCPP_VERSION
507
#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
508
#define DOCTEST_CONFIG_USE_STD_HEADERS
509
#endif
510
#endif // _LIBCPP_VERSION
511
512
#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
513
#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
514
#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
515
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
516
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
517
#include <cstddef>
518
#include <ostream>
519
#include <istream>
520
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
521
#else // DOCTEST_CONFIG_USE_STD_HEADERS
522
523
// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
524
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
525
526
namespace std { // NOLINT(cert-dcl58-cpp)
527
typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using)
528
typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using)
529
template <class charT>
530
struct char_traits;
531
template <>
532
struct char_traits<char>;
533
template <class charT, class traits>
534
class basic_ostream; // NOLINT(fuchsia-virtual-inheritance)
535
typedef basic_ostream<char, char_traits<char>> ostream; // NOLINT(modernize-use-using)
536
template<class traits>
537
// NOLINTNEXTLINE
538
basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char*);
539
template <class charT, class traits>
540
class basic_istream;
541
typedef basic_istream<char, char_traits<char>> istream; // NOLINT(modernize-use-using)
542
template <class... Types>
543
class tuple;
544
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
545
// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
546
template <class Ty>
547
class allocator;
548
template <class Elem, class Traits, class Alloc>
549
class basic_string;
550
using string = basic_string<char, char_traits<char>, allocator<char>>;
551
#endif // VS 2019
552
} // namespace std
553
554
DOCTEST_MSVC_SUPPRESS_WARNING_POP
555
556
#endif // DOCTEST_CONFIG_USE_STD_HEADERS
557
558
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
559
#include <type_traits>
560
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
561
562
namespace doctest {
563
564
using std::size_t;
565
566
DOCTEST_INTERFACE extern bool is_running_in_test;
567
568
#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE
569
#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned
570
#endif
571
572
// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length
573
// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for:
574
// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128)
575
// - if small - capacity left before going on the heap - using the lowest 5 bits
576
// - if small - 2 bits are left unused - the second and third highest ones
577
// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator)
578
// and the "is small" bit remains "0" ("as well as the capacity left") so its OK
579
// Idea taken from this lecture about the string implementation of facebook/folly - fbstring
580
// https://www.youtube.com/watch?v=kPR8h4-qZdk
581
// TODO:
582
// - optimizations - like not deleting memory unnecessarily in operator= and etc.
583
// - resize/reserve/clear
584
// - replace
585
// - back/front
586
// - iterator stuff
587
// - find & friends
588
// - push_back/pop_back
589
// - assign/insert/erase
590
// - relational operators as free functions - taking const char* as one of the params
591
class DOCTEST_INTERFACE String
592
{
593
public:
594
using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE;
595
596
private:
597
static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members
598
static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members
599
600
struct view // len should be more than sizeof(view) - because of the final byte for flags
601
{
602
char* ptr;
603
size_type size;
604
size_type capacity;
605
};
606
607
union
608
{
609
char buf[len]; // NOLINT(*-avoid-c-arrays)
610
view data;
611
};
612
613
char* allocate(size_type sz);
614
615
bool isOnStack() const noexcept { return (buf[last] & 128) == 0; }
616
void setOnHeap() noexcept;
617
void setLast(size_type in = last) noexcept;
618
void setSize(size_type sz) noexcept;
619
620
void copy(const String& other);
621
622
public:
623
static DOCTEST_CONSTEXPR size_type npos = static_cast<size_type>(-1);
624
625
String() noexcept;
626
~String();
627
628
// cppcheck-suppress noExplicitConstructor
629
String(const char* in);
630
String(const char* in, size_type in_size);
631
632
String(std::istream& in, size_type in_size);
633
634
String(const String& other);
635
String& operator=(const String& other);
636
637
String& operator+=(const String& other);
638
639
String(String&& other) noexcept;
640
String& operator=(String&& other) noexcept;
641
642
char operator[](size_type i) const;
643
char& operator[](size_type i);
644
645
// the only functions I'm willing to leave in the interface - available for inlining
646
const char* c_str() const { return const_cast<String*>(this)->c_str(); } // NOLINT
647
char* c_str() {
648
if (isOnStack()) {
649
return reinterpret_cast<char*>(buf);
650
}
651
return data.ptr;
652
}
653
654
size_type size() const;
655
size_type capacity() const;
656
657
String substr(size_type pos, size_type cnt = npos) &&;
658
String substr(size_type pos, size_type cnt = npos) const &;
659
660
size_type find(char ch, size_type pos = 0) const;
661
size_type rfind(char ch, size_type pos = npos) const;
662
663
int compare(const char* other, bool no_case = false) const;
664
int compare(const String& other, bool no_case = false) const;
665
666
friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
667
};
668
669
DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs);
670
671
DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
672
DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
673
DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
674
DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs);
675
DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs);
676
DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs);
677
678
class DOCTEST_INTERFACE Contains {
679
public:
680
explicit Contains(const String& string);
681
682
bool checkWith(const String& other) const;
683
684
String string;
685
};
686
687
DOCTEST_INTERFACE String toString(const Contains& in);
688
689
DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs);
690
DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs);
691
DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs);
692
DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs);
693
694
namespace Color {
695
enum Enum
696
{
697
None = 0,
698
White,
699
Red,
700
Green,
701
Blue,
702
Cyan,
703
Yellow,
704
Grey,
705
706
Bright = 0x10,
707
708
BrightRed = Bright | Red,
709
BrightGreen = Bright | Green,
710
LightGrey = Bright | Grey,
711
BrightWhite = Bright | White
712
};
713
714
DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code);
715
} // namespace Color
716
717
namespace assertType {
718
enum Enum
719
{
720
// macro traits
721
722
is_warn = 1,
723
is_check = 2 * is_warn,
724
is_require = 2 * is_check,
725
726
is_normal = 2 * is_require,
727
is_throws = 2 * is_normal,
728
is_throws_as = 2 * is_throws,
729
is_throws_with = 2 * is_throws_as,
730
is_nothrow = 2 * is_throws_with,
731
732
is_false = 2 * is_nothrow,
733
is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types
734
735
is_eq = 2 * is_unary,
736
is_ne = 2 * is_eq,
737
738
is_lt = 2 * is_ne,
739
is_gt = 2 * is_lt,
740
741
is_ge = 2 * is_gt,
742
is_le = 2 * is_ge,
743
744
// macro types
745
746
DT_WARN = is_normal | is_warn,
747
DT_CHECK = is_normal | is_check,
748
DT_REQUIRE = is_normal | is_require,
749
750
DT_WARN_FALSE = is_normal | is_false | is_warn,
751
DT_CHECK_FALSE = is_normal | is_false | is_check,
752
DT_REQUIRE_FALSE = is_normal | is_false | is_require,
753
754
DT_WARN_THROWS = is_throws | is_warn,
755
DT_CHECK_THROWS = is_throws | is_check,
756
DT_REQUIRE_THROWS = is_throws | is_require,
757
758
DT_WARN_THROWS_AS = is_throws_as | is_warn,
759
DT_CHECK_THROWS_AS = is_throws_as | is_check,
760
DT_REQUIRE_THROWS_AS = is_throws_as | is_require,
761
762
DT_WARN_THROWS_WITH = is_throws_with | is_warn,
763
DT_CHECK_THROWS_WITH = is_throws_with | is_check,
764
DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
765
766
DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
767
DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
768
DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
769
770
DT_WARN_NOTHROW = is_nothrow | is_warn,
771
DT_CHECK_NOTHROW = is_nothrow | is_check,
772
DT_REQUIRE_NOTHROW = is_nothrow | is_require,
773
774
DT_WARN_EQ = is_normal | is_eq | is_warn,
775
DT_CHECK_EQ = is_normal | is_eq | is_check,
776
DT_REQUIRE_EQ = is_normal | is_eq | is_require,
777
778
DT_WARN_NE = is_normal | is_ne | is_warn,
779
DT_CHECK_NE = is_normal | is_ne | is_check,
780
DT_REQUIRE_NE = is_normal | is_ne | is_require,
781
782
DT_WARN_GT = is_normal | is_gt | is_warn,
783
DT_CHECK_GT = is_normal | is_gt | is_check,
784
DT_REQUIRE_GT = is_normal | is_gt | is_require,
785
786
DT_WARN_LT = is_normal | is_lt | is_warn,
787
DT_CHECK_LT = is_normal | is_lt | is_check,
788
DT_REQUIRE_LT = is_normal | is_lt | is_require,
789
790
DT_WARN_GE = is_normal | is_ge | is_warn,
791
DT_CHECK_GE = is_normal | is_ge | is_check,
792
DT_REQUIRE_GE = is_normal | is_ge | is_require,
793
794
DT_WARN_LE = is_normal | is_le | is_warn,
795
DT_CHECK_LE = is_normal | is_le | is_check,
796
DT_REQUIRE_LE = is_normal | is_le | is_require,
797
798
DT_WARN_UNARY = is_normal | is_unary | is_warn,
799
DT_CHECK_UNARY = is_normal | is_unary | is_check,
800
DT_REQUIRE_UNARY = is_normal | is_unary | is_require,
801
802
DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn,
803
DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check,
804
DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require,
805
};
806
} // namespace assertType
807
808
DOCTEST_INTERFACE const char* assertString(assertType::Enum at);
809
DOCTEST_INTERFACE const char* failureString(assertType::Enum at);
810
DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file);
811
812
struct DOCTEST_INTERFACE TestCaseData
813
{
814
String m_file; // the file in which the test was registered (using String - see #350)
815
unsigned m_line; // the line where the test was registered
816
const char* m_name; // name of the test case
817
const char* m_test_suite; // the test suite in which the test was added
818
const char* m_description;
819
bool m_skip;
820
bool m_no_breaks;
821
bool m_no_output;
822
bool m_may_fail;
823
bool m_should_fail;
824
int m_expected_failures;
825
double m_timeout;
826
};
827
828
struct DOCTEST_INTERFACE AssertData
829
{
830
// common - for all asserts
831
const TestCaseData* m_test_case;
832
assertType::Enum m_at;
833
const char* m_file;
834
int m_line;
835
const char* m_expr;
836
bool m_failed;
837
838
// exception-related - for all asserts
839
bool m_threw;
840
String m_exception;
841
842
// for normal asserts
843
String m_decomp;
844
845
// for specific exception-related asserts
846
bool m_threw_as;
847
const char* m_exception_type;
848
849
class DOCTEST_INTERFACE StringContains {
850
private:
851
Contains content;
852
bool isContains;
853
854
public:
855
StringContains(const String& str) : content(str), isContains(false) { }
856
StringContains(Contains cntn) : content(static_cast<Contains&&>(cntn)), isContains(true) { }
857
858
bool check(const String& str) { return isContains ? (content == str) : (content.string == str); }
859
860
operator const String&() const { return content.string; }
861
862
const char* c_str() const { return content.string.c_str(); }
863
} m_exception_string;
864
865
AssertData(assertType::Enum at, const char* file, int line, const char* expr,
866
const char* exception_type, const StringContains& exception_string);
867
};
868
869
struct DOCTEST_INTERFACE MessageData
870
{
871
String m_string;
872
const char* m_file;
873
int m_line;
874
assertType::Enum m_severity;
875
};
876
877
struct DOCTEST_INTERFACE SubcaseSignature
878
{
879
String m_name;
880
const char* m_file;
881
int m_line;
882
883
bool operator==(const SubcaseSignature& other) const;
884
bool operator<(const SubcaseSignature& other) const;
885
};
886
887
struct DOCTEST_INTERFACE IContextScope
888
{
889
DOCTEST_DECLARE_INTERFACE(IContextScope)
890
virtual void stringify(std::ostream*) const = 0;
891
};
892
893
namespace detail {
894
struct DOCTEST_INTERFACE TestCase;
895
} // namespace detail
896
897
struct ContextOptions //!OCLINT too many fields
898
{
899
std::ostream* cout = nullptr; // stdout stream
900
String binary_name; // the test binary name
901
902
const detail::TestCase* currentTest = nullptr;
903
904
// == parameters from the command line
905
String out; // output filename
906
String order_by; // how tests should be ordered
907
unsigned rand_seed; // the seed for rand ordering
908
909
unsigned first; // the first (matching) test to be executed
910
unsigned last; // the last (matching) test to be executed
911
912
int abort_after; // stop tests after this many failed assertions
913
int subcase_filter_levels; // apply the subcase filters for the first N levels
914
915
bool success; // include successful assertions in output
916
bool case_sensitive; // if filtering should be case sensitive
917
bool exit; // if the program should be exited after the tests are ran/whatever
918
bool duration; // print the time duration of each test case
919
bool minimal; // minimal console output (only test failures)
920
bool quiet; // no console output
921
bool no_throw; // to skip exceptions-related assertion macros
922
bool no_exitcode; // if the framework should return 0 as the exitcode
923
bool no_run; // to not run the tests at all (can be done with an "*" exclude)
924
bool no_intro; // to not print the intro of the framework
925
bool no_version; // to not print the version of the framework
926
bool no_colors; // if output to the console should be colorized
927
bool force_colors; // forces the use of colors even when a tty cannot be detected
928
bool no_breaks; // to not break into the debugger
929
bool no_skip; // don't skip test cases which are marked to be skipped
930
bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x):
931
bool no_path_in_filenames; // if the path to files should be removed from the output
932
String strip_file_prefixes;// remove the longest matching one of these prefixes from any file paths in the output
933
bool no_line_numbers; // if source code line numbers should be omitted from the output
934
bool no_debug_output; // no output in the debug console when a debugger is attached
935
bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!!
936
bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!!
937
938
bool help; // to print the help
939
bool version; // to print the version
940
bool count; // if only the count of matching tests is to be retrieved
941
bool list_test_cases; // to list all tests matching the filters
942
bool list_test_suites; // to list all suites matching the filters
943
bool list_reporters; // lists all registered reporters
944
};
945
946
namespace detail {
947
namespace types {
948
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
949
using namespace std;
950
#else
951
template <bool COND, typename T = void>
952
struct enable_if { };
953
954
template <typename T>
955
struct enable_if<true, T> { using type = T; };
956
957
struct true_type { static DOCTEST_CONSTEXPR bool value = true; };
958
struct false_type { static DOCTEST_CONSTEXPR bool value = false; };
959
960
template <typename T> struct remove_reference { using type = T; };
961
template <typename T> struct remove_reference<T&> { using type = T; };
962
template <typename T> struct remove_reference<T&&> { using type = T; };
963
964
template <typename T> struct is_rvalue_reference : false_type { };
965
template <typename T> struct is_rvalue_reference<T&&> : true_type { };
966
967
template<typename T> struct remove_const { using type = T; };
968
template <typename T> struct remove_const<const T> { using type = T; };
969
970
// Compiler intrinsics
971
template <typename T> struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); };
972
template <typename T> struct underlying_type { using type = __underlying_type(T); };
973
974
template <typename T> struct is_pointer : false_type { };
975
template <typename T> struct is_pointer<T*> : true_type { };
976
977
template <typename T> struct is_array : false_type { };
978
// NOLINTNEXTLINE(*-avoid-c-arrays)
979
template <typename T, size_t SIZE> struct is_array<T[SIZE]> : true_type { };
980
#endif
981
}
982
983
// <utility>
984
template <typename T>
985
T&& declval();
986
987
template <class T>
988
DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type& t) DOCTEST_NOEXCEPT {
989
return static_cast<T&&>(t);
990
}
991
992
template <class T>
993
DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type&& t) DOCTEST_NOEXCEPT {
994
return static_cast<T&&>(t);
995
}
996
997
template <typename T>
998
struct deferred_false : types::false_type { };
999
1000
// MSVS 2015 :(
1001
#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900
1002
template <typename T, typename = void>
1003
struct has_global_insertion_operator : types::false_type { };
1004
1005
template <typename T>
1006
struct has_global_insertion_operator<T, decltype(::operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
1007
1008
template <typename T, typename = void>
1009
struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator<T>::value; };
1010
1011
template <typename T, bool global>
1012
struct insert_hack;
1013
1014
template <typename T>
1015
struct insert_hack<T, true> {
1016
static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); }
1017
};
1018
1019
template <typename T>
1020
struct insert_hack<T, false> {
1021
static void insert(std::ostream& os, const T& t) { operator<<(os, t); }
1022
};
1023
1024
template <typename T>
1025
using insert_hack_t = insert_hack<T, has_global_insertion_operator<T>::value>;
1026
#else
1027
template <typename T, typename = void>
1028
struct has_insertion_operator : types::false_type { };
1029
#endif
1030
1031
template <typename T>
1032
struct has_insertion_operator<T, decltype(operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
1033
1034
template <typename T>
1035
struct should_stringify_as_underlying_type {
1036
static DOCTEST_CONSTEXPR bool value = detail::types::is_enum<T>::value && !doctest::detail::has_insertion_operator<T>::value;
1037
};
1038
1039
DOCTEST_INTERFACE std::ostream* tlssPush();
1040
DOCTEST_INTERFACE String tlssPop();
1041
1042
template <bool C>
1043
struct StringMakerBase {
1044
template <typename T>
1045
static String convert(const DOCTEST_REF_WRAP(T)) {
1046
#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES
1047
static_assert(deferred_false<T>::value, "No stringification detected for type T. See string conversion manual");
1048
#endif
1049
return "{?}";
1050
}
1051
};
1052
1053
template <typename T>
1054
struct filldata;
1055
1056
template <typename T>
1057
void filloss(std::ostream* stream, const T& in) {
1058
filldata<T>::fill(stream, in);
1059
}
1060
1061
template <typename T, size_t N>
1062
void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays)
1063
// T[N], T(&)[N], T(&&)[N] have same behaviour.
1064
// Hence remove reference.
1065
filloss<typename types::remove_reference<decltype(in)>::type>(stream, in);
1066
}
1067
1068
template <typename T>
1069
String toStream(const T& in) {
1070
std::ostream* stream = tlssPush();
1071
filloss(stream, in);
1072
return tlssPop();
1073
}
1074
1075
template <>
1076
struct StringMakerBase<true> {
1077
template <typename T>
1078
static String convert(const DOCTEST_REF_WRAP(T) in) {
1079
return toStream(in);
1080
}
1081
};
1082
} // namespace detail
1083
1084
template <typename T>
1085
struct StringMaker : public detail::StringMakerBase<
1086
detail::has_insertion_operator<T>::value || detail::types::is_pointer<T>::value || detail::types::is_array<T>::value>
1087
{};
1088
1089
#ifndef DOCTEST_STRINGIFY
1090
#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY
1091
#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__))
1092
#else
1093
#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__)
1094
#endif
1095
#endif
1096
1097
template <typename T>
1098
String toString() {
1099
#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0
1100
String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString<TYPE>(void)
1101
String::size_type beginPos = ret.find('<');
1102
return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast<String::size_type>(sizeof(">(void)")));
1103
#else
1104
String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE]
1105
String::size_type begin = ret.find('=') + 2;
1106
return ret.substr(begin, ret.size() - begin - 1);
1107
#endif
1108
}
1109
1110
template <typename T, typename detail::types::enable_if<!detail::should_stringify_as_underlying_type<T>::value, bool>::type = true>
1111
String toString(const DOCTEST_REF_WRAP(T) value) {
1112
return StringMaker<T>::convert(value);
1113
}
1114
1115
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1116
DOCTEST_INTERFACE String toString(const char* in);
1117
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1118
1119
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
1120
// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
1121
DOCTEST_INTERFACE String toString(const std::string& in);
1122
#endif // VS 2019
1123
1124
DOCTEST_INTERFACE String toString(String in);
1125
1126
DOCTEST_INTERFACE String toString(std::nullptr_t);
1127
1128
DOCTEST_INTERFACE String toString(bool in);
1129
1130
DOCTEST_INTERFACE String toString(float in);
1131
DOCTEST_INTERFACE String toString(double in);
1132
DOCTEST_INTERFACE String toString(double long in);
1133
1134
DOCTEST_INTERFACE String toString(char in);
1135
DOCTEST_INTERFACE String toString(char signed in);
1136
DOCTEST_INTERFACE String toString(char unsigned in);
1137
DOCTEST_INTERFACE String toString(short in);
1138
DOCTEST_INTERFACE String toString(short unsigned in);
1139
DOCTEST_INTERFACE String toString(signed in);
1140
DOCTEST_INTERFACE String toString(unsigned in);
1141
DOCTEST_INTERFACE String toString(long in);
1142
DOCTEST_INTERFACE String toString(long unsigned in);
1143
DOCTEST_INTERFACE String toString(long long in);
1144
DOCTEST_INTERFACE String toString(long long unsigned in);
1145
1146
template <typename T, typename detail::types::enable_if<detail::should_stringify_as_underlying_type<T>::value, bool>::type = true>
1147
String toString(const DOCTEST_REF_WRAP(T) value) {
1148
using UT = typename detail::types::underlying_type<T>::type;
1149
return (DOCTEST_STRINGIFY(static_cast<UT>(value)));
1150
}
1151
1152
namespace detail {
1153
template <typename T>
1154
struct filldata
1155
{
1156
static void fill(std::ostream* stream, const T& in) {
1157
#if defined(_MSC_VER) && _MSC_VER <= 1900
1158
insert_hack_t<T>::insert(*stream, in);
1159
#else
1160
operator<<(*stream, in);
1161
#endif
1162
}
1163
};
1164
1165
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
1166
// NOLINTBEGIN(*-avoid-c-arrays)
1167
template <typename T, size_t N>
1168
struct filldata<T[N]> {
1169
static void fill(std::ostream* stream, const T(&in)[N]) {
1170
*stream << "[";
1171
for (size_t i = 0; i < N; i++) {
1172
if (i != 0) { *stream << ", "; }
1173
*stream << (DOCTEST_STRINGIFY(in[i]));
1174
}
1175
*stream << "]";
1176
}
1177
};
1178
// NOLINTEND(*-avoid-c-arrays)
1179
DOCTEST_MSVC_SUPPRESS_WARNING_POP
1180
1181
// Specialized since we don't want the terminating null byte!
1182
// NOLINTBEGIN(*-avoid-c-arrays)
1183
template <size_t N>
1184
struct filldata<const char[N]> {
1185
static void fill(std::ostream* stream, const char (&in)[N]) {
1186
*stream << String(in, in[N - 1] ? N : N - 1);
1187
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
1188
};
1189
// NOLINTEND(*-avoid-c-arrays)
1190
1191
template <>
1192
struct filldata<const void*> {
1193
static void fill(std::ostream* stream, const void* in);
1194
};
1195
1196
template <typename T>
1197
struct filldata<T*> {
1198
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180)
1199
static void fill(std::ostream* stream, const T* in) {
1200
DOCTEST_MSVC_SUPPRESS_WARNING_POP
1201
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast")
1202
filldata<const void*>::fill(stream,
1203
#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0)
1204
reinterpret_cast<const void*>(in)
1205
#else
1206
*reinterpret_cast<const void* const*>(&in)
1207
#endif
1208
);
1209
DOCTEST_CLANG_SUPPRESS_WARNING_POP
1210
}
1211
};
1212
}
1213
1214
struct DOCTEST_INTERFACE Approx
1215
{
1216
Approx(double value);
1217
1218
Approx operator()(double value) const;
1219
1220
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1221
template <typename T>
1222
explicit Approx(const T& value,
1223
typename detail::types::enable_if<std::is_constructible<double, T>::value>::type* =
1224
static_cast<T*>(nullptr)) {
1225
*this = static_cast<double>(value);
1226
}
1227
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1228
1229
Approx& epsilon(double newEpsilon);
1230
1231
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1232
template <typename T>
1233
typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type epsilon(
1234
const T& newEpsilon) {
1235
m_epsilon = static_cast<double>(newEpsilon);
1236
return *this;
1237
}
1238
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1239
1240
Approx& scale(double newScale);
1241
1242
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1243
template <typename T>
1244
typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type scale(
1245
const T& newScale) {
1246
m_scale = static_cast<double>(newScale);
1247
return *this;
1248
}
1249
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1250
1251
// clang-format off
1252
DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs);
1253
DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs);
1254
DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs);
1255
DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs);
1256
DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs);
1257
DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs);
1258
DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs);
1259
DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs);
1260
DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs);
1261
DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs);
1262
DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs);
1263
DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs);
1264
1265
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1266
#define DOCTEST_APPROX_PREFIX \
1267
template <typename T> friend typename std::enable_if<std::is_constructible<double, T>::value, bool>::type
1268
1269
DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast<double>(lhs), rhs); }
1270
DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); }
1271
DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
1272
DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); }
1273
DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; }
1274
DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; }
1275
DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; }
1276
DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; }
1277
DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value && lhs != rhs; }
1278
DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) && lhs != rhs; }
1279
DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value && lhs != rhs; }
1280
DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) && lhs != rhs; }
1281
#undef DOCTEST_APPROX_PREFIX
1282
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
1283
1284
// clang-format on
1285
1286
double m_epsilon;
1287
double m_scale;
1288
double m_value;
1289
};
1290
1291
DOCTEST_INTERFACE String toString(const Approx& in);
1292
1293
DOCTEST_INTERFACE const ContextOptions* getContextOptions();
1294
1295
template <typename F>
1296
struct DOCTEST_INTERFACE_DECL IsNaN
1297
{
1298
F value; bool flipped;
1299
IsNaN(F f, bool flip = false) : value(f), flipped(flip) { }
1300
IsNaN<F> operator!() const { return { value, !flipped }; }
1301
operator bool() const;
1302
};
1303
#ifndef __MINGW32__
1304
extern template struct DOCTEST_INTERFACE_DECL IsNaN<float>;
1305
extern template struct DOCTEST_INTERFACE_DECL IsNaN<double>;
1306
extern template struct DOCTEST_INTERFACE_DECL IsNaN<long double>;
1307
#endif
1308
DOCTEST_INTERFACE String toString(IsNaN<float> in);
1309
DOCTEST_INTERFACE String toString(IsNaN<double> in);
1310
DOCTEST_INTERFACE String toString(IsNaN<double long> in);
1311
1312
#ifndef DOCTEST_CONFIG_DISABLE
1313
1314
namespace detail {
1315
// clang-format off
1316
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1317
template<class T> struct decay_array { using type = T; };
1318
template<class T, unsigned N> struct decay_array<T[N]> { using type = T*; };
1319
template<class T> struct decay_array<T[]> { using type = T*; };
1320
1321
template<class T> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; };
1322
template<> struct not_char_pointer<char*> { static DOCTEST_CONSTEXPR int value = 0; };
1323
template<> struct not_char_pointer<const char*> { static DOCTEST_CONSTEXPR int value = 0; };
1324
1325
template<class T> struct can_use_op : public not_char_pointer<typename decay_array<T>::type> {};
1326
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1327
// clang-format on
1328
1329
struct DOCTEST_INTERFACE TestFailureException
1330
{
1331
};
1332
1333
DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at);
1334
1335
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
1336
DOCTEST_NORETURN
1337
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
1338
DOCTEST_INTERFACE void throwException();
1339
1340
struct DOCTEST_INTERFACE Subcase
1341
{
1342
SubcaseSignature m_signature;
1343
bool m_entered = false;
1344
1345
Subcase(const String& name, const char* file, int line);
1346
Subcase(const Subcase&) = delete;
1347
Subcase(Subcase&&) = delete;
1348
Subcase& operator=(const Subcase&) = delete;
1349
Subcase& operator=(Subcase&&) = delete;
1350
~Subcase();
1351
1352
operator bool() const;
1353
1354
private:
1355
bool checkFilters();
1356
};
1357
1358
template <typename L, typename R>
1359
String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
1360
const DOCTEST_REF_WRAP(R) rhs) {
1361
return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs));
1362
}
1363
1364
#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
1365
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
1366
#endif
1367
1368
// This will check if there is any way it could find a operator like member or friend and uses it.
1369
// If not it doesn't find the operator or if the operator at global scope is defined after
1370
// this template, the template won't be instantiated due to SFINAE. Once the template is not
1371
// instantiated it can look for global operator using normal conversions.
1372
#ifdef __NVCC__
1373
#define SFINAE_OP(ret,op) ret
1374
#else
1375
#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval<L>() op doctest::detail::declval<R>()),ret{})
1376
#endif
1377
1378
#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
1379
template <typename R> \
1380
DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
1381
bool res = op_macro(doctest::detail::forward<const L>(lhs), doctest::detail::forward<R>(rhs)); \
1382
if(m_at & assertType::is_false) \
1383
res = !res; \
1384
if(!res || doctest::getContextOptions()->success) \
1385
return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \
1386
return Result(res); \
1387
}
1388
1389
// more checks could be added - like in Catch:
1390
// https://github.com/catchorg/Catch2/pull/1480/files
1391
// https://github.com/catchorg/Catch2/pull/1481/files
1392
#define DOCTEST_FORBIT_EXPRESSION(rt, op) \
1393
template <typename R> \
1394
rt& operator op(const R&) { \
1395
static_assert(deferred_false<R>::value, \
1396
"Expression Too Complex Please Rewrite As Binary Comparison!"); \
1397
return *this; \
1398
}
1399
1400
struct DOCTEST_INTERFACE Result // NOLINT(*-member-init)
1401
{
1402
bool m_passed;
1403
String m_decomp;
1404
1405
Result() = default; // TODO: Why do we need this? (To remove NOLINT)
1406
Result(bool passed, const String& decomposition = String());
1407
1408
// forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
1409
DOCTEST_FORBIT_EXPRESSION(Result, &)
1410
DOCTEST_FORBIT_EXPRESSION(Result, ^)
1411
DOCTEST_FORBIT_EXPRESSION(Result, |)
1412
DOCTEST_FORBIT_EXPRESSION(Result, &&)
1413
DOCTEST_FORBIT_EXPRESSION(Result, ||)
1414
DOCTEST_FORBIT_EXPRESSION(Result, ==)
1415
DOCTEST_FORBIT_EXPRESSION(Result, !=)
1416
DOCTEST_FORBIT_EXPRESSION(Result, <)
1417
DOCTEST_FORBIT_EXPRESSION(Result, >)
1418
DOCTEST_FORBIT_EXPRESSION(Result, <=)
1419
DOCTEST_FORBIT_EXPRESSION(Result, >=)
1420
DOCTEST_FORBIT_EXPRESSION(Result, =)
1421
DOCTEST_FORBIT_EXPRESSION(Result, +=)
1422
DOCTEST_FORBIT_EXPRESSION(Result, -=)
1423
DOCTEST_FORBIT_EXPRESSION(Result, *=)
1424
DOCTEST_FORBIT_EXPRESSION(Result, /=)
1425
DOCTEST_FORBIT_EXPRESSION(Result, %=)
1426
DOCTEST_FORBIT_EXPRESSION(Result, <<=)
1427
DOCTEST_FORBIT_EXPRESSION(Result, >>=)
1428
DOCTEST_FORBIT_EXPRESSION(Result, &=)
1429
DOCTEST_FORBIT_EXPRESSION(Result, ^=)
1430
DOCTEST_FORBIT_EXPRESSION(Result, |=)
1431
};
1432
1433
#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
1434
1435
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
1436
DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
1437
DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare")
1438
//DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion")
1439
//DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion")
1440
//DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal")
1441
1442
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
1443
DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
1444
DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare")
1445
//DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion")
1446
//DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
1447
//DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
1448
1449
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
1450
// https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389
1451
DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch
1452
DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch
1453
DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch
1454
//DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation
1455
1456
#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
1457
1458
// clang-format off
1459
#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1460
#define DOCTEST_COMPARISON_RETURN_TYPE bool
1461
#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1462
#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
1463
inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
1464
inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
1465
inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
1466
inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); }
1467
inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); }
1468
inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); }
1469
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1470
// clang-format on
1471
1472
#define DOCTEST_RELATIONAL_OP(name, op) \
1473
template <typename L, typename R> \
1474
DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \
1475
const DOCTEST_REF_WRAP(R) rhs) { \
1476
return lhs op rhs; \
1477
}
1478
1479
DOCTEST_RELATIONAL_OP(eq, ==)
1480
DOCTEST_RELATIONAL_OP(ne, !=)
1481
DOCTEST_RELATIONAL_OP(lt, <)
1482
DOCTEST_RELATIONAL_OP(gt, >)
1483
DOCTEST_RELATIONAL_OP(le, <=)
1484
DOCTEST_RELATIONAL_OP(ge, >=)
1485
1486
#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1487
#define DOCTEST_CMP_EQ(l, r) l == r
1488
#define DOCTEST_CMP_NE(l, r) l != r
1489
#define DOCTEST_CMP_GT(l, r) l > r
1490
#define DOCTEST_CMP_LT(l, r) l < r
1491
#define DOCTEST_CMP_GE(l, r) l >= r
1492
#define DOCTEST_CMP_LE(l, r) l <= r
1493
#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1494
#define DOCTEST_CMP_EQ(l, r) eq(l, r)
1495
#define DOCTEST_CMP_NE(l, r) ne(l, r)
1496
#define DOCTEST_CMP_GT(l, r) gt(l, r)
1497
#define DOCTEST_CMP_LT(l, r) lt(l, r)
1498
#define DOCTEST_CMP_GE(l, r) ge(l, r)
1499
#define DOCTEST_CMP_LE(l, r) le(l, r)
1500
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
1501
1502
template <typename L>
1503
// cppcheck-suppress copyCtorAndEqOperator
1504
struct Expression_lhs
1505
{
1506
L lhs;
1507
assertType::Enum m_at;
1508
1509
explicit Expression_lhs(L&& in, assertType::Enum at)
1510
: lhs(static_cast<L&&>(in))
1511
, m_at(at) {}
1512
1513
DOCTEST_NOINLINE operator Result() {
1514
// this is needed only for MSVC 2015
1515
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
1516
bool res = static_cast<bool>(lhs);
1517
DOCTEST_MSVC_SUPPRESS_WARNING_POP
1518
if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
1519
res = !res;
1520
}
1521
1522
if(!res || getContextOptions()->success) {
1523
return { res, (DOCTEST_STRINGIFY(lhs)) };
1524
}
1525
return { res };
1526
}
1527
1528
/* This is required for user-defined conversions from Expression_lhs to L */
1529
operator L() const { return lhs; }
1530
1531
// clang-format off
1532
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
1533
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional
1534
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional
1535
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional
1536
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional
1537
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional
1538
// clang-format on
1539
1540
// forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
1541
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &)
1542
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^)
1543
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |)
1544
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&)
1545
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||)
1546
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =)
1547
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=)
1548
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=)
1549
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=)
1550
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=)
1551
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=)
1552
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=)
1553
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=)
1554
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=)
1555
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=)
1556
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=)
1557
// these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the
1558
// ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression...
1559
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<)
1560
DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>)
1561
};
1562
1563
#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
1564
1565
DOCTEST_CLANG_SUPPRESS_WARNING_POP
1566
DOCTEST_MSVC_SUPPRESS_WARNING_POP
1567
DOCTEST_GCC_SUPPRESS_WARNING_POP
1568
1569
#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION
1570
1571
#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
1572
DOCTEST_CLANG_SUPPRESS_WARNING_POP
1573
#endif
1574
1575
struct DOCTEST_INTERFACE ExpressionDecomposer
1576
{
1577
assertType::Enum m_at;
1578
1579
ExpressionDecomposer(assertType::Enum at);
1580
1581
// The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table)
1582
// but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now...
1583
// https://github.com/catchorg/Catch2/issues/870
1584
// https://github.com/catchorg/Catch2/issues/565
1585
template <typename L>
1586
Expression_lhs<const L&&> operator<<(const L&& operand) { //bitfields bind to universal ref but not const rvalue ref
1587
return Expression_lhs<const L&&>(static_cast<const L&&>(operand), m_at);
1588
}
1589
1590
template <typename L,typename types::enable_if<!doctest::detail::types::is_rvalue_reference<L>::value,void >::type* = nullptr>
1591
Expression_lhs<const L&> operator<<(const L &operand) {
1592
return Expression_lhs<const L&>(operand, m_at);
1593
}
1594
};
1595
1596
struct DOCTEST_INTERFACE TestSuite
1597
{
1598
const char* m_test_suite = nullptr;
1599
const char* m_description = nullptr;
1600
bool m_skip = false;
1601
bool m_no_breaks = false;
1602
bool m_no_output = false;
1603
bool m_may_fail = false;
1604
bool m_should_fail = false;
1605
int m_expected_failures = 0;
1606
double m_timeout = 0;
1607
1608
TestSuite& operator*(const char* in);
1609
1610
template <typename T>
1611
TestSuite& operator*(const T& in) {
1612
in.fill(*this);
1613
return *this;
1614
}
1615
};
1616
1617
using funcType = void (*)();
1618
1619
struct DOCTEST_INTERFACE TestCase : public TestCaseData
1620
{
1621
funcType m_test; // a function pointer to the test case
1622
1623
String m_type; // for templated test cases - gets appended to the real name
1624
int m_template_id; // an ID used to distinguish between the different versions of a templated test case
1625
String m_full_name; // contains the name (only for templated test cases!) + the template type
1626
1627
TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
1628
const String& type = String(), int template_id = -1);
1629
1630
TestCase(const TestCase& other);
1631
TestCase(TestCase&&) = delete;
1632
1633
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
1634
TestCase& operator=(const TestCase& other);
1635
DOCTEST_MSVC_SUPPRESS_WARNING_POP
1636
1637
TestCase& operator=(TestCase&&) = delete;
1638
1639
TestCase& operator*(const char* in);
1640
1641
template <typename T>
1642
TestCase& operator*(const T& in) {
1643
in.fill(*this);
1644
return *this;
1645
}
1646
1647
bool operator<(const TestCase& other) const;
1648
1649
~TestCase() = default;
1650
};
1651
1652
// forward declarations of functions used by the macros
1653
DOCTEST_INTERFACE int regTest(const TestCase& tc);
1654
DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts);
1655
DOCTEST_INTERFACE bool isDebuggerActive();
1656
1657
template<typename T>
1658
int instantiationHelper(const T&) { return 0; }
1659
1660
namespace binaryAssertComparison {
1661
enum Enum
1662
{
1663
eq = 0,
1664
ne,
1665
gt,
1666
lt,
1667
ge,
1668
le
1669
};
1670
} // namespace binaryAssertComparison
1671
1672
// clang-format off
1673
template <int, class L, class R> struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } };
1674
1675
#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \
1676
template <class L, class R> struct RelationalComparator<n, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } };
1677
// clang-format on
1678
1679
DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq)
1680
DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne)
1681
DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt)
1682
DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt)
1683
DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge)
1684
DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le)
1685
1686
struct DOCTEST_INTERFACE ResultBuilder : public AssertData
1687
{
1688
ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
1689
const char* exception_type = "", const String& exception_string = "");
1690
1691
ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
1692
const char* exception_type, const Contains& exception_string);
1693
1694
void setResult(const Result& res);
1695
1696
template <int comparison, typename L, typename R>
1697
DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs,
1698
const DOCTEST_REF_WRAP(R) rhs) {
1699
m_failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
1700
if (m_failed || getContextOptions()->success) {
1701
m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
1702
}
1703
return !m_failed;
1704
}
1705
1706
template <typename L>
1707
DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) {
1708
m_failed = !val;
1709
1710
if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
1711
m_failed = !m_failed;
1712
}
1713
1714
if (m_failed || getContextOptions()->success) {
1715
m_decomp = (DOCTEST_STRINGIFY(val));
1716
}
1717
1718
return !m_failed;
1719
}
1720
1721
void translateException();
1722
1723
bool log();
1724
void react() const;
1725
};
1726
1727
namespace assertAction {
1728
enum Enum
1729
{
1730
nothing = 0,
1731
dbgbreak = 1,
1732
shouldthrow = 2
1733
};
1734
} // namespace assertAction
1735
1736
DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad);
1737
1738
DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line,
1739
const char* expr, const Result& result);
1740
1741
#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \
1742
do { \
1743
if(!is_running_in_test) { \
1744
if(failed) { \
1745
ResultBuilder rb(at, file, line, expr); \
1746
rb.m_failed = failed; \
1747
rb.m_decomp = decomp; \
1748
failed_out_of_a_testing_context(rb); \
1749
if(isDebuggerActive() && !getContextOptions()->no_breaks) \
1750
DOCTEST_BREAK_INTO_DEBUGGER(); \
1751
if(checkIfShouldThrow(at)) \
1752
throwException(); \
1753
} \
1754
return !failed; \
1755
} \
1756
} while(false)
1757
1758
#define DOCTEST_ASSERT_IN_TESTS(decomp) \
1759
ResultBuilder rb(at, file, line, expr); \
1760
rb.m_failed = failed; \
1761
if(rb.m_failed || getContextOptions()->success) \
1762
rb.m_decomp = decomp; \
1763
if(rb.log()) \
1764
DOCTEST_BREAK_INTO_DEBUGGER(); \
1765
if(rb.m_failed && checkIfShouldThrow(at)) \
1766
throwException()
1767
1768
template <int comparison, typename L, typename R>
1769
DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line,
1770
const char* expr, const DOCTEST_REF_WRAP(L) lhs,
1771
const DOCTEST_REF_WRAP(R) rhs) {
1772
bool failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
1773
1774
// ###################################################################################
1775
// IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
1776
// THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
1777
// ###################################################################################
1778
DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
1779
DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
1780
return !failed;
1781
}
1782
1783
template <typename L>
1784
DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line,
1785
const char* expr, const DOCTEST_REF_WRAP(L) val) {
1786
bool failed = !val;
1787
1788
if(at & assertType::is_false) //!OCLINT bitwise operator in conditional
1789
failed = !failed;
1790
1791
// ###################################################################################
1792
// IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
1793
// THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
1794
// ###################################################################################
1795
DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val)));
1796
DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val)));
1797
return !failed;
1798
}
1799
1800
struct DOCTEST_INTERFACE IExceptionTranslator
1801
{
1802
DOCTEST_DECLARE_INTERFACE(IExceptionTranslator)
1803
virtual bool translate(String&) const = 0;
1804
};
1805
1806
template <typename T>
1807
class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class
1808
{
1809
public:
1810
explicit ExceptionTranslator(String (*translateFunction)(T))
1811
: m_translateFunction(translateFunction) {}
1812
1813
bool translate(String& res) const override {
1814
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
1815
try {
1816
throw; // lgtm [cpp/rethrow-no-exception]
1817
// cppcheck-suppress catchExceptionByValue
1818
} catch(const T& ex) {
1819
res = m_translateFunction(ex); //!OCLINT parameter reassignment
1820
return true;
1821
} catch(...) {} //!OCLINT - empty catch statement
1822
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
1823
static_cast<void>(res); // to silence -Wunused-parameter
1824
return false;
1825
}
1826
1827
private:
1828
String (*m_translateFunction)(T);
1829
};
1830
1831
DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
1832
1833
// ContextScope base class used to allow implementing methods of ContextScope
1834
// that don't depend on the template parameter in doctest.cpp.
1835
struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
1836
ContextScopeBase(const ContextScopeBase&) = delete;
1837
1838
ContextScopeBase& operator=(const ContextScopeBase&) = delete;
1839
ContextScopeBase& operator=(ContextScopeBase&&) = delete;
1840
1841
~ContextScopeBase() override = default;
1842
1843
protected:
1844
ContextScopeBase();
1845
ContextScopeBase(ContextScopeBase&& other) noexcept;
1846
1847
void destroy();
1848
bool need_to_destroy{true};
1849
};
1850
1851
template <typename L> class ContextScope : public ContextScopeBase
1852
{
1853
L lambda_;
1854
1855
public:
1856
explicit ContextScope(const L &lambda) : lambda_(lambda) {}
1857
explicit ContextScope(L&& lambda) : lambda_(static_cast<L&&>(lambda)) { }
1858
1859
ContextScope(const ContextScope&) = delete;
1860
ContextScope(ContextScope&&) noexcept = default;
1861
1862
ContextScope& operator=(const ContextScope&) = delete;
1863
ContextScope& operator=(ContextScope&&) = delete;
1864
1865
void stringify(std::ostream* s) const override { lambda_(s); }
1866
1867
~ContextScope() override {
1868
if (need_to_destroy) {
1869
destroy();
1870
}
1871
}
1872
};
1873
1874
struct DOCTEST_INTERFACE MessageBuilder : public MessageData
1875
{
1876
std::ostream* m_stream;
1877
bool logged = false;
1878
1879
MessageBuilder(const char* file, int line, assertType::Enum severity);
1880
1881
MessageBuilder(const MessageBuilder&) = delete;
1882
MessageBuilder(MessageBuilder&&) = delete;
1883
1884
MessageBuilder& operator=(const MessageBuilder&) = delete;
1885
MessageBuilder& operator=(MessageBuilder&&) = delete;
1886
1887
~MessageBuilder();
1888
1889
// the preferred way of chaining parameters for stringification
1890
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
1891
template <typename T>
1892
MessageBuilder& operator,(const T& in) {
1893
*m_stream << (DOCTEST_STRINGIFY(in));
1894
return *this;
1895
}
1896
DOCTEST_MSVC_SUPPRESS_WARNING_POP
1897
1898
// kept here just for backwards-compatibility - the comma operator should be preferred now
1899
template <typename T>
1900
MessageBuilder& operator<<(const T& in) { return this->operator,(in); }
1901
1902
// the `,` operator has the lowest operator precedence - if `<<` is used by the user then
1903
// the `,` operator will be called last which is not what we want and thus the `*` operator
1904
// is used first (has higher operator precedence compared to `<<`) so that we guarantee that
1905
// an operator of the MessageBuilder class is called first before the rest of the parameters
1906
template <typename T>
1907
MessageBuilder& operator*(const T& in) { return this->operator,(in); }
1908
1909
bool log();
1910
void react();
1911
};
1912
1913
template <typename L>
1914
ContextScope<L> MakeContextScope(const L &lambda) {
1915
return ContextScope<L>(lambda);
1916
}
1917
} // namespace detail
1918
1919
#define DOCTEST_DEFINE_DECORATOR(name, type, def) \
1920
struct name \
1921
{ \
1922
type data; \
1923
name(type in = def) \
1924
: data(in) {} \
1925
void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \
1926
void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \
1927
}
1928
1929
DOCTEST_DEFINE_DECORATOR(test_suite, const char*, "");
1930
DOCTEST_DEFINE_DECORATOR(description, const char*, "");
1931
DOCTEST_DEFINE_DECORATOR(skip, bool, true);
1932
DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true);
1933
DOCTEST_DEFINE_DECORATOR(no_output, bool, true);
1934
DOCTEST_DEFINE_DECORATOR(timeout, double, 0);
1935
DOCTEST_DEFINE_DECORATOR(may_fail, bool, true);
1936
DOCTEST_DEFINE_DECORATOR(should_fail, bool, true);
1937
DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0);
1938
1939
template <typename T>
1940
int registerExceptionTranslator(String (*translateFunction)(T)) {
1941
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors")
1942
static detail::ExceptionTranslator<T> exceptionTranslator(translateFunction);
1943
DOCTEST_CLANG_SUPPRESS_WARNING_POP
1944
detail::registerExceptionTranslatorImpl(&exceptionTranslator);
1945
return 0;
1946
}
1947
1948
} // namespace doctest
1949
1950
// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro
1951
// introduces an anonymous namespace in which getCurrentTestSuite gets overridden
1952
namespace doctest_detail_test_suite_ns {
1953
DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite();
1954
} // namespace doctest_detail_test_suite_ns
1955
1956
namespace doctest {
1957
#else // DOCTEST_CONFIG_DISABLE
1958
template <typename T>
1959
int registerExceptionTranslator(String (*)(T)) {
1960
return 0;
1961
}
1962
#endif // DOCTEST_CONFIG_DISABLE
1963
1964
namespace detail {
1965
using assert_handler = void (*)(const AssertData&);
1966
struct ContextState;
1967
} // namespace detail
1968
1969
class DOCTEST_INTERFACE Context
1970
{
1971
detail::ContextState* p;
1972
1973
void parseArgs(int argc, const char* const* argv, bool withDefaults = false);
1974
1975
public:
1976
explicit Context(int argc = 0, const char* const* argv = nullptr);
1977
1978
Context(const Context&) = delete;
1979
Context(Context&&) = delete;
1980
1981
Context& operator=(const Context&) = delete;
1982
Context& operator=(Context&&) = delete;
1983
1984
~Context(); // NOLINT(performance-trivially-destructible)
1985
1986
void applyCommandLine(int argc, const char* const* argv);
1987
1988
void addFilter(const char* filter, const char* value);
1989
void clearFilters();
1990
void setOption(const char* option, bool value);
1991
void setOption(const char* option, int value);
1992
void setOption(const char* option, const char* value);
1993
1994
bool shouldExit();
1995
1996
void setAsDefaultForAssertsOutOfTestCases();
1997
1998
void setAssertHandler(detail::assert_handler ah);
1999
2000
void setCout(std::ostream* out);
2001
2002
int run();
2003
};
2004
2005
namespace TestCaseFailureReason {
2006
enum Enum
2007
{
2008
None = 0,
2009
AssertFailure = 1, // an assertion has failed in the test case
2010
Exception = 2, // test case threw an exception
2011
Crash = 4, // a crash...
2012
TooManyFailedAsserts = 8, // the abort-after option
2013
Timeout = 16, // see the timeout decorator
2014
ShouldHaveFailedButDidnt = 32, // see the should_fail decorator
2015
ShouldHaveFailedAndDid = 64, // see the should_fail decorator
2016
DidntFailExactlyNumTimes = 128, // see the expected_failures decorator
2017
FailedExactlyNumTimes = 256, // see the expected_failures decorator
2018
CouldHaveFailedAndDid = 512 // see the may_fail decorator
2019
};
2020
} // namespace TestCaseFailureReason
2021
2022
struct DOCTEST_INTERFACE CurrentTestCaseStats
2023
{
2024
int numAssertsCurrentTest;
2025
int numAssertsFailedCurrentTest;
2026
double seconds;
2027
int failure_flags; // use TestCaseFailureReason::Enum
2028
bool testCaseSuccess;
2029
};
2030
2031
struct DOCTEST_INTERFACE TestCaseException
2032
{
2033
String error_string;
2034
bool is_crash;
2035
};
2036
2037
struct DOCTEST_INTERFACE TestRunStats
2038
{
2039
unsigned numTestCases;
2040
unsigned numTestCasesPassingFilters;
2041
unsigned numTestSuitesPassingFilters;
2042
unsigned numTestCasesFailed;
2043
int numAsserts;
2044
int numAssertsFailed;
2045
};
2046
2047
struct QueryData
2048
{
2049
const TestRunStats* run_stats = nullptr;
2050
const TestCaseData** data = nullptr;
2051
unsigned num_data = 0;
2052
};
2053
2054
struct DOCTEST_INTERFACE IReporter
2055
{
2056
// The constructor has to accept "const ContextOptions&" as a single argument
2057
// which has most of the options for the run + a pointer to the stdout stream
2058
// Reporter(const ContextOptions& in)
2059
2060
// called when a query should be reported (listing test cases, printing the version, etc.)
2061
virtual void report_query(const QueryData&) = 0;
2062
2063
// called when the whole test run starts
2064
virtual void test_run_start() = 0;
2065
// called when the whole test run ends (caching a pointer to the input doesn't make sense here)
2066
virtual void test_run_end(const TestRunStats&) = 0;
2067
2068
// called when a test case is started (safe to cache a pointer to the input)
2069
virtual void test_case_start(const TestCaseData&) = 0;
2070
// called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input)
2071
virtual void test_case_reenter(const TestCaseData&) = 0;
2072
// called when a test case has ended
2073
virtual void test_case_end(const CurrentTestCaseStats&) = 0;
2074
2075
// called when an exception is thrown from the test case (or it crashes)
2076
virtual void test_case_exception(const TestCaseException&) = 0;
2077
2078
// called whenever a subcase is entered (don't cache pointers to the input)
2079
virtual void subcase_start(const SubcaseSignature&) = 0;
2080
// called whenever a subcase is exited (don't cache pointers to the input)
2081
virtual void subcase_end() = 0;
2082
2083
// called for each assert (don't cache pointers to the input)
2084
virtual void log_assert(const AssertData&) = 0;
2085
// called for each message (don't cache pointers to the input)
2086
virtual void log_message(const MessageData&) = 0;
2087
2088
// called when a test case is skipped either because it doesn't pass the filters, has a skip decorator
2089
// or isn't in the execution range (between first and last) (safe to cache a pointer to the input)
2090
virtual void test_case_skipped(const TestCaseData&) = 0;
2091
2092
DOCTEST_DECLARE_INTERFACE(IReporter)
2093
2094
// can obtain all currently active contexts and stringify them if one wishes to do so
2095
static int get_num_active_contexts();
2096
static const IContextScope* const* get_active_contexts();
2097
2098
// can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown
2099
static int get_num_stringified_contexts();
2100
static const String* get_stringified_contexts();
2101
};
2102
2103
namespace detail {
2104
using reporterCreatorFunc = IReporter* (*)(const ContextOptions&);
2105
2106
DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter);
2107
2108
template <typename Reporter>
2109
IReporter* reporterCreator(const ContextOptions& o) {
2110
return new Reporter(o);
2111
}
2112
} // namespace detail
2113
2114
template <typename Reporter>
2115
int registerReporter(const char* name, int priority, bool isReporter) {
2116
detail::registerReporterImpl(name, priority, detail::reporterCreator<Reporter>, isReporter);
2117
return 0;
2118
}
2119
} // namespace doctest
2120
2121
#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
2122
#define DOCTEST_FUNC_EMPTY [] { return false; }()
2123
#else
2124
#define DOCTEST_FUNC_EMPTY (void)0
2125
#endif
2126
2127
// if registering is not disabled
2128
#ifndef DOCTEST_CONFIG_DISABLE
2129
2130
#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
2131
#define DOCTEST_FUNC_SCOPE_BEGIN [&]
2132
#define DOCTEST_FUNC_SCOPE_END ()
2133
#define DOCTEST_FUNC_SCOPE_RET(v) return v
2134
#else
2135
#define DOCTEST_FUNC_SCOPE_BEGIN do
2136
#define DOCTEST_FUNC_SCOPE_END while(false)
2137
#define DOCTEST_FUNC_SCOPE_RET(v) (void)0
2138
#endif
2139
2140
// common code in asserts - for convenience
2141
#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \
2142
if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \
2143
b.react(); \
2144
DOCTEST_FUNC_SCOPE_RET(!b.m_failed)
2145
2146
#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
2147
#define DOCTEST_WRAP_IN_TRY(x) x;
2148
#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
2149
#define DOCTEST_WRAP_IN_TRY(x) \
2150
try { \
2151
x; \
2152
} catch(...) { DOCTEST_RB.translateException(); }
2153
#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
2154
2155
#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
2156
#define DOCTEST_CAST_TO_VOID(...) \
2157
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \
2158
static_cast<void>(__VA_ARGS__); \
2159
DOCTEST_GCC_SUPPRESS_WARNING_POP
2160
#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
2161
#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__;
2162
#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
2163
2164
// registers the test by initializing a dummy var with a function
2165
#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \
2166
global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \
2167
doctest::detail::regTest( \
2168
doctest::detail::TestCase( \
2169
f, __FILE__, __LINE__, \
2170
doctest_detail_test_suite_ns::getCurrentTestSuite()) * \
2171
decorators))
2172
2173
#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \
2174
namespace { /* NOLINT */ \
2175
struct der : public base \
2176
{ \
2177
void f(); \
2178
}; \
2179
static DOCTEST_INLINE_NOINLINE void func() { \
2180
der v; \
2181
v.f(); \
2182
} \
2183
DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \
2184
} \
2185
DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers)
2186
2187
#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \
2188
static void f(); \
2189
DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \
2190
static void f()
2191
2192
#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \
2193
static doctest::detail::funcType proxy() { return f; } \
2194
DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \
2195
static void f()
2196
2197
// for registering tests
2198
#define DOCTEST_TEST_CASE(decorators) \
2199
DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
2200
2201
// for registering tests in classes - requires C++17 for inline variables!
2202
#if DOCTEST_CPLUSPLUS >= 201703L
2203
#define DOCTEST_TEST_CASE_CLASS(decorators) \
2204
DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \
2205
DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \
2206
decorators)
2207
#else // DOCTEST_TEST_CASE_CLASS
2208
#define DOCTEST_TEST_CASE_CLASS(...) \
2209
TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER
2210
#endif // DOCTEST_TEST_CASE_CLASS
2211
2212
// for registering tests with a fixture
2213
#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \
2214
DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \
2215
DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
2216
2217
// for converting types to strings without the <typeinfo> header and demangling
2218
#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \
2219
namespace doctest { \
2220
template <> \
2221
inline String toString<__VA_ARGS__>() { \
2222
return str; \
2223
} \
2224
} \
2225
static_assert(true, "")
2226
2227
#define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__)
2228
2229
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
2230
template <typename T> \
2231
static void func(); \
2232
namespace { /* NOLINT */ \
2233
template <typename Tuple> \
2234
struct iter; \
2235
template <typename Type, typename... Rest> \
2236
struct iter<std::tuple<Type, Rest...>> \
2237
{ \
2238
iter(const char* file, unsigned line, int index) { \
2239
doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line, \
2240
doctest_detail_test_suite_ns::getCurrentTestSuite(), \
2241
doctest::toString<Type>(), \
2242
int(line) * 1000 + index) \
2243
* dec); \
2244
iter<std::tuple<Rest...>>(file, line, index + 1); \
2245
} \
2246
}; \
2247
template <> \
2248
struct iter<std::tuple<>> \
2249
{ \
2250
iter(const char*, unsigned, int) {} \
2251
}; \
2252
} \
2253
template <typename T> \
2254
static void func()
2255
2256
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \
2257
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
2258
DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_))
2259
2260
#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
2261
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \
2262
doctest::detail::instantiationHelper( \
2263
DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0)))
2264
2265
#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
2266
DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
2267
static_assert(true, "")
2268
2269
#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
2270
DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \
2271
static_assert(true, "")
2272
2273
#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
2274
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
2275
DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \
2276
template <typename T> \
2277
static void anon()
2278
2279
#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \
2280
DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__)
2281
2282
// for subcases
2283
#define DOCTEST_SUBCASE(name) \
2284
if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \
2285
doctest::detail::Subcase(name, __FILE__, __LINE__))
2286
2287
// for grouping tests in test suites by using code blocks
2288
#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \
2289
namespace ns_name { namespace doctest_detail_test_suite_ns { \
2290
static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \
2291
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \
2292
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \
2293
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \
2294
static doctest::detail::TestSuite data{}; \
2295
static bool inited = false; \
2296
DOCTEST_MSVC_SUPPRESS_WARNING_POP \
2297
DOCTEST_CLANG_SUPPRESS_WARNING_POP \
2298
DOCTEST_GCC_SUPPRESS_WARNING_POP \
2299
if(!inited) { \
2300
data* decorators; \
2301
inited = true; \
2302
} \
2303
return data; \
2304
} \
2305
} \
2306
} \
2307
namespace ns_name
2308
2309
#define DOCTEST_TEST_SUITE(decorators) \
2310
DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_))
2311
2312
// for starting a testsuite block
2313
#define DOCTEST_TEST_SUITE_BEGIN(decorators) \
2314
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \
2315
doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \
2316
static_assert(true, "")
2317
2318
// for ending a testsuite block
2319
#define DOCTEST_TEST_SUITE_END \
2320
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \
2321
doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \
2322
using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
2323
2324
// for registering exception translators
2325
#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \
2326
inline doctest::String translatorName(signature); \
2327
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \
2328
doctest::registerExceptionTranslator(translatorName)) \
2329
doctest::String translatorName(signature)
2330
2331
#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
2332
DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \
2333
signature)
2334
2335
// for registering reporters
2336
#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \
2337
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
2338
doctest::registerReporter<reporter>(name, priority, true)) \
2339
static_assert(true, "")
2340
2341
// for registering listeners
2342
#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \
2343
DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
2344
doctest::registerReporter<reporter>(name, priority, false)) \
2345
static_assert(true, "")
2346
2347
// clang-format off
2348
// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557
2349
#define DOCTEST_INFO(...) \
2350
DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \
2351
DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \
2352
__VA_ARGS__)
2353
// clang-format on
2354
2355
#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \
2356
auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \
2357
[&](std::ostream* s_name) { \
2358
doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
2359
mb_name.m_stream = s_name; \
2360
mb_name * __VA_ARGS__; \
2361
})
2362
2363
#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x)
2364
2365
#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \
2366
DOCTEST_FUNC_SCOPE_BEGIN { \
2367
doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \
2368
mb * __VA_ARGS__; \
2369
if(mb.log()) \
2370
DOCTEST_BREAK_INTO_DEBUGGER(); \
2371
mb.react(); \
2372
} DOCTEST_FUNC_SCOPE_END
2373
2374
// clang-format off
2375
#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
2376
#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
2377
#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
2378
// clang-format on
2379
2380
#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__)
2381
#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__)
2382
#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__)
2383
2384
#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility.
2385
2386
#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
2387
2388
#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \
2389
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
2390
/* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \
2391
doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
2392
__LINE__, #__VA_ARGS__); \
2393
DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \
2394
doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
2395
<< __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \
2396
DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \
2397
DOCTEST_CLANG_SUPPRESS_WARNING_POP
2398
2399
#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
2400
DOCTEST_FUNC_SCOPE_BEGIN { \
2401
DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \
2402
} DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
2403
2404
#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \
2405
DOCTEST_FUNC_SCOPE_BEGIN { \
2406
doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
2407
__LINE__, #__VA_ARGS__); \
2408
DOCTEST_WRAP_IN_TRY( \
2409
DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>( \
2410
__VA_ARGS__)) \
2411
DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
2412
} DOCTEST_FUNC_SCOPE_END
2413
2414
#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
2415
DOCTEST_FUNC_SCOPE_BEGIN { \
2416
doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
2417
__LINE__, #__VA_ARGS__); \
2418
DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \
2419
DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
2420
} DOCTEST_FUNC_SCOPE_END
2421
2422
#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
2423
2424
// necessary for <ASSERT>_MESSAGE
2425
#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1
2426
2427
#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
2428
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
2429
doctest::detail::decomp_assert( \
2430
doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \
2431
doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
2432
<< __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP
2433
2434
#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \
2435
doctest::detail::binary_assert<doctest::detail::binaryAssertComparison::comparison>( \
2436
doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__)
2437
2438
#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
2439
doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \
2440
#__VA_ARGS__, __VA_ARGS__)
2441
2442
#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
2443
2444
#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__)
2445
#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__)
2446
#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__)
2447
#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__)
2448
#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__)
2449
#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__)
2450
2451
// clang-format off
2452
#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END
2453
#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END
2454
#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END
2455
#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
2456
#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
2457
#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
2458
// clang-format on
2459
2460
#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__)
2461
#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__)
2462
#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__)
2463
#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__)
2464
#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__)
2465
#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__)
2466
#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__)
2467
#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__)
2468
#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__)
2469
#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__)
2470
#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__)
2471
#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__)
2472
#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__)
2473
#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__)
2474
#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__)
2475
#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__)
2476
#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__)
2477
#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__)
2478
2479
#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__)
2480
#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__)
2481
#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__)
2482
#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__)
2483
#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__)
2484
#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__)
2485
2486
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
2487
2488
#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \
2489
DOCTEST_FUNC_SCOPE_BEGIN { \
2490
if(!doctest::getContextOptions()->no_throw) { \
2491
doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
2492
__LINE__, #expr, #__VA_ARGS__, message); \
2493
try { \
2494
DOCTEST_CAST_TO_VOID(expr) \
2495
} catch(const typename doctest::detail::types::remove_const< \
2496
typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\
2497
DOCTEST_RB.translateException(); \
2498
DOCTEST_RB.m_threw_as = true; \
2499
} catch(...) { DOCTEST_RB.translateException(); } \
2500
DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
2501
} else { /* NOLINT(*-else-after-return) */ \
2502
DOCTEST_FUNC_SCOPE_RET(false); \
2503
} \
2504
} DOCTEST_FUNC_SCOPE_END
2505
2506
#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \
2507
DOCTEST_FUNC_SCOPE_BEGIN { \
2508
if(!doctest::getContextOptions()->no_throw) { \
2509
doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
2510
__LINE__, expr_str, "", __VA_ARGS__); \
2511
try { \
2512
DOCTEST_CAST_TO_VOID(expr) \
2513
} catch(...) { DOCTEST_RB.translateException(); } \
2514
DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
2515
} else { /* NOLINT(*-else-after-return) */ \
2516
DOCTEST_FUNC_SCOPE_RET(false); \
2517
} \
2518
} DOCTEST_FUNC_SCOPE_END
2519
2520
#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \
2521
DOCTEST_FUNC_SCOPE_BEGIN { \
2522
doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
2523
__LINE__, #__VA_ARGS__); \
2524
try { \
2525
DOCTEST_CAST_TO_VOID(__VA_ARGS__) \
2526
} catch(...) { DOCTEST_RB.translateException(); } \
2527
DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
2528
} DOCTEST_FUNC_SCOPE_END
2529
2530
// clang-format off
2531
#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "")
2532
#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "")
2533
#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "")
2534
2535
#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__)
2536
#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__)
2537
#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__)
2538
2539
#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__)
2540
#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__)
2541
#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__)
2542
2543
#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__)
2544
#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__)
2545
#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__)
2546
2547
#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__)
2548
#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__)
2549
#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__)
2550
2551
#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
2552
#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
2553
#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
2554
#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
2555
#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
2556
#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
2557
#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
2558
#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
2559
#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
2560
#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
2561
#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
2562
#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
2563
#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
2564
#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
2565
#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
2566
// clang-format on
2567
2568
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
2569
2570
// =================================================================================================
2571
// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! ==
2572
// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! ==
2573
// =================================================================================================
2574
#else // DOCTEST_CONFIG_DISABLE
2575
2576
#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
2577
namespace /* NOLINT */ { \
2578
template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
2579
struct der : public base \
2580
{ void f(); }; \
2581
} \
2582
template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
2583
inline void der<DOCTEST_UNUSED_TEMPLATE_TYPE>::f()
2584
2585
#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \
2586
template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
2587
static inline void f()
2588
2589
// for registering tests
2590
#define DOCTEST_TEST_CASE(name) \
2591
DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
2592
2593
// for registering tests in classes
2594
#define DOCTEST_TEST_CASE_CLASS(name) \
2595
DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
2596
2597
// for registering tests with a fixture
2598
#define DOCTEST_TEST_CASE_FIXTURE(x, name) \
2599
DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \
2600
DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
2601
2602
// for converting types to strings without the <typeinfo> header and demangling
2603
#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "")
2604
#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "")
2605
2606
// for typed tests
2607
#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \
2608
template <typename type> \
2609
inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
2610
2611
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \
2612
template <typename type> \
2613
inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
2614
2615
#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "")
2616
#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "")
2617
2618
// for subcases
2619
#define DOCTEST_SUBCASE(name)
2620
2621
// for a testsuite block
2622
#define DOCTEST_TEST_SUITE(name) namespace // NOLINT
2623
2624
// for starting a testsuite block
2625
#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "")
2626
2627
// for ending a testsuite block
2628
#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
2629
2630
#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
2631
template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
2632
static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature)
2633
2634
#define DOCTEST_REGISTER_REPORTER(name, priority, reporter)
2635
#define DOCTEST_REGISTER_LISTENER(name, priority, reporter)
2636
2637
#define DOCTEST_INFO(...) (static_cast<void>(0))
2638
#define DOCTEST_CAPTURE(x) (static_cast<void>(0))
2639
#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast<void>(0))
2640
#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast<void>(0))
2641
#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast<void>(0))
2642
#define DOCTEST_MESSAGE(...) (static_cast<void>(0))
2643
#define DOCTEST_FAIL_CHECK(...) (static_cast<void>(0))
2644
#define DOCTEST_FAIL(...) (static_cast<void>(0))
2645
2646
#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \
2647
&& defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES)
2648
2649
#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }()
2650
#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }()
2651
#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }()
2652
#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }()
2653
#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }()
2654
#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }()
2655
2656
#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }()
2657
#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }()
2658
#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }()
2659
#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
2660
#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
2661
#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
2662
2663
namespace doctest {
2664
namespace detail {
2665
#define DOCTEST_RELATIONAL_OP(name, op) \
2666
template <typename L, typename R> \
2667
bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; }
2668
2669
DOCTEST_RELATIONAL_OP(eq, ==)
2670
DOCTEST_RELATIONAL_OP(ne, !=)
2671
DOCTEST_RELATIONAL_OP(lt, <)
2672
DOCTEST_RELATIONAL_OP(gt, >)
2673
DOCTEST_RELATIONAL_OP(le, <=)
2674
DOCTEST_RELATIONAL_OP(ge, >=)
2675
} // namespace detail
2676
} // namespace doctest
2677
2678
#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
2679
#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
2680
#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
2681
#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
2682
#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
2683
#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
2684
#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
2685
#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
2686
#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
2687
#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
2688
#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
2689
#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
2690
#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
2691
#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
2692
#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
2693
#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
2694
#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
2695
#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
2696
#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }()
2697
#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }()
2698
#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }()
2699
#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
2700
#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
2701
#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
2702
2703
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
2704
2705
#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }()
2706
#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
2707
#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
2708
#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
2709
#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
2710
#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
2711
2712
#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
2713
#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
2714
#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
2715
#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
2716
#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
2717
#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
2718
2719
#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
2720
#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
2721
#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
2722
#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
2723
#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
2724
#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
2725
#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
2726
#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
2727
#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
2728
2729
#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
2730
#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
2731
#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
2732
#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
2733
#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
2734
#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
2735
#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
2736
#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
2737
#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
2738
2739
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
2740
2741
#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
2742
2743
#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY
2744
#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY
2745
#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY
2746
#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY
2747
#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY
2748
#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY
2749
2750
#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
2751
#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
2752
#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
2753
#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
2754
#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
2755
#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
2756
2757
#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY
2758
#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY
2759
#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY
2760
#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY
2761
#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY
2762
#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY
2763
#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY
2764
#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY
2765
#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY
2766
#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY
2767
#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY
2768
#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY
2769
#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY
2770
#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY
2771
#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY
2772
#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY
2773
#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY
2774
#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY
2775
2776
#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY
2777
#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY
2778
#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY
2779
#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
2780
#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
2781
#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
2782
2783
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
2784
2785
#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY
2786
#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY
2787
#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY
2788
#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
2789
#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
2790
#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
2791
#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
2792
#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
2793
#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
2794
#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
2795
#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
2796
#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
2797
#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY
2798
#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY
2799
#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY
2800
2801
#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
2802
#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
2803
#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
2804
#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
2805
#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
2806
#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
2807
#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
2808
#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
2809
#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
2810
#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
2811
#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
2812
#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
2813
#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
2814
#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
2815
#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
2816
2817
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
2818
2819
#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
2820
2821
#endif // DOCTEST_CONFIG_DISABLE
2822
2823
#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
2824
2825
#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
2826
#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY
2827
#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
2828
#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \
2829
"Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }()
2830
2831
#undef DOCTEST_REQUIRE
2832
#undef DOCTEST_REQUIRE_FALSE
2833
#undef DOCTEST_REQUIRE_MESSAGE
2834
#undef DOCTEST_REQUIRE_FALSE_MESSAGE
2835
#undef DOCTEST_REQUIRE_EQ
2836
#undef DOCTEST_REQUIRE_NE
2837
#undef DOCTEST_REQUIRE_GT
2838
#undef DOCTEST_REQUIRE_LT
2839
#undef DOCTEST_REQUIRE_GE
2840
#undef DOCTEST_REQUIRE_LE
2841
#undef DOCTEST_REQUIRE_UNARY
2842
#undef DOCTEST_REQUIRE_UNARY_FALSE
2843
2844
#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC
2845
#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
2846
#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
2847
#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
2848
#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC
2849
#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC
2850
#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC
2851
#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC
2852
#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC
2853
#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC
2854
#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC
2855
#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
2856
2857
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
2858
2859
#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
2860
#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
2861
#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
2862
#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2863
#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2864
#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2865
#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2866
#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2867
#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2868
#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2869
#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2870
#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2871
#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
2872
#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
2873
#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
2874
2875
#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2876
#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2877
#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2878
#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2879
#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2880
#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2881
#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2882
#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2883
#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2884
#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2885
#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2886
#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2887
#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2888
#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2889
#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
2890
2891
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
2892
2893
// clang-format off
2894
// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS
2895
#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ
2896
#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ
2897
#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ
2898
#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE
2899
#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE
2900
#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE
2901
#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT
2902
#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT
2903
#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT
2904
#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT
2905
#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT
2906
#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT
2907
#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE
2908
#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE
2909
#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE
2910
#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE
2911
#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE
2912
#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE
2913
2914
#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY
2915
#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY
2916
#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY
2917
#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE
2918
#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE
2919
#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE
2920
2921
#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__)
2922
// clang-format on
2923
2924
// BDD style macros
2925
// clang-format off
2926
#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name)
2927
#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name)
2928
#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__)
2929
#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id)
2930
2931
#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name)
2932
#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name)
2933
#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name)
2934
#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name)
2935
#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name)
2936
// clang-format on
2937
2938
// == SHORT VERSIONS OF THE MACROS
2939
#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
2940
2941
#define TEST_CASE(name) DOCTEST_TEST_CASE(name)
2942
#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name)
2943
#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name)
2944
#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__)
2945
#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__)
2946
#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__)
2947
#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id)
2948
#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__)
2949
#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__)
2950
#define SUBCASE(name) DOCTEST_SUBCASE(name)
2951
#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators)
2952
#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name)
2953
#define TEST_SUITE_END DOCTEST_TEST_SUITE_END
2954
#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature)
2955
#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter)
2956
#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter)
2957
#define INFO(...) DOCTEST_INFO(__VA_ARGS__)
2958
#define CAPTURE(x) DOCTEST_CAPTURE(x)
2959
#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__)
2960
#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__)
2961
#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__)
2962
#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__)
2963
#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__)
2964
#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__)
2965
#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__)
2966
2967
#define WARN(...) DOCTEST_WARN(__VA_ARGS__)
2968
#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__)
2969
#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__)
2970
#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__)
2971
#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__)
2972
#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__)
2973
#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__)
2974
#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__)
2975
#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__)
2976
#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__)
2977
#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__)
2978
#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__)
2979
#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__)
2980
#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__)
2981
#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__)
2982
#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__)
2983
#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__)
2984
#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__)
2985
#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__)
2986
#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__)
2987
#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__)
2988
2989
#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__)
2990
#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__)
2991
#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__)
2992
#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
2993
#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
2994
#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
2995
#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__)
2996
#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__)
2997
#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__)
2998
#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__)
2999
#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
3000
#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
3001
#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
3002
#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__)
3003
#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__)
3004
#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__)
3005
#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__)
3006
#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__)
3007
#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__)
3008
#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__)
3009
#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__)
3010
3011
#define SCENARIO(name) DOCTEST_SCENARIO(name)
3012
#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name)
3013
#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__)
3014
#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id)
3015
#define GIVEN(name) DOCTEST_GIVEN(name)
3016
#define WHEN(name) DOCTEST_WHEN(name)
3017
#define AND_WHEN(name) DOCTEST_AND_WHEN(name)
3018
#define THEN(name) DOCTEST_THEN(name)
3019
#define AND_THEN(name) DOCTEST_AND_THEN(name)
3020
3021
#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__)
3022
#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__)
3023
#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__)
3024
#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__)
3025
#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__)
3026
#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__)
3027
#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__)
3028
#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__)
3029
#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__)
3030
#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__)
3031
#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__)
3032
#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__)
3033
#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__)
3034
#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__)
3035
#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__)
3036
#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__)
3037
#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__)
3038
#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__)
3039
#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__)
3040
#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__)
3041
#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__)
3042
#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__)
3043
#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__)
3044
#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
3045
3046
// KEPT FOR BACKWARDS COMPATIBILITY
3047
#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__)
3048
#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__)
3049
#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__)
3050
#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__)
3051
#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__)
3052
#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__)
3053
#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__)
3054
#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__)
3055
#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__)
3056
#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__)
3057
#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__)
3058
#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__)
3059
#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__)
3060
#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__)
3061
#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__)
3062
#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__)
3063
#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__)
3064
#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__)
3065
3066
#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__)
3067
#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__)
3068
#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__)
3069
#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__)
3070
#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__)
3071
#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__)
3072
3073
#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__)
3074
3075
#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
3076
3077
#ifndef DOCTEST_CONFIG_DISABLE
3078
3079
// this is here to clear the 'current test suite' for the current translation unit - at the top
3080
DOCTEST_TEST_SUITE_END();
3081
3082
#endif // DOCTEST_CONFIG_DISABLE
3083
3084
DOCTEST_CLANG_SUPPRESS_WARNING_POP
3085
DOCTEST_MSVC_SUPPRESS_WARNING_POP
3086
DOCTEST_GCC_SUPPRESS_WARNING_POP
3087
3088
DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
3089
3090
#endif // DOCTEST_LIBRARY_INCLUDED
3091
3092
#ifndef DOCTEST_SINGLE_HEADER
3093
#define DOCTEST_SINGLE_HEADER
3094
#endif // DOCTEST_SINGLE_HEADER
3095
3096
#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER)
3097
3098
#ifndef DOCTEST_SINGLE_HEADER
3099
#include "doctest_fwd.h"
3100
#endif // DOCTEST_SINGLE_HEADER
3101
3102
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros")
3103
3104
#ifndef DOCTEST_LIBRARY_IMPLEMENTATION
3105
#define DOCTEST_LIBRARY_IMPLEMENTATION
3106
3107
DOCTEST_CLANG_SUPPRESS_WARNING_POP
3108
3109
DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
3110
3111
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
3112
DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors")
3113
DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
3114
DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
3115
DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32")
3116
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations")
3117
DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch")
3118
DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum")
3119
DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default")
3120
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn")
3121
DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion")
3122
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces")
3123
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers")
3124
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
3125
DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path")
3126
3127
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
3128
DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
3129
DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
3130
DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers")
3131
DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces")
3132
DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch")
3133
DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum")
3134
DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default")
3135
DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations")
3136
DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast")
3137
DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function")
3138
DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance")
3139
DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute")
3140
3141
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
3142
DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data
3143
DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled
3144
DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified
3145
DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal
3146
DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch
3147
DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C
3148
DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning)
3149
DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed
3150
3151
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
3152
3153
// required includes - will go only in one translation unit!
3154
#include <ctime>
3155
#include <cmath>
3156
#include <climits>
3157
// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37
3158
#ifdef __BORLANDC__
3159
#include <math.h>
3160
#endif // __BORLANDC__
3161
#include <new>
3162
#include <cstdio>
3163
#include <cstdlib>
3164
#include <cstring>
3165
#include <limits>
3166
#include <utility>
3167
#include <fstream>
3168
#include <sstream>
3169
#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
3170
#include <iostream>
3171
#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
3172
#include <algorithm>
3173
#include <iomanip>
3174
#include <vector>
3175
#ifndef DOCTEST_CONFIG_NO_MULTITHREADING
3176
#include <atomic>
3177
#include <mutex>
3178
#define DOCTEST_DECLARE_MUTEX(name) std::mutex name;
3179
#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name)
3180
#define DOCTEST_LOCK_MUTEX(name) std::lock_guard<std::mutex> DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name);
3181
#else // DOCTEST_CONFIG_NO_MULTITHREADING
3182
#define DOCTEST_DECLARE_MUTEX(name)
3183
#define DOCTEST_DECLARE_STATIC_MUTEX(name)
3184
#define DOCTEST_LOCK_MUTEX(name)
3185
#endif // DOCTEST_CONFIG_NO_MULTITHREADING
3186
#include <set>
3187
#include <map>
3188
#include <unordered_set>
3189
#include <exception>
3190
#include <stdexcept>
3191
#include <csignal>
3192
#include <cfloat>
3193
#include <cctype>
3194
#include <cstdint>
3195
#include <string>
3196
3197
#ifdef DOCTEST_PLATFORM_MAC
3198
#include <sys/types.h>
3199
#include <unistd.h>
3200
#include <sys/sysctl.h>
3201
#endif // DOCTEST_PLATFORM_MAC
3202
3203
#ifdef DOCTEST_PLATFORM_WINDOWS
3204
3205
// defines for a leaner windows.h
3206
#ifndef WIN32_LEAN_AND_MEAN
3207
#define WIN32_LEAN_AND_MEAN
3208
#define DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
3209
#endif // WIN32_LEAN_AND_MEAN
3210
#ifndef NOMINMAX
3211
#define NOMINMAX
3212
#define DOCTEST_UNDEF_NOMINMAX
3213
#endif // NOMINMAX
3214
3215
// not sure what AfxWin.h is for - here I do what Catch does
3216
#ifdef __AFXDLL
3217
#include <AfxWin.h>
3218
#else
3219
#include <windows.h>
3220
#endif
3221
#include <io.h>
3222
3223
#else // DOCTEST_PLATFORM_WINDOWS
3224
3225
#include <sys/time.h>
3226
#include <unistd.h>
3227
3228
#endif // DOCTEST_PLATFORM_WINDOWS
3229
3230
// this is a fix for https://github.com/doctest/doctest/issues/348
3231
// https://mail.gnome.org/archives/xml/2012-January/msg00000.html
3232
#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO)
3233
#define STDOUT_FILENO fileno(stdout)
3234
#endif // HAVE_UNISTD_H
3235
3236
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
3237
3238
// counts the number of elements in a C array
3239
#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
3240
3241
#ifdef DOCTEST_CONFIG_DISABLE
3242
#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled
3243
#else // DOCTEST_CONFIG_DISABLE
3244
#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled
3245
#endif // DOCTEST_CONFIG_DISABLE
3246
3247
#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX
3248
#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-"
3249
#endif
3250
3251
#ifndef DOCTEST_CONFIG_OPTIONS_FILE_PREFIX_SEPARATOR
3252
#define DOCTEST_CONFIG_OPTIONS_FILE_PREFIX_SEPARATOR ':'
3253
#endif
3254
3255
#ifndef DOCTEST_THREAD_LOCAL
3256
#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
3257
#define DOCTEST_THREAD_LOCAL
3258
#else // DOCTEST_MSVC
3259
#define DOCTEST_THREAD_LOCAL thread_local
3260
#endif // DOCTEST_MSVC
3261
#endif // DOCTEST_THREAD_LOCAL
3262
3263
#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES
3264
#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32
3265
#endif
3266
3267
#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE
3268
#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64
3269
#endif
3270
3271
#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
3272
#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX
3273
#else
3274
#define DOCTEST_OPTIONS_PREFIX_DISPLAY ""
3275
#endif
3276
3277
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
3278
#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
3279
#endif
3280
3281
#ifndef DOCTEST_CDECL
3282
#define DOCTEST_CDECL __cdecl
3283
#endif
3284
3285
namespace doctest {
3286
3287
bool is_running_in_test = false;
3288
3289
namespace {
3290
using namespace detail;
3291
3292
template <typename Ex>
3293
DOCTEST_NORETURN void throw_exception(Ex const& e) {
3294
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
3295
throw e;
3296
#else // DOCTEST_CONFIG_NO_EXCEPTIONS
3297
#ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION
3298
DOCTEST_CONFIG_HANDLE_EXCEPTION(e);
3299
#else // DOCTEST_CONFIG_HANDLE_EXCEPTION
3300
#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
3301
std::cerr << "doctest will terminate because it needed to throw an exception.\n"
3302
<< "The message was: " << e.what() << '\n';
3303
#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
3304
#endif // DOCTEST_CONFIG_HANDLE_EXCEPTION
3305
std::terminate();
3306
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
3307
}
3308
3309
#ifndef DOCTEST_INTERNAL_ERROR
3310
#define DOCTEST_INTERNAL_ERROR(msg) \
3311
throw_exception(std::logic_error( \
3312
__FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
3313
#endif // DOCTEST_INTERNAL_ERROR
3314
3315
// case insensitive strcmp
3316
int stricmp(const char* a, const char* b) {
3317
for(;; a++, b++) {
3318
const int d = tolower(*a) - tolower(*b);
3319
if(d != 0 || !*a)
3320
return d;
3321
}
3322
}
3323
3324
struct Endianness
3325
{
3326
enum Arch
3327
{
3328
Big,
3329
Little
3330
};
3331
3332
static Arch which() {
3333
int x = 1;
3334
// casting any data pointer to char* is allowed
3335
auto ptr = reinterpret_cast<char*>(&x);
3336
if(*ptr)
3337
return Little;
3338
return Big;
3339
}
3340
};
3341
} // namespace
3342
3343
namespace detail {
3344
DOCTEST_THREAD_LOCAL class
3345
{
3346
std::vector<std::streampos> stack;
3347
std::stringstream ss;
3348
3349
public:
3350
std::ostream* push() {
3351
stack.push_back(ss.tellp());
3352
return &ss;
3353
}
3354
3355
String pop() {
3356
if (stack.empty())
3357
DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!");
3358
3359
std::streampos pos = stack.back();
3360
stack.pop_back();
3361
unsigned sz = static_cast<unsigned>(ss.tellp() - pos);
3362
ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out);
3363
return String(ss, sz);
3364
}
3365
} g_oss;
3366
3367
std::ostream* tlssPush() {
3368
return g_oss.push();
3369
}
3370
3371
String tlssPop() {
3372
return g_oss.pop();
3373
}
3374
3375
#ifndef DOCTEST_CONFIG_DISABLE
3376
3377
namespace timer_large_integer
3378
{
3379
3380
#if defined(DOCTEST_PLATFORM_WINDOWS)
3381
using type = ULONGLONG;
3382
#else // DOCTEST_PLATFORM_WINDOWS
3383
using type = std::uint64_t;
3384
#endif // DOCTEST_PLATFORM_WINDOWS
3385
}
3386
3387
using ticks_t = timer_large_integer::type;
3388
3389
#ifdef DOCTEST_CONFIG_GETCURRENTTICKS
3390
ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); }
3391
#elif defined(DOCTEST_PLATFORM_WINDOWS)
3392
ticks_t getCurrentTicks() {
3393
static LARGE_INTEGER hz = { {0} }, hzo = { {0} };
3394
if(!hz.QuadPart) {
3395
QueryPerformanceFrequency(&hz);
3396
QueryPerformanceCounter(&hzo);
3397
}
3398
LARGE_INTEGER t;
3399
QueryPerformanceCounter(&t);
3400
return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart;
3401
}
3402
#else // DOCTEST_PLATFORM_WINDOWS
3403
ticks_t getCurrentTicks() {
3404
timeval t;
3405
gettimeofday(&t, nullptr);
3406
return static_cast<ticks_t>(t.tv_sec) * 1000000 + static_cast<ticks_t>(t.tv_usec);
3407
}
3408
#endif // DOCTEST_PLATFORM_WINDOWS
3409
3410
struct Timer
3411
{
3412
void start() { m_ticks = getCurrentTicks(); }
3413
unsigned int getElapsedMicroseconds() const {
3414
return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
3415
}
3416
//unsigned int getElapsedMilliseconds() const {
3417
// return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
3418
//}
3419
double getElapsedSeconds() const { return static_cast<double>(getCurrentTicks() - m_ticks) / 1000000.0; }
3420
3421
private:
3422
ticks_t m_ticks = 0;
3423
};
3424
3425
#ifdef DOCTEST_CONFIG_NO_MULTITHREADING
3426
template <typename T>
3427
using Atomic = T;
3428
#else // DOCTEST_CONFIG_NO_MULTITHREADING
3429
template <typename T>
3430
using Atomic = std::atomic<T>;
3431
#endif // DOCTEST_CONFIG_NO_MULTITHREADING
3432
3433
#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING)
3434
template <typename T>
3435
using MultiLaneAtomic = Atomic<T>;
3436
#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
3437
// Provides a multilane implementation of an atomic variable that supports add, sub, load,
3438
// store. Instead of using a single atomic variable, this splits up into multiple ones,
3439
// each sitting on a separate cache line. The goal is to provide a speedup when most
3440
// operations are modifying. It achieves this with two properties:
3441
//
3442
// * Multiple atomics are used, so chance of congestion from the same atomic is reduced.
3443
// * Each atomic sits on a separate cache line, so false sharing is reduced.
3444
//
3445
// The disadvantage is that there is a small overhead due to the use of TLS, and load/store
3446
// is slower because all atomics have to be accessed.
3447
template <typename T>
3448
class MultiLaneAtomic
3449
{
3450
struct CacheLineAlignedAtomic
3451
{
3452
Atomic<T> atomic{};
3453
char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic<T>)];
3454
};
3455
CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES];
3456
3457
static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE,
3458
"guarantee one atomic takes exactly one cache line");
3459
3460
public:
3461
T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; }
3462
3463
T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); }
3464
3465
T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
3466
return myAtomic().fetch_add(arg, order);
3467
}
3468
3469
T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
3470
return myAtomic().fetch_sub(arg, order);
3471
}
3472
3473
operator T() const DOCTEST_NOEXCEPT { return load(); }
3474
3475
T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT {
3476
auto result = T();
3477
for(auto const& c : m_atomics) {
3478
result += c.atomic.load(order);
3479
}
3480
return result;
3481
}
3482
3483
T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this]
3484
store(desired);
3485
return desired;
3486
}
3487
3488
void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT {
3489
// first value becomes desired", all others become 0.
3490
for(auto& c : m_atomics) {
3491
c.atomic.store(desired, order);
3492
desired = {};
3493
}
3494
}
3495
3496
private:
3497
// Each thread has a different atomic that it operates on. If more than NumLanes threads
3498
// use this, some will use the same atomic. So performance will degrade a bit, but still
3499
// everything will work.
3500
//
3501
// The logic here is a bit tricky. The call should be as fast as possible, so that there
3502
// is minimal to no overhead in determining the correct atomic for the current thread.
3503
//
3504
// 1. A global static counter laneCounter counts continuously up.
3505
// 2. Each successive thread will use modulo operation of that counter so it gets an atomic
3506
// assigned in a round-robin fashion.
3507
// 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with
3508
// little overhead.
3509
Atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
3510
static Atomic<size_t> laneCounter;
3511
DOCTEST_THREAD_LOCAL size_t tlsLaneIdx =
3512
laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES;
3513
3514
return m_atomics[tlsLaneIdx].atomic;
3515
}
3516
};
3517
#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
3518
3519
// this holds both parameters from the command line and runtime data for tests
3520
struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats
3521
{
3522
MultiLaneAtomic<int> numAssertsCurrentTest_atomic;
3523
MultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
3524
3525
std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters
3526
3527
std::vector<IReporter*> reporters_currently_used;
3528
3529
assert_handler ah = nullptr;
3530
3531
Timer timer;
3532
3533
std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
3534
3535
// stuff for subcases
3536
bool reachedLeaf;
3537
std::vector<SubcaseSignature> subcaseStack;
3538
std::vector<SubcaseSignature> nextSubcaseStack;
3539
std::unordered_set<unsigned long long> fullyTraversedSubcases;
3540
size_t currentSubcaseDepth;
3541
Atomic<bool> shouldLogCurrentException;
3542
3543
void resetRunData() {
3544
numTestCases = 0;
3545
numTestCasesPassingFilters = 0;
3546
numTestSuitesPassingFilters = 0;
3547
numTestCasesFailed = 0;
3548
numAsserts = 0;
3549
numAssertsFailed = 0;
3550
numAssertsCurrentTest = 0;
3551
numAssertsFailedCurrentTest = 0;
3552
}
3553
3554
void finalizeTestCaseData() {
3555
seconds = timer.getElapsedSeconds();
3556
3557
// update the non-atomic counters
3558
numAsserts += numAssertsCurrentTest_atomic;
3559
numAssertsFailed += numAssertsFailedCurrentTest_atomic;
3560
numAssertsCurrentTest = numAssertsCurrentTest_atomic;
3561
numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic;
3562
3563
if(numAssertsFailedCurrentTest)
3564
failure_flags |= TestCaseFailureReason::AssertFailure;
3565
3566
if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 &&
3567
Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout)
3568
failure_flags |= TestCaseFailureReason::Timeout;
3569
3570
if(currentTest->m_should_fail) {
3571
if(failure_flags) {
3572
failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid;
3573
} else {
3574
failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt;
3575
}
3576
} else if(failure_flags && currentTest->m_may_fail) {
3577
failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid;
3578
} else if(currentTest->m_expected_failures > 0) {
3579
if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) {
3580
failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes;
3581
} else {
3582
failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes;
3583
}
3584
}
3585
3586
bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) ||
3587
(TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) ||
3588
(TestCaseFailureReason::FailedExactlyNumTimes & failure_flags);
3589
3590
// if any subcase has failed - the whole test case has failed
3591
testCaseSuccess = !(failure_flags && !ok_to_fail);
3592
if(!testCaseSuccess)
3593
numTestCasesFailed++;
3594
}
3595
};
3596
3597
ContextState* g_cs = nullptr;
3598
3599
// used to avoid locks for the debug output
3600
// TODO: figure out if this is indeed necessary/correct - seems like either there still
3601
// could be a race or that there wouldn't be a race even if using the context directly
3602
DOCTEST_THREAD_LOCAL bool g_no_colors;
3603
3604
#endif // DOCTEST_CONFIG_DISABLE
3605
} // namespace detail
3606
3607
char* String::allocate(size_type sz) {
3608
if (sz <= last) {
3609
buf[sz] = '\0';
3610
setLast(last - sz);
3611
return buf;
3612
} else {
3613
setOnHeap();
3614
data.size = sz;
3615
data.capacity = data.size + 1;
3616
data.ptr = new char[data.capacity];
3617
data.ptr[sz] = '\0';
3618
return data.ptr;
3619
}
3620
}
3621
3622
void String::setOnHeap() noexcept { *reinterpret_cast<unsigned char*>(&buf[last]) = 128; }
3623
void String::setLast(size_type in) noexcept { buf[last] = char(in); }
3624
void String::setSize(size_type sz) noexcept {
3625
if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); }
3626
else { data.ptr[sz] = '\0'; data.size = sz; }
3627
}
3628
3629
void String::copy(const String& other) {
3630
if(other.isOnStack()) {
3631
memcpy(buf, other.buf, len);
3632
} else {
3633
memcpy(allocate(other.data.size), other.data.ptr, other.data.size);
3634
}
3635
}
3636
3637
String::String() noexcept {
3638
buf[0] = '\0';
3639
setLast();
3640
}
3641
3642
String::~String() {
3643
if(!isOnStack())
3644
delete[] data.ptr;
3645
} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
3646
3647
String::String(const char* in)
3648
: String(in, strlen(in)) {}
3649
3650
String::String(const char* in, size_type in_size) {
3651
memcpy(allocate(in_size), in, in_size);
3652
}
3653
3654
String::String(std::istream& in, size_type in_size) {
3655
in.read(allocate(in_size), in_size);
3656
}
3657
3658
String::String(const String& other) { copy(other); }
3659
3660
String& String::operator=(const String& other) {
3661
if(this != &other) {
3662
if(!isOnStack())
3663
delete[] data.ptr;
3664
3665
copy(other);
3666
}
3667
3668
return *this;
3669
}
3670
3671
String& String::operator+=(const String& other) {
3672
const size_type my_old_size = size();
3673
const size_type other_size = other.size();
3674
const size_type total_size = my_old_size + other_size;
3675
if(isOnStack()) {
3676
if(total_size < len) {
3677
// append to the current stack space
3678
memcpy(buf + my_old_size, other.c_str(), other_size + 1);
3679
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
3680
setLast(last - total_size);
3681
} else {
3682
// alloc new chunk
3683
char* temp = new char[total_size + 1];
3684
// copy current data to new location before writing in the union
3685
memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed
3686
// update data in union
3687
setOnHeap();
3688
data.size = total_size;
3689
data.capacity = data.size + 1;
3690
data.ptr = temp;
3691
// transfer the rest of the data
3692
memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
3693
}
3694
} else {
3695
if(data.capacity > total_size) {
3696
// append to the current heap block
3697
data.size = total_size;
3698
memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
3699
} else {
3700
// resize
3701
data.capacity *= 2;
3702
if(data.capacity <= total_size)
3703
data.capacity = total_size + 1;
3704
// alloc new chunk
3705
char* temp = new char[data.capacity];
3706
// copy current data to new location before releasing it
3707
memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed
3708
// release old chunk
3709
delete[] data.ptr;
3710
// update the rest of the union members
3711
data.size = total_size;
3712
data.ptr = temp;
3713
// transfer the rest of the data
3714
memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1);
3715
}
3716
}
3717
3718
return *this;
3719
}
3720
3721
String::String(String&& other) noexcept {
3722
memcpy(buf, other.buf, len);
3723
other.buf[0] = '\0';
3724
other.setLast();
3725
}
3726
3727
String& String::operator=(String&& other) noexcept {
3728
if(this != &other) {
3729
if(!isOnStack())
3730
delete[] data.ptr;
3731
memcpy(buf, other.buf, len);
3732
other.buf[0] = '\0';
3733
other.setLast();
3734
}
3735
return *this;
3736
}
3737
3738
char String::operator[](size_type i) const {
3739
return const_cast<String*>(this)->operator[](i);
3740
}
3741
3742
char& String::operator[](size_type i) {
3743
if(isOnStack())
3744
return reinterpret_cast<char*>(buf)[i];
3745
return data.ptr[i];
3746
}
3747
3748
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized")
3749
String::size_type String::size() const {
3750
if(isOnStack())
3751
return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32
3752
return data.size;
3753
}
3754
DOCTEST_GCC_SUPPRESS_WARNING_POP
3755
3756
String::size_type String::capacity() const {
3757
if(isOnStack())
3758
return len;
3759
return data.capacity;
3760
}
3761
3762
String String::substr(size_type pos, size_type cnt) && {
3763
cnt = std::min(cnt, size() - pos);
3764
char* cptr = c_str();
3765
memmove(cptr, cptr + pos, cnt);
3766
setSize(cnt);
3767
return std::move(*this);
3768
}
3769
3770
String String::substr(size_type pos, size_type cnt) const & {
3771
cnt = std::min(cnt, size() - pos);
3772
return String{ c_str() + pos, cnt };
3773
}
3774
3775
String::size_type String::find(char ch, size_type pos) const {
3776
const char* begin = c_str();
3777
const char* end = begin + size();
3778
const char* it = begin + pos;
3779
for (; it < end && *it != ch; it++);
3780
if (it < end) { return static_cast<size_type>(it - begin); }
3781
else { return npos; }
3782
}
3783
3784
String::size_type String::rfind(char ch, size_type pos) const {
3785
const char* begin = c_str();
3786
const char* it = begin + std::min(pos, size() - 1);
3787
for (; it >= begin && *it != ch; it--);
3788
if (it >= begin) { return static_cast<size_type>(it - begin); }
3789
else { return npos; }
3790
}
3791
3792
int String::compare(const char* other, bool no_case) const {
3793
if(no_case)
3794
return doctest::stricmp(c_str(), other);
3795
return std::strcmp(c_str(), other);
3796
}
3797
3798
int String::compare(const String& other, bool no_case) const {
3799
return compare(other.c_str(), no_case);
3800
}
3801
3802
String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; }
3803
3804
bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
3805
bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
3806
bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
3807
bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
3808
bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
3809
bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
3810
3811
std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); }
3812
3813
Contains::Contains(const String& str) : string(str) { }
3814
3815
bool Contains::checkWith(const String& other) const {
3816
return strstr(other.c_str(), string.c_str()) != nullptr;
3817
}
3818
3819
String toString(const Contains& in) {
3820
return "Contains( " + in.string + " )";
3821
}
3822
3823
bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); }
3824
bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); }
3825
bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); }
3826
bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); }
3827
3828
namespace {
3829
void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;)
3830
} // namespace
3831
3832
namespace Color {
3833
std::ostream& operator<<(std::ostream& s, Color::Enum code) {
3834
color_to_stream(s, code);
3835
return s;
3836
}
3837
} // namespace Color
3838
3839
// clang-format off
3840
const char* assertString(assertType::Enum at) {
3841
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled
3842
#define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type
3843
#define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \
3844
DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \
3845
DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \
3846
DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type)
3847
switch(at) {
3848
DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN);
3849
DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK);
3850
DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE);
3851
3852
DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE);
3853
3854
DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS);
3855
3856
DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS);
3857
3858
DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH);
3859
3860
DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS);
3861
3862
DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW);
3863
3864
DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ);
3865
DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE);
3866
DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT);
3867
DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT);
3868
DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE);
3869
DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE);
3870
3871
DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY);
3872
DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE);
3873
3874
default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!");
3875
}
3876
DOCTEST_MSVC_SUPPRESS_WARNING_POP
3877
}
3878
// clang-format on
3879
3880
const char* failureString(assertType::Enum at) {
3881
if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional
3882
return "WARNING";
3883
if(at & assertType::is_check) //!OCLINT bitwise operator in conditional
3884
return "ERROR";
3885
if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
3886
return "FATAL ERROR";
3887
return "";
3888
}
3889
3890
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
3891
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference")
3892
// depending on the current options this will remove the path of filenames
3893
const char* skipPathFromFilename(const char* file) {
3894
#ifndef DOCTEST_CONFIG_DISABLE
3895
if(getContextOptions()->no_path_in_filenames) {
3896
auto back = std::strrchr(file, '\\');
3897
auto forward = std::strrchr(file, '/');
3898
if(back || forward) {
3899
if(back > forward)
3900
forward = back;
3901
return forward + 1;
3902
}
3903
} else {
3904
const auto prefixes = getContextOptions()->strip_file_prefixes;
3905
const char separator = DOCTEST_CONFIG_OPTIONS_FILE_PREFIX_SEPARATOR;
3906
String::size_type longest_match = 0U;
3907
for(String::size_type pos = 0U; pos < prefixes.size(); ++pos)
3908
{
3909
const auto prefix_start = pos;
3910
pos = std::min(prefixes.find(separator, prefix_start), prefixes.size());
3911
3912
const auto prefix_size = pos - prefix_start;
3913
if(prefix_size > longest_match)
3914
{
3915
// TODO under DOCTEST_MSVC: does the comparison need strnicmp() to work with drive letter capitalization?
3916
if(0 == std::strncmp(prefixes.c_str() + prefix_start, file, prefix_size))
3917
{
3918
longest_match = prefix_size;
3919
}
3920
}
3921
}
3922
return &file[longest_match];
3923
}
3924
#endif // DOCTEST_CONFIG_DISABLE
3925
return file;
3926
}
3927
DOCTEST_CLANG_SUPPRESS_WARNING_POP
3928
DOCTEST_GCC_SUPPRESS_WARNING_POP
3929
3930
bool SubcaseSignature::operator==(const SubcaseSignature& other) const {
3931
return m_line == other.m_line
3932
&& std::strcmp(m_file, other.m_file) == 0
3933
&& m_name == other.m_name;
3934
}
3935
3936
bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
3937
if(m_line != other.m_line)
3938
return m_line < other.m_line;
3939
if(std::strcmp(m_file, other.m_file) != 0)
3940
return std::strcmp(m_file, other.m_file) < 0;
3941
return m_name.compare(other.m_name) < 0;
3942
}
3943
3944
DOCTEST_DEFINE_INTERFACE(IContextScope)
3945
3946
namespace detail {
3947
void filldata<const void*>::fill(std::ostream* stream, const void* in) {
3948
if (in) { *stream << in; }
3949
else { *stream << "nullptr"; }
3950
}
3951
3952
template <typename T>
3953
String toStreamLit(T t) {
3954
std::ostream* os = tlssPush();
3955
os->operator<<(t);
3956
return tlssPop();
3957
}
3958
}
3959
3960
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
3961
String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
3962
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
3963
3964
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
3965
// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
3966
String toString(const std::string& in) { return in.c_str(); }
3967
#endif // VS 2019
3968
3969
String toString(String in) { return in; }
3970
3971
String toString(std::nullptr_t) { return "nullptr"; }
3972
3973
String toString(bool in) { return in ? "true" : "false"; }
3974
3975
String toString(float in) { return toStreamLit(in); }
3976
String toString(double in) { return toStreamLit(in); }
3977
String toString(double long in) { return toStreamLit(in); }
3978
3979
String toString(char in) { return toStreamLit(static_cast<signed>(in)); }
3980
String toString(char signed in) { return toStreamLit(static_cast<signed>(in)); }
3981
String toString(char unsigned in) { return toStreamLit(static_cast<unsigned>(in)); }
3982
String toString(short in) { return toStreamLit(in); }
3983
String toString(short unsigned in) { return toStreamLit(in); }
3984
String toString(signed in) { return toStreamLit(in); }
3985
String toString(unsigned in) { return toStreamLit(in); }
3986
String toString(long in) { return toStreamLit(in); }
3987
String toString(long unsigned in) { return toStreamLit(in); }
3988
String toString(long long in) { return toStreamLit(in); }
3989
String toString(long long unsigned in) { return toStreamLit(in); }
3990
3991
Approx::Approx(double value)
3992
: m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
3993
, m_scale(1.0)
3994
, m_value(value) {}
3995
3996
Approx Approx::operator()(double value) const {
3997
Approx approx(value);
3998
approx.epsilon(m_epsilon);
3999
approx.scale(m_scale);
4000
return approx;
4001
}
4002
4003
Approx& Approx::epsilon(double newEpsilon) {
4004
m_epsilon = newEpsilon;
4005
return *this;
4006
}
4007
Approx& Approx::scale(double newScale) {
4008
m_scale = newScale;
4009
return *this;
4010
}
4011
4012
bool operator==(double lhs, const Approx& rhs) {
4013
// Thanks to Richard Harris for his help refining this formula
4014
return std::fabs(lhs - rhs.m_value) <
4015
rhs.m_epsilon * (rhs.m_scale + std::max<double>(std::fabs(lhs), std::fabs(rhs.m_value)));
4016
}
4017
bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); }
4018
bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
4019
bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); }
4020
bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; }
4021
bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; }
4022
bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; }
4023
bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; }
4024
bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; }
4025
bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; }
4026
bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; }
4027
bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; }
4028
4029
String toString(const Approx& in) {
4030
return "Approx( " + doctest::toString(in.m_value) + " )";
4031
}
4032
const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); }
4033
4034
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738)
4035
template <typename F>
4036
IsNaN<F>::operator bool() const {
4037
return std::isnan(value) ^ flipped;
4038
}
4039
DOCTEST_MSVC_SUPPRESS_WARNING_POP
4040
template struct DOCTEST_INTERFACE_DEF IsNaN<float>;
4041
template struct DOCTEST_INTERFACE_DEF IsNaN<double>;
4042
template struct DOCTEST_INTERFACE_DEF IsNaN<long double>;
4043
template <typename F>
4044
String toString(IsNaN<F> in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; }
4045
String toString(IsNaN<float> in) { return toString<float>(in); }
4046
String toString(IsNaN<double> in) { return toString<double>(in); }
4047
String toString(IsNaN<double long> in) { return toString<double long>(in); }
4048
4049
} // namespace doctest
4050
4051
#ifdef DOCTEST_CONFIG_DISABLE
4052
namespace doctest {
4053
Context::Context(int, const char* const*) {}
4054
Context::~Context() = default;
4055
void Context::applyCommandLine(int, const char* const*) {}
4056
void Context::addFilter(const char*, const char*) {}
4057
void Context::clearFilters() {}
4058
void Context::setOption(const char*, bool) {}
4059
void Context::setOption(const char*, int) {}
4060
void Context::setOption(const char*, const char*) {}
4061
bool Context::shouldExit() { return false; }
4062
void Context::setAsDefaultForAssertsOutOfTestCases() {}
4063
void Context::setAssertHandler(detail::assert_handler) {}
4064
void Context::setCout(std::ostream*) {}
4065
int Context::run() { return 0; }
4066
4067
int IReporter::get_num_active_contexts() { return 0; }
4068
const IContextScope* const* IReporter::get_active_contexts() { return nullptr; }
4069
int IReporter::get_num_stringified_contexts() { return 0; }
4070
const String* IReporter::get_stringified_contexts() { return nullptr; }
4071
4072
int registerReporter(const char*, int, IReporter*) { return 0; }
4073
4074
} // namespace doctest
4075
#else // DOCTEST_CONFIG_DISABLE
4076
4077
#if !defined(DOCTEST_CONFIG_COLORS_NONE)
4078
#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI)
4079
#ifdef DOCTEST_PLATFORM_WINDOWS
4080
#define DOCTEST_CONFIG_COLORS_WINDOWS
4081
#else // linux
4082
#define DOCTEST_CONFIG_COLORS_ANSI
4083
#endif // platform
4084
#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI
4085
#endif // DOCTEST_CONFIG_COLORS_NONE
4086
4087
namespace doctest_detail_test_suite_ns {
4088
// holds the current test suite
4089
doctest::detail::TestSuite& getCurrentTestSuite() {
4090
static doctest::detail::TestSuite data{};
4091
return data;
4092
}
4093
} // namespace doctest_detail_test_suite_ns
4094
4095
namespace doctest {
4096
namespace {
4097
// the int (priority) is part of the key for automatic sorting - sadly one can register a
4098
// reporter with a duplicate name and a different priority but hopefully that won't happen often :|
4099
using reporterMap = std::map<std::pair<int, String>, reporterCreatorFunc>;
4100
4101
reporterMap& getReporters() {
4102
static reporterMap data;
4103
return data;
4104
}
4105
reporterMap& getListeners() {
4106
static reporterMap data;
4107
return data;
4108
}
4109
} // namespace
4110
namespace detail {
4111
#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \
4112
for(auto& curr_rep : g_cs->reporters_currently_used) \
4113
curr_rep->function(__VA_ARGS__)
4114
4115
bool checkIfShouldThrow(assertType::Enum at) {
4116
if(at & assertType::is_require) //!OCLINT bitwise operator in conditional
4117
return true;
4118
4119
if((at & assertType::is_check) //!OCLINT bitwise operator in conditional
4120
&& getContextOptions()->abort_after > 0 &&
4121
(g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >=
4122
getContextOptions()->abort_after)
4123
return true;
4124
4125
return false;
4126
}
4127
4128
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
4129
DOCTEST_NORETURN void throwException() {
4130
g_cs->shouldLogCurrentException = false;
4131
throw TestFailureException(); // NOLINT(hicpp-exception-baseclass)
4132
}
4133
#else // DOCTEST_CONFIG_NO_EXCEPTIONS
4134
void throwException() {}
4135
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
4136
} // namespace detail
4137
4138
namespace {
4139
using namespace detail;
4140
// matching of a string against a wildcard mask (case sensitivity configurable) taken from
4141
// https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
4142
int wildcmp(const char* str, const char* wild, bool caseSensitive) {
4143
const char* cp = str;
4144
const char* mp = wild;
4145
4146
while((*str) && (*wild != '*')) {
4147
if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) &&
4148
(*wild != '?')) {
4149
return 0;
4150
}
4151
wild++;
4152
str++;
4153
}
4154
4155
while(*str) {
4156
if(*wild == '*') {
4157
if(!*++wild) {
4158
return 1;
4159
}
4160
mp = wild;
4161
cp = str + 1;
4162
} else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) ||
4163
(*wild == '?')) {
4164
wild++;
4165
str++;
4166
} else {
4167
wild = mp; //!OCLINT parameter reassignment
4168
str = cp++; //!OCLINT parameter reassignment
4169
}
4170
}
4171
4172
while(*wild == '*') {
4173
wild++;
4174
}
4175
return !*wild;
4176
}
4177
4178
// checks if the name matches any of the filters (and can be configured what to do when empty)
4179
bool matchesAny(const char* name, const std::vector<String>& filters, bool matchEmpty,
4180
bool caseSensitive) {
4181
if (filters.empty() && matchEmpty)
4182
return true;
4183
for (auto& curr : filters)
4184
if (wildcmp(name, curr.c_str(), caseSensitive))
4185
return true;
4186
return false;
4187
}
4188
4189
DOCTEST_NO_SANITIZE_INTEGER
4190
unsigned long long hash(unsigned long long a, unsigned long long b) {
4191
return (a << 5) + b;
4192
}
4193
4194
// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
4195
DOCTEST_NO_SANITIZE_INTEGER
4196
unsigned long long hash(const char* str) {
4197
unsigned long long hash = 5381;
4198
char c;
4199
while ((c = *str++))
4200
hash = ((hash << 5) + hash) + c; // hash * 33 + c
4201
return hash;
4202
}
4203
4204
unsigned long long hash(const SubcaseSignature& sig) {
4205
return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line);
4206
}
4207
4208
unsigned long long hash(const std::vector<SubcaseSignature>& sigs, size_t count) {
4209
unsigned long long running = 0;
4210
auto end = sigs.begin() + count;
4211
for (auto it = sigs.begin(); it != end; it++) {
4212
running = hash(running, hash(*it));
4213
}
4214
return running;
4215
}
4216
4217
unsigned long long hash(const std::vector<SubcaseSignature>& sigs) {
4218
unsigned long long running = 0;
4219
for (const SubcaseSignature& sig : sigs) {
4220
running = hash(running, hash(sig));
4221
}
4222
return running;
4223
}
4224
} // namespace
4225
namespace detail {
4226
bool Subcase::checkFilters() {
4227
if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) {
4228
if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive))
4229
return true;
4230
if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive))
4231
return true;
4232
}
4233
return false;
4234
}
4235
4236
Subcase::Subcase(const String& name, const char* file, int line)
4237
: m_signature({name, file, line}) {
4238
if (!g_cs->reachedLeaf) {
4239
if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size()
4240
|| g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) {
4241
// Going down.
4242
if (checkFilters()) { return; }
4243
4244
g_cs->subcaseStack.push_back(m_signature);
4245
g_cs->currentSubcaseDepth++;
4246
m_entered = true;
4247
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
4248
}
4249
} else {
4250
if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) {
4251
// This subcase is reentered via control flow.
4252
g_cs->currentSubcaseDepth++;
4253
m_entered = true;
4254
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
4255
} else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth
4256
&& g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature)))
4257
== g_cs->fullyTraversedSubcases.end()) {
4258
if (checkFilters()) { return; }
4259
// This subcase is part of the one to be executed next.
4260
g_cs->nextSubcaseStack.clear();
4261
g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(),
4262
g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth);
4263
g_cs->nextSubcaseStack.push_back(m_signature);
4264
}
4265
}
4266
}
4267
4268
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
4269
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
4270
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
4271
4272
Subcase::~Subcase() {
4273
if (m_entered) {
4274
g_cs->currentSubcaseDepth--;
4275
4276
if (!g_cs->reachedLeaf) {
4277
// Leaf.
4278
g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
4279
g_cs->nextSubcaseStack.clear();
4280
g_cs->reachedLeaf = true;
4281
} else if (g_cs->nextSubcaseStack.empty()) {
4282
// All children are finished.
4283
g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
4284
}
4285
4286
#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
4287
if(std::uncaught_exceptions() > 0
4288
#else
4289
if(std::uncaught_exception()
4290
#endif
4291
&& g_cs->shouldLogCurrentException) {
4292
DOCTEST_ITERATE_THROUGH_REPORTERS(
4293
test_case_exception, {"exception thrown in subcase - will translate later "
4294
"when the whole test case has been exited (cannot "
4295
"translate while there is an active exception)",
4296
false});
4297
g_cs->shouldLogCurrentException = false;
4298
}
4299
4300
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
4301
}
4302
}
4303
4304
DOCTEST_CLANG_SUPPRESS_WARNING_POP
4305
DOCTEST_GCC_SUPPRESS_WARNING_POP
4306
DOCTEST_MSVC_SUPPRESS_WARNING_POP
4307
4308
Subcase::operator bool() const { return m_entered; }
4309
4310
Result::Result(bool passed, const String& decomposition)
4311
: m_passed(passed)
4312
, m_decomp(decomposition) {}
4313
4314
ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at)
4315
: m_at(at) {}
4316
4317
TestSuite& TestSuite::operator*(const char* in) {
4318
m_test_suite = in;
4319
return *this;
4320
}
4321
4322
TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
4323
const String& type, int template_id) {
4324
m_file = file;
4325
m_line = line;
4326
m_name = nullptr; // will be later overridden in operator*
4327
m_test_suite = test_suite.m_test_suite;
4328
m_description = test_suite.m_description;
4329
m_skip = test_suite.m_skip;
4330
m_no_breaks = test_suite.m_no_breaks;
4331
m_no_output = test_suite.m_no_output;
4332
m_may_fail = test_suite.m_may_fail;
4333
m_should_fail = test_suite.m_should_fail;
4334
m_expected_failures = test_suite.m_expected_failures;
4335
m_timeout = test_suite.m_timeout;
4336
4337
m_test = test;
4338
m_type = type;
4339
m_template_id = template_id;
4340
}
4341
4342
TestCase::TestCase(const TestCase& other)
4343
: TestCaseData() {
4344
*this = other;
4345
}
4346
4347
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
4348
TestCase& TestCase::operator=(const TestCase& other) {
4349
TestCaseData::operator=(other);
4350
m_test = other.m_test;
4351
m_type = other.m_type;
4352
m_template_id = other.m_template_id;
4353
m_full_name = other.m_full_name;
4354
4355
if(m_template_id != -1)
4356
m_name = m_full_name.c_str();
4357
return *this;
4358
}
4359
DOCTEST_MSVC_SUPPRESS_WARNING_POP
4360
4361
TestCase& TestCase::operator*(const char* in) {
4362
m_name = in;
4363
// make a new name with an appended type for templated test case
4364
if(m_template_id != -1) {
4365
m_full_name = String(m_name) + "<" + m_type + ">";
4366
// redirect the name to point to the newly constructed full name
4367
m_name = m_full_name.c_str();
4368
}
4369
return *this;
4370
}
4371
4372
bool TestCase::operator<(const TestCase& other) const {
4373
// this will be used only to differentiate between test cases - not relevant for sorting
4374
if(m_line != other.m_line)
4375
return m_line < other.m_line;
4376
const int name_cmp = strcmp(m_name, other.m_name);
4377
if(name_cmp != 0)
4378
return name_cmp < 0;
4379
const int file_cmp = m_file.compare(other.m_file);
4380
if(file_cmp != 0)
4381
return file_cmp < 0;
4382
return m_template_id < other.m_template_id;
4383
}
4384
4385
// all the registered tests
4386
std::set<TestCase>& getRegisteredTests() {
4387
static std::set<TestCase> data;
4388
return data;
4389
}
4390
} // namespace detail
4391
namespace {
4392
using namespace detail;
4393
// for sorting tests by file/line
4394
bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) {
4395
// this is needed because MSVC gives different case for drive letters
4396
// for __FILE__ when evaluated in a header and a source file
4397
const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC));
4398
if(res != 0)
4399
return res < 0;
4400
if(lhs->m_line != rhs->m_line)
4401
return lhs->m_line < rhs->m_line;
4402
return lhs->m_template_id < rhs->m_template_id;
4403
}
4404
4405
// for sorting tests by suite/file/line
4406
bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) {
4407
const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite);
4408
if(res != 0)
4409
return res < 0;
4410
return fileOrderComparator(lhs, rhs);
4411
}
4412
4413
// for sorting tests by name/suite/file/line
4414
bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) {
4415
const int res = std::strcmp(lhs->m_name, rhs->m_name);
4416
if(res != 0)
4417
return res < 0;
4418
return suiteOrderComparator(lhs, rhs);
4419
}
4420
4421
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
4422
void color_to_stream(std::ostream& s, Color::Enum code) {
4423
static_cast<void>(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS
4424
static_cast<void>(code); // for DOCTEST_CONFIG_COLORS_NONE
4425
#ifdef DOCTEST_CONFIG_COLORS_ANSI
4426
if(g_no_colors ||
4427
(isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false))
4428
return;
4429
4430
auto col = "";
4431
// clang-format off
4432
switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement
4433
case Color::Red: col = "[0;31m"; break;
4434
case Color::Green: col = "[0;32m"; break;
4435
case Color::Blue: col = "[0;34m"; break;
4436
case Color::Cyan: col = "[0;36m"; break;
4437
case Color::Yellow: col = "[0;33m"; break;
4438
case Color::Grey: col = "[1;30m"; break;
4439
case Color::LightGrey: col = "[0;37m"; break;
4440
case Color::BrightRed: col = "[1;31m"; break;
4441
case Color::BrightGreen: col = "[1;32m"; break;
4442
case Color::BrightWhite: col = "[1;37m"; break;
4443
case Color::Bright: // invalid
4444
case Color::None:
4445
case Color::White:
4446
default: col = "[0m";
4447
}
4448
// clang-format on
4449
s << "\033" << col;
4450
#endif // DOCTEST_CONFIG_COLORS_ANSI
4451
4452
#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
4453
if(g_no_colors ||
4454
(_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false))
4455
return;
4456
4457
static struct ConsoleHelper {
4458
HANDLE stdoutHandle;
4459
WORD origFgAttrs;
4460
WORD origBgAttrs;
4461
4462
ConsoleHelper() {
4463
stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
4464
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
4465
GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
4466
origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
4467
BACKGROUND_BLUE | BACKGROUND_INTENSITY);
4468
origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
4469
FOREGROUND_BLUE | FOREGROUND_INTENSITY);
4470
}
4471
} ch;
4472
4473
#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs)
4474
4475
// clang-format off
4476
switch (code) {
4477
case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
4478
case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break;
4479
case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break;
4480
case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break;
4481
case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break;
4482
case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break;
4483
case Color::Grey: DOCTEST_SET_ATTR(0); break;
4484
case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break;
4485
case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break;
4486
case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break;
4487
case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
4488
case Color::None:
4489
case Color::Bright: // invalid
4490
default: DOCTEST_SET_ATTR(ch.origFgAttrs);
4491
}
4492
// clang-format on
4493
#endif // DOCTEST_CONFIG_COLORS_WINDOWS
4494
}
4495
DOCTEST_CLANG_SUPPRESS_WARNING_POP
4496
4497
std::vector<const IExceptionTranslator*>& getExceptionTranslators() {
4498
static std::vector<const IExceptionTranslator*> data;
4499
return data;
4500
}
4501
4502
String translateActiveException() {
4503
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
4504
String res;
4505
auto& translators = getExceptionTranslators();
4506
for(auto& curr : translators)
4507
if(curr->translate(res))
4508
return res;
4509
// clang-format off
4510
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value")
4511
try {
4512
throw;
4513
} catch(std::exception& ex) {
4514
return ex.what();
4515
} catch(std::string& msg) {
4516
return msg.c_str();
4517
} catch(const char* msg) {
4518
return msg;
4519
} catch(...) {
4520
return "unknown exception";
4521
}
4522
DOCTEST_GCC_SUPPRESS_WARNING_POP
4523
// clang-format on
4524
#else // DOCTEST_CONFIG_NO_EXCEPTIONS
4525
return "";
4526
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
4527
}
4528
} // namespace
4529
4530
namespace detail {
4531
// used by the macros for registering tests
4532
int regTest(const TestCase& tc) {
4533
getRegisteredTests().insert(tc);
4534
return 0;
4535
}
4536
4537
// sets the current test suite
4538
int setTestSuite(const TestSuite& ts) {
4539
doctest_detail_test_suite_ns::getCurrentTestSuite() = ts;
4540
return 0;
4541
}
4542
4543
#ifdef DOCTEST_IS_DEBUGGER_ACTIVE
4544
bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); }
4545
#else // DOCTEST_IS_DEBUGGER_ACTIVE
4546
#ifdef DOCTEST_PLATFORM_LINUX
4547
class ErrnoGuard {
4548
public:
4549
ErrnoGuard() : m_oldErrno(errno) {}
4550
~ErrnoGuard() { errno = m_oldErrno; }
4551
private:
4552
int m_oldErrno;
4553
};
4554
// See the comments in Catch2 for the reasoning behind this implementation:
4555
// https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102
4556
bool isDebuggerActive() {
4557
ErrnoGuard guard;
4558
std::ifstream in("/proc/self/status");
4559
for(std::string line; std::getline(in, line);) {
4560
static const int PREFIX_LEN = 11;
4561
if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) {
4562
return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
4563
}
4564
}
4565
return false;
4566
}
4567
#elif defined(DOCTEST_PLATFORM_MAC)
4568
// The following function is taken directly from the following technical note:
4569
// https://developer.apple.com/library/archive/qa/qa1361/_index.html
4570
// Returns true if the current process is being debugged (either
4571
// running under the debugger or has a debugger attached post facto).
4572
bool isDebuggerActive() {
4573
int mib[4];
4574
kinfo_proc info;
4575
size_t size;
4576
// Initialize the flags so that, if sysctl fails for some bizarre
4577
// reason, we get a predictable result.
4578
info.kp_proc.p_flag = 0;
4579
// Initialize mib, which tells sysctl the info we want, in this case
4580
// we're looking for information about a specific process ID.
4581
mib[0] = CTL_KERN;
4582
mib[1] = KERN_PROC;
4583
mib[2] = KERN_PROC_PID;
4584
mib[3] = getpid();
4585
// Call sysctl.
4586
size = sizeof(info);
4587
if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) {
4588
std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n";
4589
return false;
4590
}
4591
// We're being debugged if the P_TRACED flag is set.
4592
return ((info.kp_proc.p_flag & P_TRACED) != 0);
4593
}
4594
#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__)
4595
bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; }
4596
#else
4597
bool isDebuggerActive() { return false; }
4598
#endif // Platform
4599
#endif // DOCTEST_IS_DEBUGGER_ACTIVE
4600
4601
void registerExceptionTranslatorImpl(const IExceptionTranslator* et) {
4602
if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) ==
4603
getExceptionTranslators().end())
4604
getExceptionTranslators().push_back(et);
4605
}
4606
4607
DOCTEST_THREAD_LOCAL std::vector<IContextScope*> g_infoContexts; // for logging with INFO()
4608
4609
ContextScopeBase::ContextScopeBase() {
4610
g_infoContexts.push_back(this);
4611
}
4612
4613
ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept {
4614
if (other.need_to_destroy) {
4615
other.destroy();
4616
}
4617
other.need_to_destroy = false;
4618
g_infoContexts.push_back(this);
4619
}
4620
4621
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
4622
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
4623
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
4624
4625
// destroy cannot be inlined into the destructor because that would mean calling stringify after
4626
// ContextScope has been destroyed (base class destructors run after derived class destructors).
4627
// Instead, ContextScope calls this method directly from its destructor.
4628
void ContextScopeBase::destroy() {
4629
#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
4630
if(std::uncaught_exceptions() > 0) {
4631
#else
4632
if(std::uncaught_exception()) {
4633
#endif
4634
std::ostringstream s;
4635
this->stringify(&s);
4636
g_cs->stringifiedContexts.push_back(s.str().c_str());
4637
}
4638
g_infoContexts.pop_back();
4639
}
4640
4641
DOCTEST_CLANG_SUPPRESS_WARNING_POP
4642
DOCTEST_GCC_SUPPRESS_WARNING_POP
4643
DOCTEST_MSVC_SUPPRESS_WARNING_POP
4644
} // namespace detail
4645
namespace {
4646
using namespace detail;
4647
4648
#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
4649
struct FatalConditionHandler
4650
{
4651
static void reset() {}
4652
static void allocateAltStackMem() {}
4653
static void freeAltStackMem() {}
4654
};
4655
#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
4656
4657
void reportFatal(const std::string&);
4658
4659
#ifdef DOCTEST_PLATFORM_WINDOWS
4660
4661
struct SignalDefs
4662
{
4663
DWORD id;
4664
const char* name;
4665
};
4666
// There is no 1-1 mapping between signals and windows exceptions.
4667
// Windows can easily distinguish between SO and SigSegV,
4668
// but SigInt, SigTerm, etc are handled differently.
4669
SignalDefs signalDefs[] = {
4670
{static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION),
4671
"SIGILL - Illegal instruction signal"},
4672
{static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"},
4673
{static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION),
4674
"SIGSEGV - Segmentation violation signal"},
4675
{static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"},
4676
};
4677
4678
struct FatalConditionHandler
4679
{
4680
static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) {
4681
// Multiple threads may enter this filter/handler at once. We want the error message to be printed on the
4682
// console just once no matter how many threads have crashed.
4683
DOCTEST_DECLARE_STATIC_MUTEX(mutex)
4684
static bool execute = true;
4685
{
4686
DOCTEST_LOCK_MUTEX(mutex)
4687
if(execute) {
4688
bool reported = false;
4689
for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
4690
if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
4691
reportFatal(signalDefs[i].name);
4692
reported = true;
4693
break;
4694
}
4695
}
4696
if(reported == false)
4697
reportFatal("Unhandled SEH exception caught");
4698
if(isDebuggerActive() && !g_cs->no_breaks)
4699
DOCTEST_BREAK_INTO_DEBUGGER();
4700
}
4701
execute = false;
4702
}
4703
std::exit(EXIT_FAILURE);
4704
}
4705
4706
static void allocateAltStackMem() {}
4707
static void freeAltStackMem() {}
4708
4709
FatalConditionHandler() {
4710
isSet = true;
4711
// 32k seems enough for doctest to handle stack overflow,
4712
// but the value was found experimentally, so there is no strong guarantee
4713
guaranteeSize = 32 * 1024;
4714
// Register an unhandled exception filter
4715
previousTop = SetUnhandledExceptionFilter(handleException);
4716
// Pass in guarantee size to be filled
4717
SetThreadStackGuarantee(&guaranteeSize);
4718
4719
// On Windows uncaught exceptions from another thread, exceptions from
4720
// destructors, or calls to std::terminate are not a SEH exception
4721
4722
// The terminal handler gets called when:
4723
// - std::terminate is called FROM THE TEST RUNNER THREAD
4724
// - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD
4725
original_terminate_handler = std::get_terminate();
4726
std::set_terminate([]() DOCTEST_NOEXCEPT {
4727
reportFatal("Terminate handler called");
4728
if(isDebuggerActive() && !g_cs->no_breaks)
4729
DOCTEST_BREAK_INTO_DEBUGGER();
4730
std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well
4731
});
4732
4733
// SIGABRT is raised when:
4734
// - std::terminate is called FROM A DIFFERENT THREAD
4735
// - an exception is thrown from a destructor FROM A DIFFERENT THREAD
4736
// - an uncaught exception is thrown FROM A DIFFERENT THREAD
4737
prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT {
4738
if(signal == SIGABRT) {
4739
reportFatal("SIGABRT - Abort (abnormal termination) signal");
4740
if(isDebuggerActive() && !g_cs->no_breaks)
4741
DOCTEST_BREAK_INTO_DEBUGGER();
4742
std::exit(EXIT_FAILURE);
4743
}
4744
});
4745
4746
// The following settings are taken from google test, and more
4747
// specifically from UnitTest::Run() inside of gtest.cc
4748
4749
// the user does not want to see pop-up dialogs about crashes
4750
prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
4751
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
4752
// This forces the abort message to go to stderr in all circumstances.
4753
prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR);
4754
// In the debug version, Visual Studio pops up a separate dialog
4755
// offering a choice to debug the aborted program - we want to disable that.
4756
prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
4757
// In debug mode, the Windows CRT can crash with an assertion over invalid
4758
// input (e.g. passing an invalid file descriptor). The default handling
4759
// for these assertions is to pop up a dialog and wait for user input.
4760
// Instead ask the CRT to dump such assertions to stderr non-interactively.
4761
prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
4762
prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
4763
}
4764
4765
static void reset() {
4766
if(isSet) {
4767
// Unregister handler and restore the old guarantee
4768
SetUnhandledExceptionFilter(previousTop);
4769
SetThreadStackGuarantee(&guaranteeSize);
4770
std::set_terminate(original_terminate_handler);
4771
std::signal(SIGABRT, prev_sigabrt_handler);
4772
SetErrorMode(prev_error_mode_1);
4773
_set_error_mode(prev_error_mode_2);
4774
_set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
4775
static_cast<void>(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode));
4776
static_cast<void>(_CrtSetReportFile(_CRT_ASSERT, prev_report_file));
4777
isSet = false;
4778
}
4779
}
4780
4781
~FatalConditionHandler() { reset(); }
4782
4783
private:
4784
static UINT prev_error_mode_1;
4785
static int prev_error_mode_2;
4786
static unsigned int prev_abort_behavior;
4787
static int prev_report_mode;
4788
static _HFILE prev_report_file;
4789
static void (DOCTEST_CDECL *prev_sigabrt_handler)(int);
4790
static std::terminate_handler original_terminate_handler;
4791
static bool isSet;
4792
static ULONG guaranteeSize;
4793
static LPTOP_LEVEL_EXCEPTION_FILTER previousTop;
4794
};
4795
4796
UINT FatalConditionHandler::prev_error_mode_1;
4797
int FatalConditionHandler::prev_error_mode_2;
4798
unsigned int FatalConditionHandler::prev_abort_behavior;
4799
int FatalConditionHandler::prev_report_mode;
4800
_HFILE FatalConditionHandler::prev_report_file;
4801
void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int);
4802
std::terminate_handler FatalConditionHandler::original_terminate_handler;
4803
bool FatalConditionHandler::isSet = false;
4804
ULONG FatalConditionHandler::guaranteeSize = 0;
4805
LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr;
4806
4807
#else // DOCTEST_PLATFORM_WINDOWS
4808
4809
struct SignalDefs
4810
{
4811
int id;
4812
const char* name;
4813
};
4814
SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"},
4815
{SIGILL, "SIGILL - Illegal instruction signal"},
4816
{SIGFPE, "SIGFPE - Floating point error signal"},
4817
{SIGSEGV, "SIGSEGV - Segmentation violation signal"},
4818
{SIGTERM, "SIGTERM - Termination request signal"},
4819
{SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}};
4820
4821
struct FatalConditionHandler
4822
{
4823
static bool isSet;
4824
static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)];
4825
static stack_t oldSigStack;
4826
static size_t altStackSize;
4827
static char* altStackMem;
4828
4829
static void handleSignal(int sig) {
4830
const char* name = "<unknown signal>";
4831
for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
4832
SignalDefs& def = signalDefs[i];
4833
if(sig == def.id) {
4834
name = def.name;
4835
break;
4836
}
4837
}
4838
reset();
4839
reportFatal(name);
4840
raise(sig);
4841
}
4842
4843
static void allocateAltStackMem() {
4844
altStackMem = new char[altStackSize];
4845
}
4846
4847
static void freeAltStackMem() {
4848
delete[] altStackMem;
4849
}
4850
4851
FatalConditionHandler() {
4852
isSet = true;
4853
stack_t sigStack;
4854
sigStack.ss_sp = altStackMem;
4855
sigStack.ss_size = altStackSize;
4856
sigStack.ss_flags = 0;
4857
sigaltstack(&sigStack, &oldSigStack);
4858
struct sigaction sa = {};
4859
sa.sa_handler = handleSignal;
4860
sa.sa_flags = SA_ONSTACK;
4861
for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
4862
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
4863
}
4864
}
4865
4866
~FatalConditionHandler() { reset(); }
4867
static void reset() {
4868
if(isSet) {
4869
// Set signals back to previous values -- hopefully nobody overwrote them in the meantime
4870
for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
4871
sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
4872
}
4873
// Return the old stack
4874
sigaltstack(&oldSigStack, nullptr);
4875
isSet = false;
4876
}
4877
}
4878
};
4879
4880
bool FatalConditionHandler::isSet = false;
4881
struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {};
4882
stack_t FatalConditionHandler::oldSigStack = {};
4883
size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ;
4884
char* FatalConditionHandler::altStackMem = nullptr;
4885
4886
#endif // DOCTEST_PLATFORM_WINDOWS
4887
#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
4888
4889
} // namespace
4890
4891
namespace {
4892
using namespace detail;
4893
4894
#ifdef DOCTEST_PLATFORM_WINDOWS
4895
#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text)
4896
#else
4897
// TODO: integration with XCode and other IDEs
4898
#define DOCTEST_OUTPUT_DEBUG_STRING(text)
4899
#endif // Platform
4900
4901
void addAssert(assertType::Enum at) {
4902
if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
4903
g_cs->numAssertsCurrentTest_atomic++;
4904
}
4905
4906
void addFailedAssert(assertType::Enum at) {
4907
if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional
4908
g_cs->numAssertsFailedCurrentTest_atomic++;
4909
}
4910
4911
#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH)
4912
void reportFatal(const std::string& message) {
4913
g_cs->failure_flags |= TestCaseFailureReason::Crash;
4914
4915
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
4916
4917
while (g_cs->subcaseStack.size()) {
4918
g_cs->subcaseStack.pop_back();
4919
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
4920
}
4921
4922
g_cs->finalizeTestCaseData();
4923
4924
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
4925
4926
DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
4927
}
4928
#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
4929
} // namespace
4930
4931
AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr,
4932
const char* exception_type, const StringContains& exception_string)
4933
: m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr),
4934
m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type),
4935
m_exception_string(exception_string) {
4936
#if DOCTEST_MSVC
4937
if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
4938
++m_expr;
4939
#endif // MSVC
4940
}
4941
4942
namespace detail {
4943
ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
4944
const char* exception_type, const String& exception_string)
4945
: AssertData(at, file, line, expr, exception_type, exception_string) { }
4946
4947
ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
4948
const char* exception_type, const Contains& exception_string)
4949
: AssertData(at, file, line, expr, exception_type, exception_string) { }
4950
4951
void ResultBuilder::setResult(const Result& res) {
4952
m_decomp = res.m_decomp;
4953
m_failed = !res.m_passed;
4954
}
4955
4956
void ResultBuilder::translateException() {
4957
m_threw = true;
4958
m_exception = translateActiveException();
4959
}
4960
4961
bool ResultBuilder::log() {
4962
if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
4963
m_failed = !m_threw;
4964
} else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT
4965
m_failed = !m_threw_as || !m_exception_string.check(m_exception);
4966
} else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
4967
m_failed = !m_threw_as;
4968
} else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
4969
m_failed = !m_exception_string.check(m_exception);
4970
} else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
4971
m_failed = m_threw;
4972
}
4973
4974
if(m_exception.size())
4975
m_exception = "\"" + m_exception + "\"";
4976
4977
if(is_running_in_test) {
4978
addAssert(m_at);
4979
DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this);
4980
4981
if(m_failed)
4982
addFailedAssert(m_at);
4983
} else if(m_failed) {
4984
failed_out_of_a_testing_context(*this);
4985
}
4986
4987
return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks &&
4988
(g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
4989
}
4990
4991
void ResultBuilder::react() const {
4992
if(m_failed && checkIfShouldThrow(m_at))
4993
throwException();
4994
}
4995
4996
void failed_out_of_a_testing_context(const AssertData& ad) {
4997
if(g_cs->ah)
4998
g_cs->ah(ad);
4999
else
5000
std::abort();
5001
}
5002
5003
bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
5004
const Result& result) {
5005
bool failed = !result.m_passed;
5006
5007
// ###################################################################################
5008
// IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
5009
// THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
5010
// ###################################################################################
5011
DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp);
5012
DOCTEST_ASSERT_IN_TESTS(result.m_decomp);
5013
return !failed;
5014
}
5015
5016
MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) {
5017
m_stream = tlssPush();
5018
m_file = file;
5019
m_line = line;
5020
m_severity = severity;
5021
}
5022
5023
MessageBuilder::~MessageBuilder() {
5024
if (!logged)
5025
tlssPop();
5026
}
5027
5028
DOCTEST_DEFINE_INTERFACE(IExceptionTranslator)
5029
5030
bool MessageBuilder::log() {
5031
if (!logged) {
5032
m_string = tlssPop();
5033
logged = true;
5034
}
5035
5036
DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this);
5037
5038
const bool isWarn = m_severity & assertType::is_warn;
5039
5040
// warn is just a message in this context so we don't treat it as an assert
5041
if(!isWarn) {
5042
addAssert(m_severity);
5043
addFailedAssert(m_severity);
5044
}
5045
5046
return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn &&
5047
(g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger
5048
}
5049
5050
void MessageBuilder::react() {
5051
if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional
5052
throwException();
5053
}
5054
} // namespace detail
5055
namespace {
5056
using namespace detail;
5057
5058
// clang-format off
5059
5060
// =================================================================================================
5061
// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
5062
// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
5063
// =================================================================================================
5064
5065
class XmlEncode {
5066
public:
5067
enum ForWhat { ForTextNodes, ForAttributes };
5068
5069
XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
5070
5071
void encodeTo( std::ostream& os ) const;
5072
5073
friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
5074
5075
private:
5076
std::string m_str;
5077
ForWhat m_forWhat;
5078
};
5079
5080
class XmlWriter {
5081
public:
5082
5083
class ScopedElement {
5084
public:
5085
ScopedElement( XmlWriter* writer );
5086
5087
ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT;
5088
ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT;
5089
5090
~ScopedElement();
5091
5092
ScopedElement& writeText( std::string const& text, bool indent = true );
5093
5094
template<typename T>
5095
ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
5096
m_writer->writeAttribute( name, attribute );
5097
return *this;
5098
}
5099
5100
private:
5101
mutable XmlWriter* m_writer = nullptr;
5102
};
5103
5104
#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
5105
XmlWriter( std::ostream& os = std::cout );
5106
#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
5107
XmlWriter( std::ostream& os );
5108
#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
5109
~XmlWriter();
5110
5111
XmlWriter( XmlWriter const& ) = delete;
5112
XmlWriter& operator=( XmlWriter const& ) = delete;
5113
5114
XmlWriter& startElement( std::string const& name );
5115
5116
ScopedElement scopedElement( std::string const& name );
5117
5118
XmlWriter& endElement();
5119
5120
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
5121
5122
XmlWriter& writeAttribute( std::string const& name, const char* attribute );
5123
5124
XmlWriter& writeAttribute( std::string const& name, bool attribute );
5125
5126
template<typename T>
5127
XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
5128
std::stringstream rss;
5129
rss << attribute;
5130
return writeAttribute( name, rss.str() );
5131
}
5132
5133
XmlWriter& writeText( std::string const& text, bool indent = true );
5134
5135
//XmlWriter& writeComment( std::string const& text );
5136
5137
//void writeStylesheetRef( std::string const& url );
5138
5139
//XmlWriter& writeBlankLine();
5140
5141
void ensureTagClosed();
5142
5143
void writeDeclaration();
5144
5145
private:
5146
5147
void newlineIfNecessary();
5148
5149
bool m_tagIsOpen = false;
5150
bool m_needsNewline = false;
5151
std::vector<std::string> m_tags;
5152
std::string m_indent;
5153
std::ostream& m_os;
5154
};
5155
5156
// =================================================================================================
5157
// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp
5158
// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched.
5159
// =================================================================================================
5160
5161
using uchar = unsigned char;
5162
5163
namespace {
5164
5165
size_t trailingBytes(unsigned char c) {
5166
if ((c & 0xE0) == 0xC0) {
5167
return 2;
5168
}
5169
if ((c & 0xF0) == 0xE0) {
5170
return 3;
5171
}
5172
if ((c & 0xF8) == 0xF0) {
5173
return 4;
5174
}
5175
DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
5176
}
5177
5178
uint32_t headerValue(unsigned char c) {
5179
if ((c & 0xE0) == 0xC0) {
5180
return c & 0x1F;
5181
}
5182
if ((c & 0xF0) == 0xE0) {
5183
return c & 0x0F;
5184
}
5185
if ((c & 0xF8) == 0xF0) {
5186
return c & 0x07;
5187
}
5188
DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
5189
}
5190
5191
void hexEscapeChar(std::ostream& os, unsigned char c) {
5192
std::ios_base::fmtflags f(os.flags());
5193
os << "\\x"
5194
<< std::uppercase << std::hex << std::setfill('0') << std::setw(2)
5195
<< static_cast<int>(c);
5196
os.flags(f);
5197
}
5198
5199
} // anonymous namespace
5200
5201
XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
5202
: m_str( str ),
5203
m_forWhat( forWhat )
5204
{}
5205
5206
void XmlEncode::encodeTo( std::ostream& os ) const {
5207
// Apostrophe escaping not necessary if we always use " to write attributes
5208
// (see: https://www.w3.org/TR/xml/#syntax)
5209
5210
for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
5211
uchar c = m_str[idx];
5212
switch (c) {
5213
case '<': os << "&lt;"; break;
5214
case '&': os << "&amp;"; break;
5215
5216
case '>':
5217
// See: https://www.w3.org/TR/xml/#syntax
5218
if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
5219
os << "&gt;";
5220
else
5221
os << c;
5222
break;
5223
5224
case '\"':
5225
if (m_forWhat == ForAttributes)
5226
os << "&quot;";
5227
else
5228
os << c;
5229
break;
5230
5231
default:
5232
// Check for control characters and invalid utf-8
5233
5234
// Escape control characters in standard ascii
5235
// see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
5236
if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
5237
hexEscapeChar(os, c);
5238
break;
5239
}
5240
5241
// Plain ASCII: Write it to stream
5242
if (c < 0x7F) {
5243
os << c;
5244
break;
5245
}
5246
5247
// UTF-8 territory
5248
// Check if the encoding is valid and if it is not, hex escape bytes.
5249
// Important: We do not check the exact decoded values for validity, only the encoding format
5250
// First check that this bytes is a valid lead byte:
5251
// This means that it is not encoded as 1111 1XXX
5252
// Or as 10XX XXXX
5253
if (c < 0xC0 ||
5254
c >= 0xF8) {
5255
hexEscapeChar(os, c);
5256
break;
5257
}
5258
5259
auto encBytes = trailingBytes(c);
5260
// Are there enough bytes left to avoid accessing out-of-bounds memory?
5261
if (idx + encBytes - 1 >= m_str.size()) {
5262
hexEscapeChar(os, c);
5263
break;
5264
}
5265
// The header is valid, check data
5266
// The next encBytes bytes must together be a valid utf-8
5267
// This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
5268
bool valid = true;
5269
uint32_t value = headerValue(c);
5270
for (std::size_t n = 1; n < encBytes; ++n) {
5271
uchar nc = m_str[idx + n];
5272
valid &= ((nc & 0xC0) == 0x80);
5273
value = (value << 6) | (nc & 0x3F);
5274
}
5275
5276
if (
5277
// Wrong bit pattern of following bytes
5278
(!valid) ||
5279
// Overlong encodings
5280
(value < 0x80) ||
5281
( value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant
5282
(0x800 < value && value < 0x10000 && encBytes > 3) ||
5283
// Encoded value out of range
5284
(value >= 0x110000)
5285
) {
5286
hexEscapeChar(os, c);
5287
break;
5288
}
5289
5290
// If we got here, this is in fact a valid(ish) utf-8 sequence
5291
for (std::size_t n = 0; n < encBytes; ++n) {
5292
os << m_str[idx + n];
5293
}
5294
idx += encBytes - 1;
5295
break;
5296
}
5297
}
5298
}
5299
5300
std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
5301
xmlEncode.encodeTo( os );
5302
return os;
5303
}
5304
5305
XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
5306
: m_writer( writer )
5307
{}
5308
5309
XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT
5310
: m_writer( other.m_writer ){
5311
other.m_writer = nullptr;
5312
}
5313
XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT {
5314
if ( m_writer ) {
5315
m_writer->endElement();
5316
}
5317
m_writer = other.m_writer;
5318
other.m_writer = nullptr;
5319
return *this;
5320
}
5321
5322
5323
XmlWriter::ScopedElement::~ScopedElement() {
5324
if( m_writer )
5325
m_writer->endElement();
5326
}
5327
5328
XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
5329
m_writer->writeText( text, indent );
5330
return *this;
5331
}
5332
5333
XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
5334
{
5335
// writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627
5336
}
5337
5338
XmlWriter::~XmlWriter() {
5339
while( !m_tags.empty() )
5340
endElement();
5341
}
5342
5343
XmlWriter& XmlWriter::startElement( std::string const& name ) {
5344
ensureTagClosed();
5345
newlineIfNecessary();
5346
m_os << m_indent << '<' << name;
5347
m_tags.push_back( name );
5348
m_indent += " ";
5349
m_tagIsOpen = true;
5350
return *this;
5351
}
5352
5353
XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
5354
ScopedElement scoped( this );
5355
startElement( name );
5356
return scoped;
5357
}
5358
5359
XmlWriter& XmlWriter::endElement() {
5360
newlineIfNecessary();
5361
m_indent = m_indent.substr( 0, m_indent.size()-2 );
5362
if( m_tagIsOpen ) {
5363
m_os << "/>";
5364
m_tagIsOpen = false;
5365
}
5366
else {
5367
m_os << m_indent << "</" << m_tags.back() << ">";
5368
}
5369
m_os << std::endl;
5370
m_tags.pop_back();
5371
return *this;
5372
}
5373
5374
XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
5375
if( !name.empty() && !attribute.empty() )
5376
m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
5377
return *this;
5378
}
5379
5380
XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) {
5381
if( !name.empty() && attribute && attribute[0] != '\0' )
5382
m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
5383
return *this;
5384
}
5385
5386
XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
5387
m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
5388
return *this;
5389
}
5390
5391
XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
5392
if( !text.empty() ){
5393
bool tagWasOpen = m_tagIsOpen;
5394
ensureTagClosed();
5395
if( tagWasOpen && indent )
5396
m_os << m_indent;
5397
m_os << XmlEncode( text );
5398
m_needsNewline = true;
5399
}
5400
return *this;
5401
}
5402
5403
//XmlWriter& XmlWriter::writeComment( std::string const& text ) {
5404
// ensureTagClosed();
5405
// m_os << m_indent << "<!--" << text << "-->";
5406
// m_needsNewline = true;
5407
// return *this;
5408
//}
5409
5410
//void XmlWriter::writeStylesheetRef( std::string const& url ) {
5411
// m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
5412
//}
5413
5414
//XmlWriter& XmlWriter::writeBlankLine() {
5415
// ensureTagClosed();
5416
// m_os << '\n';
5417
// return *this;
5418
//}
5419
5420
void XmlWriter::ensureTagClosed() {
5421
if( m_tagIsOpen ) {
5422
m_os << ">" << std::endl;
5423
m_tagIsOpen = false;
5424
}
5425
}
5426
5427
void XmlWriter::writeDeclaration() {
5428
m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
5429
}
5430
5431
void XmlWriter::newlineIfNecessary() {
5432
if( m_needsNewline ) {
5433
m_os << std::endl;
5434
m_needsNewline = false;
5435
}
5436
}
5437
5438
// =================================================================================================
5439
// End of copy-pasted code from Catch
5440
// =================================================================================================
5441
5442
// clang-format on
5443
5444
struct XmlReporter : public IReporter
5445
{
5446
XmlWriter xml;
5447
DOCTEST_DECLARE_MUTEX(mutex)
5448
5449
// caching pointers/references to objects of these types - safe to do
5450
const ContextOptions& opt;
5451
const TestCaseData* tc = nullptr;
5452
5453
XmlReporter(const ContextOptions& co)
5454
: xml(*co.cout)
5455
, opt(co) {}
5456
5457
void log_contexts() {
5458
int num_contexts = get_num_active_contexts();
5459
if(num_contexts) {
5460
auto contexts = get_active_contexts();
5461
std::stringstream ss;
5462
for(int i = 0; i < num_contexts; ++i) {
5463
contexts[i]->stringify(&ss);
5464
xml.scopedElement("Info").writeText(ss.str());
5465
ss.str("");
5466
}
5467
}
5468
}
5469
5470
unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
5471
5472
void test_case_start_impl(const TestCaseData& in) {
5473
bool open_ts_tag = false;
5474
if(tc != nullptr) { // we have already opened a test suite
5475
if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) {
5476
xml.endElement();
5477
open_ts_tag = true;
5478
}
5479
}
5480
else {
5481
open_ts_tag = true; // first test case ==> first test suite
5482
}
5483
5484
if(open_ts_tag) {
5485
xml.startElement("TestSuite");
5486
xml.writeAttribute("name", in.m_test_suite);
5487
}
5488
5489
tc = &in;
5490
xml.startElement("TestCase")
5491
.writeAttribute("name", in.m_name)
5492
.writeAttribute("filename", skipPathFromFilename(in.m_file.c_str()))
5493
.writeAttribute("line", line(in.m_line))
5494
.writeAttribute("description", in.m_description);
5495
5496
if(Approx(in.m_timeout) != 0)
5497
xml.writeAttribute("timeout", in.m_timeout);
5498
if(in.m_may_fail)
5499
xml.writeAttribute("may_fail", true);
5500
if(in.m_should_fail)
5501
xml.writeAttribute("should_fail", true);
5502
}
5503
5504
// =========================================================================================
5505
// WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
5506
// =========================================================================================
5507
5508
void report_query(const QueryData& in) override {
5509
test_run_start();
5510
if(opt.list_reporters) {
5511
for(auto& curr : getListeners())
5512
xml.scopedElement("Listener")
5513
.writeAttribute("priority", curr.first.first)
5514
.writeAttribute("name", curr.first.second);
5515
for(auto& curr : getReporters())
5516
xml.scopedElement("Reporter")
5517
.writeAttribute("priority", curr.first.first)
5518
.writeAttribute("name", curr.first.second);
5519
} else if(opt.count || opt.list_test_cases) {
5520
for(unsigned i = 0; i < in.num_data; ++i) {
5521
xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name)
5522
.writeAttribute("testsuite", in.data[i]->m_test_suite)
5523
.writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str()))
5524
.writeAttribute("line", line(in.data[i]->m_line))
5525
.writeAttribute("skipped", in.data[i]->m_skip);
5526
}
5527
xml.scopedElement("OverallResultsTestCases")
5528
.writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
5529
} else if(opt.list_test_suites) {
5530
for(unsigned i = 0; i < in.num_data; ++i)
5531
xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite);
5532
xml.scopedElement("OverallResultsTestCases")
5533
.writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
5534
xml.scopedElement("OverallResultsTestSuites")
5535
.writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters);
5536
}
5537
xml.endElement();
5538
}
5539
5540
void test_run_start() override {
5541
xml.writeDeclaration();
5542
5543
// remove .exe extension - mainly to have the same output on UNIX and Windows
5544
std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
5545
#ifdef DOCTEST_PLATFORM_WINDOWS
5546
if(binary_name.rfind(".exe") != std::string::npos)
5547
binary_name = binary_name.substr(0, binary_name.length() - 4);
5548
#endif // DOCTEST_PLATFORM_WINDOWS
5549
5550
xml.startElement("doctest").writeAttribute("binary", binary_name);
5551
if(opt.no_version == false)
5552
xml.writeAttribute("version", DOCTEST_VERSION_STR);
5553
5554
// only the consequential ones (TODO: filters)
5555
xml.scopedElement("Options")
5556
.writeAttribute("order_by", opt.order_by.c_str())
5557
.writeAttribute("rand_seed", opt.rand_seed)
5558
.writeAttribute("first", opt.first)
5559
.writeAttribute("last", opt.last)
5560
.writeAttribute("abort_after", opt.abort_after)
5561
.writeAttribute("subcase_filter_levels", opt.subcase_filter_levels)
5562
.writeAttribute("case_sensitive", opt.case_sensitive)
5563
.writeAttribute("no_throw", opt.no_throw)
5564
.writeAttribute("no_skip", opt.no_skip);
5565
}
5566
5567
void test_run_end(const TestRunStats& p) override {
5568
if(tc) // the TestSuite tag - only if there has been at least 1 test case
5569
xml.endElement();
5570
5571
xml.scopedElement("OverallResultsAsserts")
5572
.writeAttribute("successes", p.numAsserts - p.numAssertsFailed)
5573
.writeAttribute("failures", p.numAssertsFailed);
5574
5575
xml.startElement("OverallResultsTestCases")
5576
.writeAttribute("successes",
5577
p.numTestCasesPassingFilters - p.numTestCasesFailed)
5578
.writeAttribute("failures", p.numTestCasesFailed);
5579
if(opt.no_skipped_summary == false)
5580
xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters);
5581
xml.endElement();
5582
5583
xml.endElement();
5584
}
5585
5586
void test_case_start(const TestCaseData& in) override {
5587
test_case_start_impl(in);
5588
xml.ensureTagClosed();
5589
}
5590
5591
void test_case_reenter(const TestCaseData&) override {}
5592
5593
void test_case_end(const CurrentTestCaseStats& st) override {
5594
xml.startElement("OverallResultsAsserts")
5595
.writeAttribute("successes",
5596
st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest)
5597
.writeAttribute("failures", st.numAssertsFailedCurrentTest)
5598
.writeAttribute("test_case_success", st.testCaseSuccess);
5599
if(opt.duration)
5600
xml.writeAttribute("duration", st.seconds);
5601
if(tc->m_expected_failures)
5602
xml.writeAttribute("expected_failures", tc->m_expected_failures);
5603
xml.endElement();
5604
5605
xml.endElement();
5606
}
5607
5608
void test_case_exception(const TestCaseException& e) override {
5609
DOCTEST_LOCK_MUTEX(mutex)
5610
5611
xml.scopedElement("Exception")
5612
.writeAttribute("crash", e.is_crash)
5613
.writeText(e.error_string.c_str());
5614
}
5615
5616
void subcase_start(const SubcaseSignature& in) override {
5617
xml.startElement("SubCase")
5618
.writeAttribute("name", in.m_name)
5619
.writeAttribute("filename", skipPathFromFilename(in.m_file))
5620
.writeAttribute("line", line(in.m_line));
5621
xml.ensureTagClosed();
5622
}
5623
5624
void subcase_end() override { xml.endElement(); }
5625
5626
void log_assert(const AssertData& rb) override {
5627
if(!rb.m_failed && !opt.success)
5628
return;
5629
5630
DOCTEST_LOCK_MUTEX(mutex)
5631
5632
xml.startElement("Expression")
5633
.writeAttribute("success", !rb.m_failed)
5634
.writeAttribute("type", assertString(rb.m_at))
5635
.writeAttribute("filename", skipPathFromFilename(rb.m_file))
5636
.writeAttribute("line", line(rb.m_line));
5637
5638
xml.scopedElement("Original").writeText(rb.m_expr);
5639
5640
if(rb.m_threw)
5641
xml.scopedElement("Exception").writeText(rb.m_exception.c_str());
5642
5643
if(rb.m_at & assertType::is_throws_as)
5644
xml.scopedElement("ExpectedException").writeText(rb.m_exception_type);
5645
if(rb.m_at & assertType::is_throws_with)
5646
xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str());
5647
if((rb.m_at & assertType::is_normal) && !rb.m_threw)
5648
xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str());
5649
5650
log_contexts();
5651
5652
xml.endElement();
5653
}
5654
5655
void log_message(const MessageData& mb) override {
5656
DOCTEST_LOCK_MUTEX(mutex)
5657
5658
xml.startElement("Message")
5659
.writeAttribute("type", failureString(mb.m_severity))
5660
.writeAttribute("filename", skipPathFromFilename(mb.m_file))
5661
.writeAttribute("line", line(mb.m_line));
5662
5663
xml.scopedElement("Text").writeText(mb.m_string.c_str());
5664
5665
log_contexts();
5666
5667
xml.endElement();
5668
}
5669
5670
void test_case_skipped(const TestCaseData& in) override {
5671
if(opt.no_skipped_summary == false) {
5672
test_case_start_impl(in);
5673
xml.writeAttribute("skipped", "true");
5674
xml.endElement();
5675
}
5676
}
5677
};
5678
5679
DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter);
5680
5681
void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) {
5682
if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) ==
5683
0) //!OCLINT bitwise operator in conditional
5684
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) "
5685
<< Color::None;
5686
5687
if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
5688
s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n";
5689
} else if((rb.m_at & assertType::is_throws_as) &&
5690
(rb.m_at & assertType::is_throws_with)) { //!OCLINT
5691
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
5692
<< rb.m_exception_string.c_str()
5693
<< "\", " << rb.m_exception_type << " ) " << Color::None;
5694
if(rb.m_threw) {
5695
if(!rb.m_failed) {
5696
s << "threw as expected!\n";
5697
} else {
5698
s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n";
5699
}
5700
} else {
5701
s << "did NOT throw at all!\n";
5702
}
5703
} else if(rb.m_at &
5704
assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
5705
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", "
5706
<< rb.m_exception_type << " ) " << Color::None
5707
<< (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" :
5708
"threw a DIFFERENT exception: ") :
5709
"did NOT throw at all!")
5710
<< Color::Cyan << rb.m_exception << "\n";
5711
} else if(rb.m_at &
5712
assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
5713
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
5714
<< rb.m_exception_string.c_str()
5715
<< "\" ) " << Color::None
5716
<< (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
5717
"threw a DIFFERENT exception: ") :
5718
"did NOT throw at all!")
5719
<< Color::Cyan << rb.m_exception << "\n";
5720
} else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
5721
s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan
5722
<< rb.m_exception << "\n";
5723
} else {
5724
s << (rb.m_threw ? "THREW exception: " :
5725
(!rb.m_failed ? "is correct!\n" : "is NOT correct!\n"));
5726
if(rb.m_threw)
5727
s << rb.m_exception << "\n";
5728
else
5729
s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n";
5730
}
5731
}
5732
5733
// TODO:
5734
// - log_message()
5735
// - respond to queries
5736
// - honor remaining options
5737
// - more attributes in tags
5738
struct JUnitReporter : public IReporter
5739
{
5740
XmlWriter xml;
5741
DOCTEST_DECLARE_MUTEX(mutex)
5742
Timer timer;
5743
std::vector<String> deepestSubcaseStackNames;
5744
5745
struct JUnitTestCaseData
5746
{
5747
static std::string getCurrentTimestamp() {
5748
// Beware, this is not reentrant because of backward compatibility issues
5749
// Also, UTC only, again because of backward compatibility (%z is C++11)
5750
time_t rawtime;
5751
std::time(&rawtime);
5752
auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
5753
5754
std::tm timeInfo;
5755
#ifdef DOCTEST_PLATFORM_WINDOWS
5756
gmtime_s(&timeInfo, &rawtime);
5757
#else // DOCTEST_PLATFORM_WINDOWS
5758
gmtime_r(&rawtime, &timeInfo);
5759
#endif // DOCTEST_PLATFORM_WINDOWS
5760
5761
char timeStamp[timeStampSize];
5762
const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
5763
5764
std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
5765
return std::string(timeStamp);
5766
}
5767
5768
struct JUnitTestMessage
5769
{
5770
JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details)
5771
: message(_message), type(_type), details(_details) {}
5772
5773
JUnitTestMessage(const std::string& _message, const std::string& _details)
5774
: message(_message), type(), details(_details) {}
5775
5776
std::string message, type, details;
5777
};
5778
5779
struct JUnitTestCase
5780
{
5781
JUnitTestCase(const std::string& _classname, const std::string& _name)
5782
: classname(_classname), name(_name), time(0), failures() {}
5783
5784
std::string classname, name;
5785
double time;
5786
std::vector<JUnitTestMessage> failures, errors;
5787
};
5788
5789
void add(const std::string& classname, const std::string& name) {
5790
testcases.emplace_back(classname, name);
5791
}
5792
5793
void appendSubcaseNamesToLastTestcase(std::vector<String> nameStack) {
5794
for(auto& curr: nameStack)
5795
if(curr.size())
5796
testcases.back().name += std::string("/") + curr.c_str();
5797
}
5798
5799
void addTime(double time) {
5800
if(time < 1e-4)
5801
time = 0;
5802
testcases.back().time = time;
5803
totalSeconds += time;
5804
}
5805
5806
void addFailure(const std::string& message, const std::string& type, const std::string& details) {
5807
testcases.back().failures.emplace_back(message, type, details);
5808
++totalFailures;
5809
}
5810
5811
void addError(const std::string& message, const std::string& details) {
5812
testcases.back().errors.emplace_back(message, details);
5813
++totalErrors;
5814
}
5815
5816
std::vector<JUnitTestCase> testcases;
5817
double totalSeconds = 0;
5818
int totalErrors = 0, totalFailures = 0;
5819
};
5820
5821
JUnitTestCaseData testCaseData;
5822
5823
// caching pointers/references to objects of these types - safe to do
5824
const ContextOptions& opt;
5825
const TestCaseData* tc = nullptr;
5826
5827
JUnitReporter(const ContextOptions& co)
5828
: xml(*co.cout)
5829
, opt(co) {}
5830
5831
unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; }
5832
5833
// =========================================================================================
5834
// WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
5835
// =========================================================================================
5836
5837
void report_query(const QueryData&) override {
5838
xml.writeDeclaration();
5839
}
5840
5841
void test_run_start() override {
5842
xml.writeDeclaration();
5843
}
5844
5845
void test_run_end(const TestRunStats& p) override {
5846
// remove .exe extension - mainly to have the same output on UNIX and Windows
5847
std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
5848
#ifdef DOCTEST_PLATFORM_WINDOWS
5849
if(binary_name.rfind(".exe") != std::string::npos)
5850
binary_name = binary_name.substr(0, binary_name.length() - 4);
5851
#endif // DOCTEST_PLATFORM_WINDOWS
5852
xml.startElement("testsuites");
5853
xml.startElement("testsuite").writeAttribute("name", binary_name)
5854
.writeAttribute("errors", testCaseData.totalErrors)
5855
.writeAttribute("failures", testCaseData.totalFailures)
5856
.writeAttribute("tests", p.numAsserts);
5857
if(opt.no_time_in_output == false) {
5858
xml.writeAttribute("time", testCaseData.totalSeconds);
5859
xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp());
5860
}
5861
if(opt.no_version == false)
5862
xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR);
5863
5864
for(const auto& testCase : testCaseData.testcases) {
5865
xml.startElement("testcase")
5866
.writeAttribute("classname", testCase.classname)
5867
.writeAttribute("name", testCase.name);
5868
if(opt.no_time_in_output == false)
5869
xml.writeAttribute("time", testCase.time);
5870
// This is not ideal, but it should be enough to mimic gtest's junit output.
5871
xml.writeAttribute("status", "run");
5872
5873
for(const auto& failure : testCase.failures) {
5874
xml.scopedElement("failure")
5875
.writeAttribute("message", failure.message)
5876
.writeAttribute("type", failure.type)
5877
.writeText(failure.details, false);
5878
}
5879
5880
for(const auto& error : testCase.errors) {
5881
xml.scopedElement("error")
5882
.writeAttribute("message", error.message)
5883
.writeText(error.details);
5884
}
5885
5886
xml.endElement();
5887
}
5888
xml.endElement();
5889
xml.endElement();
5890
}
5891
5892
void test_case_start(const TestCaseData& in) override {
5893
testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
5894
timer.start();
5895
}
5896
5897
void test_case_reenter(const TestCaseData& in) override {
5898
testCaseData.addTime(timer.getElapsedSeconds());
5899
testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
5900
deepestSubcaseStackNames.clear();
5901
5902
timer.start();
5903
testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name);
5904
}
5905
5906
void test_case_end(const CurrentTestCaseStats&) override {
5907
testCaseData.addTime(timer.getElapsedSeconds());
5908
testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames);
5909
deepestSubcaseStackNames.clear();
5910
}
5911
5912
void test_case_exception(const TestCaseException& e) override {
5913
DOCTEST_LOCK_MUTEX(mutex)
5914
testCaseData.addError("exception", e.error_string.c_str());
5915
}
5916
5917
void subcase_start(const SubcaseSignature& in) override {
5918
deepestSubcaseStackNames.push_back(in.m_name);
5919
}
5920
5921
void subcase_end() override {}
5922
5923
void log_assert(const AssertData& rb) override {
5924
if(!rb.m_failed) // report only failures & ignore the `success` option
5925
return;
5926
5927
DOCTEST_LOCK_MUTEX(mutex)
5928
5929
std::ostringstream os;
5930
os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(")
5931
<< line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
5932
5933
fulltext_log_assert_to_stream(os, rb);
5934
log_contexts(os);
5935
testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str());
5936
}
5937
5938
void log_message(const MessageData& mb) override {
5939
if(mb.m_severity & assertType::is_warn) // report only failures
5940
return;
5941
5942
DOCTEST_LOCK_MUTEX(mutex)
5943
5944
std::ostringstream os;
5945
os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(")
5946
<< line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl;
5947
5948
os << mb.m_string.c_str() << "\n";
5949
log_contexts(os);
5950
5951
testCaseData.addFailure(mb.m_string.c_str(),
5952
mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str());
5953
}
5954
5955
void test_case_skipped(const TestCaseData&) override {}
5956
5957
void log_contexts(std::ostringstream& s) {
5958
int num_contexts = get_num_active_contexts();
5959
if(num_contexts) {
5960
auto contexts = get_active_contexts();
5961
5962
s << " logged: ";
5963
for(int i = 0; i < num_contexts; ++i) {
5964
s << (i == 0 ? "" : " ");
5965
contexts[i]->stringify(&s);
5966
s << std::endl;
5967
}
5968
}
5969
}
5970
};
5971
5972
DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter);
5973
5974
struct Whitespace
5975
{
5976
int nrSpaces;
5977
explicit Whitespace(int nr)
5978
: nrSpaces(nr) {}
5979
};
5980
5981
std::ostream& operator<<(std::ostream& out, const Whitespace& ws) {
5982
if(ws.nrSpaces != 0)
5983
out << std::setw(ws.nrSpaces) << ' ';
5984
return out;
5985
}
5986
5987
struct ConsoleReporter : public IReporter
5988
{
5989
std::ostream& s;
5990
bool hasLoggedCurrentTestStart;
5991
std::vector<SubcaseSignature> subcasesStack;
5992
size_t currentSubcaseLevel;
5993
DOCTEST_DECLARE_MUTEX(mutex)
5994
5995
// caching pointers/references to objects of these types - safe to do
5996
const ContextOptions& opt;
5997
const TestCaseData* tc;
5998
5999
ConsoleReporter(const ContextOptions& co)
6000
: s(*co.cout)
6001
, opt(co) {}
6002
6003
ConsoleReporter(const ContextOptions& co, std::ostream& ostr)
6004
: s(ostr)
6005
, opt(co) {}
6006
6007
// =========================================================================================
6008
// WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE
6009
// =========================================================================================
6010
6011
void separator_to_stream() {
6012
s << Color::Yellow
6013
<< "==============================================================================="
6014
"\n";
6015
}
6016
6017
const char* getSuccessOrFailString(bool success, assertType::Enum at,
6018
const char* success_str) {
6019
if(success)
6020
return success_str;
6021
return failureString(at);
6022
}
6023
6024
Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) {
6025
return success ? Color::BrightGreen :
6026
(at & assertType::is_warn) ? Color::Yellow : Color::Red;
6027
}
6028
6029
void successOrFailColoredStringToStream(bool success, assertType::Enum at,
6030
const char* success_str = "SUCCESS") {
6031
s << getSuccessOrFailColor(success, at)
6032
<< getSuccessOrFailString(success, at, success_str) << ": ";
6033
}
6034
6035
void log_contexts() {
6036
int num_contexts = get_num_active_contexts();
6037
if(num_contexts) {
6038
auto contexts = get_active_contexts();
6039
6040
s << Color::None << " logged: ";
6041
for(int i = 0; i < num_contexts; ++i) {
6042
s << (i == 0 ? "" : " ");
6043
contexts[i]->stringify(&s);
6044
s << "\n";
6045
}
6046
}
6047
6048
s << "\n";
6049
}
6050
6051
// this was requested to be made virtual so users could override it
6052
virtual void file_line_to_stream(const char* file, int line,
6053
const char* tail = "") {
6054
s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(")
6055
<< (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option
6056
<< (opt.gnu_file_line ? ":" : "):") << tail;
6057
}
6058
6059
void logTestStart() {
6060
if(hasLoggedCurrentTestStart)
6061
return;
6062
6063
separator_to_stream();
6064
file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n");
6065
if(tc->m_description)
6066
s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n";
6067
if(tc->m_test_suite && tc->m_test_suite[0] != '\0')
6068
s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n";
6069
if(strncmp(tc->m_name, " Scenario:", 11) != 0)
6070
s << Color::Yellow << "TEST CASE: ";
6071
s << Color::None << tc->m_name << "\n";
6072
6073
for(size_t i = 0; i < currentSubcaseLevel; ++i) {
6074
if(subcasesStack[i].m_name[0] != '\0')
6075
s << " " << subcasesStack[i].m_name << "\n";
6076
}
6077
6078
if(currentSubcaseLevel != subcasesStack.size()) {
6079
s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None;
6080
for(size_t i = 0; i < subcasesStack.size(); ++i) {
6081
if(subcasesStack[i].m_name[0] != '\0')
6082
s << " " << subcasesStack[i].m_name << "\n";
6083
}
6084
}
6085
6086
s << "\n";
6087
6088
hasLoggedCurrentTestStart = true;
6089
}
6090
6091
void printVersion() {
6092
if(opt.no_version == false)
6093
s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \""
6094
<< DOCTEST_VERSION_STR << "\"\n";
6095
}
6096
6097
void printIntro() {
6098
if(opt.no_intro == false) {
6099
printVersion();
6100
s << Color::Cyan << "[doctest] " << Color::None
6101
<< "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
6102
}
6103
}
6104
6105
void printHelp() {
6106
int sizePrefixDisplay = static_cast<int>(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY));
6107
printVersion();
6108
// clang-format off
6109
s << Color::Cyan << "[doctest]\n" << Color::None;
6110
s << Color::Cyan << "[doctest] " << Color::None;
6111
s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n";
6112
s << Color::Cyan << "[doctest] " << Color::None;
6113
s << "filter values: \"str1,str2,str3\" (comma separated strings)\n";
6114
s << Color::Cyan << "[doctest]\n" << Color::None;
6115
s << Color::Cyan << "[doctest] " << Color::None;
6116
s << "filters use wildcards for matching strings\n";
6117
s << Color::Cyan << "[doctest] " << Color::None;
6118
s << "something passes a filter if any of the strings in a filter matches\n";
6119
#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
6120
s << Color::Cyan << "[doctest]\n" << Color::None;
6121
s << Color::Cyan << "[doctest] " << Color::None;
6122
s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n";
6123
#endif
6124
s << Color::Cyan << "[doctest]\n" << Color::None;
6125
s << Color::Cyan << "[doctest] " << Color::None;
6126
s << "Query flags - the program quits after them. Available:\n\n";
6127
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h "
6128
<< Whitespace(sizePrefixDisplay*0) << "prints this message\n";
6129
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version "
6130
<< Whitespace(sizePrefixDisplay*1) << "prints the version\n";
6131
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count "
6132
<< Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n";
6133
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases "
6134
<< Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n";
6135
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites "
6136
<< Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n";
6137
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters "
6138
<< Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n";
6139
// ================================================================================== << 79
6140
s << Color::Cyan << "[doctest] " << Color::None;
6141
s << "The available <int>/<string> options/filters are:\n\n";
6142
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case=<filters> "
6143
<< Whitespace(sizePrefixDisplay*1) << "filters tests by their name\n";
6144
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude=<filters> "
6145
<< Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n";
6146
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file=<filters> "
6147
<< Whitespace(sizePrefixDisplay*1) << "filters tests by their file\n";
6148
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude=<filters> "
6149
<< Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n";
6150
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite=<filters> "
6151
<< Whitespace(sizePrefixDisplay*1) << "filters tests by their test suite\n";
6152
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude=<filters> "
6153
<< Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n";
6154
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase=<filters> "
6155
<< Whitespace(sizePrefixDisplay*1) << "filters subcases by their name\n";
6156
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude=<filters> "
6157
<< Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n";
6158
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters=<filters> "
6159
<< Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n";
6160
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out=<string> "
6161
<< Whitespace(sizePrefixDisplay*1) << "output filename\n";
6162
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by=<string> "
6163
<< Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n";
6164
s << Whitespace(sizePrefixDisplay*3) << " <string> - [file/suite/name/rand/none]\n";
6165
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed=<int> "
6166
<< Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n";
6167
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first=<int> "
6168
<< Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n";
6169
s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n";
6170
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last=<int> "
6171
<< Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n";
6172
s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n";
6173
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after=<int> "
6174
<< Whitespace(sizePrefixDisplay*1) << "stop after <int> failed assertions\n";
6175
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels=<int> "
6176
<< Whitespace(sizePrefixDisplay*1) << "apply filters for the first <int> levels\n";
6177
s << Color::Cyan << "\n[doctest] " << Color::None;
6178
s << "Bool options - can be used like flags and true is assumed. Available:\n\n";
6179
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success=<bool> "
6180
<< Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n";
6181
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive=<bool> "
6182
<< Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n";
6183
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit=<bool> "
6184
<< Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n";
6185
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration=<bool> "
6186
<< Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n";
6187
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal=<bool> "
6188
<< Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n";
6189
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet=<bool> "
6190
<< Whitespace(sizePrefixDisplay*1) << "no console output\n";
6191
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw=<bool> "
6192
<< Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n";
6193
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode=<bool> "
6194
<< Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n";
6195
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run=<bool> "
6196
<< Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n";
6197
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro=<bool> "
6198
<< Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n";
6199
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version=<bool> "
6200
<< Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n";
6201
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors=<bool> "
6202
<< Whitespace(sizePrefixDisplay*1) << "disables colors in output\n";
6203
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors=<bool> "
6204
<< Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n";
6205
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks=<bool> "
6206
<< Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n";
6207
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip=<bool> "
6208
<< Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n";
6209
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line=<bool> "
6210
<< Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n";
6211
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames=<bool> "
6212
<< Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n";
6213
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "spp, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "skip-path-prefixes=<p1:p2> "
6214
<< Whitespace(sizePrefixDisplay*1) << "whenever file paths start with this prefix, remove it from the output\n";
6215
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers=<bool> "
6216
<< Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n";
6217
// ================================================================================== << 79
6218
// clang-format on
6219
6220
s << Color::Cyan << "\n[doctest] " << Color::None;
6221
s << "for more information visit the project documentation\n\n";
6222
}
6223
6224
void printRegisteredReporters() {
6225
printVersion();
6226
auto printReporters = [this] (const reporterMap& reporters, const char* type) {
6227
if(reporters.size()) {
6228
s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n";
6229
for(auto& curr : reporters)
6230
s << "priority: " << std::setw(5) << curr.first.first
6231
<< " name: " << curr.first.second << "\n";
6232
}
6233
};
6234
printReporters(getListeners(), "listeners");
6235
printReporters(getReporters(), "reporters");
6236
}
6237
6238
// =========================================================================================
6239
// WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
6240
// =========================================================================================
6241
6242
void report_query(const QueryData& in) override {
6243
if(opt.version) {
6244
printVersion();
6245
} else if(opt.help) {
6246
printHelp();
6247
} else if(opt.list_reporters) {
6248
printRegisteredReporters();
6249
} else if(opt.count || opt.list_test_cases) {
6250
if(opt.list_test_cases) {
6251
s << Color::Cyan << "[doctest] " << Color::None
6252
<< "listing all test case names\n";
6253
separator_to_stream();
6254
}
6255
6256
for(unsigned i = 0; i < in.num_data; ++i)
6257
s << Color::None << in.data[i]->m_name << "\n";
6258
6259
separator_to_stream();
6260
6261
s << Color::Cyan << "[doctest] " << Color::None
6262
<< "unskipped test cases passing the current filters: "
6263
<< g_cs->numTestCasesPassingFilters << "\n";
6264
6265
} else if(opt.list_test_suites) {
6266
s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n";
6267
separator_to_stream();
6268
6269
for(unsigned i = 0; i < in.num_data; ++i)
6270
s << Color::None << in.data[i]->m_test_suite << "\n";
6271
6272
separator_to_stream();
6273
6274
s << Color::Cyan << "[doctest] " << Color::None
6275
<< "unskipped test cases passing the current filters: "
6276
<< g_cs->numTestCasesPassingFilters << "\n";
6277
s << Color::Cyan << "[doctest] " << Color::None
6278
<< "test suites with unskipped test cases passing the current filters: "
6279
<< g_cs->numTestSuitesPassingFilters << "\n";
6280
}
6281
}
6282
6283
void test_run_start() override {
6284
if(!opt.minimal)
6285
printIntro();
6286
}
6287
6288
void test_run_end(const TestRunStats& p) override {
6289
if(opt.minimal && p.numTestCasesFailed == 0)
6290
return;
6291
6292
separator_to_stream();
6293
s << std::dec;
6294
6295
auto totwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesPassingFilters, static_cast<unsigned>(p.numAsserts))) + 1)));
6296
auto passwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast<unsigned>(p.numAsserts - p.numAssertsFailed))) + 1)));
6297
auto failwidth = int(std::ceil(log10(static_cast<double>(std::max(p.numTestCasesFailed, static_cast<unsigned>(p.numAssertsFailed))) + 1)));
6298
const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0;
6299
s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth)
6300
<< p.numTestCasesPassingFilters << " | "
6301
<< ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None :
6302
Color::Green)
6303
<< std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed"
6304
<< Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None)
6305
<< std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |";
6306
if(opt.no_skipped_summary == false) {
6307
const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters;
6308
s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped
6309
<< " skipped" << Color::None;
6310
}
6311
s << "\n";
6312
s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth)
6313
<< p.numAsserts << " | "
6314
<< ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green)
6315
<< std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None
6316
<< " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth)
6317
<< p.numAssertsFailed << " failed" << Color::None << " |\n";
6318
s << Color::Cyan << "[doctest] " << Color::None
6319
<< "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green)
6320
<< ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl;
6321
}
6322
6323
void test_case_start(const TestCaseData& in) override {
6324
hasLoggedCurrentTestStart = false;
6325
tc = &in;
6326
subcasesStack.clear();
6327
currentSubcaseLevel = 0;
6328
}
6329
6330
void test_case_reenter(const TestCaseData&) override {
6331
subcasesStack.clear();
6332
}
6333
6334
void test_case_end(const CurrentTestCaseStats& st) override {
6335
if(tc->m_no_output)
6336
return;
6337
6338
// log the preamble of the test case only if there is something
6339
// else to print - something other than that an assert has failed
6340
if(opt.duration ||
6341
(st.failure_flags && st.failure_flags != static_cast<int>(TestCaseFailureReason::AssertFailure)))
6342
logTestStart();
6343
6344
if(opt.duration)
6345
s << Color::None << std::setprecision(6) << std::fixed << st.seconds
6346
<< " s: " << tc->m_name << "\n";
6347
6348
if(st.failure_flags & TestCaseFailureReason::Timeout)
6349
s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6)
6350
<< std::fixed << tc->m_timeout << "!\n";
6351
6352
if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) {
6353
s << Color::Red << "Should have failed but didn't! Marking it as failed!\n";
6354
} else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) {
6355
s << Color::Yellow << "Failed as expected so marking it as not failed\n";
6356
} else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) {
6357
s << Color::Yellow << "Allowed to fail so marking it as not failed\n";
6358
} else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) {
6359
s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures
6360
<< " times so marking it as failed!\n";
6361
} else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) {
6362
s << Color::Yellow << "Failed exactly " << tc->m_expected_failures
6363
<< " times as expected so marking it as not failed!\n";
6364
}
6365
if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) {
6366
s << Color::Red << "Aborting - too many failed asserts!\n";
6367
}
6368
s << Color::None; // lgtm [cpp/useless-expression]
6369
}
6370
6371
void test_case_exception(const TestCaseException& e) override {
6372
DOCTEST_LOCK_MUTEX(mutex)
6373
if(tc->m_no_output)
6374
return;
6375
6376
logTestStart();
6377
6378
file_line_to_stream(tc->m_file.c_str(), tc->m_line, " ");
6379
successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require :
6380
assertType::is_check);
6381
s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ")
6382
<< Color::Cyan << e.error_string << "\n";
6383
6384
int num_stringified_contexts = get_num_stringified_contexts();
6385
if(num_stringified_contexts) {
6386
auto stringified_contexts = get_stringified_contexts();
6387
s << Color::None << " logged: ";
6388
for(int i = num_stringified_contexts; i > 0; --i) {
6389
s << (i == num_stringified_contexts ? "" : " ")
6390
<< stringified_contexts[i - 1] << "\n";
6391
}
6392
}
6393
s << "\n" << Color::None;
6394
}
6395
6396
void subcase_start(const SubcaseSignature& subc) override {
6397
subcasesStack.push_back(subc);
6398
++currentSubcaseLevel;
6399
hasLoggedCurrentTestStart = false;
6400
}
6401
6402
void subcase_end() override {
6403
--currentSubcaseLevel;
6404
hasLoggedCurrentTestStart = false;
6405
}
6406
6407
void log_assert(const AssertData& rb) override {
6408
if((!rb.m_failed && !opt.success) || tc->m_no_output)
6409
return;
6410
6411
DOCTEST_LOCK_MUTEX(mutex)
6412
6413
logTestStart();
6414
6415
file_line_to_stream(rb.m_file, rb.m_line, " ");
6416
successOrFailColoredStringToStream(!rb.m_failed, rb.m_at);
6417
6418
fulltext_log_assert_to_stream(s, rb);
6419
6420
log_contexts();
6421
}
6422
6423
void log_message(const MessageData& mb) override {
6424
if(tc->m_no_output)
6425
return;
6426
6427
DOCTEST_LOCK_MUTEX(mutex)
6428
6429
logTestStart();
6430
6431
file_line_to_stream(mb.m_file, mb.m_line, " ");
6432
s << getSuccessOrFailColor(false, mb.m_severity)
6433
<< getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity,
6434
"MESSAGE") << ": ";
6435
s << Color::None << mb.m_string << "\n";
6436
log_contexts();
6437
}
6438
6439
void test_case_skipped(const TestCaseData&) override {}
6440
};
6441
6442
DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter);
6443
6444
#ifdef DOCTEST_PLATFORM_WINDOWS
6445
struct DebugOutputWindowReporter : public ConsoleReporter
6446
{
6447
DOCTEST_THREAD_LOCAL static std::ostringstream oss;
6448
6449
DebugOutputWindowReporter(const ContextOptions& co)
6450
: ConsoleReporter(co, oss) {}
6451
6452
#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \
6453
void func(type arg) override { \
6454
bool with_col = g_no_colors; \
6455
g_no_colors = false; \
6456
ConsoleReporter::func(arg); \
6457
if(oss.tellp() != std::streampos{}) { \
6458
DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \
6459
oss.str(""); \
6460
} \
6461
g_no_colors = with_col; \
6462
}
6463
6464
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
6465
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in)
6466
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in)
6467
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in)
6468
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in)
6469
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in)
6470
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in)
6471
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY)
6472
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in)
6473
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in)
6474
DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in)
6475
};
6476
6477
DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss;
6478
#endif // DOCTEST_PLATFORM_WINDOWS
6479
6480
// the implementation of parseOption()
6481
bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) {
6482
// going from the end to the beginning and stopping on the first occurrence from the end
6483
for(int i = argc; i > 0; --i) {
6484
auto index = i - 1;
6485
auto temp = std::strstr(argv[index], pattern);
6486
if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue
6487
// eliminate matches in which the chars before the option are not '-'
6488
bool noBadCharsFound = true;
6489
auto curr = argv[index];
6490
while(curr != temp) {
6491
if(*curr++ != '-') {
6492
noBadCharsFound = false;
6493
break;
6494
}
6495
}
6496
if(noBadCharsFound && argv[index][0] == '-') {
6497
if(value) {
6498
// parsing the value of an option
6499
temp += strlen(pattern);
6500
const unsigned len = strlen(temp);
6501
if(len) {
6502
*value = temp;
6503
return true;
6504
}
6505
} else {
6506
// just a flag - no value
6507
return true;
6508
}
6509
}
6510
}
6511
}
6512
return false;
6513
}
6514
6515
// parses an option and returns the string after the '=' character
6516
bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr,
6517
const String& defaultVal = String()) {
6518
if(value)
6519
*value = defaultVal;
6520
#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
6521
// offset (normally 3 for "dt-") to skip prefix
6522
if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value))
6523
return true;
6524
#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
6525
return parseOptionImpl(argc, argv, pattern, value);
6526
}
6527
6528
// locates a flag on the command line
6529
bool parseFlag(int argc, const char* const* argv, const char* pattern) {
6530
return parseOption(argc, argv, pattern);
6531
}
6532
6533
// parses a comma separated list of words after a pattern in one of the arguments in argv
6534
bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern,
6535
std::vector<String>& res) {
6536
String filtersString;
6537
if(parseOption(argc, argv, pattern, &filtersString)) {
6538
// tokenize with "," as a separator, unless escaped with backslash
6539
std::ostringstream s;
6540
auto flush = [&s, &res]() {
6541
auto string = s.str();
6542
if(string.size() > 0) {
6543
res.push_back(string.c_str());
6544
}
6545
s.str("");
6546
};
6547
6548
bool seenBackslash = false;
6549
const char* current = filtersString.c_str();
6550
const char* end = current + strlen(current);
6551
while(current != end) {
6552
char character = *current++;
6553
if(seenBackslash) {
6554
seenBackslash = false;
6555
if(character == ',' || character == '\\') {
6556
s.put(character);
6557
continue;
6558
}
6559
s.put('\\');
6560
}
6561
if(character == '\\') {
6562
seenBackslash = true;
6563
} else if(character == ',') {
6564
flush();
6565
} else {
6566
s.put(character);
6567
}
6568
}
6569
6570
if(seenBackslash) {
6571
s.put('\\');
6572
}
6573
flush();
6574
return true;
6575
}
6576
return false;
6577
}
6578
6579
enum optionType
6580
{
6581
option_bool,
6582
option_int
6583
};
6584
6585
// parses an int/bool option from the command line
6586
bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type,
6587
int& res) {
6588
String parsedValue;
6589
if(!parseOption(argc, argv, pattern, &parsedValue))
6590
return false;
6591
6592
if(type) {
6593
// integer
6594
// TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
6595
int theInt = std::atoi(parsedValue.c_str());
6596
if (theInt != 0) {
6597
res = theInt; //!OCLINT parameter reassignment
6598
return true;
6599
}
6600
} else {
6601
// boolean
6602
const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1
6603
const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1
6604
6605
// if the value matches any of the positive/negative possibilities
6606
for (unsigned i = 0; i < 4; i++) {
6607
if (parsedValue.compare(positive[i], true) == 0) {
6608
res = 1; //!OCLINT parameter reassignment
6609
return true;
6610
}
6611
if (parsedValue.compare(negative[i], true) == 0) {
6612
res = 0; //!OCLINT parameter reassignment
6613
return true;
6614
}
6615
}
6616
}
6617
return false;
6618
}
6619
} // namespace
6620
6621
Context::Context(int argc, const char* const* argv)
6622
: p(new detail::ContextState) {
6623
parseArgs(argc, argv, true);
6624
if(argc)
6625
p->binary_name = argv[0];
6626
}
6627
6628
Context::~Context() {
6629
if(g_cs == p)
6630
g_cs = nullptr;
6631
delete p;
6632
}
6633
6634
void Context::applyCommandLine(int argc, const char* const* argv) {
6635
parseArgs(argc, argv);
6636
if(argc)
6637
p->binary_name = argv[0];
6638
}
6639
6640
// parses args
6641
void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
6642
using namespace detail;
6643
6644
// clang-format off
6645
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]);
6646
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]);
6647
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]);
6648
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]);
6649
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]);
6650
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]);
6651
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]);
6652
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]);
6653
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]);
6654
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]);
6655
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]);
6656
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]);
6657
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]);
6658
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]);
6659
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]);
6660
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]);
6661
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]);
6662
parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]);
6663
// clang-format on
6664
6665
int intRes = 0;
6666
String strRes;
6667
6668
#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \
6669
if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \
6670
parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \
6671
p->var = static_cast<bool>(intRes); \
6672
else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \
6673
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \
6674
p->var = true; \
6675
else if(withDefaults) \
6676
p->var = default
6677
6678
#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \
6679
if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \
6680
parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \
6681
p->var = intRes; \
6682
else if(withDefaults) \
6683
p->var = default
6684
6685
#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \
6686
if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \
6687
parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \
6688
withDefaults) \
6689
p->var = strRes
6690
6691
// clang-format off
6692
DOCTEST_PARSE_STR_OPTION("out", "o", out, "");
6693
DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file");
6694
DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0);
6695
6696
DOCTEST_PARSE_INT_OPTION("first", "f", first, 0);
6697
DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX);
6698
6699
DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0);
6700
DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX);
6701
6702
DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false);
6703
DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false);
6704
DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false);
6705
DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false);
6706
DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false);
6707
DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false);
6708
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false);
6709
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false);
6710
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false);
6711
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false);
6712
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false);
6713
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false);
6714
DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false);
6715
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false);
6716
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false);
6717
DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC));
6718
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false);
6719
DOCTEST_PARSE_STR_OPTION("strip-file-prefixes", "sfp", strip_file_prefixes, "");
6720
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false);
6721
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false);
6722
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false);
6723
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false);
6724
// clang-format on
6725
6726
if(withDefaults) {
6727
p->help = false;
6728
p->version = false;
6729
p->count = false;
6730
p->list_test_cases = false;
6731
p->list_test_suites = false;
6732
p->list_reporters = false;
6733
}
6734
if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") ||
6735
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") ||
6736
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) {
6737
p->help = true;
6738
p->exit = true;
6739
}
6740
if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") ||
6741
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) {
6742
p->version = true;
6743
p->exit = true;
6744
}
6745
if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") ||
6746
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) {
6747
p->count = true;
6748
p->exit = true;
6749
}
6750
if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") ||
6751
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) {
6752
p->list_test_cases = true;
6753
p->exit = true;
6754
}
6755
if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") ||
6756
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) {
6757
p->list_test_suites = true;
6758
p->exit = true;
6759
}
6760
if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") ||
6761
parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) {
6762
p->list_reporters = true;
6763
p->exit = true;
6764
}
6765
}
6766
6767
// allows the user to add procedurally to the filters from the command line
6768
void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); }
6769
6770
// allows the user to clear all filters from the command line
6771
void Context::clearFilters() {
6772
for(auto& curr : p->filters)
6773
curr.clear();
6774
}
6775
6776
// allows the user to override procedurally the bool options from the command line
6777
void Context::setOption(const char* option, bool value) {
6778
setOption(option, value ? "true" : "false");
6779
}
6780
6781
// allows the user to override procedurally the int options from the command line
6782
void Context::setOption(const char* option, int value) {
6783
setOption(option, toString(value).c_str());
6784
}
6785
6786
// allows the user to override procedurally the string options from the command line
6787
void Context::setOption(const char* option, const char* value) {
6788
auto argv = String("-") + option + "=" + value;
6789
auto lvalue = argv.c_str();
6790
parseArgs(1, &lvalue);
6791
}
6792
6793
// users should query this in their main() and exit the program if true
6794
bool Context::shouldExit() { return p->exit; }
6795
6796
void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; }
6797
6798
void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; }
6799
6800
void Context::setCout(std::ostream* out) { p->cout = out; }
6801
6802
static class DiscardOStream : public std::ostream
6803
{
6804
private:
6805
class : public std::streambuf
6806
{
6807
private:
6808
// allowing some buffering decreases the amount of calls to overflow
6809
char buf[1024];
6810
6811
protected:
6812
std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; }
6813
6814
int_type overflow(int_type ch) override {
6815
setp(std::begin(buf), std::end(buf));
6816
return traits_type::not_eof(ch);
6817
}
6818
} discardBuf;
6819
6820
public:
6821
DiscardOStream()
6822
: std::ostream(&discardBuf) {}
6823
} discardOut;
6824
6825
// the main function that does all the filtering and test running
6826
int Context::run() {
6827
using namespace detail;
6828
6829
// save the old context state in case such was setup - for using asserts out of a testing context
6830
auto old_cs = g_cs;
6831
// this is the current contest
6832
g_cs = p;
6833
is_running_in_test = true;
6834
6835
g_no_colors = p->no_colors;
6836
p->resetRunData();
6837
6838
std::fstream fstr;
6839
if(p->cout == nullptr) {
6840
if(p->quiet) {
6841
p->cout = &discardOut;
6842
} else if(p->out.size()) {
6843
// to a file if specified
6844
fstr.open(p->out.c_str(), std::fstream::out);
6845
p->cout = &fstr;
6846
} else {
6847
#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
6848
// stdout by default
6849
p->cout = &std::cout;
6850
#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
6851
return EXIT_FAILURE;
6852
#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM
6853
}
6854
}
6855
6856
FatalConditionHandler::allocateAltStackMem();
6857
6858
auto cleanup_and_return = [&]() {
6859
FatalConditionHandler::freeAltStackMem();
6860
6861
if(fstr.is_open())
6862
fstr.close();
6863
6864
// restore context
6865
g_cs = old_cs;
6866
is_running_in_test = false;
6867
6868
// we have to free the reporters which were allocated when the run started
6869
for(auto& curr : p->reporters_currently_used)
6870
delete curr;
6871
p->reporters_currently_used.clear();
6872
6873
if(p->numTestCasesFailed && !p->no_exitcode)
6874
return EXIT_FAILURE;
6875
return EXIT_SUCCESS;
6876
};
6877
6878
// setup default reporter if none is given through the command line
6879
if(p->filters[8].empty())
6880
p->filters[8].push_back("console");
6881
6882
// check to see if any of the registered reporters has been selected
6883
for(auto& curr : getReporters()) {
6884
if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive))
6885
p->reporters_currently_used.push_back(curr.second(*g_cs));
6886
}
6887
6888
// TODO: check if there is nothing in reporters_currently_used
6889
6890
// prepend all listeners
6891
for(auto& curr : getListeners())
6892
p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs));
6893
6894
#ifdef DOCTEST_PLATFORM_WINDOWS
6895
if(isDebuggerActive() && p->no_debug_output == false)
6896
p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs));
6897
#endif // DOCTEST_PLATFORM_WINDOWS
6898
6899
// handle version, help and no_run
6900
if(p->no_run || p->version || p->help || p->list_reporters) {
6901
DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData());
6902
6903
return cleanup_and_return();
6904
}
6905
6906
std::vector<const TestCase*> testArray;
6907
for(auto& curr : getRegisteredTests())
6908
testArray.push_back(&curr);
6909
p->numTestCases = testArray.size();
6910
6911
// sort the collected records
6912
if(!testArray.empty()) {
6913
if(p->order_by.compare("file", true) == 0) {
6914
std::sort(testArray.begin(), testArray.end(), fileOrderComparator);
6915
} else if(p->order_by.compare("suite", true) == 0) {
6916
std::sort(testArray.begin(), testArray.end(), suiteOrderComparator);
6917
} else if(p->order_by.compare("name", true) == 0) {
6918
std::sort(testArray.begin(), testArray.end(), nameOrderComparator);
6919
} else if(p->order_by.compare("rand", true) == 0) {
6920
std::srand(p->rand_seed);
6921
6922
// random_shuffle implementation
6923
const auto first = &testArray[0];
6924
for(size_t i = testArray.size() - 1; i > 0; --i) {
6925
int idxToSwap = std::rand() % (i + 1);
6926
6927
const auto temp = first[i];
6928
6929
first[i] = first[idxToSwap];
6930
first[idxToSwap] = temp;
6931
}
6932
} else if(p->order_by.compare("none", true) == 0) {
6933
// means no sorting - beneficial for death tests which call into the executable
6934
// with a specific test case in mind - we don't want to slow down the startup times
6935
}
6936
}
6937
6938
std::set<String> testSuitesPassingFilt;
6939
6940
bool query_mode = p->count || p->list_test_cases || p->list_test_suites;
6941
std::vector<const TestCaseData*> queryResults;
6942
6943
if(!query_mode)
6944
DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY);
6945
6946
// invoke the registered functions if they match the filter criteria (or just count them)
6947
for(auto& curr : testArray) {
6948
const auto& tc = *curr;
6949
6950
bool skip_me = false;
6951
if(tc.m_skip && !p->no_skip)
6952
skip_me = true;
6953
6954
if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive))
6955
skip_me = true;
6956
if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive))
6957
skip_me = true;
6958
if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive))
6959
skip_me = true;
6960
if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive))
6961
skip_me = true;
6962
if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive))
6963
skip_me = true;
6964
if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive))
6965
skip_me = true;
6966
6967
if(!skip_me)
6968
p->numTestCasesPassingFilters++;
6969
6970
// skip the test if it is not in the execution range
6971
if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) ||
6972
(p->first > p->numTestCasesPassingFilters))
6973
skip_me = true;
6974
6975
if(skip_me) {
6976
if(!query_mode)
6977
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc);
6978
continue;
6979
}
6980
6981
// do not execute the test if we are to only count the number of filter passing tests
6982
if(p->count)
6983
continue;
6984
6985
// print the name of the test and don't execute it
6986
if(p->list_test_cases) {
6987
queryResults.push_back(&tc);
6988
continue;
6989
}
6990
6991
// print the name of the test suite if not done already and don't execute it
6992
if(p->list_test_suites) {
6993
if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') {
6994
queryResults.push_back(&tc);
6995
testSuitesPassingFilt.insert(tc.m_test_suite);
6996
p->numTestSuitesPassingFilters++;
6997
}
6998
continue;
6999
}
7000
7001
// execute the test if it passes all the filtering
7002
{
7003
p->currentTest = &tc;
7004
7005
p->failure_flags = TestCaseFailureReason::None;
7006
p->seconds = 0;
7007
7008
// reset atomic counters
7009
p->numAssertsFailedCurrentTest_atomic = 0;
7010
p->numAssertsCurrentTest_atomic = 0;
7011
7012
p->fullyTraversedSubcases.clear();
7013
7014
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc);
7015
7016
p->timer.start();
7017
7018
bool run_test = true;
7019
7020
do {
7021
// reset some of the fields for subcases (except for the set of fully passed ones)
7022
p->reachedLeaf = false;
7023
// May not be empty if previous subcase exited via exception.
7024
p->subcaseStack.clear();
7025
p->currentSubcaseDepth = 0;
7026
7027
p->shouldLogCurrentException = true;
7028
7029
// reset stuff for logging with INFO()
7030
p->stringifiedContexts.clear();
7031
7032
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
7033
try {
7034
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
7035
// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method)
7036
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable
7037
FatalConditionHandler fatalConditionHandler; // Handle signals
7038
// execute the test
7039
tc.m_test();
7040
fatalConditionHandler.reset();
7041
DOCTEST_MSVC_SUPPRESS_WARNING_POP
7042
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
7043
} catch(const TestFailureException&) {
7044
p->failure_flags |= TestCaseFailureReason::AssertFailure;
7045
} catch(...) {
7046
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception,
7047
{translateActiveException(), false});
7048
p->failure_flags |= TestCaseFailureReason::Exception;
7049
}
7050
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
7051
7052
// exit this loop if enough assertions have failed - even if there are more subcases
7053
if(p->abort_after > 0 &&
7054
p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) {
7055
run_test = false;
7056
p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
7057
}
7058
7059
if(!p->nextSubcaseStack.empty() && run_test)
7060
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
7061
if(p->nextSubcaseStack.empty())
7062
run_test = false;
7063
} while(run_test);
7064
7065
p->finalizeTestCaseData();
7066
7067
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs);
7068
7069
p->currentTest = nullptr;
7070
7071
// stop executing tests if enough assertions have failed
7072
if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after)
7073
break;
7074
}
7075
}
7076
7077
if(!query_mode) {
7078
DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs);
7079
} else {
7080
QueryData qdata;
7081
qdata.run_stats = g_cs;
7082
qdata.data = queryResults.data();
7083
qdata.num_data = unsigned(queryResults.size());
7084
DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
7085
}
7086
7087
return cleanup_and_return();
7088
}
7089
7090
DOCTEST_DEFINE_INTERFACE(IReporter)
7091
7092
int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); }
7093
const IContextScope* const* IReporter::get_active_contexts() {
7094
return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr;
7095
}
7096
7097
int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); }
7098
const String* IReporter::get_stringified_contexts() {
7099
return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr;
7100
}
7101
7102
namespace detail {
7103
void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) {
7104
if(isReporter)
7105
getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
7106
else
7107
getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c));
7108
}
7109
} // namespace detail
7110
7111
} // namespace doctest
7112
7113
#endif // DOCTEST_CONFIG_DISABLE
7114
7115
#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
7116
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182
7117
int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); }
7118
DOCTEST_MSVC_SUPPRESS_WARNING_POP
7119
#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
7120
7121
DOCTEST_CLANG_SUPPRESS_WARNING_POP
7122
DOCTEST_MSVC_SUPPRESS_WARNING_POP
7123
DOCTEST_GCC_SUPPRESS_WARNING_POP
7124
7125
DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
7126
7127
#endif // DOCTEST_LIBRARY_IMPLEMENTATION
7128
#endif // DOCTEST_CONFIG_IMPLEMENT
7129
7130
#ifdef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
7131
#undef WIN32_LEAN_AND_MEAN
7132
#undef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
7133
#endif // DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN
7134
7135
#ifdef DOCTEST_UNDEF_NOMINMAX
7136
#undef NOMINMAX
7137
#undef DOCTEST_UNDEF_NOMINMAX
7138
#endif // DOCTEST_UNDEF_NOMINMAX
7139
7140