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