aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/catch_amalgamated.hpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--unit_tests/catch_amalgamated.hpp14106
1 files changed, 14106 insertions, 0 deletions
diff --git a/unit_tests/catch_amalgamated.hpp b/unit_tests/catch_amalgamated.hpp
new file mode 100644
index 0000000..b7c768b
--- /dev/null
+++ b/unit_tests/catch_amalgamated.hpp
@@ -0,0 +1,14106 @@
1
2// Copyright Catch2 Authors
3// Distributed under the Boost Software License, Version 1.0.
4// (See accompanying file LICENSE.txt or copy at
5// https://www.boost.org/LICENSE_1_0.txt)
6
7// SPDX-License-Identifier: BSL-1.0
8
9// Catch v3.7.1
10// Generated: 2024-09-17 10:36:40.974985
11// ----------------------------------------------------------
12// This file is an amalgamation of multiple different files.
13// You probably shouldn't edit it directly.
14// ----------------------------------------------------------
15#ifndef CATCH_AMALGAMATED_HPP_INCLUDED
16#define CATCH_AMALGAMATED_HPP_INCLUDED
17
18
19/** \file
20 * This is a convenience header for Catch2. It includes **all** of Catch2 headers.
21 *
22 * Generally the Catch2 users should use specific includes they need,
23 * but this header can be used instead for ease-of-experimentation, or
24 * just plain convenience, at the cost of (significantly) increased
25 * compilation times.
26 *
27 * When a new header is added to either the top level folder, or to the
28 * corresponding internal subfolder, it should be added here. Headers
29 * added to the various subparts (e.g. matchers, generators, etc...),
30 * should go their respective catch-all headers.
31 */
32
33#ifndef CATCH_ALL_HPP_INCLUDED
34#define CATCH_ALL_HPP_INCLUDED
35
36
37
38/** \file
39 * This is a convenience header for Catch2's benchmarking. It includes
40 * **all** of Catch2 headers related to benchmarking.
41 *
42 * Generally the Catch2 users should use specific includes they need,
43 * but this header can be used instead for ease-of-experimentation, or
44 * just plain convenience, at the cost of (significantly) increased
45 * compilation times.
46 *
47 * When a new header is added to either the `benchmark` folder, or to
48 * the corresponding internal (detail) subfolder, it should be added here.
49 */
50
51#ifndef CATCH_BENCHMARK_ALL_HPP_INCLUDED
52#define CATCH_BENCHMARK_ALL_HPP_INCLUDED
53
54
55
56// Adapted from donated nonius code.
57
58#ifndef CATCH_BENCHMARK_HPP_INCLUDED
59#define CATCH_BENCHMARK_HPP_INCLUDED
60
61
62
63#ifndef CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
64#define CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
65
66// Detect a number of compiler features - by compiler
67// The following features are defined:
68//
69// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
70// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
71// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
72// ****************
73// Note to maintainers: if new toggles are added please document them
74// in configuration.md, too
75// ****************
76
77// In general each macro has a _NO_<feature name> form
78// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
79// Many features, at point of detection, define an _INTERNAL_ macro, so they
80// can be combined, en-mass, with the _NO_ forms later.
81
82
83
84#ifndef CATCH_PLATFORM_HPP_INCLUDED
85#define CATCH_PLATFORM_HPP_INCLUDED
86
87// See e.g.:
88// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
89#ifdef __APPLE__
90# ifndef __has_extension
91# define __has_extension(x) 0
92# endif
93# include <TargetConditionals.h>
94# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
95 (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
96# define CATCH_PLATFORM_MAC
97# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
98# define CATCH_PLATFORM_IPHONE
99# endif
100
101#elif defined(linux) || defined(__linux) || defined(__linux__)
102# define CATCH_PLATFORM_LINUX
103
104#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
105# define CATCH_PLATFORM_WINDOWS
106
107# if defined( WINAPI_FAMILY ) && ( WINAPI_FAMILY == WINAPI_FAMILY_APP )
108# define CATCH_PLATFORM_WINDOWS_UWP
109# endif
110
111#elif defined(__ORBIS__) || defined(__PROSPERO__)
112# define CATCH_PLATFORM_PLAYSTATION
113
114#endif
115
116#endif // CATCH_PLATFORM_HPP_INCLUDED
117
118#ifdef __cplusplus
119
120# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
121# define CATCH_CPP17_OR_GREATER
122# endif
123
124# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
125# define CATCH_CPP20_OR_GREATER
126# endif
127
128#endif
129
130// Only GCC compiler should be used in this block, so other compilers trying to
131// mask themselves as GCC should be ignored.
132#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) && !defined(__NVCOMPILER)
133# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
134# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
135
136// This only works on GCC 9+. so we have to also add a global suppression of Wparentheses
137// for older versions of GCC.
138# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
139 _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
140
141# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
142 _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" )
143
144# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
145 _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" )
146
147# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
148 _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" )
149
150# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
151 _Pragma( "GCC diagnostic ignored \"-Wshadow\"" )
152
153# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
154
155#endif
156
157#if defined(__NVCOMPILER)
158# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "diag push" )
159# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "diag pop" )
160# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress declared_but_not_referenced" )
161#endif
162
163#if defined(__CUDACC__) && !defined(__clang__)
164# ifdef __NVCC_DIAG_PRAGMA_SUPPORT__
165// New pragmas introduced in CUDA 11.5+
166# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" )
167# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic pop" )
168# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" )
169# else
170# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" )
171# endif
172#endif
173
174// clang-cl defines _MSC_VER as well as __clang__, which could cause the
175// start/stop internal suppression macros to be double defined.
176#if defined(__clang__) && !defined(_MSC_VER)
177
178# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
179# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
180
181#endif // __clang__ && !_MSC_VER
182
183#if defined(__clang__)
184
185// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
186// which results in calls to destructors being emitted for each temporary,
187// without a matching initialization. In practice, this can result in something
188// like `std::string::~string` being called on an uninitialized value.
189//
190// For example, this code will likely segfault under IBM XL:
191// ```
192// REQUIRE(std::string("12") + "34" == "1234")
193// ```
194//
195// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which
196// results in calls to the immediately evaluated lambda expressions to be
197// reported as unevaluated lambdas.
198// https://developer.nvidia.com/nvidia_bug/3321845.
199//
200// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
201# if !defined(__ibmxl__) && !defined(__CUDACC__) && !defined( __NVCOMPILER )
202# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
203# endif
204
205
206# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
207 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
208 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
209
210# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
211 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
212
213# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
214 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
215
216# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
217 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
218
219# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
220 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
221
222# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
223 _Pragma( "clang diagnostic ignored \"-Wcomma\"" )
224
225# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
226 _Pragma( "clang diagnostic ignored \"-Wshadow\"" )
227
228#endif // __clang__
229
230
231////////////////////////////////////////////////////////////////////////////////
232// We know some environments not to support full POSIX signals
233#if defined( CATCH_PLATFORM_WINDOWS ) || \
234 defined( CATCH_PLATFORM_PLAYSTATION ) || \
235 defined( __CYGWIN__ ) || \
236 defined( __QNX__ ) || \
237 defined( __EMSCRIPTEN__ ) || \
238 defined( __DJGPP__ ) || \
239 defined( __OS400__ )
240# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
241#else
242# define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
243#endif
244
245////////////////////////////////////////////////////////////////////////////////
246// Assume that some platforms do not support getenv.
247#if defined( CATCH_PLATFORM_WINDOWS_UWP ) || \
248 defined( CATCH_PLATFORM_PLAYSTATION ) || \
249 defined( _GAMING_XBOX )
250# define CATCH_INTERNAL_CONFIG_NO_GETENV
251#else
252# define CATCH_INTERNAL_CONFIG_GETENV
253#endif
254
255////////////////////////////////////////////////////////////////////////////////
256// Android somehow still does not support std::to_string
257#if defined(__ANDROID__)
258# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
259#endif
260
261////////////////////////////////////////////////////////////////////////////////
262// Not all Windows environments support SEH properly
263#if defined(__MINGW32__)
264# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
265#endif
266
267////////////////////////////////////////////////////////////////////////////////
268// PS4
269#if defined(__ORBIS__)
270# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
271#endif
272
273////////////////////////////////////////////////////////////////////////////////
274// Cygwin
275#ifdef __CYGWIN__
276
277// Required for some versions of Cygwin to declare gettimeofday
278// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
279# define _BSD_SOURCE
280// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
281// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
282# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
283 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
284
285# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
286
287# endif
288#endif // __CYGWIN__
289
290////////////////////////////////////////////////////////////////////////////////
291// Visual C++
292#if defined(_MSC_VER)
293
294// We want to defer to nvcc-specific warning suppression if we are compiled
295// with nvcc masquerading for MSVC.
296# if !defined( __CUDACC__ )
297# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
298 __pragma( warning( push ) )
299# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
300 __pragma( warning( pop ) )
301# endif
302
303// Universal Windows platform does not support SEH
304// Or console colours (or console at all...)
305# if defined(CATCH_PLATFORM_WINDOWS_UWP)
306# define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
307# else
308# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
309# endif
310
311// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
312// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
313// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
314# if !defined(__clang__) // Handle Clang masquerading for msvc
315# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
316# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
317# endif // MSVC_TRADITIONAL
318# endif // __clang__
319
320#endif // _MSC_VER
321
322#if defined(_REENTRANT) || defined(_MSC_VER)
323// Enable async processing, as -pthread is specified or no additional linking is required
324# define CATCH_INTERNAL_CONFIG_USE_ASYNC
325#endif // _MSC_VER
326
327////////////////////////////////////////////////////////////////////////////////
328// Check if we are compiled with -fno-exceptions or equivalent
329#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
330# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
331#endif
332
333
334////////////////////////////////////////////////////////////////////////////////
335// Embarcadero C++Build
336#if defined(__BORLANDC__)
337 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
338#endif
339
340////////////////////////////////////////////////////////////////////////////////
341
342// RTX is a special version of Windows that is real time.
343// This means that it is detected as Windows, but does not provide
344// the same set of capabilities as real Windows does.
345#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
346 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
347 #define CATCH_INTERNAL_CONFIG_NO_ASYNC
348 #define CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32
349#endif
350
351#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
352#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
353#endif
354
355// Various stdlib support checks that require __has_include
356#if defined(__has_include)
357 // Check if string_view is available and usable
358 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
359 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
360 #endif
361
362 // Check if optional is available and usable
363 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
364 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
365 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
366
367 // Check if byte is available and usable
368 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
369 # include <cstddef>
370 # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
371 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE
372 # endif
373 # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
374
375 // Check if variant is available and usable
376 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
377 # if defined(__clang__) && (__clang_major__ < 8)
378 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
379 // fix should be in clang 8, workaround in libstdc++ 8.2
380 # include <ciso646>
381 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
382 # define CATCH_CONFIG_NO_CPP17_VARIANT
383 # else
384 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
385 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
386 # else
387 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
388 # endif // defined(__clang__) && (__clang_major__ < 8)
389 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
390#endif // defined(__has_include)
391
392
393#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
394# define CATCH_CONFIG_WINDOWS_SEH
395#endif
396// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
397#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
398# define CATCH_CONFIG_POSIX_SIGNALS
399#endif
400
401#if defined(CATCH_INTERNAL_CONFIG_GETENV) && !defined(CATCH_INTERNAL_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_NO_GETENV) && !defined(CATCH_CONFIG_GETENV)
402# define CATCH_CONFIG_GETENV
403#endif
404
405#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
406# define CATCH_CONFIG_CPP11_TO_STRING
407#endif
408
409#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
410# define CATCH_CONFIG_CPP17_OPTIONAL
411#endif
412
413#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
414# define CATCH_CONFIG_CPP17_STRING_VIEW
415#endif
416
417#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
418# define CATCH_CONFIG_CPP17_VARIANT
419#endif
420
421#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
422# define CATCH_CONFIG_CPP17_BYTE
423#endif
424
425
426#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
427# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
428#endif
429
430#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
431# define CATCH_CONFIG_NEW_CAPTURE
432#endif
433
434#if !defined( CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED ) && \
435 !defined( CATCH_CONFIG_DISABLE_EXCEPTIONS ) && \
436 !defined( CATCH_CONFIG_NO_DISABLE_EXCEPTIONS )
437# define CATCH_CONFIG_DISABLE_EXCEPTIONS
438#endif
439
440#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
441# define CATCH_CONFIG_POLYFILL_ISNAN
442#endif
443
444#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
445# define CATCH_CONFIG_USE_ASYNC
446#endif
447
448#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
449# define CATCH_CONFIG_GLOBAL_NEXTAFTER
450#endif
451
452
453// Even if we do not think the compiler has that warning, we still have
454// to provide a macro that can be used by the code.
455#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
456# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
457#endif
458#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
459# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
460#endif
461#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
462# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
463#endif
464#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
465# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
466#endif
467#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT)
468# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT
469#endif
470#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS)
471# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS
472#endif
473#if !defined(CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS)
474# define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS
475#endif
476#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
477# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
478#endif
479#if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS )
480# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
481#endif
482#if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS )
483# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS
484#endif
485#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS )
486# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS
487#endif
488
489
490// The goal of this macro is to avoid evaluation of the arguments, but
491// still have the compiler warn on problems inside...
492#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
493# define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
494#endif
495
496#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
497# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
498#elif defined(__clang__) && (__clang_major__ < 5)
499# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
500#endif
501
502
503#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
504#define CATCH_TRY if ((true))
505#define CATCH_CATCH_ALL if ((false))
506#define CATCH_CATCH_ANON(type) if ((false))
507#else
508#define CATCH_TRY try
509#define CATCH_CATCH_ALL catch (...)
510#define CATCH_CATCH_ANON(type) catch (type)
511#endif
512
513#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
514#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
515#endif
516
517#if defined( CATCH_PLATFORM_WINDOWS ) && \
518 !defined( CATCH_CONFIG_COLOUR_WIN32 ) && \
519 !defined( CATCH_CONFIG_NO_COLOUR_WIN32 ) && \
520 !defined( CATCH_INTERNAL_CONFIG_NO_COLOUR_WIN32 )
521# define CATCH_CONFIG_COLOUR_WIN32
522#endif
523
524#if defined( CATCH_CONFIG_SHARED_LIBRARY ) && defined( _MSC_VER ) && \
525 !defined( CATCH_CONFIG_STATIC )
526# ifdef Catch2_EXPORTS
527# define CATCH_EXPORT //__declspec( dllexport ) // not needed
528# else
529# define CATCH_EXPORT __declspec( dllimport )
530# endif
531#else
532# define CATCH_EXPORT
533#endif
534
535#endif // CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
536
537
538#ifndef CATCH_CONTEXT_HPP_INCLUDED
539#define CATCH_CONTEXT_HPP_INCLUDED
540
541
542namespace Catch {
543
544 class IResultCapture;
545 class IConfig;
546
547 class Context {
548 IConfig const* m_config = nullptr;
549 IResultCapture* m_resultCapture = nullptr;
550
551 CATCH_EXPORT static Context* currentContext;
552 friend Context& getCurrentMutableContext();
553 friend Context const& getCurrentContext();
554 static void createContext();
555 friend void cleanUpContext();
556
557 public:
558 constexpr IResultCapture* getResultCapture() const {
559 return m_resultCapture;
560 }
561 constexpr IConfig const* getConfig() const { return m_config; }
562 constexpr void setResultCapture( IResultCapture* resultCapture ) {
563 m_resultCapture = resultCapture;
564 }
565 constexpr void setConfig( IConfig const* config ) { m_config = config; }
566
567 };
568
569 Context& getCurrentMutableContext();
570
571 inline Context const& getCurrentContext() {
572 // We duplicate the logic from `getCurrentMutableContext` here,
573 // to avoid paying the call overhead in debug mode.
574 if ( !Context::currentContext ) { Context::createContext(); }
575 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
576 return *Context::currentContext;
577 }
578
579 void cleanUpContext();
580
581 class SimplePcg32;
582 SimplePcg32& sharedRng();
583}
584
585#endif // CATCH_CONTEXT_HPP_INCLUDED
586
587
588#ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
589#define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
590
591#include <type_traits>
592
593//! Replacement for std::move with better compile time performance
594#define CATCH_MOVE(...) static_cast<std::remove_reference_t<decltype(__VA_ARGS__)>&&>(__VA_ARGS__)
595
596//! Replacement for std::forward with better compile time performance
597#define CATCH_FORWARD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
598
599#endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
600
601
602#ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
603#define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
604
605namespace Catch {
606
607 //! Used to signal that an assertion macro failed
608 struct TestFailureException{};
609 //! Used to signal that the remainder of a test should be skipped
610 struct TestSkipException {};
611
612 /**
613 * Outlines throwing of `TestFailureException` into a single TU
614 *
615 * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
616 */
617 [[noreturn]] void throw_test_failure_exception();
618
619 /**
620 * Outlines throwing of `TestSkipException` into a single TU
621 *
622 * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
623 */
624 [[noreturn]] void throw_test_skip_exception();
625
626} // namespace Catch
627
628#endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
629
630
631#ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED
632#define CATCH_UNIQUE_NAME_HPP_INCLUDED
633
634
635
636
637/** \file
638 * Wrapper for the CONFIG configuration option
639 *
640 * When generating internal unique names, there are two options. Either
641 * we mix in the current line number, or mix in an incrementing number.
642 * We prefer the latter, using `__COUNTER__`, but users might want to
643 * use the former.
644 */
645
646#ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED
647#define CATCH_CONFIG_COUNTER_HPP_INCLUDED
648
649
650#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
651 #define CATCH_INTERNAL_CONFIG_COUNTER
652#endif
653
654#if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \
655 !defined( CATCH_CONFIG_NO_COUNTER ) && \
656 !defined( CATCH_CONFIG_COUNTER )
657# define CATCH_CONFIG_COUNTER
658#endif
659
660
661#endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED
662#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
663#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
664#ifdef CATCH_CONFIG_COUNTER
665# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
666#else
667# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
668#endif
669
670#endif // CATCH_UNIQUE_NAME_HPP_INCLUDED
671
672
673#ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
674#define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
675
676#include <string>
677
678
679
680#ifndef CATCH_STRINGREF_HPP_INCLUDED
681#define CATCH_STRINGREF_HPP_INCLUDED
682
683#include <cstddef>
684#include <string>
685#include <iosfwd>
686#include <cassert>
687
688#include <cstring>
689
690namespace Catch {
691
692 /// A non-owning string class (similar to the forthcoming std::string_view)
693 /// Note that, because a StringRef may be a substring of another string,
694 /// it may not be null terminated.
695 class StringRef {
696 public:
697 using size_type = std::size_t;
698 using const_iterator = const char*;
699
700 static constexpr size_type npos{ static_cast<size_type>( -1 ) };
701
702 private:
703 static constexpr char const* const s_empty = "";
704
705 char const* m_start = s_empty;
706 size_type m_size = 0;
707
708 public: // construction
709 constexpr StringRef() noexcept = default;
710
711 StringRef( char const* rawChars ) noexcept;
712
713 constexpr StringRef( char const* rawChars, size_type size ) noexcept
714 : m_start( rawChars ),
715 m_size( size )
716 {}
717
718 StringRef( std::string const& stdString ) noexcept
719 : m_start( stdString.c_str() ),
720 m_size( stdString.size() )
721 {}
722
723 explicit operator std::string() const {
724 return std::string(m_start, m_size);
725 }
726
727 public: // operators
728 auto operator == ( StringRef other ) const noexcept -> bool {
729 return m_size == other.m_size
730 && (std::memcmp( m_start, other.m_start, m_size ) == 0);
731 }
732 auto operator != (StringRef other) const noexcept -> bool {
733 return !(*this == other);
734 }
735
736 constexpr auto operator[] ( size_type index ) const noexcept -> char {
737 assert(index < m_size);
738 return m_start[index];
739 }
740
741 bool operator<(StringRef rhs) const noexcept;
742
743 public: // named queries
744 constexpr auto empty() const noexcept -> bool {
745 return m_size == 0;
746 }
747 constexpr auto size() const noexcept -> size_type {
748 return m_size;
749 }
750
751 // Returns a substring of [start, start + length).
752 // If start + length > size(), then the substring is [start, size()).
753 // If start > size(), then the substring is empty.
754 constexpr StringRef substr(size_type start, size_type length) const noexcept {
755 if (start < m_size) {
756 const auto shortened_size = m_size - start;
757 return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length);
758 } else {
759 return StringRef();
760 }
761 }
762
763 // Returns the current start pointer. May not be null-terminated.
764 constexpr char const* data() const noexcept {
765 return m_start;
766 }
767
768 constexpr const_iterator begin() const { return m_start; }
769 constexpr const_iterator end() const { return m_start + m_size; }
770
771
772 friend std::string& operator += (std::string& lhs, StringRef rhs);
773 friend std::ostream& operator << (std::ostream& os, StringRef str);
774 friend std::string operator+(StringRef lhs, StringRef rhs);
775
776 /**
777 * Provides a three-way comparison with rhs
778 *
779 * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive
780 * number if lhs > rhs
781 */
782 int compare( StringRef rhs ) const;
783 };
784
785
786 constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
787 return StringRef( rawChars, size );
788 }
789} // namespace Catch
790
791constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
792 return Catch::StringRef( rawChars, size );
793}
794
795#endif // CATCH_STRINGREF_HPP_INCLUDED
796
797
798#ifndef CATCH_RESULT_TYPE_HPP_INCLUDED
799#define CATCH_RESULT_TYPE_HPP_INCLUDED
800
801namespace Catch {
802
803 // ResultWas::OfType enum
804 struct ResultWas { enum OfType {
805 Unknown = -1,
806 Ok = 0,
807 Info = 1,
808 Warning = 2,
809 // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit?
810 ExplicitSkip = 4,
811
812 FailureBit = 0x10,
813
814 ExpressionFailed = FailureBit | 1,
815 ExplicitFailure = FailureBit | 2,
816
817 Exception = 0x100 | FailureBit,
818
819 ThrewException = Exception | 1,
820 DidntThrowException = Exception | 2,
821
822 FatalErrorCondition = 0x200 | FailureBit
823
824 }; };
825
826 constexpr bool isOk( ResultWas::OfType resultType ) {
827 return ( resultType & ResultWas::FailureBit ) == 0;
828 }
829 constexpr bool isJustInfo( int flags ) { return flags == ResultWas::Info; }
830
831
832 // ResultDisposition::Flags enum
833 struct ResultDisposition { enum Flags {
834 Normal = 0x01,
835
836 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
837 FalseTest = 0x04, // Prefix expression with !
838 SuppressFail = 0x08 // Failures are reported but do not fail the test
839 }; };
840
841 constexpr ResultDisposition::Flags operator|( ResultDisposition::Flags lhs,
842 ResultDisposition::Flags rhs ) {
843 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) |
844 static_cast<int>( rhs ) );
845 }
846
847 constexpr bool isFalseTest( int flags ) {
848 return ( flags & ResultDisposition::FalseTest ) != 0;
849 }
850 constexpr bool shouldSuppressFailure( int flags ) {
851 return ( flags & ResultDisposition::SuppressFail ) != 0;
852 }
853
854} // end namespace Catch
855
856#endif // CATCH_RESULT_TYPE_HPP_INCLUDED
857
858
859#ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED
860#define CATCH_UNIQUE_PTR_HPP_INCLUDED
861
862#include <cassert>
863#include <type_traits>
864
865
866namespace Catch {
867namespace Detail {
868 /**
869 * A reimplementation of `std::unique_ptr` for improved compilation performance
870 *
871 * Does not support arrays nor custom deleters.
872 */
873 template <typename T>
874 class unique_ptr {
875 T* m_ptr;
876 public:
877 constexpr unique_ptr(std::nullptr_t = nullptr):
878 m_ptr{}
879 {}
880 explicit constexpr unique_ptr(T* ptr):
881 m_ptr(ptr)
882 {}
883
884 template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
885 unique_ptr(unique_ptr<U>&& from):
886 m_ptr(from.release())
887 {}
888
889 template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
890 unique_ptr& operator=(unique_ptr<U>&& from) {
891 reset(from.release());
892
893 return *this;
894 }
895
896 unique_ptr(unique_ptr const&) = delete;
897 unique_ptr& operator=(unique_ptr const&) = delete;
898
899 unique_ptr(unique_ptr&& rhs) noexcept:
900 m_ptr(rhs.m_ptr) {
901 rhs.m_ptr = nullptr;
902 }
903 unique_ptr& operator=(unique_ptr&& rhs) noexcept {
904 reset(rhs.release());
905
906 return *this;
907 }
908
909 ~unique_ptr() {
910 delete m_ptr;
911 }
912
913 T& operator*() {
914 assert(m_ptr);
915 return *m_ptr;
916 }
917 T const& operator*() const {
918 assert(m_ptr);
919 return *m_ptr;
920 }
921 T* operator->() noexcept {
922 assert(m_ptr);
923 return m_ptr;
924 }
925 T const* operator->() const noexcept {
926 assert(m_ptr);
927 return m_ptr;
928 }
929
930 T* get() { return m_ptr; }
931 T const* get() const { return m_ptr; }
932
933 void reset(T* ptr = nullptr) {
934 delete m_ptr;
935 m_ptr = ptr;
936 }
937
938 T* release() {
939 auto temp = m_ptr;
940 m_ptr = nullptr;
941 return temp;
942 }
943
944 explicit operator bool() const {
945 return m_ptr;
946 }
947
948 friend void swap(unique_ptr& lhs, unique_ptr& rhs) {
949 auto temp = lhs.m_ptr;
950 lhs.m_ptr = rhs.m_ptr;
951 rhs.m_ptr = temp;
952 }
953 };
954
955 //! Specialization to cause compile-time error for arrays
956 template <typename T>
957 class unique_ptr<T[]>;
958
959 template <typename T, typename... Args>
960 unique_ptr<T> make_unique(Args&&... args) {
961 return unique_ptr<T>(new T(CATCH_FORWARD(args)...));
962 }
963
964
965} // end namespace Detail
966} // end namespace Catch
967
968#endif // CATCH_UNIQUE_PTR_HPP_INCLUDED
969
970
971#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
972#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
973
974
975
976// Adapted from donated nonius code.
977
978#ifndef CATCH_CLOCK_HPP_INCLUDED
979#define CATCH_CLOCK_HPP_INCLUDED
980
981#include <chrono>
982
983namespace Catch {
984 namespace Benchmark {
985 using IDuration = std::chrono::nanoseconds;
986 using FDuration = std::chrono::duration<double, std::nano>;
987
988 template <typename Clock>
989 using TimePoint = typename Clock::time_point;
990
991 using default_clock = std::chrono::steady_clock;
992 } // namespace Benchmark
993} // namespace Catch
994
995#endif // CATCH_CLOCK_HPP_INCLUDED
996
997namespace Catch {
998
999 // We cannot forward declare the type with default template argument
1000 // multiple times, so it is split out into a separate header so that
1001 // we can prevent multiple declarations in dependees
1002 template <typename Duration = Benchmark::FDuration>
1003 struct BenchmarkStats;
1004
1005} // end namespace Catch
1006
1007#endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
1008
1009namespace Catch {
1010
1011 class AssertionResult;
1012 struct AssertionInfo;
1013 struct SectionInfo;
1014 struct SectionEndInfo;
1015 struct MessageInfo;
1016 struct MessageBuilder;
1017 struct Counts;
1018 struct AssertionReaction;
1019 struct SourceLineInfo;
1020
1021 class ITransientExpression;
1022 class IGeneratorTracker;
1023
1024 struct BenchmarkInfo;
1025
1026 namespace Generators {
1027 class GeneratorUntypedBase;
1028 using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
1029 }
1030
1031
1032 class IResultCapture {
1033 public:
1034 virtual ~IResultCapture();
1035
1036 virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0;
1037 virtual bool sectionStarted( StringRef sectionName,
1038 SourceLineInfo const& sectionLineInfo,
1039 Counts& assertions ) = 0;
1040 virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
1041 virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
1042
1043 virtual IGeneratorTracker*
1044 acquireGeneratorTracker( StringRef generatorName,
1045 SourceLineInfo const& lineInfo ) = 0;
1046 virtual IGeneratorTracker*
1047 createGeneratorTracker( StringRef generatorName,
1048 SourceLineInfo lineInfo,
1049 Generators::GeneratorBasePtr&& generator ) = 0;
1050
1051 virtual void benchmarkPreparing( StringRef name ) = 0;
1052 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
1053 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
1054 virtual void benchmarkFailed( StringRef error ) = 0;
1055
1056 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1057 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1058
1059 virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
1060
1061 virtual void handleFatalErrorCondition( StringRef message ) = 0;
1062
1063 virtual void handleExpr
1064 ( AssertionInfo const& info,
1065 ITransientExpression const& expr,
1066 AssertionReaction& reaction ) = 0;
1067 virtual void handleMessage
1068 ( AssertionInfo const& info,
1069 ResultWas::OfType resultType,
1070 std::string&& message,
1071 AssertionReaction& reaction ) = 0;
1072 virtual void handleUnexpectedExceptionNotThrown
1073 ( AssertionInfo const& info,
1074 AssertionReaction& reaction ) = 0;
1075 virtual void handleUnexpectedInflightException
1076 ( AssertionInfo const& info,
1077 std::string&& message,
1078 AssertionReaction& reaction ) = 0;
1079 virtual void handleIncomplete
1080 ( AssertionInfo const& info ) = 0;
1081 virtual void handleNonExpr
1082 ( AssertionInfo const &info,
1083 ResultWas::OfType resultType,
1084 AssertionReaction &reaction ) = 0;
1085
1086
1087
1088 virtual bool lastAssertionPassed() = 0;
1089 virtual void assertionPassed() = 0;
1090
1091 // Deprecated, do not use:
1092 virtual std::string getCurrentTestName() const = 0;
1093 virtual const AssertionResult* getLastResult() const = 0;
1094 virtual void exceptionEarlyReported() = 0;
1095 };
1096
1097 IResultCapture& getResultCapture();
1098}
1099
1100#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
1101
1102
1103#ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED
1104#define CATCH_INTERFACES_CONFIG_HPP_INCLUDED
1105
1106
1107
1108#ifndef CATCH_NONCOPYABLE_HPP_INCLUDED
1109#define CATCH_NONCOPYABLE_HPP_INCLUDED
1110
1111namespace Catch {
1112 namespace Detail {
1113
1114 //! Deriving classes become noncopyable and nonmovable
1115 class NonCopyable {
1116 NonCopyable( NonCopyable const& ) = delete;
1117 NonCopyable( NonCopyable&& ) = delete;
1118 NonCopyable& operator=( NonCopyable const& ) = delete;
1119 NonCopyable& operator=( NonCopyable&& ) = delete;
1120
1121 protected:
1122 NonCopyable() noexcept = default;
1123 };
1124
1125 } // namespace Detail
1126} // namespace Catch
1127
1128#endif // CATCH_NONCOPYABLE_HPP_INCLUDED
1129
1130#include <chrono>
1131#include <iosfwd>
1132#include <string>
1133#include <vector>
1134
1135namespace Catch {
1136
1137 enum class Verbosity {
1138 Quiet = 0,
1139 Normal,
1140 High
1141 };
1142
1143 struct WarnAbout { enum What {
1144 Nothing = 0x00,
1145 //! A test case or leaf section did not run any assertions
1146 NoAssertions = 0x01,
1147 //! A command line test spec matched no test cases
1148 UnmatchedTestSpec = 0x02,
1149 }; };
1150
1151 enum class ShowDurations {
1152 DefaultForReporter,
1153 Always,
1154 Never
1155 };
1156 enum class TestRunOrder {
1157 Declared,
1158 LexicographicallySorted,
1159 Randomized
1160 };
1161 enum class ColourMode : std::uint8_t {
1162 //! Let Catch2 pick implementation based on platform detection
1163 PlatformDefault,
1164 //! Use ANSI colour code escapes
1165 ANSI,
1166 //! Use Win32 console colour API
1167 Win32,
1168 //! Don't use any colour
1169 None
1170 };
1171 struct WaitForKeypress { enum When {
1172 Never,
1173 BeforeStart = 1,
1174 BeforeExit = 2,
1175 BeforeStartAndExit = BeforeStart | BeforeExit
1176 }; };
1177
1178 class TestSpec;
1179 class IStream;
1180
1181 class IConfig : public Detail::NonCopyable {
1182 public:
1183 virtual ~IConfig();
1184
1185 virtual bool allowThrows() const = 0;
1186 virtual StringRef name() const = 0;
1187 virtual bool includeSuccessfulResults() const = 0;
1188 virtual bool shouldDebugBreak() const = 0;
1189 virtual bool warnAboutMissingAssertions() const = 0;
1190 virtual bool warnAboutUnmatchedTestSpecs() const = 0;
1191 virtual bool zeroTestsCountAsSuccess() const = 0;
1192 virtual int abortAfter() const = 0;
1193 virtual bool showInvisibles() const = 0;
1194 virtual ShowDurations showDurations() const = 0;
1195 virtual double minDuration() const = 0;
1196 virtual TestSpec const& testSpec() const = 0;
1197 virtual bool hasTestFilters() const = 0;
1198 virtual std::vector<std::string> const& getTestsOrTags() const = 0;
1199 virtual TestRunOrder runOrder() const = 0;
1200 virtual uint32_t rngSeed() const = 0;
1201 virtual unsigned int shardCount() const = 0;
1202 virtual unsigned int shardIndex() const = 0;
1203 virtual ColourMode defaultColourMode() const = 0;
1204 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
1205 virtual Verbosity verbosity() const = 0;
1206
1207 virtual bool skipBenchmarks() const = 0;
1208 virtual bool benchmarkNoAnalysis() const = 0;
1209 virtual unsigned int benchmarkSamples() const = 0;
1210 virtual double benchmarkConfidenceInterval() const = 0;
1211 virtual unsigned int benchmarkResamples() const = 0;
1212 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
1213 };
1214}
1215
1216#endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED
1217
1218
1219#ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
1220#define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
1221
1222
1223#include <string>
1224
1225namespace Catch {
1226
1227 class TestCaseHandle;
1228 struct TestCaseInfo;
1229 class ITestCaseRegistry;
1230 class IExceptionTranslatorRegistry;
1231 class IExceptionTranslator;
1232 class ReporterRegistry;
1233 class IReporterFactory;
1234 class ITagAliasRegistry;
1235 class ITestInvoker;
1236 class IMutableEnumValuesRegistry;
1237 struct SourceLineInfo;
1238
1239 class StartupExceptionRegistry;
1240 class EventListenerFactory;
1241
1242 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
1243
1244 class IRegistryHub {
1245 public:
1246 virtual ~IRegistryHub(); // = default
1247
1248 virtual ReporterRegistry const& getReporterRegistry() const = 0;
1249 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
1250 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
1251 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
1252
1253
1254 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
1255 };
1256
1257 class IMutableRegistryHub {
1258 public:
1259 virtual ~IMutableRegistryHub(); // = default
1260 virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0;
1261 virtual void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) = 0;
1262 virtual void registerTest(Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker) = 0;
1263 virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
1264 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
1265 virtual void registerStartupException() noexcept = 0;
1266 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
1267 };
1268
1269 IRegistryHub const& getRegistryHub();
1270 IMutableRegistryHub& getMutableRegistryHub();
1271 void cleanUp();
1272 std::string translateActiveException();
1273
1274}
1275
1276#endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
1277
1278
1279#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED
1280#define CATCH_BENCHMARK_STATS_HPP_INCLUDED
1281
1282
1283
1284// Adapted from donated nonius code.
1285
1286#ifndef CATCH_ESTIMATE_HPP_INCLUDED
1287#define CATCH_ESTIMATE_HPP_INCLUDED
1288
1289namespace Catch {
1290 namespace Benchmark {
1291 template <typename Type>
1292 struct Estimate {
1293 Type point;
1294 Type lower_bound;
1295 Type upper_bound;
1296 double confidence_interval;
1297 };
1298 } // namespace Benchmark
1299} // namespace Catch
1300
1301#endif // CATCH_ESTIMATE_HPP_INCLUDED
1302
1303
1304// Adapted from donated nonius code.
1305
1306#ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
1307#define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
1308
1309namespace Catch {
1310 namespace Benchmark {
1311 struct OutlierClassification {
1312 int samples_seen = 0;
1313 int low_severe = 0; // more than 3 times IQR below Q1
1314 int low_mild = 0; // 1.5 to 3 times IQR below Q1
1315 int high_mild = 0; // 1.5 to 3 times IQR above Q3
1316 int high_severe = 0; // more than 3 times IQR above Q3
1317
1318 constexpr int total() const {
1319 return low_severe + low_mild + high_mild + high_severe;
1320 }
1321 };
1322 } // namespace Benchmark
1323} // namespace Catch
1324
1325#endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED
1326// The fwd decl & default specialization needs to be seen by VS2017 before
1327// BenchmarkStats itself, or VS2017 will report compilation error.
1328
1329#include <string>
1330#include <vector>
1331
1332namespace Catch {
1333
1334 struct BenchmarkInfo {
1335 std::string name;
1336 double estimatedDuration;
1337 int iterations;
1338 unsigned int samples;
1339 unsigned int resamples;
1340 double clockResolution;
1341 double clockCost;
1342 };
1343
1344 // We need to keep template parameter for backwards compatibility,
1345 // but we also do not want to use the template paraneter.
1346 template <class Dummy>
1347 struct BenchmarkStats {
1348 BenchmarkInfo info;
1349
1350 std::vector<Benchmark::FDuration> samples;
1351 Benchmark::Estimate<Benchmark::FDuration> mean;
1352 Benchmark::Estimate<Benchmark::FDuration> standardDeviation;
1353 Benchmark::OutlierClassification outliers;
1354 double outlierVariance;
1355 };
1356
1357
1358} // end namespace Catch
1359
1360#endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED
1361
1362
1363// Adapted from donated nonius code.
1364
1365#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED
1366#define CATCH_ENVIRONMENT_HPP_INCLUDED
1367
1368
1369namespace Catch {
1370 namespace Benchmark {
1371 struct EnvironmentEstimate {
1372 FDuration mean;
1373 OutlierClassification outliers;
1374 };
1375 struct Environment {
1376 EnvironmentEstimate clock_resolution;
1377 EnvironmentEstimate clock_cost;
1378 };
1379 } // namespace Benchmark
1380} // namespace Catch
1381
1382#endif // CATCH_ENVIRONMENT_HPP_INCLUDED
1383
1384
1385// Adapted from donated nonius code.
1386
1387#ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED
1388#define CATCH_EXECUTION_PLAN_HPP_INCLUDED
1389
1390
1391
1392// Adapted from donated nonius code.
1393
1394#ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
1395#define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
1396
1397
1398
1399// Adapted from donated nonius code.
1400
1401#ifndef CATCH_CHRONOMETER_HPP_INCLUDED
1402#define CATCH_CHRONOMETER_HPP_INCLUDED
1403
1404
1405
1406// Adapted from donated nonius code.
1407
1408#ifndef CATCH_OPTIMIZER_HPP_INCLUDED
1409#define CATCH_OPTIMIZER_HPP_INCLUDED
1410
1411#if defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
1412# include <atomic> // atomic_thread_fence
1413#endif
1414
1415
1416#include <type_traits>
1417
1418namespace Catch {
1419 namespace Benchmark {
1420#if defined(__GNUC__) || defined(__clang__)
1421 template <typename T>
1422 inline void keep_memory(T* p) {
1423 asm volatile("" : : "g"(p) : "memory");
1424 }
1425 inline void keep_memory() {
1426 asm volatile("" : : : "memory");
1427 }
1428
1429 namespace Detail {
1430 inline void optimizer_barrier() { keep_memory(); }
1431 } // namespace Detail
1432#elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
1433
1434#if defined(_MSVC_VER)
1435#pragma optimize("", off)
1436#elif defined(__IAR_SYSTEMS_ICC__)
1437// For IAR the pragma only affects the following function
1438#pragma optimize=disable
1439#endif
1440 template <typename T>
1441 inline void keep_memory(T* p) {
1442 // thanks @milleniumbug
1443 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
1444 }
1445 // TODO equivalent keep_memory()
1446#if defined(_MSVC_VER)
1447#pragma optimize("", on)
1448#endif
1449
1450 namespace Detail {
1451 inline void optimizer_barrier() {
1452 std::atomic_thread_fence(std::memory_order_seq_cst);
1453 }
1454 } // namespace Detail
1455
1456#endif
1457
1458 template <typename T>
1459 inline void deoptimize_value(T&& x) {
1460 keep_memory(&x);
1461 }
1462
1463 template <typename Fn, typename... Args>
1464 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same<void, decltype(fn(args...))>::value> {
1465 deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...));
1466 }
1467
1468 template <typename Fn, typename... Args>
1469 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> {
1470 CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...);
1471 }
1472 } // namespace Benchmark
1473} // namespace Catch
1474
1475#endif // CATCH_OPTIMIZER_HPP_INCLUDED
1476
1477
1478#ifndef CATCH_META_HPP_INCLUDED
1479#define CATCH_META_HPP_INCLUDED
1480
1481#include <type_traits>
1482
1483namespace Catch {
1484 template <typename>
1485 struct true_given : std::true_type {};
1486
1487 struct is_callable_tester {
1488 template <typename Fun, typename... Args>
1489 static true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int);
1490 template <typename...>
1491 static std::false_type test(...);
1492 };
1493
1494 template <typename T>
1495 struct is_callable;
1496
1497 template <typename Fun, typename... Args>
1498 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
1499
1500
1501#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
1502 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
1503 // replaced with std::invoke_result here.
1504 template <typename Func, typename... U>
1505 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
1506#else
1507 template <typename Func, typename... U>
1508 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::result_of_t<Func(U...)>>>;
1509#endif
1510
1511} // namespace Catch
1512
1513namespace mpl_{
1514 struct na;
1515}
1516
1517#endif // CATCH_META_HPP_INCLUDED
1518
1519namespace Catch {
1520 namespace Benchmark {
1521 namespace Detail {
1522 struct ChronometerConcept {
1523 virtual void start() = 0;
1524 virtual void finish() = 0;
1525 virtual ~ChronometerConcept(); // = default;
1526
1527 ChronometerConcept() = default;
1528 ChronometerConcept(ChronometerConcept const&) = default;
1529 ChronometerConcept& operator=(ChronometerConcept const&) = default;
1530 };
1531 template <typename Clock>
1532 struct ChronometerModel final : public ChronometerConcept {
1533 void start() override { started = Clock::now(); }
1534 void finish() override { finished = Clock::now(); }
1535
1536 IDuration elapsed() const {
1537 return std::chrono::duration_cast<std::chrono::nanoseconds>(
1538 finished - started );
1539 }
1540
1541 TimePoint<Clock> started;
1542 TimePoint<Clock> finished;
1543 };
1544 } // namespace Detail
1545
1546 struct Chronometer {
1547 public:
1548 template <typename Fun>
1549 void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable<Fun(int)>()); }
1550
1551 int runs() const { return repeats; }
1552
1553 Chronometer(Detail::ChronometerConcept& meter, int repeats_)
1554 : impl(&meter)
1555 , repeats(repeats_) {}
1556
1557 private:
1558 template <typename Fun>
1559 void measure(Fun&& fun, std::false_type) {
1560 measure([&fun](int) { return fun(); }, std::true_type());
1561 }
1562
1563 template <typename Fun>
1564 void measure(Fun&& fun, std::true_type) {
1565 Detail::optimizer_barrier();
1566 impl->start();
1567 for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i);
1568 impl->finish();
1569 Detail::optimizer_barrier();
1570 }
1571
1572 Detail::ChronometerConcept* impl;
1573 int repeats;
1574 };
1575 } // namespace Benchmark
1576} // namespace Catch
1577
1578#endif // CATCH_CHRONOMETER_HPP_INCLUDED
1579
1580#include <type_traits>
1581
1582namespace Catch {
1583 namespace Benchmark {
1584 namespace Detail {
1585 template <typename T, typename U>
1586 struct is_related
1587 : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
1588
1589 /// We need to reinvent std::function because every piece of code that might add overhead
1590 /// in a measurement context needs to have consistent performance characteristics so that we
1591 /// can account for it in the measurement.
1592 /// Implementations of std::function with optimizations that aren't always applicable, like
1593 /// small buffer optimizations, are not uncommon.
1594 /// This is effectively an implementation of std::function without any such optimizations;
1595 /// it may be slow, but it is consistently slow.
1596 struct BenchmarkFunction {
1597 private:
1598 struct callable {
1599 virtual void call(Chronometer meter) const = 0;
1600 virtual ~callable(); // = default;
1601
1602 callable() = default;
1603 callable(callable&&) = default;
1604 callable& operator=(callable&&) = default;
1605 };
1606 template <typename Fun>
1607 struct model : public callable {
1608 model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
1609 model(Fun const& fun_) : fun(fun_) {}
1610
1611 void call(Chronometer meter) const override {
1612 call(meter, is_callable<Fun(Chronometer)>());
1613 }
1614 void call(Chronometer meter, std::true_type) const {
1615 fun(meter);
1616 }
1617 void call(Chronometer meter, std::false_type) const {
1618 meter.measure(fun);
1619 }
1620
1621 Fun fun;
1622 };
1623
1624 public:
1625 BenchmarkFunction();
1626
1627 template <typename Fun,
1628 std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0>
1629 BenchmarkFunction(Fun&& fun)
1630 : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
1631
1632 BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
1633 f( CATCH_MOVE( that.f ) ) {}
1634
1635 BenchmarkFunction&
1636 operator=( BenchmarkFunction&& that ) noexcept {
1637 f = CATCH_MOVE( that.f );
1638 return *this;
1639 }
1640
1641 void operator()(Chronometer meter) const { f->call(meter); }
1642
1643 private:
1644 Catch::Detail::unique_ptr<callable> f;
1645 };
1646 } // namespace Detail
1647 } // namespace Benchmark
1648} // namespace Catch
1649
1650#endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
1651
1652
1653// Adapted from donated nonius code.
1654
1655#ifndef CATCH_REPEAT_HPP_INCLUDED
1656#define CATCH_REPEAT_HPP_INCLUDED
1657
1658#include <type_traits>
1659
1660namespace Catch {
1661 namespace Benchmark {
1662 namespace Detail {
1663 template <typename Fun>
1664 struct repeater {
1665 void operator()(int k) const {
1666 for (int i = 0; i < k; ++i) {
1667 fun();
1668 }
1669 }
1670 Fun fun;
1671 };
1672 template <typename Fun>
1673 repeater<std::decay_t<Fun>> repeat(Fun&& fun) {
1674 return { CATCH_FORWARD(fun) };
1675 }
1676 } // namespace Detail
1677 } // namespace Benchmark
1678} // namespace Catch
1679
1680#endif // CATCH_REPEAT_HPP_INCLUDED
1681
1682
1683// Adapted from donated nonius code.
1684
1685#ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
1686#define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
1687
1688
1689
1690// Adapted from donated nonius code.
1691
1692#ifndef CATCH_MEASURE_HPP_INCLUDED
1693#define CATCH_MEASURE_HPP_INCLUDED
1694
1695
1696
1697// Adapted from donated nonius code.
1698
1699#ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED
1700#define CATCH_COMPLETE_INVOKE_HPP_INCLUDED
1701
1702
1703namespace Catch {
1704 namespace Benchmark {
1705 namespace Detail {
1706 template <typename T>
1707 struct CompleteType { using type = T; };
1708 template <>
1709 struct CompleteType<void> { struct type {}; };
1710
1711 template <typename T>
1712 using CompleteType_t = typename CompleteType<T>::type;
1713
1714 template <typename Result>
1715 struct CompleteInvoker {
1716 template <typename Fun, typename... Args>
1717 static Result invoke(Fun&& fun, Args&&... args) {
1718 return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
1719 }
1720 };
1721 template <>
1722 struct CompleteInvoker<void> {
1723 template <typename Fun, typename... Args>
1724 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {
1725 CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
1726 return {};
1727 }
1728 };
1729
1730 // invoke and not return void :(
1731 template <typename Fun, typename... Args>
1732 CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {
1733 return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
1734 }
1735
1736 } // namespace Detail
1737
1738 template <typename Fun>
1739 Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {
1740 return Detail::complete_invoke(CATCH_FORWARD(fun));
1741 }
1742 } // namespace Benchmark
1743} // namespace Catch
1744
1745#endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED
1746
1747
1748// Adapted from donated nonius code.
1749
1750#ifndef CATCH_TIMING_HPP_INCLUDED
1751#define CATCH_TIMING_HPP_INCLUDED
1752
1753
1754#include <type_traits>
1755
1756namespace Catch {
1757 namespace Benchmark {
1758 template <typename Result>
1759 struct Timing {
1760 IDuration elapsed;
1761 Result result;
1762 int iterations;
1763 };
1764 template <typename Func, typename... Args>
1765 using TimingOf = Timing<Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
1766 } // namespace Benchmark
1767} // namespace Catch
1768
1769#endif // CATCH_TIMING_HPP_INCLUDED
1770
1771namespace Catch {
1772 namespace Benchmark {
1773 namespace Detail {
1774 template <typename Clock, typename Fun, typename... Args>
1775 TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) {
1776 auto start = Clock::now();
1777 auto&& r = Detail::complete_invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
1778 auto end = Clock::now();
1779 auto delta = end - start;
1780 return { delta, CATCH_FORWARD(r), 1 };
1781 }
1782 } // namespace Detail
1783 } // namespace Benchmark
1784} // namespace Catch
1785
1786#endif // CATCH_MEASURE_HPP_INCLUDED
1787
1788#include <type_traits>
1789
1790namespace Catch {
1791 namespace Benchmark {
1792 namespace Detail {
1793 template <typename Clock, typename Fun>
1794 TimingOf<Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
1795 return Detail::measure<Clock>(fun, iters);
1796 }
1797 template <typename Clock, typename Fun>
1798 TimingOf<Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
1799 Detail::ChronometerModel<Clock> meter;
1800 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
1801
1802 return { meter.elapsed(), CATCH_MOVE(result), iters };
1803 }
1804
1805 template <typename Clock, typename Fun>
1806 using run_for_at_least_argument_t = std::conditional_t<is_callable<Fun(Chronometer)>::value, Chronometer, int>;
1807
1808
1809 [[noreturn]]
1810 void throw_optimized_away_error();
1811
1812 template <typename Clock, typename Fun>
1813 TimingOf<Fun, run_for_at_least_argument_t<Clock, Fun>>
1814 run_for_at_least(IDuration how_long,
1815 const int initial_iterations,
1816 Fun&& fun) {
1817 auto iters = initial_iterations;
1818 while (iters < (1 << 30)) {
1819 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
1820
1821 if (Timing.elapsed >= how_long) {
1822 return { Timing.elapsed, CATCH_MOVE(Timing.result), iters };
1823 }
1824 iters *= 2;
1825 }
1826 throw_optimized_away_error();
1827 }
1828 } // namespace Detail
1829 } // namespace Benchmark
1830} // namespace Catch
1831
1832#endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
1833
1834#include <vector>
1835
1836namespace Catch {
1837 namespace Benchmark {
1838 struct ExecutionPlan {
1839 int iterations_per_sample;
1840 FDuration estimated_duration;
1841 Detail::BenchmarkFunction benchmark;
1842 FDuration warmup_time;
1843 int warmup_iterations;
1844
1845 template <typename Clock>
1846 std::vector<FDuration> run(const IConfig &cfg, Environment env) const {
1847 // warmup a bit
1848 Detail::run_for_at_least<Clock>(
1849 std::chrono::duration_cast<IDuration>( warmup_time ),
1850 warmup_iterations,
1851 Detail::repeat( []() { return Clock::now(); } )
1852 );
1853
1854 std::vector<FDuration> times;
1855 const auto num_samples = cfg.benchmarkSamples();
1856 times.reserve( num_samples );
1857 for ( size_t i = 0; i < num_samples; ++i ) {
1858 Detail::ChronometerModel<Clock> model;
1859 this->benchmark( Chronometer( model, iterations_per_sample ) );
1860 auto sample_time = model.elapsed() - env.clock_cost.mean;
1861 if ( sample_time < FDuration::zero() ) {
1862 sample_time = FDuration::zero();
1863 }
1864 times.push_back(sample_time / iterations_per_sample);
1865 }
1866 return times;
1867 }
1868 };
1869 } // namespace Benchmark
1870} // namespace Catch
1871
1872#endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED
1873
1874
1875// Adapted from donated nonius code.
1876
1877#ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
1878#define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
1879
1880
1881
1882// Adapted from donated nonius code.
1883
1884#ifndef CATCH_STATS_HPP_INCLUDED
1885#define CATCH_STATS_HPP_INCLUDED
1886
1887
1888#include <vector>
1889
1890namespace Catch {
1891 namespace Benchmark {
1892 namespace Detail {
1893 using sample = std::vector<double>;
1894
1895 double weighted_average_quantile( int k,
1896 int q,
1897 double* first,
1898 double* last );
1899
1900 OutlierClassification
1901 classify_outliers( double const* first, double const* last );
1902
1903 double mean( double const* first, double const* last );
1904
1905 double normal_cdf( double x );
1906
1907 double erfc_inv(double x);
1908
1909 double normal_quantile(double p);
1910
1911 Estimate<double>
1912 bootstrap( double confidence_level,
1913 double* first,
1914 double* last,
1915 sample const& resample,
1916 double ( *estimator )( double const*, double const* ) );
1917
1918 struct bootstrap_analysis {
1919 Estimate<double> mean;
1920 Estimate<double> standard_deviation;
1921 double outlier_variance;
1922 };
1923
1924 bootstrap_analysis analyse_samples(double confidence_level,
1925 unsigned int n_resamples,
1926 double* first,
1927 double* last);
1928 } // namespace Detail
1929 } // namespace Benchmark
1930} // namespace Catch
1931
1932#endif // CATCH_STATS_HPP_INCLUDED
1933
1934#include <algorithm>
1935#include <vector>
1936#include <cmath>
1937
1938namespace Catch {
1939 namespace Benchmark {
1940 namespace Detail {
1941 template <typename Clock>
1942 std::vector<double> resolution(int k) {
1943 const size_t points = static_cast<size_t>( k + 1 );
1944 // To avoid overhead from the branch inside vector::push_back,
1945 // we allocate them all and then overwrite.
1946 std::vector<TimePoint<Clock>> times(points);
1947 for ( auto& time : times ) {
1948 time = Clock::now();
1949 }
1950
1951 std::vector<double> deltas;
1952 deltas.reserve(static_cast<size_t>(k));
1953 for ( size_t idx = 1; idx < points; ++idx ) {
1954 deltas.push_back( static_cast<double>(
1955 ( times[idx] - times[idx - 1] ).count() ) );
1956 }
1957
1958 return deltas;
1959 }
1960
1961 constexpr auto warmup_iterations = 10000;
1962 constexpr auto warmup_time = std::chrono::milliseconds(100);
1963 constexpr auto minimum_ticks = 1000;
1964 constexpr auto warmup_seed = 10000;
1965 constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
1966 constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
1967 constexpr auto clock_cost_estimation_tick_limit = 100000;
1968 constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10);
1969 constexpr auto clock_cost_estimation_iterations = 10000;
1970
1971 template <typename Clock>
1972 int warmup() {
1973 return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>)
1974 .iterations;
1975 }
1976 template <typename Clock>
1977 EnvironmentEstimate estimate_clock_resolution(int iterations) {
1978 auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>)
1979 .result;
1980 return {
1981 FDuration(mean(r.data(), r.data() + r.size())),
1982 classify_outliers(r.data(), r.data() + r.size()),
1983 };
1984 }
1985 template <typename Clock>
1986 EnvironmentEstimate estimate_clock_cost(FDuration resolution) {
1987 auto time_limit = (std::min)(
1988 resolution * clock_cost_estimation_tick_limit,
1989 FDuration(clock_cost_estimation_time_limit));
1990 auto time_clock = [](int k) {
1991 return Detail::measure<Clock>([k] {
1992 for (int i = 0; i < k; ++i) {
1993 volatile auto ignored = Clock::now();
1994 (void)ignored;
1995 }
1996 }).elapsed;
1997 };
1998 time_clock(1);
1999 int iters = clock_cost_estimation_iterations;
2000 auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock);
2001 std::vector<double> times;
2002 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
2003 times.reserve(static_cast<size_t>(nsamples));
2004 for ( int s = 0; s < nsamples; ++s ) {
2005 times.push_back( static_cast<double>(
2006 ( time_clock( r.iterations ) / r.iterations )
2007 .count() ) );
2008 }
2009 return {
2010 FDuration(mean(times.data(), times.data() + times.size())),
2011 classify_outliers(times.data(), times.data() + times.size()),
2012 };
2013 }
2014
2015 template <typename Clock>
2016 Environment measure_environment() {
2017#if defined(__clang__)
2018# pragma clang diagnostic push
2019# pragma clang diagnostic ignored "-Wexit-time-destructors"
2020#endif
2021 static Catch::Detail::unique_ptr<Environment> env;
2022#if defined(__clang__)
2023# pragma clang diagnostic pop
2024#endif
2025 if (env) {
2026 return *env;
2027 }
2028
2029 auto iters = Detail::warmup<Clock>();
2030 auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
2031 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
2032
2033 env = Catch::Detail::make_unique<Environment>( Environment{resolution, cost} );
2034 return *env;
2035 }
2036 } // namespace Detail
2037 } // namespace Benchmark
2038} // namespace Catch
2039
2040#endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
2041
2042
2043// Adapted from donated nonius code.
2044
2045#ifndef CATCH_ANALYSE_HPP_INCLUDED
2046#define CATCH_ANALYSE_HPP_INCLUDED
2047
2048
2049
2050// Adapted from donated nonius code.
2051
2052#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
2053#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
2054
2055
2056#include <vector>
2057
2058namespace Catch {
2059 namespace Benchmark {
2060 struct SampleAnalysis {
2061 std::vector<FDuration> samples;
2062 Estimate<FDuration> mean;
2063 Estimate<FDuration> standard_deviation;
2064 OutlierClassification outliers;
2065 double outlier_variance;
2066 };
2067 } // namespace Benchmark
2068} // namespace Catch
2069
2070#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
2071
2072
2073namespace Catch {
2074 class IConfig;
2075
2076 namespace Benchmark {
2077 namespace Detail {
2078 SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last);
2079 } // namespace Detail
2080 } // namespace Benchmark
2081} // namespace Catch
2082
2083#endif // CATCH_ANALYSE_HPP_INCLUDED
2084
2085#include <algorithm>
2086#include <chrono>
2087#include <exception>
2088#include <string>
2089#include <cmath>
2090
2091namespace Catch {
2092 namespace Benchmark {
2093 struct Benchmark {
2094 Benchmark(std::string&& benchmarkName)
2095 : name(CATCH_MOVE(benchmarkName)) {}
2096
2097 template <class FUN>
2098 Benchmark(std::string&& benchmarkName , FUN &&func)
2099 : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}
2100
2101 template <typename Clock>
2102 ExecutionPlan prepare(const IConfig &cfg, Environment env) {
2103 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
2104 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
2105 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun);
2106 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
2107 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), CATCH_MOVE(fun), std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
2108 }
2109
2110 template <typename Clock = default_clock>
2111 void run() {
2112 static_assert( Clock::is_steady,
2113 "Benchmarking clock should be steady" );
2114 auto const* cfg = getCurrentContext().getConfig();
2115
2116 auto env = Detail::measure_environment<Clock>();
2117
2118 getResultCapture().benchmarkPreparing(name);
2119 CATCH_TRY{
2120 auto plan = user_code([&] {
2121 return prepare<Clock>(*cfg, env);
2122 });
2123
2124 BenchmarkInfo info {
2125 CATCH_MOVE(name),
2126 plan.estimated_duration.count(),
2127 plan.iterations_per_sample,
2128 cfg->benchmarkSamples(),
2129 cfg->benchmarkResamples(),
2130 env.clock_resolution.mean.count(),
2131 env.clock_cost.mean.count()
2132 };
2133
2134 getResultCapture().benchmarkStarting(info);
2135
2136 auto samples = user_code([&] {
2137 return plan.template run<Clock>(*cfg, env);
2138 });
2139
2140 auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size());
2141 BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
2142 getResultCapture().benchmarkEnded(stats);
2143 } CATCH_CATCH_ANON (TestFailureException const&) {
2144 getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);
2145 } CATCH_CATCH_ALL{
2146 getResultCapture().benchmarkFailed(translateActiveException());
2147 // We let the exception go further up so that the
2148 // test case is marked as failed.
2149 std::rethrow_exception(std::current_exception());
2150 }
2151 }
2152
2153 // sets lambda to be used in fun *and* executes benchmark!
2154 template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0>
2155 Benchmark & operator=(Fun func) {
2156 auto const* cfg = getCurrentContext().getConfig();
2157 if (!cfg->skipBenchmarks()) {
2158 fun = Detail::BenchmarkFunction(func);
2159 run();
2160 }
2161 return *this;
2162 }
2163
2164 explicit operator bool() {
2165 return true;
2166 }
2167
2168 private:
2169 Detail::BenchmarkFunction fun;
2170 std::string name;
2171 };
2172 }
2173} // namespace Catch
2174
2175#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
2176#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
2177
2178#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
2179 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
2180 BenchmarkName = [&](int benchmarkIndex)
2181
2182#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
2183 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
2184 BenchmarkName = [&]
2185
2186#if defined(CATCH_CONFIG_PREFIX_ALL)
2187
2188#define CATCH_BENCHMARK(...) \
2189 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
2190#define CATCH_BENCHMARK_ADVANCED(name) \
2191 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
2192
2193#else
2194
2195#define BENCHMARK(...) \
2196 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
2197#define BENCHMARK_ADVANCED(name) \
2198 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
2199
2200#endif
2201
2202#endif // CATCH_BENCHMARK_HPP_INCLUDED
2203
2204
2205// Adapted from donated nonius code.
2206
2207#ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED
2208#define CATCH_CONSTRUCTOR_HPP_INCLUDED
2209
2210
2211#include <type_traits>
2212
2213namespace Catch {
2214 namespace Benchmark {
2215 namespace Detail {
2216 template <typename T, bool Destruct>
2217 struct ObjectStorage
2218 {
2219 ObjectStorage() = default;
2220
2221 ObjectStorage(const ObjectStorage& other)
2222 {
2223 new(&data) T(other.stored_object());
2224 }
2225
2226 ObjectStorage(ObjectStorage&& other)
2227 {
2228 new(data) T(CATCH_MOVE(other.stored_object()));
2229 }
2230
2231 ~ObjectStorage() { destruct_on_exit<T>(); }
2232
2233 template <typename... Args>
2234 void construct(Args&&... args)
2235 {
2236 new (data) T(CATCH_FORWARD(args)...);
2237 }
2238
2239 template <bool AllowManualDestruction = !Destruct>
2240 std::enable_if_t<AllowManualDestruction> destruct()
2241 {
2242 stored_object().~T();
2243 }
2244
2245 private:
2246 // If this is a constructor benchmark, destruct the underlying object
2247 template <typename U>
2248 void destruct_on_exit(std::enable_if_t<Destruct, U>* = nullptr) { destruct<true>(); }
2249 // Otherwise, don't
2250 template <typename U>
2251 void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { }
2252
2253#if defined( __GNUC__ ) && __GNUC__ <= 6
2254# pragma GCC diagnostic push
2255# pragma GCC diagnostic ignored "-Wstrict-aliasing"
2256#endif
2257 T& stored_object() { return *reinterpret_cast<T*>( data ); }
2258
2259 T const& stored_object() const {
2260 return *reinterpret_cast<T const*>( data );
2261 }
2262#if defined( __GNUC__ ) && __GNUC__ <= 6
2263# pragma GCC diagnostic pop
2264#endif
2265
2266 alignas( T ) unsigned char data[sizeof( T )]{};
2267 };
2268 } // namespace Detail
2269
2270 template <typename T>
2271 using storage_for = Detail::ObjectStorage<T, true>;
2272
2273 template <typename T>
2274 using destructable_object = Detail::ObjectStorage<T, false>;
2275 } // namespace Benchmark
2276} // namespace Catch
2277
2278#endif // CATCH_CONSTRUCTOR_HPP_INCLUDED
2279
2280#endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED
2281
2282
2283#ifndef CATCH_APPROX_HPP_INCLUDED
2284#define CATCH_APPROX_HPP_INCLUDED
2285
2286
2287
2288#ifndef CATCH_TOSTRING_HPP_INCLUDED
2289#define CATCH_TOSTRING_HPP_INCLUDED
2290
2291
2292#include <vector>
2293#include <cstddef>
2294#include <type_traits>
2295#include <string>
2296
2297
2298
2299
2300/** \file
2301 * Wrapper for the WCHAR configuration option
2302 *
2303 * We want to support platforms that do not provide `wchar_t`, so we
2304 * sometimes have to disable providing wchar_t overloads through Catch2,
2305 * e.g. the StringMaker specialization for `std::wstring`.
2306 */
2307
2308#ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED
2309#define CATCH_CONFIG_WCHAR_HPP_INCLUDED
2310
2311
2312// We assume that WCHAR should be enabled by default, and only disabled
2313// for a shortlist (so far only DJGPP) of compilers.
2314
2315#if defined(__DJGPP__)
2316# define CATCH_INTERNAL_CONFIG_NO_WCHAR
2317#endif // __DJGPP__
2318
2319#if !defined( CATCH_INTERNAL_CONFIG_NO_WCHAR ) && \
2320 !defined( CATCH_CONFIG_NO_WCHAR ) && \
2321 !defined( CATCH_CONFIG_WCHAR )
2322# define CATCH_CONFIG_WCHAR
2323#endif
2324
2325#endif // CATCH_CONFIG_WCHAR_HPP_INCLUDED
2326
2327
2328#ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
2329#define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
2330
2331
2332#include <iosfwd>
2333#include <cstddef>
2334#include <ostream>
2335#include <string>
2336
2337namespace Catch {
2338
2339 class ReusableStringStream : Detail::NonCopyable {
2340 std::size_t m_index;
2341 std::ostream* m_oss;
2342 public:
2343 ReusableStringStream();
2344 ~ReusableStringStream();
2345
2346 //! Returns the serialized state
2347 std::string str() const;
2348 //! Sets internal state to `str`
2349 void str(std::string const& str);
2350
2351#if defined(__GNUC__) && !defined(__clang__)
2352#pragma GCC diagnostic push
2353// Old versions of GCC do not understand -Wnonnull-compare
2354#pragma GCC diagnostic ignored "-Wpragmas"
2355// Streaming a function pointer triggers Waddress and Wnonnull-compare
2356// on GCC, because it implicitly converts it to bool and then decides
2357// that the check it uses (a? true : false) is tautological and cannot
2358// be null...
2359#pragma GCC diagnostic ignored "-Waddress"
2360#pragma GCC diagnostic ignored "-Wnonnull-compare"
2361#endif
2362
2363 template<typename T>
2364 auto operator << ( T const& value ) -> ReusableStringStream& {
2365 *m_oss << value;
2366 return *this;
2367 }
2368
2369#if defined(__GNUC__) && !defined(__clang__)
2370#pragma GCC diagnostic pop
2371#endif
2372 auto get() -> std::ostream& { return *m_oss; }
2373 };
2374}
2375
2376#endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
2377
2378
2379#ifndef CATCH_VOID_TYPE_HPP_INCLUDED
2380#define CATCH_VOID_TYPE_HPP_INCLUDED
2381
2382
2383namespace Catch {
2384 namespace Detail {
2385
2386 template <typename...>
2387 struct make_void { using type = void; };
2388
2389 template <typename... Ts>
2390 using void_t = typename make_void<Ts...>::type;
2391
2392 } // namespace Detail
2393} // namespace Catch
2394
2395
2396#endif // CATCH_VOID_TYPE_HPP_INCLUDED
2397
2398
2399#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
2400#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
2401
2402
2403#include <vector>
2404
2405namespace Catch {
2406
2407 namespace Detail {
2408 struct EnumInfo {
2409 StringRef m_name;
2410 std::vector<std::pair<int, StringRef>> m_values;
2411
2412 ~EnumInfo();
2413
2414 StringRef lookup( int value ) const;
2415 };
2416 } // namespace Detail
2417
2418 class IMutableEnumValuesRegistry {
2419 public:
2420 virtual ~IMutableEnumValuesRegistry(); // = default;
2421
2422 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
2423
2424 template<typename E>
2425 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
2426 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
2427 std::vector<int> intValues;
2428 intValues.reserve( values.size() );
2429 for( auto enumValue : values )
2430 intValues.push_back( static_cast<int>( enumValue ) );
2431 return registerEnum( enumName, allEnums, intValues );
2432 }
2433 };
2434
2435} // Catch
2436
2437#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
2438
2439#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2440#include <string_view>
2441#endif
2442
2443#ifdef _MSC_VER
2444#pragma warning(push)
2445#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
2446#endif
2447
2448// We need a dummy global operator<< so we can bring it into Catch namespace later
2449struct Catch_global_namespace_dummy{};
2450std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
2451
2452namespace Catch {
2453 // Bring in global namespace operator<< for ADL lookup in
2454 // `IsStreamInsertable` below.
2455 using ::operator<<;
2456
2457 namespace Detail {
2458
2459 inline std::size_t catch_strnlen(const char *str, std::size_t n) {
2460 auto ret = std::char_traits<char>::find(str, n, '\0');
2461 if (ret != nullptr) {
2462 return static_cast<std::size_t>(ret - str);
2463 }
2464 return n;
2465 }
2466
2467 constexpr StringRef unprintableString = "{?}"_sr;
2468
2469 //! Encases `string in quotes, and optionally escapes invisibles
2470 std::string convertIntoString( StringRef string, bool escapeInvisibles );
2471
2472 //! Encases `string` in quotes, and escapes invisibles if user requested
2473 //! it via CLI
2474 std::string convertIntoString( StringRef string );
2475
2476 std::string rawMemoryToString( const void *object, std::size_t size );
2477
2478 template<typename T>
2479 std::string rawMemoryToString( const T& object ) {
2480 return rawMemoryToString( &object, sizeof(object) );
2481 }
2482
2483 template<typename T>
2484 class IsStreamInsertable {
2485 template<typename Stream, typename U>
2486 static auto test(int)
2487 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
2488
2489 template<typename, typename>
2490 static auto test(...)->std::false_type;
2491
2492 public:
2493 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
2494 };
2495
2496 template<typename E>
2497 std::string convertUnknownEnumToString( E e );
2498
2499 template<typename T>
2500 std::enable_if_t<
2501 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
2502 std::string> convertUnstreamable( T const& ) {
2503 return std::string(Detail::unprintableString);
2504 }
2505 template<typename T>
2506 std::enable_if_t<
2507 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
2508 std::string> convertUnstreamable(T const& ex) {
2509 return ex.what();
2510 }
2511
2512
2513 template<typename T>
2514 std::enable_if_t<
2515 std::is_enum<T>::value,
2516 std::string> convertUnstreamable( T const& value ) {
2517 return convertUnknownEnumToString( value );
2518 }
2519
2520#if defined(_MANAGED)
2521 //! Convert a CLR string to a utf8 std::string
2522 template<typename T>
2523 std::string clrReferenceToString( T^ ref ) {
2524 if (ref == nullptr)
2525 return std::string("null");
2526 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
2527 cli::pin_ptr<System::Byte> p = &bytes[0];
2528 return std::string(reinterpret_cast<char const *>(p), bytes->Length);
2529 }
2530#endif
2531
2532 } // namespace Detail
2533
2534
2535 template <typename T, typename = void>
2536 struct StringMaker {
2537 template <typename Fake = T>
2538 static
2539 std::enable_if_t<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
2540 convert(const Fake& value) {
2541 ReusableStringStream rss;
2542 // NB: call using the function-like syntax to avoid ambiguity with
2543 // user-defined templated operator<< under clang.
2544 rss.operator<<(value);
2545 return rss.str();
2546 }
2547
2548 template <typename Fake = T>
2549 static
2550 std::enable_if_t<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
2551 convert( const Fake& value ) {
2552#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
2553 return Detail::convertUnstreamable(value);
2554#else
2555 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
2556#endif
2557 }
2558 };
2559
2560 namespace Detail {
2561
2562 // This function dispatches all stringification requests inside of Catch.
2563 // Should be preferably called fully qualified, like ::Catch::Detail::stringify
2564 template <typename T>
2565 std::string stringify(const T& e) {
2566 return ::Catch::StringMaker<std::remove_cv_t<std::remove_reference_t<T>>>::convert(e);
2567 }
2568
2569 template<typename E>
2570 std::string convertUnknownEnumToString( E e ) {
2571 return ::Catch::Detail::stringify(static_cast<std::underlying_type_t<E>>(e));
2572 }
2573
2574#if defined(_MANAGED)
2575 template <typename T>
2576 std::string stringify( T^ e ) {
2577 return ::Catch::StringMaker<T^>::convert(e);
2578 }
2579#endif
2580
2581 } // namespace Detail
2582
2583 // Some predefined specializations
2584
2585 template<>
2586 struct StringMaker<std::string> {
2587 static std::string convert(const std::string& str);
2588 };
2589
2590#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2591 template<>
2592 struct StringMaker<std::string_view> {
2593 static std::string convert(std::string_view str);
2594 };
2595#endif
2596
2597 template<>
2598 struct StringMaker<char const *> {
2599 static std::string convert(char const * str);
2600 };
2601 template<>
2602 struct StringMaker<char *> {
2603 static std::string convert(char * str);
2604 };
2605
2606#if defined(CATCH_CONFIG_WCHAR)
2607 template<>
2608 struct StringMaker<std::wstring> {
2609 static std::string convert(const std::wstring& wstr);
2610 };
2611
2612# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2613 template<>
2614 struct StringMaker<std::wstring_view> {
2615 static std::string convert(std::wstring_view str);
2616 };
2617# endif
2618
2619 template<>
2620 struct StringMaker<wchar_t const *> {
2621 static std::string convert(wchar_t const * str);
2622 };
2623 template<>
2624 struct StringMaker<wchar_t *> {
2625 static std::string convert(wchar_t * str);
2626 };
2627#endif // CATCH_CONFIG_WCHAR
2628
2629 template<size_t SZ>
2630 struct StringMaker<char[SZ]> {
2631 static std::string convert(char const* str) {
2632 return Detail::convertIntoString(
2633 StringRef( str, Detail::catch_strnlen( str, SZ ) ) );
2634 }
2635 };
2636 template<size_t SZ>
2637 struct StringMaker<signed char[SZ]> {
2638 static std::string convert(signed char const* str) {
2639 auto reinterpreted = reinterpret_cast<char const*>(str);
2640 return Detail::convertIntoString(
2641 StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
2642 }
2643 };
2644 template<size_t SZ>
2645 struct StringMaker<unsigned char[SZ]> {
2646 static std::string convert(unsigned char const* str) {
2647 auto reinterpreted = reinterpret_cast<char const*>(str);
2648 return Detail::convertIntoString(
2649 StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
2650 }
2651 };
2652
2653#if defined(CATCH_CONFIG_CPP17_BYTE)
2654 template<>
2655 struct StringMaker<std::byte> {
2656 static std::string convert(std::byte value);
2657 };
2658#endif // defined(CATCH_CONFIG_CPP17_BYTE)
2659 template<>
2660 struct StringMaker<int> {
2661 static std::string convert(int value);
2662 };
2663 template<>
2664 struct StringMaker<long> {
2665 static std::string convert(long value);
2666 };
2667 template<>
2668 struct StringMaker<long long> {
2669 static std::string convert(long long value);
2670 };
2671 template<>
2672 struct StringMaker<unsigned int> {
2673 static std::string convert(unsigned int value);
2674 };
2675 template<>
2676 struct StringMaker<unsigned long> {
2677 static std::string convert(unsigned long value);
2678 };
2679 template<>
2680 struct StringMaker<unsigned long long> {
2681 static std::string convert(unsigned long long value);
2682 };
2683
2684 template<>
2685 struct StringMaker<bool> {
2686 static std::string convert(bool b) {
2687 using namespace std::string_literals;
2688 return b ? "true"s : "false"s;
2689 }
2690 };
2691
2692 template<>
2693 struct StringMaker<char> {
2694 static std::string convert(char c);
2695 };
2696 template<>
2697 struct StringMaker<signed char> {
2698 static std::string convert(signed char value);
2699 };
2700 template<>
2701 struct StringMaker<unsigned char> {
2702 static std::string convert(unsigned char value);
2703 };
2704
2705 template<>
2706 struct StringMaker<std::nullptr_t> {
2707 static std::string convert(std::nullptr_t) {
2708 using namespace std::string_literals;
2709 return "nullptr"s;
2710 }
2711 };
2712
2713 template<>
2714 struct StringMaker<float> {
2715 static std::string convert(float value);
2716 CATCH_EXPORT static int precision;
2717 };
2718
2719 template<>
2720 struct StringMaker<double> {
2721 static std::string convert(double value);
2722 CATCH_EXPORT static int precision;
2723 };
2724
2725 template <typename T>
2726 struct StringMaker<T*> {
2727 template <typename U>
2728 static std::string convert(U* p) {
2729 if (p) {
2730 return ::Catch::Detail::rawMemoryToString(p);
2731 } else {
2732 return "nullptr";
2733 }
2734 }
2735 };
2736
2737 template <typename R, typename C>
2738 struct StringMaker<R C::*> {
2739 static std::string convert(R C::* p) {
2740 if (p) {
2741 return ::Catch::Detail::rawMemoryToString(p);
2742 } else {
2743 return "nullptr";
2744 }
2745 }
2746 };
2747
2748#if defined(_MANAGED)
2749 template <typename T>
2750 struct StringMaker<T^> {
2751 static std::string convert( T^ ref ) {
2752 return ::Catch::Detail::clrReferenceToString(ref);
2753 }
2754 };
2755#endif
2756
2757 namespace Detail {
2758 template<typename InputIterator, typename Sentinel = InputIterator>
2759 std::string rangeToString(InputIterator first, Sentinel last) {
2760 ReusableStringStream rss;
2761 rss << "{ ";
2762 if (first != last) {
2763 rss << ::Catch::Detail::stringify(*first);
2764 for (++first; first != last; ++first)
2765 rss << ", " << ::Catch::Detail::stringify(*first);
2766 }
2767 rss << " }";
2768 return rss.str();
2769 }
2770 }
2771
2772} // namespace Catch
2773
2774//////////////////////////////////////////////////////
2775// Separate std-lib types stringification, so it can be selectively enabled
2776// This means that we do not bring in their headers
2777
2778#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
2779# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
2780# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
2781# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
2782# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
2783#endif
2784
2785// Separate std::pair specialization
2786#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
2787#include <utility>
2788namespace Catch {
2789 template<typename T1, typename T2>
2790 struct StringMaker<std::pair<T1, T2> > {
2791 static std::string convert(const std::pair<T1, T2>& pair) {
2792 ReusableStringStream rss;
2793 rss << "{ "
2794 << ::Catch::Detail::stringify(pair.first)
2795 << ", "
2796 << ::Catch::Detail::stringify(pair.second)
2797 << " }";
2798 return rss.str();
2799 }
2800 };
2801}
2802#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
2803
2804#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
2805#include <optional>
2806namespace Catch {
2807 template<typename T>
2808 struct StringMaker<std::optional<T> > {
2809 static std::string convert(const std::optional<T>& optional) {
2810 if (optional.has_value()) {
2811 return ::Catch::Detail::stringify(*optional);
2812 } else {
2813 return "{ }";
2814 }
2815 }
2816 };
2817 template <>
2818 struct StringMaker<std::nullopt_t> {
2819 static std::string convert(const std::nullopt_t&) {
2820 return "{ }";
2821 }
2822 };
2823}
2824#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
2825
2826// Separate std::tuple specialization
2827#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
2828#include <tuple>
2829namespace Catch {
2830 namespace Detail {
2831 template<
2832 typename Tuple,
2833 std::size_t N = 0,
2834 bool = (N < std::tuple_size<Tuple>::value)
2835 >
2836 struct TupleElementPrinter {
2837 static void print(const Tuple& tuple, std::ostream& os) {
2838 os << (N ? ", " : " ")
2839 << ::Catch::Detail::stringify(std::get<N>(tuple));
2840 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
2841 }
2842 };
2843
2844 template<
2845 typename Tuple,
2846 std::size_t N
2847 >
2848 struct TupleElementPrinter<Tuple, N, false> {
2849 static void print(const Tuple&, std::ostream&) {}
2850 };
2851
2852 }
2853
2854
2855 template<typename ...Types>
2856 struct StringMaker<std::tuple<Types...>> {
2857 static std::string convert(const std::tuple<Types...>& tuple) {
2858 ReusableStringStream rss;
2859 rss << '{';
2860 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
2861 rss << " }";
2862 return rss.str();
2863 }
2864 };
2865}
2866#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
2867
2868#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
2869#include <variant>
2870namespace Catch {
2871 template<>
2872 struct StringMaker<std::monostate> {
2873 static std::string convert(const std::monostate&) {
2874 return "{ }";
2875 }
2876 };
2877
2878 template<typename... Elements>
2879 struct StringMaker<std::variant<Elements...>> {
2880 static std::string convert(const std::variant<Elements...>& variant) {
2881 if (variant.valueless_by_exception()) {
2882 return "{valueless variant}";
2883 } else {
2884 return std::visit(
2885 [](const auto& value) {
2886 return ::Catch::Detail::stringify(value);
2887 },
2888 variant
2889 );
2890 }
2891 }
2892 };
2893}
2894#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
2895
2896namespace Catch {
2897 // Import begin/ end from std here
2898 using std::begin;
2899 using std::end;
2900
2901 namespace Detail {
2902 template <typename T, typename = void>
2903 struct is_range_impl : std::false_type {};
2904
2905 template <typename T>
2906 struct is_range_impl<T, void_t<decltype(begin(std::declval<T>()))>> : std::true_type {};
2907 } // namespace Detail
2908
2909 template <typename T>
2910 struct is_range : Detail::is_range_impl<T> {};
2911
2912#if defined(_MANAGED) // Managed types are never ranges
2913 template <typename T>
2914 struct is_range<T^> {
2915 static const bool value = false;
2916 };
2917#endif
2918
2919 template<typename Range>
2920 std::string rangeToString( Range const& range ) {
2921 return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
2922 }
2923
2924 // Handle vector<bool> specially
2925 template<typename Allocator>
2926 std::string rangeToString( std::vector<bool, Allocator> const& v ) {
2927 ReusableStringStream rss;
2928 rss << "{ ";
2929 bool first = true;
2930 for( bool b : v ) {
2931 if( first )
2932 first = false;
2933 else
2934 rss << ", ";
2935 rss << ::Catch::Detail::stringify( b );
2936 }
2937 rss << " }";
2938 return rss.str();
2939 }
2940
2941 template<typename R>
2942 struct StringMaker<R, std::enable_if_t<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>> {
2943 static std::string convert( R const& range ) {
2944 return rangeToString( range );
2945 }
2946 };
2947
2948 template <typename T, size_t SZ>
2949 struct StringMaker<T[SZ]> {
2950 static std::string convert(T const(&arr)[SZ]) {
2951 return rangeToString(arr);
2952 }
2953 };
2954
2955
2956} // namespace Catch
2957
2958// Separate std::chrono::duration specialization
2959#include <ctime>
2960#include <ratio>
2961#include <chrono>
2962
2963
2964namespace Catch {
2965
2966template <class Ratio>
2967struct ratio_string {
2968 static std::string symbol() {
2969 Catch::ReusableStringStream rss;
2970 rss << '[' << Ratio::num << '/'
2971 << Ratio::den << ']';
2972 return rss.str();
2973 }
2974};
2975
2976template <>
2977struct ratio_string<std::atto> {
2978 static char symbol() { return 'a'; }
2979};
2980template <>
2981struct ratio_string<std::femto> {
2982 static char symbol() { return 'f'; }
2983};
2984template <>
2985struct ratio_string<std::pico> {
2986 static char symbol() { return 'p'; }
2987};
2988template <>
2989struct ratio_string<std::nano> {
2990 static char symbol() { return 'n'; }
2991};
2992template <>
2993struct ratio_string<std::micro> {
2994 static char symbol() { return 'u'; }
2995};
2996template <>
2997struct ratio_string<std::milli> {
2998 static char symbol() { return 'm'; }
2999};
3000
3001 ////////////
3002 // std::chrono::duration specializations
3003 template<typename Value, typename Ratio>
3004 struct StringMaker<std::chrono::duration<Value, Ratio>> {
3005 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
3006 ReusableStringStream rss;
3007 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
3008 return rss.str();
3009 }
3010 };
3011 template<typename Value>
3012 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
3013 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
3014 ReusableStringStream rss;
3015 rss << duration.count() << " s";
3016 return rss.str();
3017 }
3018 };
3019 template<typename Value>
3020 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
3021 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
3022 ReusableStringStream rss;
3023 rss << duration.count() << " m";
3024 return rss.str();
3025 }
3026 };
3027 template<typename Value>
3028 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
3029 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
3030 ReusableStringStream rss;
3031 rss << duration.count() << " h";
3032 return rss.str();
3033 }
3034 };
3035
3036 ////////////
3037 // std::chrono::time_point specialization
3038 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
3039 template<typename Clock, typename Duration>
3040 struct StringMaker<std::chrono::time_point<Clock, Duration>> {
3041 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
3042 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
3043 }
3044 };
3045 // std::chrono::time_point<system_clock> specialization
3046 template<typename Duration>
3047 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
3048 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
3049 auto converted = std::chrono::system_clock::to_time_t(time_point);
3050
3051#ifdef _MSC_VER
3052 std::tm timeInfo = {};
3053 gmtime_s(&timeInfo, &converted);
3054#else
3055 std::tm* timeInfo = std::gmtime(&converted);
3056#endif
3057
3058 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
3059 char timeStamp[timeStampSize];
3060 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
3061
3062#ifdef _MSC_VER
3063 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
3064#else
3065 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
3066#endif
3067 return std::string(timeStamp, timeStampSize - 1);
3068 }
3069 };
3070}
3071
3072
3073#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
3074namespace Catch { \
3075 template<> struct StringMaker<enumName> { \
3076 static std::string convert( enumName value ) { \
3077 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
3078 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
3079 } \
3080 }; \
3081}
3082
3083#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
3084
3085#ifdef _MSC_VER
3086#pragma warning(pop)
3087#endif
3088
3089#endif // CATCH_TOSTRING_HPP_INCLUDED
3090
3091#include <type_traits>
3092
3093namespace Catch {
3094
3095 class Approx {
3096 private:
3097 bool equalityComparisonImpl(double other) const;
3098 // Sets and validates the new margin (margin >= 0)
3099 void setMargin(double margin);
3100 // Sets and validates the new epsilon (0 < epsilon < 1)
3101 void setEpsilon(double epsilon);
3102
3103 public:
3104 explicit Approx ( double value );
3105
3106 static Approx custom();
3107
3108 Approx operator-() const;
3109
3110 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3111 Approx operator()( T const& value ) const {
3112 Approx approx( static_cast<double>(value) );
3113 approx.m_epsilon = m_epsilon;
3114 approx.m_margin = m_margin;
3115 approx.m_scale = m_scale;
3116 return approx;
3117 }
3118
3119 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3120 explicit Approx( T const& value ): Approx(static_cast<double>(value))
3121 {}
3122
3123
3124 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3125 friend bool operator == ( const T& lhs, Approx const& rhs ) {
3126 auto lhs_v = static_cast<double>(lhs);
3127 return rhs.equalityComparisonImpl(lhs_v);
3128 }
3129
3130 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3131 friend bool operator == ( Approx const& lhs, const T& rhs ) {
3132 return operator==( rhs, lhs );
3133 }
3134
3135 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3136 friend bool operator != ( T const& lhs, Approx const& rhs ) {
3137 return !operator==( lhs, rhs );
3138 }
3139
3140 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3141 friend bool operator != ( Approx const& lhs, T const& rhs ) {
3142 return !operator==( rhs, lhs );
3143 }
3144
3145 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3146 friend bool operator <= ( T const& lhs, Approx const& rhs ) {
3147 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
3148 }
3149
3150 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3151 friend bool operator <= ( Approx const& lhs, T const& rhs ) {
3152 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
3153 }
3154
3155 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3156 friend bool operator >= ( T const& lhs, Approx const& rhs ) {
3157 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
3158 }
3159
3160 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3161 friend bool operator >= ( Approx const& lhs, T const& rhs ) {
3162 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
3163 }
3164
3165 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3166 Approx& epsilon( T const& newEpsilon ) {
3167 const auto epsilonAsDouble = static_cast<double>(newEpsilon);
3168 setEpsilon(epsilonAsDouble);
3169 return *this;
3170 }
3171
3172 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3173 Approx& margin( T const& newMargin ) {
3174 const auto marginAsDouble = static_cast<double>(newMargin);
3175 setMargin(marginAsDouble);
3176 return *this;
3177 }
3178
3179 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3180 Approx& scale( T const& newScale ) {
3181 m_scale = static_cast<double>(newScale);
3182 return *this;
3183 }
3184
3185 std::string toString() const;
3186
3187 private:
3188 double m_epsilon;
3189 double m_margin;
3190 double m_scale;
3191 double m_value;
3192 };
3193
3194namespace literals {
3195 Approx operator ""_a(long double val);
3196 Approx operator ""_a(unsigned long long val);
3197} // end namespace literals
3198
3199template<>
3200struct StringMaker<Catch::Approx> {
3201 static std::string convert(Catch::Approx const& value);
3202};
3203
3204} // end namespace Catch
3205
3206#endif // CATCH_APPROX_HPP_INCLUDED
3207
3208
3209#ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED
3210#define CATCH_ASSERTION_INFO_HPP_INCLUDED
3211
3212
3213
3214#ifndef CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
3215#define CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
3216
3217#include <cstddef>
3218#include <iosfwd>
3219
3220namespace Catch {
3221
3222 struct SourceLineInfo {
3223
3224 SourceLineInfo() = delete;
3225 constexpr SourceLineInfo( char const* _file, std::size_t _line ) noexcept:
3226 file( _file ),
3227 line( _line )
3228 {}
3229
3230 bool operator == ( SourceLineInfo const& other ) const noexcept;
3231 bool operator < ( SourceLineInfo const& other ) const noexcept;
3232
3233 char const* file;
3234 std::size_t line;
3235
3236 friend std::ostream& operator << (std::ostream& os, SourceLineInfo const& info);
3237 };
3238}
3239
3240#define CATCH_INTERNAL_LINEINFO \
3241 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
3242
3243#endif // CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
3244
3245namespace Catch {
3246
3247 struct AssertionInfo {
3248 // AssertionInfo() = delete;
3249
3250 StringRef macroName;
3251 SourceLineInfo lineInfo;
3252 StringRef capturedExpression;
3253 ResultDisposition::Flags resultDisposition;
3254 };
3255
3256} // end namespace Catch
3257
3258#endif // CATCH_ASSERTION_INFO_HPP_INCLUDED
3259
3260
3261#ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED
3262#define CATCH_ASSERTION_RESULT_HPP_INCLUDED
3263
3264
3265
3266#ifndef CATCH_LAZY_EXPR_HPP_INCLUDED
3267#define CATCH_LAZY_EXPR_HPP_INCLUDED
3268
3269#include <iosfwd>
3270
3271namespace Catch {
3272
3273 class ITransientExpression;
3274
3275 class LazyExpression {
3276 friend class AssertionHandler;
3277 friend struct AssertionStats;
3278 friend class RunContext;
3279
3280 ITransientExpression const* m_transientExpression = nullptr;
3281 bool m_isNegated;
3282 public:
3283 constexpr LazyExpression( bool isNegated ):
3284 m_isNegated(isNegated)
3285 {}
3286 constexpr LazyExpression(LazyExpression const& other) = default;
3287 LazyExpression& operator = ( LazyExpression const& ) = delete;
3288
3289 constexpr explicit operator bool() const {
3290 return m_transientExpression != nullptr;
3291 }
3292
3293 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
3294 };
3295
3296} // namespace Catch
3297
3298#endif // CATCH_LAZY_EXPR_HPP_INCLUDED
3299
3300#include <string>
3301
3302namespace Catch {
3303
3304 struct AssertionResultData
3305 {
3306 AssertionResultData() = delete;
3307
3308 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
3309
3310 std::string message;
3311 mutable std::string reconstructedExpression;
3312 LazyExpression lazyExpression;
3313 ResultWas::OfType resultType;
3314
3315 std::string reconstructExpression() const;
3316 };
3317
3318 class AssertionResult {
3319 public:
3320 AssertionResult() = delete;
3321 AssertionResult( AssertionInfo const& info, AssertionResultData&& data );
3322
3323 bool isOk() const;
3324 bool succeeded() const;
3325 ResultWas::OfType getResultType() const;
3326 bool hasExpression() const;
3327 bool hasMessage() const;
3328 std::string getExpression() const;
3329 std::string getExpressionInMacro() const;
3330 bool hasExpandedExpression() const;
3331 std::string getExpandedExpression() const;
3332 StringRef getMessage() const;
3333 SourceLineInfo getSourceInfo() const;
3334 StringRef getTestMacroName() const;
3335
3336 //protected:
3337 AssertionInfo m_info;
3338 AssertionResultData m_resultData;
3339 };
3340
3341} // end namespace Catch
3342
3343#endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED
3344
3345
3346#ifndef CATCH_CASE_SENSITIVE_HPP_INCLUDED
3347#define CATCH_CASE_SENSITIVE_HPP_INCLUDED
3348
3349namespace Catch {
3350
3351 enum class CaseSensitive { Yes, No };
3352
3353} // namespace Catch
3354
3355#endif // CATCH_CASE_SENSITIVE_HPP_INCLUDED
3356
3357
3358#ifndef CATCH_CONFIG_HPP_INCLUDED
3359#define CATCH_CONFIG_HPP_INCLUDED
3360
3361
3362
3363#ifndef CATCH_TEST_SPEC_HPP_INCLUDED
3364#define CATCH_TEST_SPEC_HPP_INCLUDED
3365
3366#ifdef __clang__
3367#pragma clang diagnostic push
3368#pragma clang diagnostic ignored "-Wpadded"
3369#endif
3370
3371
3372
3373#ifndef CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3374#define CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3375
3376
3377#include <string>
3378
3379namespace Catch
3380{
3381 class WildcardPattern {
3382 enum WildcardPosition {
3383 NoWildcard = 0,
3384 WildcardAtStart = 1,
3385 WildcardAtEnd = 2,
3386 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3387 };
3388
3389 public:
3390
3391 WildcardPattern( std::string const& pattern, CaseSensitive caseSensitivity );
3392 bool matches( std::string const& str ) const;
3393
3394 private:
3395 std::string normaliseString( std::string const& str ) const;
3396 CaseSensitive m_caseSensitivity;
3397 WildcardPosition m_wildcard = NoWildcard;
3398 std::string m_pattern;
3399 };
3400}
3401
3402#endif // CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3403
3404#include <iosfwd>
3405#include <string>
3406#include <vector>
3407
3408namespace Catch {
3409
3410 class IConfig;
3411 struct TestCaseInfo;
3412 class TestCaseHandle;
3413
3414 class TestSpec {
3415
3416 class Pattern {
3417 public:
3418 explicit Pattern( std::string const& name );
3419 virtual ~Pattern();
3420 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3421 std::string const& name() const;
3422 private:
3423 virtual void serializeTo( std::ostream& out ) const = 0;
3424 // Writes string that would be reparsed into the pattern
3425 friend std::ostream& operator<<(std::ostream& out,
3426 Pattern const& pattern) {
3427 pattern.serializeTo( out );
3428 return out;
3429 }
3430
3431 std::string const m_name;
3432 };
3433
3434 class NamePattern : public Pattern {
3435 public:
3436 explicit NamePattern( std::string const& name, std::string const& filterString );
3437 bool matches( TestCaseInfo const& testCase ) const override;
3438 private:
3439 void serializeTo( std::ostream& out ) const override;
3440
3441 WildcardPattern m_wildcardPattern;
3442 };
3443
3444 class TagPattern : public Pattern {
3445 public:
3446 explicit TagPattern( std::string const& tag, std::string const& filterString );
3447 bool matches( TestCaseInfo const& testCase ) const override;
3448 private:
3449 void serializeTo( std::ostream& out ) const override;
3450
3451 std::string m_tag;
3452 };
3453
3454 struct Filter {
3455 std::vector<Detail::unique_ptr<Pattern>> m_required;
3456 std::vector<Detail::unique_ptr<Pattern>> m_forbidden;
3457
3458 //! Serializes this filter into a string that would be parsed into
3459 //! an equivalent filter
3460 void serializeTo( std::ostream& out ) const;
3461 friend std::ostream& operator<<(std::ostream& out, Filter const& f) {
3462 f.serializeTo( out );
3463 return out;
3464 }
3465
3466 bool matches( TestCaseInfo const& testCase ) const;
3467 };
3468
3469 static std::string extractFilterName( Filter const& filter );
3470
3471 public:
3472 struct FilterMatch {
3473 std::string name;
3474 std::vector<TestCaseHandle const*> tests;
3475 };
3476 using Matches = std::vector<FilterMatch>;
3477 using vectorStrings = std::vector<std::string>;
3478
3479 bool hasFilters() const;
3480 bool matches( TestCaseInfo const& testCase ) const;
3481 Matches matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const;
3482 const vectorStrings & getInvalidSpecs() const;
3483
3484 private:
3485 std::vector<Filter> m_filters;
3486 std::vector<std::string> m_invalidSpecs;
3487
3488 friend class TestSpecParser;
3489 //! Serializes this test spec into a string that would be parsed into
3490 //! equivalent test spec
3491 void serializeTo( std::ostream& out ) const;
3492 friend std::ostream& operator<<(std::ostream& out,
3493 TestSpec const& spec) {
3494 spec.serializeTo( out );
3495 return out;
3496 }
3497 };
3498}
3499
3500#ifdef __clang__
3501#pragma clang diagnostic pop
3502#endif
3503
3504#endif // CATCH_TEST_SPEC_HPP_INCLUDED
3505
3506
3507#ifndef CATCH_OPTIONAL_HPP_INCLUDED
3508#define CATCH_OPTIONAL_HPP_INCLUDED
3509
3510
3511#include <cassert>
3512
3513namespace Catch {
3514
3515 // An optional type
3516 template<typename T>
3517 class Optional {
3518 public:
3519 Optional(): nullableValue( nullptr ) {}
3520 ~Optional() { reset(); }
3521
3522 Optional( T const& _value ):
3523 nullableValue( new ( storage ) T( _value ) ) {}
3524 Optional( T&& _value ):
3525 nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {}
3526
3527 Optional& operator=( T const& _value ) {
3528 reset();
3529 nullableValue = new ( storage ) T( _value );
3530 return *this;
3531 }
3532 Optional& operator=( T&& _value ) {
3533 reset();
3534 nullableValue = new ( storage ) T( CATCH_MOVE( _value ) );
3535 return *this;
3536 }
3537
3538 Optional( Optional const& _other ):
3539 nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {}
3540 Optional( Optional&& _other ):
3541 nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) )
3542 : nullptr ) {}
3543
3544 Optional& operator=( Optional const& _other ) {
3545 if ( &_other != this ) {
3546 reset();
3547 if ( _other ) { nullableValue = new ( storage ) T( *_other ); }
3548 }
3549 return *this;
3550 }
3551 Optional& operator=( Optional&& _other ) {
3552 if ( &_other != this ) {
3553 reset();
3554 if ( _other ) {
3555 nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) );
3556 }
3557 }
3558 return *this;
3559 }
3560
3561 void reset() {
3562 if ( nullableValue ) { nullableValue->~T(); }
3563 nullableValue = nullptr;
3564 }
3565
3566 T& operator*() {
3567 assert(nullableValue);
3568 return *nullableValue;
3569 }
3570 T const& operator*() const {
3571 assert(nullableValue);
3572 return *nullableValue;
3573 }
3574 T* operator->() {
3575 assert(nullableValue);
3576 return nullableValue;
3577 }
3578 const T* operator->() const {
3579 assert(nullableValue);
3580 return nullableValue;
3581 }
3582
3583 T valueOr( T const& defaultValue ) const {
3584 return nullableValue ? *nullableValue : defaultValue;
3585 }
3586
3587 bool some() const { return nullableValue != nullptr; }
3588 bool none() const { return nullableValue == nullptr; }
3589
3590 bool operator !() const { return nullableValue == nullptr; }
3591 explicit operator bool() const {
3592 return some();
3593 }
3594
3595 friend bool operator==(Optional const& a, Optional const& b) {
3596 if (a.none() && b.none()) {
3597 return true;
3598 } else if (a.some() && b.some()) {
3599 return *a == *b;
3600 } else {
3601 return false;
3602 }
3603 }
3604 friend bool operator!=(Optional const& a, Optional const& b) {
3605 return !( a == b );
3606 }
3607
3608 private:
3609 T* nullableValue;
3610 alignas(alignof(T)) char storage[sizeof(T)];
3611 };
3612
3613} // end namespace Catch
3614
3615#endif // CATCH_OPTIONAL_HPP_INCLUDED
3616
3617
3618#ifndef CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
3619#define CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
3620
3621#include <cstdint>
3622
3623namespace Catch {
3624
3625 enum class GenerateFrom {
3626 Time,
3627 RandomDevice,
3628 //! Currently equivalent to RandomDevice, but can change at any point
3629 Default
3630 };
3631
3632 std::uint32_t generateRandomSeed(GenerateFrom from);
3633
3634} // end namespace Catch
3635
3636#endif // CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
3637
3638
3639#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
3640#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
3641
3642
3643#include <map>
3644#include <string>
3645#include <vector>
3646
3647namespace Catch {
3648
3649 enum class ColourMode : std::uint8_t;
3650
3651 namespace Detail {
3652 //! Splits the reporter spec into reporter name and kv-pair options
3653 std::vector<std::string> splitReporterSpec( StringRef reporterSpec );
3654
3655 Optional<ColourMode> stringToColourMode( StringRef colourMode );
3656 }
3657
3658 /**
3659 * Structured reporter spec that a reporter can be created from
3660 *
3661 * Parsing has been validated, but semantics have not. This means e.g.
3662 * that the colour mode is known to Catch2, but it might not be
3663 * compiled into the binary, and the output filename might not be
3664 * openable.
3665 */
3666 class ReporterSpec {
3667 std::string m_name;
3668 Optional<std::string> m_outputFileName;
3669 Optional<ColourMode> m_colourMode;
3670 std::map<std::string, std::string> m_customOptions;
3671
3672 friend bool operator==( ReporterSpec const& lhs,
3673 ReporterSpec const& rhs );
3674 friend bool operator!=( ReporterSpec const& lhs,
3675 ReporterSpec const& rhs ) {
3676 return !( lhs == rhs );
3677 }
3678
3679 public:
3680 ReporterSpec(
3681 std::string name,
3682 Optional<std::string> outputFileName,
3683 Optional<ColourMode> colourMode,
3684 std::map<std::string, std::string> customOptions );
3685
3686 std::string const& name() const { return m_name; }
3687
3688 Optional<std::string> const& outputFile() const {
3689 return m_outputFileName;
3690 }
3691
3692 Optional<ColourMode> const& colourMode() const { return m_colourMode; }
3693
3694 std::map<std::string, std::string> const& customOptions() const {
3695 return m_customOptions;
3696 }
3697 };
3698
3699 /**
3700 * Parses provided reporter spec string into
3701 *
3702 * Returns empty optional on errors, e.g.
3703 * * field that is not first and not a key+value pair
3704 * * duplicated keys in kv pair
3705 * * unknown catch reporter option
3706 * * empty key/value in an custom kv pair
3707 * * ...
3708 */
3709 Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec );
3710
3711}
3712
3713#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
3714
3715#include <chrono>
3716#include <map>
3717#include <string>
3718#include <vector>
3719
3720namespace Catch {
3721
3722 class IStream;
3723
3724 /**
3725 * `ReporterSpec` but with the defaults filled in.
3726 *
3727 * Like `ReporterSpec`, the semantics are unchecked.
3728 */
3729 struct ProcessedReporterSpec {
3730 std::string name;
3731 std::string outputFilename;
3732 ColourMode colourMode;
3733 std::map<std::string, std::string> customOptions;
3734 friend bool operator==( ProcessedReporterSpec const& lhs,
3735 ProcessedReporterSpec const& rhs );
3736 friend bool operator!=( ProcessedReporterSpec const& lhs,
3737 ProcessedReporterSpec const& rhs ) {
3738 return !( lhs == rhs );
3739 }
3740 };
3741
3742 struct ConfigData {
3743
3744 bool listTests = false;
3745 bool listTags = false;
3746 bool listReporters = false;
3747 bool listListeners = false;
3748
3749 bool showSuccessfulTests = false;
3750 bool shouldDebugBreak = false;
3751 bool noThrow = false;
3752 bool showHelp = false;
3753 bool showInvisibles = false;
3754 bool filenamesAsTags = false;
3755 bool libIdentify = false;
3756 bool allowZeroTests = false;
3757
3758 int abortAfter = -1;
3759 uint32_t rngSeed = generateRandomSeed(GenerateFrom::Default);
3760
3761 unsigned int shardCount = 1;
3762 unsigned int shardIndex = 0;
3763
3764 bool skipBenchmarks = false;
3765 bool benchmarkNoAnalysis = false;
3766 unsigned int benchmarkSamples = 100;
3767 double benchmarkConfidenceInterval = 0.95;
3768 unsigned int benchmarkResamples = 100'000;
3769 std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
3770
3771 Verbosity verbosity = Verbosity::Normal;
3772 WarnAbout::What warnings = WarnAbout::Nothing;
3773 ShowDurations showDurations = ShowDurations::DefaultForReporter;
3774 double minDuration = -1;
3775 TestRunOrder runOrder = TestRunOrder::Declared;
3776 ColourMode defaultColourMode = ColourMode::PlatformDefault;
3777 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
3778
3779 std::string defaultOutputFilename;
3780 std::string name;
3781 std::string processName;
3782 std::vector<ReporterSpec> reporterSpecifications;
3783
3784 std::vector<std::string> testsOrTags;
3785 std::vector<std::string> sectionsToRun;
3786 };
3787
3788
3789 class Config : public IConfig {
3790 public:
3791
3792 Config() = default;
3793 Config( ConfigData const& data );
3794 ~Config() override; // = default in the cpp file
3795
3796 bool listTests() const;
3797 bool listTags() const;
3798 bool listReporters() const;
3799 bool listListeners() const;
3800
3801 std::vector<ReporterSpec> const& getReporterSpecs() const;
3802 std::vector<ProcessedReporterSpec> const&
3803 getProcessedReporterSpecs() const;
3804
3805 std::vector<std::string> const& getTestsOrTags() const override;
3806 std::vector<std::string> const& getSectionsToRun() const override;
3807
3808 TestSpec const& testSpec() const override;
3809 bool hasTestFilters() const override;
3810
3811 bool showHelp() const;
3812
3813 // IConfig interface
3814 bool allowThrows() const override;
3815 StringRef name() const override;
3816 bool includeSuccessfulResults() const override;
3817 bool warnAboutMissingAssertions() const override;
3818 bool warnAboutUnmatchedTestSpecs() const override;
3819 bool zeroTestsCountAsSuccess() const override;
3820 ShowDurations showDurations() const override;
3821 double minDuration() const override;
3822 TestRunOrder runOrder() const override;
3823 uint32_t rngSeed() const override;
3824 unsigned int shardCount() const override;
3825 unsigned int shardIndex() const override;
3826 ColourMode defaultColourMode() const override;
3827 bool shouldDebugBreak() const override;
3828 int abortAfter() const override;
3829 bool showInvisibles() const override;
3830 Verbosity verbosity() const override;
3831 bool skipBenchmarks() const override;
3832 bool benchmarkNoAnalysis() const override;
3833 unsigned int benchmarkSamples() const override;
3834 double benchmarkConfidenceInterval() const override;
3835 unsigned int benchmarkResamples() const override;
3836 std::chrono::milliseconds benchmarkWarmupTime() const override;
3837
3838 private:
3839 // Reads Bazel env vars and applies them to the config
3840 void readBazelEnvVars();
3841
3842 ConfigData m_data;
3843 std::vector<ProcessedReporterSpec> m_processedReporterSpecs;
3844 TestSpec m_testSpec;
3845 bool m_hasTestFilters = false;
3846 };
3847} // end namespace Catch
3848
3849#endif // CATCH_CONFIG_HPP_INCLUDED
3850
3851
3852#ifndef CATCH_GET_RANDOM_SEED_HPP_INCLUDED
3853#define CATCH_GET_RANDOM_SEED_HPP_INCLUDED
3854
3855#include <cstdint>
3856
3857namespace Catch {
3858 //! Returns Catch2's current RNG seed.
3859 std::uint32_t getSeed();
3860}
3861
3862#endif // CATCH_GET_RANDOM_SEED_HPP_INCLUDED
3863
3864
3865#ifndef CATCH_MESSAGE_HPP_INCLUDED
3866#define CATCH_MESSAGE_HPP_INCLUDED
3867
3868
3869
3870
3871/** \file
3872 * Wrapper for the CATCH_CONFIG_PREFIX_MESSAGES configuration option
3873 *
3874 * CATCH_CONFIG_PREFIX_ALL can be used to avoid clashes with other macros
3875 * by prepending CATCH_. This may not be desirable if the only clashes are with
3876 * logger macros such as INFO and WARN. In this cases
3877 * CATCH_CONFIG_PREFIX_MESSAGES can be used to only prefix a small subset
3878 * of relevant macros.
3879 *
3880 */
3881
3882#ifndef CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
3883#define CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
3884
3885
3886#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_PREFIX_MESSAGES)
3887 #define CATCH_CONFIG_PREFIX_MESSAGES
3888#endif
3889
3890#endif // CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
3891
3892
3893#ifndef CATCH_STREAM_END_STOP_HPP_INCLUDED
3894#define CATCH_STREAM_END_STOP_HPP_INCLUDED
3895
3896
3897namespace Catch {
3898
3899 // Use this in variadic streaming macros to allow
3900 // << +StreamEndStop
3901 // as well as
3902 // << stuff +StreamEndStop
3903 struct StreamEndStop {
3904 constexpr StringRef operator+() const { return StringRef(); }
3905
3906 template <typename T>
3907 constexpr friend T const& operator+( T const& value, StreamEndStop ) {
3908 return value;
3909 }
3910 };
3911
3912} // namespace Catch
3913
3914#endif // CATCH_STREAM_END_STOP_HPP_INCLUDED
3915
3916
3917#ifndef CATCH_MESSAGE_INFO_HPP_INCLUDED
3918#define CATCH_MESSAGE_INFO_HPP_INCLUDED
3919
3920
3921#include <string>
3922
3923namespace Catch {
3924
3925 struct MessageInfo {
3926 MessageInfo( StringRef _macroName,
3927 SourceLineInfo const& _lineInfo,
3928 ResultWas::OfType _type );
3929
3930 StringRef macroName;
3931 std::string message;
3932 SourceLineInfo lineInfo;
3933 ResultWas::OfType type;
3934 unsigned int sequence;
3935
3936 bool operator == (MessageInfo const& other) const {
3937 return sequence == other.sequence;
3938 }
3939 bool operator < (MessageInfo const& other) const {
3940 return sequence < other.sequence;
3941 }
3942 private:
3943 static unsigned int globalCount;
3944 };
3945
3946} // end namespace Catch
3947
3948#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED
3949
3950#include <string>
3951#include <vector>
3952
3953namespace Catch {
3954
3955 struct SourceLineInfo;
3956 class IResultCapture;
3957
3958 struct MessageStream {
3959
3960 template<typename T>
3961 MessageStream& operator << ( T const& value ) {
3962 m_stream << value;
3963 return *this;
3964 }
3965
3966 ReusableStringStream m_stream;
3967 };
3968
3969 struct MessageBuilder : MessageStream {
3970 MessageBuilder( StringRef macroName,
3971 SourceLineInfo const& lineInfo,
3972 ResultWas::OfType type ):
3973 m_info(macroName, lineInfo, type) {}
3974
3975 template<typename T>
3976 MessageBuilder&& operator << ( T const& value ) && {
3977 m_stream << value;
3978 return CATCH_MOVE(*this);
3979 }
3980
3981 MessageInfo m_info;
3982 };
3983
3984 class ScopedMessage {
3985 public:
3986 explicit ScopedMessage( MessageBuilder&& builder );
3987 ScopedMessage( ScopedMessage& duplicate ) = delete;
3988 ScopedMessage( ScopedMessage&& old ) noexcept;
3989 ~ScopedMessage();
3990
3991 MessageInfo m_info;
3992 bool m_moved = false;
3993 };
3994
3995 class Capturer {
3996 std::vector<MessageInfo> m_messages;
3997 IResultCapture& m_resultCapture;
3998 size_t m_captured = 0;
3999 public:
4000 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
4001
4002 Capturer(Capturer const&) = delete;
4003 Capturer& operator=(Capturer const&) = delete;
4004
4005 ~Capturer();
4006
4007 void captureValue( size_t index, std::string const& value );
4008
4009 template<typename T>
4010 void captureValues( size_t index, T const& value ) {
4011 captureValue( index, Catch::Detail::stringify( value ) );
4012 }
4013
4014 template<typename T, typename... Ts>
4015 void captureValues( size_t index, T const& value, Ts const&... values ) {
4016 captureValue( index, Catch::Detail::stringify(value) );
4017 captureValues( index+1, values... );
4018 }
4019 };
4020
4021} // end namespace Catch
4022
4023///////////////////////////////////////////////////////////////////////////////
4024#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
4025 do { \
4026 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
4027 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
4028 catchAssertionHandler.complete(); \
4029 } while( false )
4030
4031///////////////////////////////////////////////////////////////////////////////
4032#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
4033 Catch::Capturer varName( macroName##_catch_sr, \
4034 CATCH_INTERNAL_LINEINFO, \
4035 Catch::ResultWas::Info, \
4036 #__VA_ARGS__##_catch_sr ); \
4037 varName.captureValues( 0, __VA_ARGS__ )
4038
4039///////////////////////////////////////////////////////////////////////////////
4040#define INTERNAL_CATCH_INFO( macroName, log ) \
4041 const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
4042
4043///////////////////////////////////////////////////////////////////////////////
4044#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
4045 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
4046
4047
4048#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
4049
4050 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
4051 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
4052 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
4053 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ )
4054
4055#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
4056
4057 #define CATCH_INFO( msg ) (void)(0)
4058 #define CATCH_UNSCOPED_INFO( msg ) (void)(0)
4059 #define CATCH_WARN( msg ) (void)(0)
4060 #define CATCH_CAPTURE( ... ) (void)(0)
4061
4062#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
4063
4064 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
4065 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
4066 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
4067 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ )
4068
4069#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
4070
4071 #define INFO( msg ) (void)(0)
4072 #define UNSCOPED_INFO( msg ) (void)(0)
4073 #define WARN( msg ) (void)(0)
4074 #define CAPTURE( ... ) (void)(0)
4075
4076#endif // end of user facing macro declarations
4077
4078
4079
4080
4081#endif // CATCH_MESSAGE_HPP_INCLUDED
4082
4083
4084#ifndef CATCH_SECTION_INFO_HPP_INCLUDED
4085#define CATCH_SECTION_INFO_HPP_INCLUDED
4086
4087
4088
4089#ifndef CATCH_TOTALS_HPP_INCLUDED
4090#define CATCH_TOTALS_HPP_INCLUDED
4091
4092#include <cstdint>
4093
4094namespace Catch {
4095
4096 struct Counts {
4097 Counts operator - ( Counts const& other ) const;
4098 Counts& operator += ( Counts const& other );
4099
4100 std::uint64_t total() const;
4101 bool allPassed() const;
4102 bool allOk() const;
4103
4104 std::uint64_t passed = 0;
4105 std::uint64_t failed = 0;
4106 std::uint64_t failedButOk = 0;
4107 std::uint64_t skipped = 0;
4108 };
4109
4110 struct Totals {
4111
4112 Totals operator - ( Totals const& other ) const;
4113 Totals& operator += ( Totals const& other );
4114
4115 Totals delta( Totals const& prevTotals ) const;
4116
4117 Counts assertions;
4118 Counts testCases;
4119 };
4120}
4121
4122#endif // CATCH_TOTALS_HPP_INCLUDED
4123
4124#include <string>
4125
4126namespace Catch {
4127
4128 struct SectionInfo {
4129 // The last argument is ignored, so that people can write
4130 // SECTION("ShortName", "Proper description that is long") and
4131 // still use the `-c` flag comfortably.
4132 SectionInfo( SourceLineInfo const& _lineInfo, std::string _name,
4133 const char* const = nullptr ):
4134 name(CATCH_MOVE(_name)),
4135 lineInfo(_lineInfo)
4136 {}
4137
4138 std::string name;
4139 SourceLineInfo lineInfo;
4140 };
4141
4142 struct SectionEndInfo {
4143 SectionInfo sectionInfo;
4144 Counts prevAssertions;
4145 double durationInSeconds;
4146 };
4147
4148} // end namespace Catch
4149
4150#endif // CATCH_SECTION_INFO_HPP_INCLUDED
4151
4152
4153#ifndef CATCH_SESSION_HPP_INCLUDED
4154#define CATCH_SESSION_HPP_INCLUDED
4155
4156
4157
4158#ifndef CATCH_COMMANDLINE_HPP_INCLUDED
4159#define CATCH_COMMANDLINE_HPP_INCLUDED
4160
4161
4162
4163#ifndef CATCH_CLARA_HPP_INCLUDED
4164#define CATCH_CLARA_HPP_INCLUDED
4165
4166#if defined( __clang__ )
4167# pragma clang diagnostic push
4168# pragma clang diagnostic ignored "-Wweak-vtables"
4169# pragma clang diagnostic ignored "-Wshadow"
4170# pragma clang diagnostic ignored "-Wdeprecated"
4171#endif
4172
4173#if defined( __GNUC__ )
4174# pragma GCC diagnostic push
4175# pragma GCC diagnostic ignored "-Wsign-conversion"
4176#endif
4177
4178#ifndef CLARA_CONFIG_OPTIONAL_TYPE
4179# ifdef __has_include
4180# if __has_include( <optional>) && __cplusplus >= 201703L
4181# include <optional>
4182# define CLARA_CONFIG_OPTIONAL_TYPE std::optional
4183# endif
4184# endif
4185#endif
4186
4187
4188#include <cassert>
4189#include <memory>
4190#include <ostream>
4191#include <sstream>
4192#include <string>
4193#include <type_traits>
4194#include <vector>
4195
4196namespace Catch {
4197 namespace Clara {
4198
4199 class Args;
4200 class Parser;
4201
4202 // enum of result types from a parse
4203 enum class ParseResultType {
4204 Matched,
4205 NoMatch,
4206 ShortCircuitAll,
4207 ShortCircuitSame
4208 };
4209
4210 struct accept_many_t {};
4211 constexpr accept_many_t accept_many {};
4212
4213 namespace Detail {
4214 struct fake_arg {
4215 template <typename T>
4216 operator T();
4217 };
4218
4219 template <typename F, typename = void>
4220 struct is_unary_function : std::false_type {};
4221
4222 template <typename F>
4223 struct is_unary_function<
4224 F,
4225 Catch::Detail::void_t<decltype(
4226 std::declval<F>()( fake_arg() ) )
4227 >
4228 > : std::true_type {};
4229
4230 // Traits for extracting arg and return type of lambdas (for single
4231 // argument lambdas)
4232 template <typename L>
4233 struct UnaryLambdaTraits
4234 : UnaryLambdaTraits<decltype( &L::operator() )> {};
4235
4236 template <typename ClassT, typename ReturnT, typename... Args>
4237 struct UnaryLambdaTraits<ReturnT ( ClassT::* )( Args... ) const> {
4238 static const bool isValid = false;
4239 };
4240
4241 template <typename ClassT, typename ReturnT, typename ArgT>
4242 struct UnaryLambdaTraits<ReturnT ( ClassT::* )( ArgT ) const> {
4243 static const bool isValid = true;
4244 using ArgType = std::remove_const_t<std::remove_reference_t<ArgT>>;
4245 using ReturnType = ReturnT;
4246 };
4247
4248 class TokenStream;
4249
4250 // Wraps a token coming from a token stream. These may not directly
4251 // correspond to strings as a single string may encode an option +
4252 // its argument if the : or = form is used
4253 enum class TokenType { Option, Argument };
4254 struct Token {
4255 TokenType type;
4256 StringRef token;
4257 };
4258
4259 // Abstracts iterators into args as a stream of tokens, with option
4260 // arguments uniformly handled
4261 class TokenStream {
4262 using Iterator = std::vector<StringRef>::const_iterator;
4263 Iterator it;
4264 Iterator itEnd;
4265 std::vector<Token> m_tokenBuffer;
4266 void loadBuffer();
4267
4268 public:
4269 explicit TokenStream( Args const& args );
4270 TokenStream( Iterator it, Iterator itEnd );
4271
4272 explicit operator bool() const {
4273 return !m_tokenBuffer.empty() || it != itEnd;
4274 }
4275
4276 size_t count() const {
4277 return m_tokenBuffer.size() + ( itEnd - it );
4278 }
4279
4280 Token operator*() const {
4281 assert( !m_tokenBuffer.empty() );
4282 return m_tokenBuffer.front();
4283 }
4284
4285 Token const* operator->() const {
4286 assert( !m_tokenBuffer.empty() );
4287 return &m_tokenBuffer.front();
4288 }
4289
4290 TokenStream& operator++();
4291 };
4292
4293 //! Denotes type of a parsing result
4294 enum class ResultType {
4295 Ok, ///< No errors
4296 LogicError, ///< Error in user-specified arguments for
4297 ///< construction
4298 RuntimeError ///< Error in parsing inputs
4299 };
4300
4301 class ResultBase {
4302 protected:
4303 ResultBase( ResultType type ): m_type( type ) {}
4304 virtual ~ResultBase(); // = default;
4305
4306
4307 ResultBase(ResultBase const&) = default;
4308 ResultBase& operator=(ResultBase const&) = default;
4309 ResultBase(ResultBase&&) = default;
4310 ResultBase& operator=(ResultBase&&) = default;
4311
4312 virtual void enforceOk() const = 0;
4313
4314 ResultType m_type;
4315 };
4316
4317 template <typename T>
4318 class ResultValueBase : public ResultBase {
4319 public:
4320 T const& value() const& {
4321 enforceOk();
4322 return m_value;
4323 }
4324 T&& value() && {
4325 enforceOk();
4326 return CATCH_MOVE( m_value );
4327 }
4328
4329 protected:
4330 ResultValueBase( ResultType type ): ResultBase( type ) {}
4331
4332 ResultValueBase( ResultValueBase const& other ):
4333 ResultBase( other ) {
4334 if ( m_type == ResultType::Ok )
4335 new ( &m_value ) T( other.m_value );
4336 }
4337 ResultValueBase( ResultValueBase&& other ):
4338 ResultBase( other ) {
4339 if ( m_type == ResultType::Ok )
4340 new ( &m_value ) T( CATCH_MOVE(other.m_value) );
4341 }
4342
4343
4344 ResultValueBase( ResultType, T const& value ):
4345 ResultBase( ResultType::Ok ) {
4346 new ( &m_value ) T( value );
4347 }
4348 ResultValueBase( ResultType, T&& value ):
4349 ResultBase( ResultType::Ok ) {
4350 new ( &m_value ) T( CATCH_MOVE(value) );
4351 }
4352
4353 ResultValueBase& operator=( ResultValueBase const& other ) {
4354 if ( m_type == ResultType::Ok )
4355 m_value.~T();
4356 ResultBase::operator=( other );
4357 if ( m_type == ResultType::Ok )
4358 new ( &m_value ) T( other.m_value );
4359 return *this;
4360 }
4361 ResultValueBase& operator=( ResultValueBase&& other ) {
4362 if ( m_type == ResultType::Ok ) m_value.~T();
4363 ResultBase::operator=( other );
4364 if ( m_type == ResultType::Ok )
4365 new ( &m_value ) T( CATCH_MOVE(other.m_value) );
4366 return *this;
4367 }
4368
4369
4370 ~ResultValueBase() override {
4371 if ( m_type == ResultType::Ok )
4372 m_value.~T();
4373 }
4374
4375 union {
4376 T m_value;
4377 };
4378 };
4379
4380 template <> class ResultValueBase<void> : public ResultBase {
4381 protected:
4382 using ResultBase::ResultBase;
4383 };
4384
4385 template <typename T = void>
4386 class BasicResult : public ResultValueBase<T> {
4387 public:
4388 template <typename U>
4389 explicit BasicResult( BasicResult<U> const& other ):
4390 ResultValueBase<T>( other.type() ),
4391 m_errorMessage( other.errorMessage() ) {
4392 assert( type() != ResultType::Ok );
4393 }
4394
4395 template <typename U>
4396 static auto ok( U&& value ) -> BasicResult {
4397 return { ResultType::Ok, CATCH_FORWARD(value) };
4398 }
4399 static auto ok() -> BasicResult { return { ResultType::Ok }; }
4400 static auto logicError( std::string&& message )
4401 -> BasicResult {
4402 return { ResultType::LogicError, CATCH_MOVE(message) };
4403 }
4404 static auto runtimeError( std::string&& message )
4405 -> BasicResult {
4406 return { ResultType::RuntimeError, CATCH_MOVE(message) };
4407 }
4408
4409 explicit operator bool() const {
4410 return m_type == ResultType::Ok;
4411 }
4412 auto type() const -> ResultType { return m_type; }
4413 auto errorMessage() const -> std::string const& {
4414 return m_errorMessage;
4415 }
4416
4417 protected:
4418 void enforceOk() const override {
4419
4420 // Errors shouldn't reach this point, but if they do
4421 // the actual error message will be in m_errorMessage
4422 assert( m_type != ResultType::LogicError );
4423 assert( m_type != ResultType::RuntimeError );
4424 if ( m_type != ResultType::Ok )
4425 std::abort();
4426 }
4427
4428 std::string
4429 m_errorMessage; // Only populated if resultType is an error
4430
4431 BasicResult( ResultType type,
4432 std::string&& message ):
4433 ResultValueBase<T>( type ), m_errorMessage( CATCH_MOVE(message) ) {
4434 assert( m_type != ResultType::Ok );
4435 }
4436
4437 using ResultValueBase<T>::ResultValueBase;
4438 using ResultBase::m_type;
4439 };
4440
4441 class ParseState {
4442 public:
4443 ParseState( ParseResultType type,
4444 TokenStream remainingTokens );
4445
4446 ParseResultType type() const { return m_type; }
4447 TokenStream const& remainingTokens() const& {
4448 return m_remainingTokens;
4449 }
4450 TokenStream&& remainingTokens() && {
4451 return CATCH_MOVE( m_remainingTokens );
4452 }
4453
4454 private:
4455 ParseResultType m_type;
4456 TokenStream m_remainingTokens;
4457 };
4458
4459 using Result = BasicResult<void>;
4460 using ParserResult = BasicResult<ParseResultType>;
4461 using InternalParseResult = BasicResult<ParseState>;
4462
4463 struct HelpColumns {
4464 std::string left;
4465 StringRef descriptions;
4466 };
4467
4468 template <typename T>
4469 ParserResult convertInto( std::string const& source, T& target ) {
4470 std::stringstream ss( source );
4471 ss >> target;
4472 if ( ss.fail() ) {
4473 return ParserResult::runtimeError(
4474 "Unable to convert '" + source +
4475 "' to destination type" );
4476 } else {
4477 return ParserResult::ok( ParseResultType::Matched );
4478 }
4479 }
4480 ParserResult convertInto( std::string const& source,
4481 std::string& target );
4482 ParserResult convertInto( std::string const& source, bool& target );
4483
4484#ifdef CLARA_CONFIG_OPTIONAL_TYPE
4485 template <typename T>
4486 auto convertInto( std::string const& source,
4487 CLARA_CONFIG_OPTIONAL_TYPE<T>& target )
4488 -> ParserResult {
4489 T temp;
4490 auto result = convertInto( source, temp );
4491 if ( result )
4492 target = CATCH_MOVE( temp );
4493 return result;
4494 }
4495#endif // CLARA_CONFIG_OPTIONAL_TYPE
4496
4497 struct BoundRef : Catch::Detail::NonCopyable {
4498 virtual ~BoundRef() = default;
4499 virtual bool isContainer() const;
4500 virtual bool isFlag() const;
4501 };
4502 struct BoundValueRefBase : BoundRef {
4503 virtual auto setValue( std::string const& arg )
4504 -> ParserResult = 0;
4505 };
4506 struct BoundFlagRefBase : BoundRef {
4507 virtual auto setFlag( bool flag ) -> ParserResult = 0;
4508 bool isFlag() const override;
4509 };
4510
4511 template <typename T> struct BoundValueRef : BoundValueRefBase {
4512 T& m_ref;
4513
4514 explicit BoundValueRef( T& ref ): m_ref( ref ) {}
4515
4516 ParserResult setValue( std::string const& arg ) override {
4517 return convertInto( arg, m_ref );
4518 }
4519 };
4520
4521 template <typename T>
4522 struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
4523 std::vector<T>& m_ref;
4524
4525 explicit BoundValueRef( std::vector<T>& ref ): m_ref( ref ) {}
4526
4527 auto isContainer() const -> bool override { return true; }
4528
4529 auto setValue( std::string const& arg )
4530 -> ParserResult override {
4531 T temp;
4532 auto result = convertInto( arg, temp );
4533 if ( result )
4534 m_ref.push_back( temp );
4535 return result;
4536 }
4537 };
4538
4539 struct BoundFlagRef : BoundFlagRefBase {
4540 bool& m_ref;
4541
4542 explicit BoundFlagRef( bool& ref ): m_ref( ref ) {}
4543
4544 ParserResult setFlag( bool flag ) override;
4545 };
4546
4547 template <typename ReturnType> struct LambdaInvoker {
4548 static_assert(
4549 std::is_same<ReturnType, ParserResult>::value,
4550 "Lambda must return void or clara::ParserResult" );
4551
4552 template <typename L, typename ArgType>
4553 static auto invoke( L const& lambda, ArgType const& arg )
4554 -> ParserResult {
4555 return lambda( arg );
4556 }
4557 };
4558
4559 template <> struct LambdaInvoker<void> {
4560 template <typename L, typename ArgType>
4561 static auto invoke( L const& lambda, ArgType const& arg )
4562 -> ParserResult {
4563 lambda( arg );
4564 return ParserResult::ok( ParseResultType::Matched );
4565 }
4566 };
4567
4568 template <typename ArgType, typename L>
4569 auto invokeLambda( L const& lambda, std::string const& arg )
4570 -> ParserResult {
4571 ArgType temp{};
4572 auto result = convertInto( arg, temp );
4573 return !result ? result
4574 : LambdaInvoker<typename UnaryLambdaTraits<
4575 L>::ReturnType>::invoke( lambda, temp );
4576 }
4577
4578 template <typename L> struct BoundLambda : BoundValueRefBase {
4579 L m_lambda;
4580
4581 static_assert(
4582 UnaryLambdaTraits<L>::isValid,
4583 "Supplied lambda must take exactly one argument" );
4584 explicit BoundLambda( L const& lambda ): m_lambda( lambda ) {}
4585
4586 auto setValue( std::string const& arg )
4587 -> ParserResult override {
4588 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(
4589 m_lambda, arg );
4590 }
4591 };
4592
4593 template <typename L> struct BoundManyLambda : BoundLambda<L> {
4594 explicit BoundManyLambda( L const& lambda ): BoundLambda<L>( lambda ) {}
4595 bool isContainer() const override { return true; }
4596 };
4597
4598 template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
4599 L m_lambda;
4600
4601 static_assert(
4602 UnaryLambdaTraits<L>::isValid,
4603 "Supplied lambda must take exactly one argument" );
4604 static_assert(
4605 std::is_same<typename UnaryLambdaTraits<L>::ArgType,
4606 bool>::value,
4607 "flags must be boolean" );
4608
4609 explicit BoundFlagLambda( L const& lambda ):
4610 m_lambda( lambda ) {}
4611
4612 auto setFlag( bool flag ) -> ParserResult override {
4613 return LambdaInvoker<typename UnaryLambdaTraits<
4614 L>::ReturnType>::invoke( m_lambda, flag );
4615 }
4616 };
4617
4618 enum class Optionality { Optional, Required };
4619
4620 class ParserBase {
4621 public:
4622 virtual ~ParserBase() = default;
4623 virtual auto validate() const -> Result { return Result::ok(); }
4624 virtual auto parse( std::string const& exeName,
4625 TokenStream tokens ) const
4626 -> InternalParseResult = 0;
4627 virtual size_t cardinality() const;
4628
4629 InternalParseResult parse( Args const& args ) const;
4630 };
4631
4632 template <typename DerivedT>
4633 class ComposableParserImpl : public ParserBase {
4634 public:
4635 template <typename T>
4636 auto operator|( T const& other ) const -> Parser;
4637 };
4638
4639 // Common code and state for Args and Opts
4640 template <typename DerivedT>
4641 class ParserRefImpl : public ComposableParserImpl<DerivedT> {
4642 protected:
4643 Optionality m_optionality = Optionality::Optional;
4644 std::shared_ptr<BoundRef> m_ref;
4645 StringRef m_hint;
4646 StringRef m_description;
4647
4648 explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ):
4649 m_ref( ref ) {}
4650
4651 public:
4652 template <typename LambdaT>
4653 ParserRefImpl( accept_many_t,
4654 LambdaT const& ref,
4655 StringRef hint ):
4656 m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ),
4657 m_hint( hint ) {}
4658
4659 template <typename T,
4660 typename = typename std::enable_if_t<
4661 !Detail::is_unary_function<T>::value>>
4662 ParserRefImpl( T& ref, StringRef hint ):
4663 m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
4664 m_hint( hint ) {}
4665
4666 template <typename LambdaT,
4667 typename = typename std::enable_if_t<
4668 Detail::is_unary_function<LambdaT>::value>>
4669 ParserRefImpl( LambdaT const& ref, StringRef hint ):
4670 m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
4671 m_hint( hint ) {}
4672
4673 DerivedT& operator()( StringRef description ) & {
4674 m_description = description;
4675 return static_cast<DerivedT&>( *this );
4676 }
4677 DerivedT&& operator()( StringRef description ) && {
4678 m_description = description;
4679 return static_cast<DerivedT&&>( *this );
4680 }
4681
4682 auto optional() -> DerivedT& {
4683 m_optionality = Optionality::Optional;
4684 return static_cast<DerivedT&>( *this );
4685 }
4686
4687 auto required() -> DerivedT& {
4688 m_optionality = Optionality::Required;
4689 return static_cast<DerivedT&>( *this );
4690 }
4691
4692 auto isOptional() const -> bool {
4693 return m_optionality == Optionality::Optional;
4694 }
4695
4696 auto cardinality() const -> size_t override {
4697 if ( m_ref->isContainer() )
4698 return 0;
4699 else
4700 return 1;
4701 }
4702
4703 StringRef hint() const { return m_hint; }
4704 };
4705
4706 } // namespace detail
4707
4708
4709 // A parser for arguments
4710 class Arg : public Detail::ParserRefImpl<Arg> {
4711 public:
4712 using ParserRefImpl::ParserRefImpl;
4713 using ParserBase::parse;
4714
4715 Detail::InternalParseResult
4716 parse(std::string const&,
4717 Detail::TokenStream tokens) const override;
4718 };
4719
4720 // A parser for options
4721 class Opt : public Detail::ParserRefImpl<Opt> {
4722 protected:
4723 std::vector<StringRef> m_optNames;
4724
4725 public:
4726 template <typename LambdaT>
4727 explicit Opt(LambdaT const& ref) :
4728 ParserRefImpl(
4729 std::make_shared<Detail::BoundFlagLambda<LambdaT>>(ref)) {}
4730
4731 explicit Opt(bool& ref);
4732
4733 template <typename LambdaT,
4734 typename = typename std::enable_if_t<
4735 Detail::is_unary_function<LambdaT>::value>>
4736 Opt( LambdaT const& ref, StringRef hint ):
4737 ParserRefImpl( ref, hint ) {}
4738
4739 template <typename LambdaT>
4740 Opt( accept_many_t, LambdaT const& ref, StringRef hint ):
4741 ParserRefImpl( accept_many, ref, hint ) {}
4742
4743 template <typename T,
4744 typename = typename std::enable_if_t<
4745 !Detail::is_unary_function<T>::value>>
4746 Opt( T& ref, StringRef hint ):
4747 ParserRefImpl( ref, hint ) {}
4748
4749 Opt& operator[]( StringRef optName ) & {
4750 m_optNames.push_back(optName);
4751 return *this;
4752 }
4753 Opt&& operator[]( StringRef optName ) && {
4754 m_optNames.push_back( optName );
4755 return CATCH_MOVE(*this);
4756 }
4757
4758 Detail::HelpColumns getHelpColumns() const;
4759
4760 bool isMatch(StringRef optToken) const;
4761
4762 using ParserBase::parse;
4763
4764 Detail::InternalParseResult
4765 parse(std::string const&,
4766 Detail::TokenStream tokens) const override;
4767
4768 Detail::Result validate() const override;
4769 };
4770
4771 // Specifies the name of the executable
4772 class ExeName : public Detail::ComposableParserImpl<ExeName> {
4773 std::shared_ptr<std::string> m_name;
4774 std::shared_ptr<Detail::BoundValueRefBase> m_ref;
4775
4776 public:
4777 ExeName();
4778 explicit ExeName(std::string& ref);
4779
4780 template <typename LambdaT>
4781 explicit ExeName(LambdaT const& lambda) : ExeName() {
4782 m_ref = std::make_shared<Detail::BoundLambda<LambdaT>>(lambda);
4783 }
4784
4785 // The exe name is not parsed out of the normal tokens, but is
4786 // handled specially
4787 Detail::InternalParseResult
4788 parse(std::string const&,
4789 Detail::TokenStream tokens) const override;
4790
4791 std::string const& name() const { return *m_name; }
4792 Detail::ParserResult set(std::string const& newName);
4793 };
4794
4795
4796 // A Combined parser
4797 class Parser : Detail::ParserBase {
4798 mutable ExeName m_exeName;
4799 std::vector<Opt> m_options;
4800 std::vector<Arg> m_args;
4801
4802 public:
4803
4804 auto operator|=(ExeName const& exeName) -> Parser& {
4805 m_exeName = exeName;
4806 return *this;
4807 }
4808
4809 auto operator|=(Arg const& arg) -> Parser& {
4810 m_args.push_back(arg);
4811 return *this;
4812 }
4813
4814 friend Parser& operator|=( Parser& p, Opt const& opt ) {
4815 p.m_options.push_back( opt );
4816 return p;
4817 }
4818 friend Parser& operator|=( Parser& p, Opt&& opt ) {
4819 p.m_options.push_back( CATCH_MOVE(opt) );
4820 return p;
4821 }
4822
4823 Parser& operator|=(Parser const& other);
4824
4825 template <typename T>
4826 friend Parser operator|( Parser const& p, T&& rhs ) {
4827 Parser temp( p );
4828 temp |= rhs;
4829 return temp;
4830 }
4831
4832 template <typename T>
4833 friend Parser operator|( Parser&& p, T&& rhs ) {
4834 p |= CATCH_FORWARD(rhs);
4835 return CATCH_MOVE(p);
4836 }
4837
4838 std::vector<Detail::HelpColumns> getHelpColumns() const;
4839
4840 void writeToStream(std::ostream& os) const;
4841
4842 friend auto operator<<(std::ostream& os, Parser const& parser)
4843 -> std::ostream& {
4844 parser.writeToStream(os);
4845 return os;
4846 }
4847
4848 Detail::Result validate() const override;
4849
4850 using ParserBase::parse;
4851 Detail::InternalParseResult
4852 parse(std::string const& exeName,
4853 Detail::TokenStream tokens) const override;
4854 };
4855
4856 /**
4857 * Wrapper over argc + argv, assumes that the inputs outlive it
4858 */
4859 class Args {
4860 friend Detail::TokenStream;
4861 StringRef m_exeName;
4862 std::vector<StringRef> m_args;
4863
4864 public:
4865 Args(int argc, char const* const* argv);
4866 // Helper constructor for testing
4867 Args(std::initializer_list<StringRef> args);
4868
4869 StringRef exeName() const { return m_exeName; }
4870 };
4871
4872
4873 // Convenience wrapper for option parser that specifies the help option
4874 struct Help : Opt {
4875 Help(bool& showHelpFlag);
4876 };
4877
4878 // Result type for parser operation
4879 using Detail::ParserResult;
4880
4881 namespace Detail {
4882 template <typename DerivedT>
4883 template <typename T>
4884 Parser
4885 ComposableParserImpl<DerivedT>::operator|(T const& other) const {
4886 return Parser() | static_cast<DerivedT const&>(*this) | other;
4887 }
4888 }
4889
4890 } // namespace Clara
4891} // namespace Catch
4892
4893#if defined( __clang__ )
4894# pragma clang diagnostic pop
4895#endif
4896
4897#if defined( __GNUC__ )
4898# pragma GCC diagnostic pop
4899#endif
4900
4901#endif // CATCH_CLARA_HPP_INCLUDED
4902
4903namespace Catch {
4904
4905 struct ConfigData;
4906
4907 Clara::Parser makeCommandLineParser( ConfigData& config );
4908
4909} // end namespace Catch
4910
4911#endif // CATCH_COMMANDLINE_HPP_INCLUDED
4912
4913namespace Catch {
4914
4915 class Session : Detail::NonCopyable {
4916 public:
4917
4918 Session();
4919 ~Session();
4920
4921 void showHelp() const;
4922 void libIdentify();
4923
4924 int applyCommandLine( int argc, char const * const * argv );
4925 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
4926 int applyCommandLine( int argc, wchar_t const * const * argv );
4927 #endif
4928
4929 void useConfigData( ConfigData const& configData );
4930
4931 template<typename CharT>
4932 int run(int argc, CharT const * const argv[]) {
4933 if (m_startupExceptions)
4934 return 1;
4935 int returnCode = applyCommandLine(argc, argv);
4936 if (returnCode == 0)
4937 returnCode = run();
4938 return returnCode;
4939 }
4940
4941 int run();
4942
4943 Clara::Parser const& cli() const;
4944 void cli( Clara::Parser const& newParser );
4945 ConfigData& configData();
4946 Config& config();
4947 private:
4948 int runInternal();
4949
4950 Clara::Parser m_cli;
4951 ConfigData m_configData;
4952 Detail::unique_ptr<Config> m_config;
4953 bool m_startupExceptions = false;
4954 };
4955
4956} // end namespace Catch
4957
4958#endif // CATCH_SESSION_HPP_INCLUDED
4959
4960
4961#ifndef CATCH_TAG_ALIAS_HPP_INCLUDED
4962#define CATCH_TAG_ALIAS_HPP_INCLUDED
4963
4964
4965#include <string>
4966
4967namespace Catch {
4968
4969 struct TagAlias {
4970 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo):
4971 tag(_tag),
4972 lineInfo(_lineInfo)
4973 {}
4974
4975 std::string tag;
4976 SourceLineInfo lineInfo;
4977 };
4978
4979} // end namespace Catch
4980
4981#endif // CATCH_TAG_ALIAS_HPP_INCLUDED
4982
4983
4984#ifndef CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
4985#define CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
4986
4987
4988namespace Catch {
4989
4990 struct RegistrarForTagAliases {
4991 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
4992 };
4993
4994} // end namespace Catch
4995
4996#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
4997 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
4998 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
4999 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
5000 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5001
5002#endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
5003
5004
5005#ifndef CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
5006#define CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
5007
5008// We need this suppression to leak, because it took until GCC 10
5009// for the front end to handle local suppression via _Pragma properly
5010// inside templates (so `TEMPLATE_TEST_CASE` and co).
5011// **THIS IS DIFFERENT FOR STANDARD TESTS, WHERE GCC 9 IS SUFFICIENT**
5012#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ < 10
5013#pragma GCC diagnostic ignored "-Wparentheses"
5014#endif
5015
5016
5017
5018
5019#ifndef CATCH_TEST_MACROS_HPP_INCLUDED
5020#define CATCH_TEST_MACROS_HPP_INCLUDED
5021
5022
5023
5024#ifndef CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
5025#define CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
5026
5027
5028
5029#ifndef CATCH_ASSERTION_HANDLER_HPP_INCLUDED
5030#define CATCH_ASSERTION_HANDLER_HPP_INCLUDED
5031
5032
5033
5034#ifndef CATCH_DECOMPOSER_HPP_INCLUDED
5035#define CATCH_DECOMPOSER_HPP_INCLUDED
5036
5037
5038
5039#ifndef CATCH_COMPARE_TRAITS_HPP_INCLUDED
5040#define CATCH_COMPARE_TRAITS_HPP_INCLUDED
5041
5042
5043#include <type_traits>
5044
5045namespace Catch {
5046 namespace Detail {
5047
5048#if defined( __GNUC__ ) && !defined( __clang__ )
5049# pragma GCC diagnostic push
5050 // GCC likes to complain about comparing bool with 0, in the decltype()
5051 // that defines the comparable traits below.
5052# pragma GCC diagnostic ignored "-Wbool-compare"
5053 // "ordered comparison of pointer with integer zero" same as above,
5054 // but it does not have a separate warning flag to suppress
5055# pragma GCC diagnostic ignored "-Wextra"
5056 // Did you know that comparing floats with `0` directly
5057 // is super-duper dangerous in unevaluated context?
5058# pragma GCC diagnostic ignored "-Wfloat-equal"
5059#endif
5060
5061#if defined( __clang__ )
5062# pragma clang diagnostic push
5063 // Did you know that comparing floats with `0` directly
5064 // is super-duper dangerous in unevaluated context?
5065# pragma clang diagnostic ignored "-Wfloat-equal"
5066#endif
5067
5068#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op ) \
5069 template <typename, typename, typename = void> \
5070 struct is_##id##_comparable : std::false_type {}; \
5071 template <typename T, typename U> \
5072 struct is_##id##_comparable< \
5073 T, \
5074 U, \
5075 void_t<decltype( std::declval<T>() op std::declval<U>() )>> \
5076 : std::true_type {}; \
5077 template <typename, typename = void> \
5078 struct is_##id##_0_comparable : std::false_type {}; \
5079 template <typename T> \
5080 struct is_##id##_0_comparable<T, \
5081 void_t<decltype( std::declval<T>() op 0 )>> \
5082 : std::true_type {};
5083
5084 // We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, !=
5085 CATCH_DEFINE_COMPARABLE_TRAIT( lt, < )
5086 CATCH_DEFINE_COMPARABLE_TRAIT( le, <= )
5087 CATCH_DEFINE_COMPARABLE_TRAIT( gt, > )
5088 CATCH_DEFINE_COMPARABLE_TRAIT( ge, >= )
5089 CATCH_DEFINE_COMPARABLE_TRAIT( eq, == )
5090 CATCH_DEFINE_COMPARABLE_TRAIT( ne, != )
5091
5092#undef CATCH_DEFINE_COMPARABLE_TRAIT
5093
5094#if defined( __GNUC__ ) && !defined( __clang__ )
5095# pragma GCC diagnostic pop
5096#endif
5097#if defined( __clang__ )
5098# pragma clang diagnostic pop
5099#endif
5100
5101
5102 } // namespace Detail
5103} // namespace Catch
5104
5105#endif // CATCH_COMPARE_TRAITS_HPP_INCLUDED
5106
5107
5108#ifndef CATCH_LOGICAL_TRAITS_HPP_INCLUDED
5109#define CATCH_LOGICAL_TRAITS_HPP_INCLUDED
5110
5111#include <type_traits>
5112
5113namespace Catch {
5114namespace Detail {
5115
5116#if defined( __cpp_lib_logical_traits ) && __cpp_lib_logical_traits >= 201510
5117
5118 using std::conjunction;
5119 using std::disjunction;
5120 using std::negation;
5121
5122#else
5123
5124 template <class...> struct conjunction : std::true_type {};
5125 template <class B1> struct conjunction<B1> : B1 {};
5126 template <class B1, class... Bn>
5127 struct conjunction<B1, Bn...>
5128 : std::conditional_t<bool( B1::value ), conjunction<Bn...>, B1> {};
5129
5130 template <class...> struct disjunction : std::false_type {};
5131 template <class B1> struct disjunction<B1> : B1 {};
5132 template <class B1, class... Bn>
5133 struct disjunction<B1, Bn...>
5134 : std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {};
5135
5136 template <class B>
5137 struct negation : std::integral_constant<bool, !bool(B::value)> {};
5138
5139#endif
5140
5141} // namespace Detail
5142} // namespace Catch
5143
5144#endif // CATCH_LOGICAL_TRAITS_HPP_INCLUDED
5145
5146#include <type_traits>
5147#include <iosfwd>
5148
5149/** \file
5150 * Why does decomposing look the way it does:
5151 *
5152 * Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into
5153 * `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first,
5154 * and our custom operator is used for `a == b`, because `a` is transformed
5155 * into `ExprLhs<T&>` and then into `BinaryExpr<T&, U&>`.
5156 *
5157 * In practice, decomposing ends up a mess, because we have to support
5158 * various fun things.
5159 *
5160 * 1) Types that are only comparable with literal 0, and they do this by
5161 * comparing against a magic type with pointer constructor and deleted
5162 * other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++
5163 *
5164 * 2) Types that are only comparable with literal 0, and they do this by
5165 * comparing against a magic type with consteval integer constructor.
5166 * Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL.
5167 *
5168 * 3) Types that have no linkage, and so we cannot form a reference to
5169 * them. Example: some implementations of traits.
5170 *
5171 * 4) Starting with C++20, when the compiler sees `a == b`, it also uses
5172 * `b == a` when constructing the overload set. For us this means that
5173 * when the compiler handles `ExprLhs<T> == b`, it also tries to resolve
5174 * the overload set for `b == ExprLhs<T>`.
5175 *
5176 * To accomodate these use cases, decomposer ended up rather complex.
5177 *
5178 * 1) These types are handled by adding SFINAE overloads to our comparison
5179 * operators, checking whether `T == U` are comparable with the given
5180 * operator, and if not, whether T (or U) are comparable with literal 0.
5181 * If yes, the overload compares T (or U) with 0 literal inline in the
5182 * definition.
5183 *
5184 * Note that for extra correctness, we check that the other type is
5185 * either an `int` (literal 0 is captured as `int` by templates), or
5186 * a `long` (some platforms use 0L for `NULL` and we want to support
5187 * that for pointer comparisons).
5188 *
5189 * 2) For these types, `is_foo_comparable<T, int>` is true, but letting
5190 * them fall into the overload that actually does `T == int` causes
5191 * compilation error. Handling them requires that the decomposition
5192 * is `constexpr`, so that P2564R3 applies and the `consteval` from
5193 * their accompanying magic type is propagated through the `constexpr`
5194 * call stack.
5195 *
5196 * However this is not enough to handle these types automatically,
5197 * because our default is to capture types by reference, to avoid
5198 * runtime copies. While these references cannot become dangling,
5199 * they outlive the constexpr context and thus the default capture
5200 * path cannot be actually constexpr.
5201 *
5202 * The solution is to capture these types by value, by explicitly
5203 * specializing `Catch::capture_by_value` for them. Catch2 provides
5204 * specialization for `std::foo_ordering`s, but users can specialize
5205 * the trait for their own types as well.
5206 *
5207 * 3) If a type has no linkage, we also cannot capture it by reference.
5208 * The solution is once again to capture them by value. We handle
5209 * the common cases by using `std::is_arithmetic` as the default
5210 * for `Catch::capture_by_value`, but that is only a some-effort
5211 * heuristic. But as with 2), users can specialize `capture_by_value`
5212 * for their own types as needed.
5213 *
5214 * 4) To support C++20 and make the SFINAE on our decomposing operators
5215 * work, the SFINAE has to happen in return type, rather than in
5216 * a template type. This is due to our use of logical type traits
5217 * (`conjunction`/`disjunction`/`negation`), that we use to workaround
5218 * an issue in older (9-) versions of GCC. I still blame C++20 for
5219 * this, because without the comparison order switching, the logical
5220 * traits could still be used in template type.
5221 *
5222 * There are also other side concerns, e.g. supporting both `REQUIRE(a)`
5223 * and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot
5224 * nicely into the same expression handling logic, but these are rather
5225 * straightforward and add only a bit of complexity (e.g. common base
5226 * class for decomposed expressions).
5227 */
5228
5229#ifdef _MSC_VER
5230#pragma warning(push)
5231#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
5232#pragma warning(disable:4018) // more "signed/unsigned mismatch"
5233#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
5234#pragma warning(disable:4180) // qualifier applied to function type has no meaning
5235#pragma warning(disable:4800) // Forcing result to true or false
5236#endif
5237
5238#ifdef __clang__
5239# pragma clang diagnostic push
5240# pragma clang diagnostic ignored "-Wsign-compare"
5241# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
5242#elif defined __GNUC__
5243# pragma GCC diagnostic push
5244# pragma GCC diagnostic ignored "-Wsign-compare"
5245# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
5246#endif
5247
5248#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>)
5249# include <compare>
5250# if defined( __cpp_lib_three_way_comparison ) && \
5251 __cpp_lib_three_way_comparison >= 201907L
5252# define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS
5253# endif
5254#endif
5255
5256namespace Catch {
5257
5258 namespace Detail {
5259 // This was added in C++20, but we require only C++14 for now.
5260 template <typename T>
5261 using RemoveCVRef_t = std::remove_cv_t<std::remove_reference_t<T>>;
5262 }
5263
5264 // Note: There is nothing that stops us from extending this,
5265 // e.g. to `std::is_scalar`, but the more encompassing
5266 // traits are usually also more expensive. For now we
5267 // keep this as it used to be and it can be changed later.
5268 template <typename T>
5269 struct capture_by_value
5270 : std::integral_constant<bool, std::is_arithmetic<T>{}> {};
5271
5272#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS )
5273 template <>
5274 struct capture_by_value<std::strong_ordering> : std::true_type {};
5275 template <>
5276 struct capture_by_value<std::weak_ordering> : std::true_type {};
5277 template <>
5278 struct capture_by_value<std::partial_ordering> : std::true_type {};
5279#endif
5280
5281 template <typename T>
5282 struct always_false : std::false_type {};
5283
5284 class ITransientExpression {
5285 bool m_isBinaryExpression;
5286 bool m_result;
5287
5288 protected:
5289 ~ITransientExpression() = default;
5290
5291 public:
5292 constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
5293 constexpr auto getResult() const -> bool { return m_result; }
5294 //! This function **has** to be overriden by the derived class.
5295 virtual void streamReconstructedExpression( std::ostream& os ) const;
5296
5297 constexpr ITransientExpression( bool isBinaryExpression, bool result )
5298 : m_isBinaryExpression( isBinaryExpression ),
5299 m_result( result )
5300 {}
5301
5302 constexpr ITransientExpression( ITransientExpression const& ) = default;
5303 constexpr ITransientExpression& operator=( ITransientExpression const& ) = default;
5304
5305 friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
5306 expr.streamReconstructedExpression(out);
5307 return out;
5308 }
5309 };
5310
5311 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
5312
5313 template<typename LhsT, typename RhsT>
5314 class BinaryExpr : public ITransientExpression {
5315 LhsT m_lhs;
5316 StringRef m_op;
5317 RhsT m_rhs;
5318
5319 void streamReconstructedExpression( std::ostream &os ) const override {
5320 formatReconstructedExpression
5321 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
5322 }
5323
5324 public:
5325 constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
5326 : ITransientExpression{ true, comparisonResult },
5327 m_lhs( lhs ),
5328 m_op( op ),
5329 m_rhs( rhs )
5330 {}
5331
5332 template<typename T>
5333 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5334 static_assert(always_false<T>::value,
5335 "chained comparisons are not supported inside assertions, "
5336 "wrap the expression inside parentheses, or decompose it");
5337 }
5338
5339 template<typename T>
5340 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5341 static_assert(always_false<T>::value,
5342 "chained comparisons are not supported inside assertions, "
5343 "wrap the expression inside parentheses, or decompose it");
5344 }
5345
5346 template<typename T>
5347 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5348 static_assert(always_false<T>::value,
5349 "chained comparisons are not supported inside assertions, "
5350 "wrap the expression inside parentheses, or decompose it");
5351 }
5352
5353 template<typename T>
5354 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5355 static_assert(always_false<T>::value,
5356 "chained comparisons are not supported inside assertions, "
5357 "wrap the expression inside parentheses, or decompose it");
5358 }
5359
5360 template<typename T>
5361 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5362 static_assert(always_false<T>::value,
5363 "chained comparisons are not supported inside assertions, "
5364 "wrap the expression inside parentheses, or decompose it");
5365 }
5366
5367 template<typename T>
5368 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5369 static_assert(always_false<T>::value,
5370 "chained comparisons are not supported inside assertions, "
5371 "wrap the expression inside parentheses, or decompose it");
5372 }
5373
5374 template<typename T>
5375 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5376 static_assert(always_false<T>::value,
5377 "chained comparisons are not supported inside assertions, "
5378 "wrap the expression inside parentheses, or decompose it");
5379 }
5380
5381 template<typename T>
5382 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5383 static_assert(always_false<T>::value,
5384 "chained comparisons are not supported inside assertions, "
5385 "wrap the expression inside parentheses, or decompose it");
5386 }
5387 };
5388
5389 template<typename LhsT>
5390 class UnaryExpr : public ITransientExpression {
5391 LhsT m_lhs;
5392
5393 void streamReconstructedExpression( std::ostream &os ) const override {
5394 os << Catch::Detail::stringify( m_lhs );
5395 }
5396
5397 public:
5398 explicit constexpr UnaryExpr( LhsT lhs )
5399 : ITransientExpression{ false, static_cast<bool>(lhs) },
5400 m_lhs( lhs )
5401 {}
5402 };
5403
5404
5405 template<typename LhsT>
5406 class ExprLhs {
5407 LhsT m_lhs;
5408 public:
5409 explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
5410
5411#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op ) \
5412 template <typename RhsT> \
5413 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
5414 -> std::enable_if_t< \
5415 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5416 Detail::negation<capture_by_value< \
5417 Detail::RemoveCVRef_t<RhsT>>>>::value, \
5418 BinaryExpr<LhsT, RhsT const&>> { \
5419 return { \
5420 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5421 } \
5422 template <typename RhsT> \
5423 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5424 -> std::enable_if_t< \
5425 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5426 capture_by_value<RhsT>>::value, \
5427 BinaryExpr<LhsT, RhsT>> { \
5428 return { \
5429 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5430 } \
5431 template <typename RhsT> \
5432 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5433 -> std::enable_if_t< \
5434 Detail::conjunction< \
5435 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5436 Detail::is_eq_0_comparable<LhsT>, \
5437 /* We allow long because we want `ptr op NULL` to be accepted */ \
5438 Detail::disjunction<std::is_same<RhsT, int>, \
5439 std::is_same<RhsT, long>>>::value, \
5440 BinaryExpr<LhsT, RhsT>> { \
5441 if ( rhs != 0 ) { throw_test_failure_exception(); } \
5442 return { \
5443 static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
5444 } \
5445 template <typename RhsT> \
5446 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5447 -> std::enable_if_t< \
5448 Detail::conjunction< \
5449 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5450 Detail::is_eq_0_comparable<RhsT>, \
5451 /* We allow long because we want `ptr op NULL` to be accepted */ \
5452 Detail::disjunction<std::is_same<LhsT, int>, \
5453 std::is_same<LhsT, long>>>::value, \
5454 BinaryExpr<LhsT, RhsT>> { \
5455 if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
5456 return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5457 }
5458
5459 CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
5460 CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != )
5461
5462 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
5463
5464
5465#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \
5466 template <typename RhsT> \
5467 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
5468 -> std::enable_if_t< \
5469 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5470 Detail::negation<capture_by_value< \
5471 Detail::RemoveCVRef_t<RhsT>>>>::value, \
5472 BinaryExpr<LhsT, RhsT const&>> { \
5473 return { \
5474 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5475 } \
5476 template <typename RhsT> \
5477 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5478 -> std::enable_if_t< \
5479 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5480 capture_by_value<RhsT>>::value, \
5481 BinaryExpr<LhsT, RhsT>> { \
5482 return { \
5483 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5484 } \
5485 template <typename RhsT> \
5486 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5487 -> std::enable_if_t< \
5488 Detail::conjunction< \
5489 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5490 Detail::is_##id##_0_comparable<LhsT>, \
5491 std::is_same<RhsT, int>>::value, \
5492 BinaryExpr<LhsT, RhsT>> { \
5493 if ( rhs != 0 ) { throw_test_failure_exception(); } \
5494 return { \
5495 static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
5496 } \
5497 template <typename RhsT> \
5498 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5499 -> std::enable_if_t< \
5500 Detail::conjunction< \
5501 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5502 Detail::is_##id##_0_comparable<RhsT>, \
5503 std::is_same<LhsT, int>>::value, \
5504 BinaryExpr<LhsT, RhsT>> { \
5505 if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
5506 return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5507 }
5508
5509 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < )
5510 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= )
5511 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > )
5512 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= )
5513
5514 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR
5515
5516
5517#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op ) \
5518 template <typename RhsT> \
5519 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
5520 -> std::enable_if_t< \
5521 !capture_by_value<Detail::RemoveCVRef_t<RhsT>>::value, \
5522 BinaryExpr<LhsT, RhsT const&>> { \
5523 return { \
5524 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5525 } \
5526 template <typename RhsT> \
5527 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5528 -> std::enable_if_t<capture_by_value<RhsT>::value, \
5529 BinaryExpr<LhsT, RhsT>> { \
5530 return { \
5531 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5532 }
5533
5534 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|)
5535 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&)
5536 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^)
5537
5538 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR
5539
5540 template<typename RhsT>
5541 friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
5542 static_assert(always_false<RhsT>::value,
5543 "operator&& is not supported inside assertions, "
5544 "wrap the expression inside parentheses, or decompose it");
5545 }
5546
5547 template<typename RhsT>
5548 friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
5549 static_assert(always_false<RhsT>::value,
5550 "operator|| is not supported inside assertions, "
5551 "wrap the expression inside parentheses, or decompose it");
5552 }
5553
5554 constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
5555 return UnaryExpr<LhsT>{ m_lhs };
5556 }
5557 };
5558
5559 struct Decomposer {
5560 template <typename T,
5561 std::enable_if_t<!capture_by_value<Detail::RemoveCVRef_t<T>>::value,
5562 int> = 0>
5563 constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
5564 return ExprLhs<const T&>{ lhs };
5565 }
5566
5567 template <typename T,
5568 std::enable_if_t<capture_by_value<T>::value, int> = 0>
5569 constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
5570 return ExprLhs<T>{ value };
5571 }
5572 };
5573
5574} // end namespace Catch
5575
5576#ifdef _MSC_VER
5577#pragma warning(pop)
5578#endif
5579#ifdef __clang__
5580# pragma clang diagnostic pop
5581#elif defined __GNUC__
5582# pragma GCC diagnostic pop
5583#endif
5584
5585#endif // CATCH_DECOMPOSER_HPP_INCLUDED
5586
5587#include <string>
5588
5589namespace Catch {
5590
5591 struct AssertionReaction {
5592 bool shouldDebugBreak = false;
5593 bool shouldThrow = false;
5594 bool shouldSkip = false;
5595 };
5596
5597 class AssertionHandler {
5598 AssertionInfo m_assertionInfo;
5599 AssertionReaction m_reaction;
5600 bool m_completed = false;
5601 IResultCapture& m_resultCapture;
5602
5603 public:
5604 AssertionHandler
5605 ( StringRef macroName,
5606 SourceLineInfo const& lineInfo,
5607 StringRef capturedExpression,
5608 ResultDisposition::Flags resultDisposition );
5609 ~AssertionHandler() {
5610 if ( !m_completed ) {
5611 m_resultCapture.handleIncomplete( m_assertionInfo );
5612 }
5613 }
5614
5615
5616 template<typename T>
5617 constexpr void handleExpr( ExprLhs<T> const& expr ) {
5618 handleExpr( expr.makeUnaryExpr() );
5619 }
5620 void handleExpr( ITransientExpression const& expr );
5621
5622 void handleMessage(ResultWas::OfType resultType, std::string&& message);
5623
5624 void handleExceptionThrownAsExpected();
5625 void handleUnexpectedExceptionNotThrown();
5626 void handleExceptionNotThrownAsExpected();
5627 void handleThrowingCallSkipped();
5628 void handleUnexpectedInflightException();
5629
5630 void complete();
5631
5632 // query
5633 auto allowThrows() const -> bool;
5634 };
5635
5636 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str );
5637
5638} // namespace Catch
5639
5640#endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED
5641
5642
5643#ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
5644#define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
5645
5646
5647#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
5648 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
5649#else
5650 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
5651#endif
5652
5653#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
5654
5655// We need this suppression to leak, because it took until GCC 10
5656// for the front end to handle local suppression via _Pragma properly
5657#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9
5658 #pragma GCC diagnostic ignored "-Wparentheses"
5659#endif
5660
5661#if !defined(CATCH_CONFIG_DISABLE)
5662
5663#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
5664
5665///////////////////////////////////////////////////////////////////////////////
5666// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
5667// macros.
5668#define INTERNAL_CATCH_TRY
5669#define INTERNAL_CATCH_CATCH( capturer )
5670
5671#else // CATCH_CONFIG_FAST_COMPILE
5672
5673#define INTERNAL_CATCH_TRY try
5674#define INTERNAL_CATCH_CATCH( handler ) catch(...) { (handler).handleUnexpectedInflightException(); }
5675
5676#endif
5677
5678///////////////////////////////////////////////////////////////////////////////
5679#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
5680 do { /* NOLINT(bugprone-infinite-loop) */ \
5681 /* The expression should not be evaluated, but warnings should hopefully be checked */ \
5682 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
5683 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
5684 INTERNAL_CATCH_TRY { \
5685 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5686 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
5687 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \
5688 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5689 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
5690 catchAssertionHandler.complete(); \
5691 } while( (void)0, (false) && static_cast<const bool&>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
5692 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
5693
5694///////////////////////////////////////////////////////////////////////////////
5695#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
5696 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
5697 if( Catch::getResultCapture().lastAssertionPassed() )
5698
5699///////////////////////////////////////////////////////////////////////////////
5700#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
5701 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
5702 if( !Catch::getResultCapture().lastAssertionPassed() )
5703
5704///////////////////////////////////////////////////////////////////////////////
5705#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
5706 do { \
5707 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
5708 try { \
5709 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5710 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5711 static_cast<void>(__VA_ARGS__); \
5712 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5713 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
5714 } \
5715 catch( ... ) { \
5716 catchAssertionHandler.handleUnexpectedInflightException(); \
5717 } \
5718 catchAssertionHandler.complete(); \
5719 } while( false )
5720
5721///////////////////////////////////////////////////////////////////////////////
5722#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
5723 do { \
5724 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
5725 if( catchAssertionHandler.allowThrows() ) \
5726 try { \
5727 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5728 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
5729 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5730 static_cast<void>(__VA_ARGS__); \
5731 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5732 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
5733 } \
5734 catch( ... ) { \
5735 catchAssertionHandler.handleExceptionThrownAsExpected(); \
5736 } \
5737 else \
5738 catchAssertionHandler.handleThrowingCallSkipped(); \
5739 catchAssertionHandler.complete(); \
5740 } while( false )
5741
5742///////////////////////////////////////////////////////////////////////////////
5743#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
5744 do { \
5745 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
5746 if( catchAssertionHandler.allowThrows() ) \
5747 try { \
5748 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5749 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
5750 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5751 static_cast<void>(expr); \
5752 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5753 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
5754 } \
5755 catch( exceptionType const& ) { \
5756 catchAssertionHandler.handleExceptionThrownAsExpected(); \
5757 } \
5758 catch( ... ) { \
5759 catchAssertionHandler.handleUnexpectedInflightException(); \
5760 } \
5761 else \
5762 catchAssertionHandler.handleThrowingCallSkipped(); \
5763 catchAssertionHandler.complete(); \
5764 } while( false )
5765
5766
5767
5768///////////////////////////////////////////////////////////////////////////////
5769// Although this is matcher-based, it can be used with just a string
5770#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
5771 do { \
5772 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
5773 if( catchAssertionHandler.allowThrows() ) \
5774 try { \
5775 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5776 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
5777 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5778 static_cast<void>(__VA_ARGS__); \
5779 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5780 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
5781 } \
5782 catch( ... ) { \
5783 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher ); \
5784 } \
5785 else \
5786 catchAssertionHandler.handleThrowingCallSkipped(); \
5787 catchAssertionHandler.complete(); \
5788 } while( false )
5789
5790#endif // CATCH_CONFIG_DISABLE
5791
5792#endif // CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
5793
5794
5795#ifndef CATCH_SECTION_HPP_INCLUDED
5796#define CATCH_SECTION_HPP_INCLUDED
5797
5798
5799
5800
5801/** \file
5802 * Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option
5803 *
5804 * Some of Catch2's macros can be defined differently to work better with
5805 * static analysis tools, like clang-tidy or coverity.
5806 * Currently the main use case is to show that `SECTION`s are executed
5807 * exclusively, and not all in one run of a `TEST_CASE`.
5808 */
5809
5810#ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
5811#define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
5812
5813
5814#if defined(__clang_analyzer__) || defined(__COVERITY__)
5815 #define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT
5816#endif
5817
5818#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \
5819 !defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \
5820 !defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT )
5821# define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
5822#endif
5823
5824
5825#endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
5826
5827
5828#ifndef CATCH_TIMER_HPP_INCLUDED
5829#define CATCH_TIMER_HPP_INCLUDED
5830
5831#include <cstdint>
5832
5833namespace Catch {
5834
5835 class Timer {
5836 uint64_t m_nanoseconds = 0;
5837 public:
5838 void start();
5839 auto getElapsedNanoseconds() const -> uint64_t;
5840 auto getElapsedMicroseconds() const -> uint64_t;
5841 auto getElapsedMilliseconds() const -> unsigned int;
5842 auto getElapsedSeconds() const -> double;
5843 };
5844
5845} // namespace Catch
5846
5847#endif // CATCH_TIMER_HPP_INCLUDED
5848
5849namespace Catch {
5850
5851 class Section : Detail::NonCopyable {
5852 public:
5853 Section( SectionInfo&& info );
5854 Section( SourceLineInfo const& _lineInfo,
5855 StringRef _name,
5856 const char* const = nullptr );
5857 ~Section();
5858
5859 // This indicates whether the section should be executed or not
5860 explicit operator bool() const;
5861
5862 private:
5863 SectionInfo m_info;
5864
5865 Counts m_assertions;
5866 bool m_sectionIncluded;
5867 Timer m_timer;
5868 };
5869
5870} // end namespace Catch
5871
5872#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
5873# define INTERNAL_CATCH_SECTION( ... ) \
5874 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5875 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5876 if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \
5877 catch_internal_Section ) = \
5878 Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
5879 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5880
5881# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
5882 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5883 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5884 if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \
5885 catch_internal_Section ) = \
5886 Catch::SectionInfo( \
5887 CATCH_INTERNAL_LINEINFO, \
5888 ( Catch::ReusableStringStream() << __VA_ARGS__ ) \
5889 .str() ) ) \
5890 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5891
5892#else
5893
5894// These section definitions imply that at most one section at one level
5895// will be intered (because only one section's __LINE__ can be equal to
5896// the dummy `catchInternalSectionHint` variable from `TEST_CASE`).
5897
5898namespace Catch {
5899 namespace Detail {
5900 // Intentionally without linkage, as it should only be used as a dummy
5901 // symbol for static analysis.
5902 // The arguments are used as a dummy for checking warnings in the passed
5903 // expressions.
5904 int GetNewSectionHint( StringRef, const char* const = nullptr );
5905 } // namespace Detail
5906} // namespace Catch
5907
5908
5909# define INTERNAL_CATCH_SECTION( ... ) \
5910 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5911 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5912 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
5913 if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
5914 catchInternalSectionHint, \
5915 catchInternalSectionHint = \
5916 Catch::Detail::GetNewSectionHint(__VA_ARGS__); \
5917 catchInternalPreviousSectionHint == __LINE__ ) \
5918 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5919
5920# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
5921 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5922 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5923 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
5924 if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
5925 catchInternalSectionHint, \
5926 catchInternalSectionHint = Catch::Detail::GetNewSectionHint( \
5927 ( Catch::ReusableStringStream() << __VA_ARGS__ ).str()); \
5928 catchInternalPreviousSectionHint == __LINE__ ) \
5929 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5930
5931#endif
5932
5933
5934#endif // CATCH_SECTION_HPP_INCLUDED
5935
5936
5937#ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED
5938#define CATCH_TEST_REGISTRY_HPP_INCLUDED
5939
5940
5941
5942#ifndef CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
5943#define CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
5944
5945namespace Catch {
5946
5947 class ITestInvoker {
5948 public:
5949 virtual void prepareTestCase();
5950 virtual void tearDownTestCase();
5951 virtual void invoke() const = 0;
5952 virtual ~ITestInvoker(); // = default
5953 };
5954
5955} // namespace Catch
5956
5957#endif // CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
5958
5959
5960#ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
5961#define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
5962
5963#define INTERNAL_CATCH_EXPAND1( param ) INTERNAL_CATCH_EXPAND2( param )
5964#define INTERNAL_CATCH_EXPAND2( ... ) INTERNAL_CATCH_NO##__VA_ARGS__
5965#define INTERNAL_CATCH_DEF( ... ) INTERNAL_CATCH_DEF __VA_ARGS__
5966#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
5967
5968#define INTERNAL_CATCH_REMOVE_PARENS( ... ) \
5969 INTERNAL_CATCH_EXPAND1( INTERNAL_CATCH_DEF __VA_ARGS__ )
5970
5971#endif // CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
5972
5973// GCC 5 and older do not properly handle disabling unused-variable warning
5974// with a _Pragma. This means that we have to leak the suppression to the
5975// user code as well :-(
5976#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
5977#pragma GCC diagnostic ignored "-Wunused-variable"
5978#endif
5979
5980
5981
5982namespace Catch {
5983
5984template<typename C>
5985class TestInvokerAsMethod : public ITestInvoker {
5986 void (C::*m_testAsMethod)();
5987public:
5988 constexpr TestInvokerAsMethod( void ( C::*testAsMethod )() ) noexcept:
5989 m_testAsMethod( testAsMethod ) {}
5990
5991 void invoke() const override {
5992 C obj;
5993 (obj.*m_testAsMethod)();
5994 }
5995};
5996
5997Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() );
5998
5999template<typename C>
6000Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
6001 return Detail::make_unique<TestInvokerAsMethod<C>>( testAsMethod );
6002}
6003
6004template <typename C>
6005class TestInvokerFixture : public ITestInvoker {
6006 void ( C::*m_testAsMethod )() const;
6007 Detail::unique_ptr<C> m_fixture = nullptr;
6008
6009public:
6010 constexpr TestInvokerFixture( void ( C::*testAsMethod )() const ) noexcept:
6011 m_testAsMethod( testAsMethod ) {}
6012
6013 void prepareTestCase() override {
6014 m_fixture = Detail::make_unique<C>();
6015 }
6016
6017 void tearDownTestCase() override {
6018 m_fixture.reset();
6019 }
6020
6021 void invoke() const override {
6022 auto* f = m_fixture.get();
6023 ( f->*m_testAsMethod )();
6024 }
6025};
6026
6027template<typename C>
6028Detail::unique_ptr<ITestInvoker> makeTestInvokerFixture( void ( C::*testAsMethod )() const ) {
6029 return Detail::make_unique<TestInvokerFixture<C>>( testAsMethod );
6030}
6031
6032struct NameAndTags {
6033 constexpr NameAndTags( StringRef name_ = StringRef(),
6034 StringRef tags_ = StringRef() ) noexcept:
6035 name( name_ ), tags( tags_ ) {}
6036 StringRef name;
6037 StringRef tags;
6038};
6039
6040struct AutoReg : Detail::NonCopyable {
6041 AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
6042};
6043
6044} // end namespace Catch
6045
6046#if defined(CATCH_CONFIG_DISABLE)
6047 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
6048 static inline void TestName()
6049 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
6050 namespace{ \
6051 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
6052 void test(); \
6053 }; \
6054 } \
6055 void TestName::test()
6056#endif
6057
6058
6059#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
6060
6061 ///////////////////////////////////////////////////////////////////////////////
6062 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
6063 static void TestName(); \
6064 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6065 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6066 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6067 namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
6068 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6069 static void TestName()
6070 #define INTERNAL_CATCH_TESTCASE( ... ) \
6071 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ )
6072
6073#else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
6074
6075
6076// Dummy registrator for the dumy test case macros
6077namespace Catch {
6078 namespace Detail {
6079 struct DummyUse {
6080 DummyUse( void ( * )( int ), Catch::NameAndTags const& );
6081 };
6082 } // namespace Detail
6083} // namespace Catch
6084
6085// Note that both the presence of the argument and its exact name are
6086// necessary for the section support.
6087
6088// We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE`
6089// tests can compile. The redefined `TEST_CASE` shadows this with param.
6090static int catchInternalSectionHint = 0;
6091
6092# define INTERNAL_CATCH_TESTCASE2( fname, ... ) \
6093 static void fname( int ); \
6094 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6095 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6096 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6097 static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \
6098 dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } ); \
6099 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
6100 static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
6101 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6102# define INTERNAL_CATCH_TESTCASE( ... ) \
6103 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ )
6104
6105
6106#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
6107
6108 ///////////////////////////////////////////////////////////////////////////////
6109 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
6110 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6111 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6112 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6113 namespace{ \
6114 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
6115 void test(); \
6116 }; \
6117 const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
6118 Catch::makeTestInvoker( &TestName::test ), \
6119 CATCH_INTERNAL_LINEINFO, \
6120 #ClassName##_catch_sr, \
6121 Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
6122 } \
6123 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6124 void TestName::test()
6125 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
6126 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
6127
6128 ///////////////////////////////////////////////////////////////////////////////
6129 #define INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE2( TestName, ClassName, ... ) \
6130 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6131 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6132 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6133 namespace { \
6134 struct TestName : INTERNAL_CATCH_REMOVE_PARENS( ClassName ) { \
6135 void test() const; \
6136 }; \
6137 const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
6138 Catch::makeTestInvokerFixture( &TestName::test ), \
6139 CATCH_INTERNAL_LINEINFO, \
6140 #ClassName##_catch_sr, \
6141 Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
6142 } \
6143 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6144 void TestName::test() const
6145 #define INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( ClassName, ... ) \
6146 INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
6147
6148
6149 ///////////////////////////////////////////////////////////////////////////////
6150 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
6151 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6152 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6153 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6154 namespace { \
6155 const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
6156 Catch::makeTestInvoker( &QualifiedMethod ), \
6157 CATCH_INTERNAL_LINEINFO, \
6158 "&" #QualifiedMethod##_catch_sr, \
6159 Catch::NameAndTags{ __VA_ARGS__ } ); \
6160 } /* NOLINT */ \
6161 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6162
6163
6164 ///////////////////////////////////////////////////////////////////////////////
6165 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
6166 do { \
6167 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6168 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6169 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6170 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
6171 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6172 } while(false)
6173
6174
6175#endif // CATCH_TEST_REGISTRY_HPP_INCLUDED
6176
6177
6178// All of our user-facing macros support configuration toggle, that
6179// forces them to be defined prefixed with CATCH_. We also like to
6180// support another toggle that can minimize (disable) their implementation.
6181// Given this, we have 4 different configuration options below
6182
6183#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
6184
6185 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6186 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6187
6188 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6189 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
6190 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6191
6192 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6193 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6194 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6195 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6196 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6197
6198 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6199 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
6200 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6201
6202 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
6203 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
6204 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
6205 #define CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, __VA_ARGS__ )
6206 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
6207 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
6208 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
6209 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6210 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6211 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6212 #define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6213
6214
6215 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
6216 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
6217 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
6218 #define CATCH_STATIC_CHECK( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
6219 #define CATCH_STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
6220 #else
6221 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ )
6222 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
6223 #define CATCH_STATIC_CHECK( ... ) CATCH_CHECK( __VA_ARGS__ )
6224 #define CATCH_STATIC_CHECK_FALSE( ... ) CATCH_CHECK_FALSE( __VA_ARGS__ )
6225 #endif
6226
6227
6228 // "BDD-style" convenience wrappers
6229 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
6230 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
6231 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
6232 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
6233 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
6234 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
6235 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
6236 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
6237
6238#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, implemented | vv prefixed, disabled
6239
6240 #define CATCH_REQUIRE( ... ) (void)(0)
6241 #define CATCH_REQUIRE_FALSE( ... ) (void)(0)
6242
6243 #define CATCH_REQUIRE_THROWS( ... ) (void)(0)
6244 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
6245 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
6246
6247 #define CATCH_CHECK( ... ) (void)(0)
6248 #define CATCH_CHECK_FALSE( ... ) (void)(0)
6249 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
6250 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
6251 #define CATCH_CHECK_NOFAIL( ... ) (void)(0)
6252
6253 #define CATCH_CHECK_THROWS( ... ) (void)(0)
6254 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
6255 #define CATCH_CHECK_NOTHROW( ... ) (void)(0)
6256
6257 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6258 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6259 #define CATCH_METHOD_AS_TEST_CASE( method, ... )
6260 #define CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6261 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
6262 #define CATCH_SECTION( ... )
6263 #define CATCH_DYNAMIC_SECTION( ... )
6264 #define CATCH_FAIL( ... ) (void)(0)
6265 #define CATCH_FAIL_CHECK( ... ) (void)(0)
6266 #define CATCH_SUCCEED( ... ) (void)(0)
6267 #define CATCH_SKIP( ... ) (void)(0)
6268
6269 #define CATCH_STATIC_REQUIRE( ... ) (void)(0)
6270 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
6271 #define CATCH_STATIC_CHECK( ... ) (void)(0)
6272 #define CATCH_STATIC_CHECK_FALSE( ... ) (void)(0)
6273
6274 // "BDD-style" convenience wrappers
6275 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6276 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
6277 #define CATCH_GIVEN( desc )
6278 #define CATCH_AND_GIVEN( desc )
6279 #define CATCH_WHEN( desc )
6280 #define CATCH_AND_WHEN( desc )
6281 #define CATCH_THEN( desc )
6282 #define CATCH_AND_THEN( desc )
6283
6284#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, disabled | vv unprefixed, implemented
6285
6286 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6287 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6288
6289 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6290 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
6291 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6292
6293 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6294 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6295 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6296 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6297 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6298
6299 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6300 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
6301 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6302
6303 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
6304 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
6305 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
6306 #define TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TEST_CASE_PERSISTENT_FIXTURE( className, __VA_ARGS__ )
6307 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
6308 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
6309 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
6310 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6311 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6312 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6313 #define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6314
6315
6316 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
6317 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
6318 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
6319 #define STATIC_CHECK( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
6320 #define STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
6321 #else
6322 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ )
6323 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
6324 #define STATIC_CHECK( ... ) CHECK( __VA_ARGS__ )
6325 #define STATIC_CHECK_FALSE( ... ) CHECK_FALSE( __VA_ARGS__ )
6326 #endif
6327
6328 // "BDD-style" convenience wrappers
6329 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
6330 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
6331 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
6332 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
6333 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
6334 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
6335 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
6336 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
6337
6338#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ unprefixed, implemented | vv unprefixed, disabled
6339
6340 #define REQUIRE( ... ) (void)(0)
6341 #define REQUIRE_FALSE( ... ) (void)(0)
6342
6343 #define REQUIRE_THROWS( ... ) (void)(0)
6344 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
6345 #define REQUIRE_NOTHROW( ... ) (void)(0)
6346
6347 #define CHECK( ... ) (void)(0)
6348 #define CHECK_FALSE( ... ) (void)(0)
6349 #define CHECKED_IF( ... ) if (__VA_ARGS__)
6350 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
6351 #define CHECK_NOFAIL( ... ) (void)(0)
6352
6353 #define CHECK_THROWS( ... ) (void)(0)
6354 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
6355 #define CHECK_NOTHROW( ... ) (void)(0)
6356
6357 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
6358 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6359 #define METHOD_AS_TEST_CASE( method, ... )
6360 #define TEST_CASE_PERSISTENT_FIXTURE( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
6361 #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
6362 #define SECTION( ... )
6363 #define DYNAMIC_SECTION( ... )
6364 #define FAIL( ... ) (void)(0)
6365 #define FAIL_CHECK( ... ) (void)(0)
6366 #define SUCCEED( ... ) (void)(0)
6367 #define SKIP( ... ) (void)(0)
6368
6369 #define STATIC_REQUIRE( ... ) (void)(0)
6370 #define STATIC_REQUIRE_FALSE( ... ) (void)(0)
6371 #define STATIC_CHECK( ... ) (void)(0)
6372 #define STATIC_CHECK_FALSE( ... ) (void)(0)
6373
6374 // "BDD-style" convenience wrappers
6375 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ) )
6376 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
6377
6378 #define GIVEN( desc )
6379 #define AND_GIVEN( desc )
6380 #define WHEN( desc )
6381 #define AND_WHEN( desc )
6382 #define THEN( desc )
6383 #define AND_THEN( desc )
6384
6385#endif // ^^ unprefixed, disabled
6386
6387// end of user facing macros
6388
6389#endif // CATCH_TEST_MACROS_HPP_INCLUDED
6390
6391
6392#ifndef CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
6393#define CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
6394
6395
6396
6397#ifndef CATCH_PREPROCESSOR_HPP_INCLUDED
6398#define CATCH_PREPROCESSOR_HPP_INCLUDED
6399
6400
6401#if defined(__GNUC__)
6402// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work
6403#pragma GCC system_header
6404#endif
6405
6406
6407#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
6408#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
6409#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
6410#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
6411#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
6412#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
6413
6414#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6415#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
6416// MSVC needs more evaluations
6417#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
6418#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
6419#else
6420#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
6421#endif
6422
6423#define CATCH_REC_END(...)
6424#define CATCH_REC_OUT
6425
6426#define CATCH_EMPTY()
6427#define CATCH_DEFER(id) id CATCH_EMPTY()
6428
6429#define CATCH_REC_GET_END2() 0, CATCH_REC_END
6430#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
6431#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
6432#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
6433#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
6434#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
6435
6436#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
6437#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
6438#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
6439
6440#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
6441#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
6442#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
6443
6444// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
6445// and passes userdata as the first parameter to each invocation,
6446// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
6447#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
6448
6449#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
6450
6451#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
6452#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6453#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
6454#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
6455#else
6456// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
6457#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
6458#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
6459#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
6460#endif
6461
6462#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
6463#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
6464
6465#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6466#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
6467#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
6468#else
6469#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
6470#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
6471#endif
6472
6473#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
6474 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
6475
6476#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
6477#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
6478#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
6479#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)
6480#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)
6481#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)
6482#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6)
6483#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7)
6484#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8)
6485#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)
6486#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)
6487
6488#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
6489
6490#define INTERNAL_CATCH_TYPE_GEN\
6491 template<typename...> struct TypeList {};\
6492 template<typename...Ts>\
6493 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
6494 template<template<typename...> class...> struct TemplateTypeList{};\
6495 template<template<typename...> class...Cs>\
6496 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
6497 template<typename...>\
6498 struct append;\
6499 template<typename...>\
6500 struct rewrap;\
6501 template<template<typename...> class, typename...>\
6502 struct create;\
6503 template<template<typename...> class, typename>\
6504 struct convert;\
6505 \
6506 template<typename T> \
6507 struct append<T> { using type = T; };\
6508 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
6509 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
6510 template< template<typename...> class L1, typename...E1, typename...Rest>\
6511 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
6512 \
6513 template< template<typename...> class Container, template<typename...> class List, typename...elems>\
6514 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
6515 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
6516 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
6517 \
6518 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
6519 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
6520 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
6521 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
6522
6523#define INTERNAL_CATCH_NTTP_1(signature, ...)\
6524 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
6525 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6526 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
6527 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
6528 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
6529 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
6530 \
6531 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6532 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
6533 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
6534 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
6535 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
6536 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
6537
6538#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
6539#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
6540 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6541 static void TestName()
6542#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
6543 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6544 static void TestName()
6545
6546#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
6547#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
6548 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6549 static void TestName()
6550#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
6551 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6552 static void TestName()
6553
6554#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
6555 template<typename Type>\
6556 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
6557 {\
6558 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
6559 }
6560
6561#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
6562 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6563 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
6564 {\
6565 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
6566 }
6567
6568#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
6569 template<typename Type>\
6570 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
6571 {\
6572 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
6573 }
6574
6575#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
6576 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6577 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
6578 {\
6579 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
6580 }
6581
6582#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
6583#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
6584 template<typename TestType> \
6585 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
6586 void test();\
6587 }
6588
6589#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
6590 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
6591 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
6592 void test();\
6593 }
6594
6595#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
6596#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
6597 template<typename TestType> \
6598 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
6599#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
6600 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
6601 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
6602
6603#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6604#define INTERNAL_CATCH_NTTP_0
6605#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0)
6606#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)
6607#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)
6608#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)
6609#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)
6610#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)
6611#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)
6612#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)
6613#else
6614#define INTERNAL_CATCH_NTTP_0(signature)
6615#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__))
6616#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
6617#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
6618#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
6619#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
6620#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
6621#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
6622#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
6623#endif
6624
6625#endif // CATCH_PREPROCESSOR_HPP_INCLUDED
6626
6627
6628// GCC 5 and older do not properly handle disabling unused-variable warning
6629// with a _Pragma. This means that we have to leak the suppression to the
6630// user code as well :-(
6631#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
6632#pragma GCC diagnostic ignored "-Wunused-variable"
6633#endif
6634
6635#if defined(CATCH_CONFIG_DISABLE)
6636 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \
6637 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
6638 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
6639 namespace{ \
6640 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
6641 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
6642 } \
6643 } \
6644 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
6645
6646 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6647 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
6648 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ )
6649 #else
6650 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
6651 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
6652 #endif
6653
6654 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6655 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
6656 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ )
6657 #else
6658 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
6659 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
6660 #endif
6661
6662 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6663 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
6664 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
6665 #else
6666 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
6667 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
6668 #endif
6669
6670 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6671 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
6672 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
6673 #else
6674 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
6675 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
6676 #endif
6677#endif
6678
6679
6680 ///////////////////////////////////////////////////////////////////////////////
6681 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
6682 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6683 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6684 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6685 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6686 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6687 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6688 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
6689 namespace {\
6690 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
6691 INTERNAL_CATCH_TYPE_GEN\
6692 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6693 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6694 template<typename...Types> \
6695 struct TestName{\
6696 TestName(){\
6697 size_t index = 0; \
6698 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
6699 using expander = size_t[]; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
6700 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
6701 }\
6702 };\
6703 static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6704 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
6705 return 0;\
6706 }();\
6707 }\
6708 }\
6709 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6710 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
6711
6712#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6713 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
6714 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ )
6715#else
6716 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
6717 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
6718#endif
6719
6720#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6721 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
6722 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ )
6723#else
6724 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
6725 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
6726#endif
6727
6728 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
6729 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6730 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6731 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6732 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6733 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6734 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6735 template<typename TestType> static void TestFuncName(); \
6736 namespace {\
6737 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
6738 INTERNAL_CATCH_TYPE_GEN \
6739 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
6740 template<typename... Types> \
6741 struct TestName { \
6742 void reg_tests() { \
6743 size_t index = 0; \
6744 using expander = size_t[]; \
6745 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
6746 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
6747 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
6748 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + std::string(types_list[index % num_types]) + '>', Tags } ), index++)... };/* NOLINT */\
6749 } \
6750 }; \
6751 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
6752 using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
6753 TestInit t; \
6754 t.reg_tests(); \
6755 return 0; \
6756 }(); \
6757 } \
6758 } \
6759 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6760 template<typename TestType> \
6761 static void TestFuncName()
6762
6763#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6764 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
6765 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T,__VA_ARGS__)
6766#else
6767 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
6768 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, typename T, __VA_ARGS__ ) )
6769#endif
6770
6771#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6772 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
6773 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__)
6774#else
6775 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
6776 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, Signature, __VA_ARGS__ ) )
6777#endif
6778
6779 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
6780 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6781 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6782 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6783 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6784 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6785 template<typename TestType> static void TestFunc(); \
6786 namespace {\
6787 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
6788 INTERNAL_CATCH_TYPE_GEN\
6789 template<typename... Types> \
6790 struct TestName { \
6791 void reg_tests() { \
6792 size_t index = 0; \
6793 using expander = size_t[]; \
6794 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
6795 } \
6796 };\
6797 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
6798 using TestInit = typename convert<TestName, TmplList>::type; \
6799 TestInit t; \
6800 t.reg_tests(); \
6801 return 0; \
6802 }(); \
6803 }}\
6804 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6805 template<typename TestType> \
6806 static void TestFunc()
6807
6808 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
6809 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), Name, Tags, TmplList )
6810
6811
6812 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
6813 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6814 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6815 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6816 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6817 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6818 namespace {\
6819 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
6820 INTERNAL_CATCH_TYPE_GEN\
6821 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6822 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
6823 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6824 template<typename...Types> \
6825 struct TestNameClass{\
6826 TestNameClass(){\
6827 size_t index = 0; \
6828 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
6829 using expander = size_t[];\
6830 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
6831 }\
6832 };\
6833 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6834 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
6835 return 0;\
6836 }();\
6837 }\
6838 }\
6839 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6840 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
6841
6842#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6843 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
6844 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
6845#else
6846 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
6847 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
6848#endif
6849
6850#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6851 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
6852 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
6853#else
6854 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
6855 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_CLASS_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
6856#endif
6857
6858 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
6859 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6860 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6861 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6862 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6863 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6864 template<typename TestType> \
6865 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
6866 void test();\
6867 };\
6868 namespace {\
6869 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
6870 INTERNAL_CATCH_TYPE_GEN \
6871 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6872 template<typename...Types>\
6873 struct TestNameClass{\
6874 void reg_tests(){\
6875 std::size_t index = 0;\
6876 using expander = std::size_t[];\
6877 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
6878 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
6879 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
6880 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + '<' + std::string(types_list[index % num_types]) + '>', Tags } ), index++)... };/* NOLINT */ \
6881 }\
6882 };\
6883 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6884 using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
6885 TestInit t;\
6886 t.reg_tests();\
6887 return 0;\
6888 }(); \
6889 }\
6890 }\
6891 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6892 template<typename TestType> \
6893 void TestName<TestType>::test()
6894
6895#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6896 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
6897 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
6898#else
6899 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
6900 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
6901#endif
6902
6903#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6904 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
6905 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
6906#else
6907 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
6908 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
6909#endif
6910
6911 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
6912 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6913 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6914 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6915 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6916 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6917 template<typename TestType> \
6918 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
6919 void test();\
6920 };\
6921 namespace {\
6922 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
6923 INTERNAL_CATCH_TYPE_GEN\
6924 template<typename...Types>\
6925 struct TestNameClass{\
6926 void reg_tests(){\
6927 size_t index = 0;\
6928 using expander = size_t[];\
6929 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName##_catch_sr, Catch::NameAndTags{ Name " - " INTERNAL_CATCH_STRINGIZE(TmplList) " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
6930 }\
6931 };\
6932 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6933 using TestInit = typename convert<TestNameClass, TmplList>::type;\
6934 TestInit t;\
6935 t.reg_tests();\
6936 return 0;\
6937 }(); \
6938 }}\
6939 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6940 template<typename TestType> \
6941 void TestName<TestType>::test()
6942
6943#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
6944 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEMPLATE_TEST_ ), ClassName, Name, Tags, TmplList )
6945
6946
6947#endif // CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
6948
6949
6950#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
6951
6952 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6953 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
6954 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
6955 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6956 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
6957 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
6958 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
6959 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
6960 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
6961 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
6962 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
6963 #else
6964 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
6965 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
6966 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6967 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
6968 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
6969 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
6970 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6971 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
6972 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
6973 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6974 #endif
6975
6976#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
6977
6978 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6979 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
6980 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
6981 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
6982 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
6983 #else
6984 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
6985 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
6986 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
6987 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
6988 #endif
6989
6990 // When disabled, these can be shared between proper preprocessor and MSVC preprocessor
6991 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
6992 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
6993 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6994 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6995 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
6996 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6997
6998#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
6999
7000 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
7001 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
7002 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
7003 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
7004 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
7005 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
7006 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
7007 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
7008 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
7009 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
7010 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
7011 #else
7012 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
7013 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
7014 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
7015 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
7016 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
7017 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
7018 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
7019 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
7020 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
7021 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
7022 #endif
7023
7024#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
7025
7026 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
7027 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
7028 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
7029 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
7030 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
7031 #else
7032 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
7033 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
7034 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
7035 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
7036 #endif
7037
7038 // When disabled, these can be shared between proper preprocessor and MSVC preprocessor
7039 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
7040 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
7041 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
7042 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
7043 #define TEMPLATE_LIST_TEST_CASE( ... ) TEMPLATE_TEST_CASE(__VA_ARGS__)
7044 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
7045
7046#endif // end of user facing macro declarations
7047
7048
7049#endif // CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
7050
7051
7052#ifndef CATCH_TEST_CASE_INFO_HPP_INCLUDED
7053#define CATCH_TEST_CASE_INFO_HPP_INCLUDED
7054
7055
7056
7057#include <cstdint>
7058#include <string>
7059#include <vector>
7060
7061#ifdef __clang__
7062#pragma clang diagnostic push
7063#pragma clang diagnostic ignored "-Wpadded"
7064#endif
7065
7066namespace Catch {
7067
7068 /**
7069 * A **view** of a tag string that provides case insensitive comparisons
7070 *
7071 * Note that in Catch2 internals, the square brackets around tags are
7072 * not a part of tag's representation, so e.g. "[cool-tag]" is represented
7073 * as "cool-tag" internally.
7074 */
7075 struct Tag {
7076 constexpr Tag(StringRef original_):
7077 original(original_)
7078 {}
7079 StringRef original;
7080
7081 friend bool operator< ( Tag const& lhs, Tag const& rhs );
7082 friend bool operator==( Tag const& lhs, Tag const& rhs );
7083 };
7084
7085 class ITestInvoker;
7086 struct NameAndTags;
7087
7088 enum class TestCaseProperties : uint8_t {
7089 None = 0,
7090 IsHidden = 1 << 1,
7091 ShouldFail = 1 << 2,
7092 MayFail = 1 << 3,
7093 Throws = 1 << 4,
7094 NonPortable = 1 << 5,
7095 Benchmark = 1 << 6
7096 };
7097
7098 /**
7099 * Various metadata about the test case.
7100 *
7101 * A test case is uniquely identified by its (class)name and tags
7102 * combination, with source location being ignored, and other properties
7103 * being determined from tags.
7104 *
7105 * Tags are kept sorted.
7106 */
7107 struct TestCaseInfo : Detail::NonCopyable {
7108
7109 TestCaseInfo(StringRef _className,
7110 NameAndTags const& _nameAndTags,
7111 SourceLineInfo const& _lineInfo);
7112
7113 bool isHidden() const;
7114 bool throws() const;
7115 bool okToFail() const;
7116 bool expectedToFail() const;
7117
7118 // Adds the tag(s) with test's filename (for the -# flag)
7119 void addFilenameTag();
7120
7121 //! Orders by name, classname and tags
7122 friend bool operator<( TestCaseInfo const& lhs,
7123 TestCaseInfo const& rhs );
7124
7125
7126 std::string tagsAsString() const;
7127
7128 std::string name;
7129 StringRef className;
7130 private:
7131 std::string backingTags;
7132 // Internally we copy tags to the backing storage and then add
7133 // refs to this storage to the tags vector.
7134 void internalAppendTag(StringRef tagString);
7135 public:
7136 std::vector<Tag> tags;
7137 SourceLineInfo lineInfo;
7138 TestCaseProperties properties = TestCaseProperties::None;
7139 };
7140
7141 /**
7142 * Wrapper over the test case information and the test case invoker
7143 *
7144 * Does not own either, and is specifically made to be cheap
7145 * to copy around.
7146 */
7147 class TestCaseHandle {
7148 TestCaseInfo* m_info;
7149 ITestInvoker* m_invoker;
7150 public:
7151 constexpr TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) :
7152 m_info(info), m_invoker(invoker) {}
7153
7154 void prepareTestCase() const {
7155 m_invoker->prepareTestCase();
7156 }
7157
7158 void tearDownTestCase() const {
7159 m_invoker->tearDownTestCase();
7160 }
7161
7162 void invoke() const {
7163 m_invoker->invoke();
7164 }
7165
7166 constexpr TestCaseInfo const& getTestCaseInfo() const {
7167 return *m_info;
7168 }
7169 };
7170
7171 Detail::unique_ptr<TestCaseInfo>
7172 makeTestCaseInfo( StringRef className,
7173 NameAndTags const& nameAndTags,
7174 SourceLineInfo const& lineInfo );
7175}
7176
7177#ifdef __clang__
7178#pragma clang diagnostic pop
7179#endif
7180
7181#endif // CATCH_TEST_CASE_INFO_HPP_INCLUDED
7182
7183
7184#ifndef CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
7185#define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
7186
7187
7188
7189#ifndef CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
7190#define CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
7191
7192
7193#include <string>
7194#include <vector>
7195
7196namespace Catch {
7197 using exceptionTranslateFunction = std::string(*)();
7198
7199 class IExceptionTranslator;
7200 using ExceptionTranslators = std::vector<Detail::unique_ptr<IExceptionTranslator const>>;
7201
7202 class IExceptionTranslator {
7203 public:
7204 virtual ~IExceptionTranslator(); // = default
7205 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
7206 };
7207
7208 class IExceptionTranslatorRegistry {
7209 public:
7210 virtual ~IExceptionTranslatorRegistry(); // = default
7211 virtual std::string translateActiveException() const = 0;
7212 };
7213
7214} // namespace Catch
7215
7216#endif // CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
7217
7218#include <exception>
7219
7220namespace Catch {
7221 namespace Detail {
7222 void registerTranslatorImpl(
7223 Detail::unique_ptr<IExceptionTranslator>&& translator );
7224 }
7225
7226 class ExceptionTranslatorRegistrar {
7227 template<typename T>
7228 class ExceptionTranslator : public IExceptionTranslator {
7229 public:
7230
7231 constexpr ExceptionTranslator( std::string(*translateFunction)( T const& ) )
7232 : m_translateFunction( translateFunction )
7233 {}
7234
7235 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
7236#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
7237 try {
7238 if( it == itEnd )
7239 std::rethrow_exception(std::current_exception());
7240 else
7241 return (*it)->translate( it+1, itEnd );
7242 }
7243 catch( T const& ex ) {
7244 return m_translateFunction( ex );
7245 }
7246#else
7247 return "You should never get here!";
7248#endif
7249 }
7250
7251 protected:
7252 std::string(*m_translateFunction)( T const& );
7253 };
7254
7255 public:
7256 template<typename T>
7257 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T const& ) ) {
7258 Detail::registerTranslatorImpl(
7259 Detail::make_unique<ExceptionTranslator<T>>(
7260 translateFunction ) );
7261 }
7262 };
7263
7264} // namespace Catch
7265
7266///////////////////////////////////////////////////////////////////////////////
7267#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
7268 static std::string translatorName( signature ); \
7269 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
7270 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
7271 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
7272 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
7273 static std::string translatorName( signature )
7274
7275#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
7276
7277#if defined(CATCH_CONFIG_DISABLE)
7278 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
7279 static std::string translatorName( signature )
7280#endif
7281
7282
7283// This macro is always prefixed
7284#if !defined(CATCH_CONFIG_DISABLE)
7285#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
7286#else
7287#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
7288#endif
7289
7290
7291#endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
7292
7293
7294#ifndef CATCH_VERSION_HPP_INCLUDED
7295#define CATCH_VERSION_HPP_INCLUDED
7296
7297#include <iosfwd>
7298
7299namespace Catch {
7300
7301 // Versioning information
7302 struct Version {
7303 Version( Version const& ) = delete;
7304 Version& operator=( Version const& ) = delete;
7305 Version( unsigned int _majorVersion,
7306 unsigned int _minorVersion,
7307 unsigned int _patchNumber,
7308 char const * const _branchName,
7309 unsigned int _buildNumber );
7310
7311 unsigned int const majorVersion;
7312 unsigned int const minorVersion;
7313 unsigned int const patchNumber;
7314
7315 // buildNumber is only used if branchName is not null
7316 char const * const branchName;
7317 unsigned int const buildNumber;
7318
7319 friend std::ostream& operator << ( std::ostream& os, Version const& version );
7320 };
7321
7322 Version const& libraryVersion();
7323}
7324
7325#endif // CATCH_VERSION_HPP_INCLUDED
7326
7327
7328#ifndef CATCH_VERSION_MACROS_HPP_INCLUDED
7329#define CATCH_VERSION_MACROS_HPP_INCLUDED
7330
7331#define CATCH_VERSION_MAJOR 3
7332#define CATCH_VERSION_MINOR 7
7333#define CATCH_VERSION_PATCH 1
7334
7335#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
7336
7337
7338/** \file
7339 * This is a convenience header for Catch2's Generator support. It includes
7340 * **all** of Catch2 headers related to generators.
7341 *
7342 * Generally the Catch2 users should use specific includes they need,
7343 * but this header can be used instead for ease-of-experimentation, or
7344 * just plain convenience, at the cost of (significantly) increased
7345 * compilation times.
7346 *
7347 * When a new header is added to either the `generators` folder,
7348 * or to the corresponding internal subfolder, it should be added here.
7349 */
7350
7351#ifndef CATCH_GENERATORS_ALL_HPP_INCLUDED
7352#define CATCH_GENERATORS_ALL_HPP_INCLUDED
7353
7354
7355
7356#ifndef CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
7357#define CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
7358
7359#include <exception>
7360
7361namespace Catch {
7362
7363 // Exception type to be thrown when a Generator runs into an error,
7364 // e.g. it cannot initialize the first return value based on
7365 // runtime information
7366 class GeneratorException : public std::exception {
7367 const char* const m_msg = "";
7368
7369 public:
7370 GeneratorException(const char* msg):
7371 m_msg(msg)
7372 {}
7373
7374 const char* what() const noexcept override final;
7375 };
7376
7377} // end namespace Catch
7378
7379#endif // CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
7380
7381
7382#ifndef CATCH_GENERATORS_HPP_INCLUDED
7383#define CATCH_GENERATORS_HPP_INCLUDED
7384
7385
7386
7387#ifndef CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
7388#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
7389
7390
7391#include <string>
7392
7393namespace Catch {
7394
7395 namespace Generators {
7396 class GeneratorUntypedBase {
7397 // Caches result from `toStringImpl`, assume that when it is an
7398 // empty string, the cache is invalidated.
7399 mutable std::string m_stringReprCache;
7400
7401 // Counts based on `next` returning true
7402 std::size_t m_currentElementIndex = 0;
7403
7404 /**
7405 * Attempts to move the generator to the next element
7406 *
7407 * Returns true iff the move succeeded (and a valid element
7408 * can be retrieved).
7409 */
7410 virtual bool next() = 0;
7411
7412 //! Customization point for `currentElementAsString`
7413 virtual std::string stringifyImpl() const = 0;
7414
7415 public:
7416 GeneratorUntypedBase() = default;
7417 // Generation of copy ops is deprecated (and Clang will complain)
7418 // if there is a user destructor defined
7419 GeneratorUntypedBase(GeneratorUntypedBase const&) = default;
7420 GeneratorUntypedBase& operator=(GeneratorUntypedBase const&) = default;
7421
7422 virtual ~GeneratorUntypedBase(); // = default;
7423
7424 /**
7425 * Attempts to move the generator to the next element
7426 *
7427 * Serves as a non-virtual interface to `next`, so that the
7428 * top level interface can provide sanity checking and shared
7429 * features.
7430 *
7431 * As with `next`, returns true iff the move succeeded and
7432 * the generator has new valid element to provide.
7433 */
7434 bool countedNext();
7435
7436 std::size_t currentElementIndex() const { return m_currentElementIndex; }
7437
7438 /**
7439 * Returns generator's current element as user-friendly string.
7440 *
7441 * By default returns string equivalent to calling
7442 * `Catch::Detail::stringify` on the current element, but generators
7443 * can customize their implementation as needed.
7444 *
7445 * Not thread-safe due to internal caching.
7446 *
7447 * The returned ref is valid only until the generator instance
7448 * is destructed, or it moves onto the next element, whichever
7449 * comes first.
7450 */
7451 StringRef currentElementAsString() const;
7452 };
7453 using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
7454
7455 } // namespace Generators
7456
7457 class IGeneratorTracker {
7458 public:
7459 virtual ~IGeneratorTracker(); // = default;
7460 virtual auto hasGenerator() const -> bool = 0;
7461 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
7462 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
7463 };
7464
7465} // namespace Catch
7466
7467#endif // CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
7468
7469#include <vector>
7470#include <tuple>
7471
7472namespace Catch {
7473
7474namespace Generators {
7475
7476namespace Detail {
7477
7478 //! Throws GeneratorException with the provided message
7479 [[noreturn]]
7480 void throw_generator_exception(char const * msg);
7481
7482} // end namespace detail
7483
7484 template<typename T>
7485 class IGenerator : public GeneratorUntypedBase {
7486 std::string stringifyImpl() const override {
7487 return ::Catch::Detail::stringify( get() );
7488 }
7489
7490 public:
7491 // Returns the current element of the generator
7492 //
7493 // \Precondition The generator is either freshly constructed,
7494 // or the last call to `next()` returned true
7495 virtual T const& get() const = 0;
7496 using type = T;
7497 };
7498
7499 template <typename T>
7500 using GeneratorPtr = Catch::Detail::unique_ptr<IGenerator<T>>;
7501
7502 template <typename T>
7503 class GeneratorWrapper final {
7504 GeneratorPtr<T> m_generator;
7505 public:
7506 //! Takes ownership of the passed pointer.
7507 GeneratorWrapper(IGenerator<T>* generator):
7508 m_generator(generator) {}
7509 GeneratorWrapper(GeneratorPtr<T> generator):
7510 m_generator(CATCH_MOVE(generator)) {}
7511
7512 T const& get() const {
7513 return m_generator->get();
7514 }
7515 bool next() {
7516 return m_generator->countedNext();
7517 }
7518 };
7519
7520
7521 template<typename T>
7522 class SingleValueGenerator final : public IGenerator<T> {
7523 T m_value;
7524 public:
7525 SingleValueGenerator(T const& value) :
7526 m_value(value)
7527 {}
7528 SingleValueGenerator(T&& value):
7529 m_value(CATCH_MOVE(value))
7530 {}
7531
7532 T const& get() const override {
7533 return m_value;
7534 }
7535 bool next() override {
7536 return false;
7537 }
7538 };
7539
7540 template<typename T>
7541 class FixedValuesGenerator final : public IGenerator<T> {
7542 static_assert(!std::is_same<T, bool>::value,
7543 "FixedValuesGenerator does not support bools because of std::vector<bool>"
7544 "specialization, use SingleValue Generator instead.");
7545 std::vector<T> m_values;
7546 size_t m_idx = 0;
7547 public:
7548 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
7549
7550 T const& get() const override {
7551 return m_values[m_idx];
7552 }
7553 bool next() override {
7554 ++m_idx;
7555 return m_idx < m_values.size();
7556 }
7557 };
7558
7559 template <typename T, typename DecayedT = std::decay_t<T>>
7560 GeneratorWrapper<DecayedT> value( T&& value ) {
7561 return GeneratorWrapper<DecayedT>(
7562 Catch::Detail::make_unique<SingleValueGenerator<DecayedT>>(
7563 CATCH_FORWARD( value ) ) );
7564 }
7565 template <typename T>
7566 GeneratorWrapper<T> values(std::initializer_list<T> values) {
7567 return GeneratorWrapper<T>(Catch::Detail::make_unique<FixedValuesGenerator<T>>(values));
7568 }
7569
7570 template<typename T>
7571 class Generators : public IGenerator<T> {
7572 std::vector<GeneratorWrapper<T>> m_generators;
7573 size_t m_current = 0;
7574
7575 void add_generator( GeneratorWrapper<T>&& generator ) {
7576 m_generators.emplace_back( CATCH_MOVE( generator ) );
7577 }
7578 void add_generator( T const& val ) {
7579 m_generators.emplace_back( value( val ) );
7580 }
7581 void add_generator( T&& val ) {
7582 m_generators.emplace_back( value( CATCH_MOVE( val ) ) );
7583 }
7584 template <typename U>
7585 std::enable_if_t<!std::is_same<std::decay_t<U>, T>::value>
7586 add_generator( U&& val ) {
7587 add_generator( T( CATCH_FORWARD( val ) ) );
7588 }
7589
7590 template <typename U> void add_generators( U&& valueOrGenerator ) {
7591 add_generator( CATCH_FORWARD( valueOrGenerator ) );
7592 }
7593
7594 template <typename U, typename... Gs>
7595 void add_generators( U&& valueOrGenerator, Gs&&... moreGenerators ) {
7596 add_generator( CATCH_FORWARD( valueOrGenerator ) );
7597 add_generators( CATCH_FORWARD( moreGenerators )... );
7598 }
7599
7600 public:
7601 template <typename... Gs>
7602 Generators(Gs &&... moreGenerators) {
7603 m_generators.reserve(sizeof...(Gs));
7604 add_generators(CATCH_FORWARD(moreGenerators)...);
7605 }
7606
7607 T const& get() const override {
7608 return m_generators[m_current].get();
7609 }
7610
7611 bool next() override {
7612 if (m_current >= m_generators.size()) {
7613 return false;
7614 }
7615 const bool current_status = m_generators[m_current].next();
7616 if (!current_status) {
7617 ++m_current;
7618 }
7619 return m_current < m_generators.size();
7620 }
7621 };
7622
7623
7624 template <typename... Ts>
7625 GeneratorWrapper<std::tuple<std::decay_t<Ts>...>>
7626 table( std::initializer_list<std::tuple<std::decay_t<Ts>...>> tuples ) {
7627 return values<std::tuple<Ts...>>( tuples );
7628 }
7629
7630 // Tag type to signal that a generator sequence should convert arguments to a specific type
7631 template <typename T>
7632 struct as {};
7633
7634 template<typename T, typename... Gs>
7635 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
7636 return Generators<T>(CATCH_MOVE(generator), CATCH_FORWARD(moreGenerators)...);
7637 }
7638 template<typename T>
7639 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
7640 return Generators<T>(CATCH_MOVE(generator));
7641 }
7642 template<typename T, typename... Gs>
7643 auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<std::decay_t<T>> {
7644 return makeGenerators( value( CATCH_FORWARD( val ) ), CATCH_FORWARD( moreGenerators )... );
7645 }
7646 template<typename T, typename U, typename... Gs>
7647 auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
7648 return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... );
7649 }
7650
7651 IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName,
7652 SourceLineInfo const& lineInfo );
7653 IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
7654 SourceLineInfo lineInfo,
7655 GeneratorBasePtr&& generator );
7656
7657 template<typename L>
7658 auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
7659 using UnderlyingType = typename decltype(generatorExpression())::type;
7660
7661 IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo );
7662 // Creation of tracker is delayed after generator creation, so
7663 // that constructing generator can fail without breaking everything.
7664 if (!tracker) {
7665 tracker = createGeneratorTracker(
7666 generatorName,
7667 lineInfo,
7668 Catch::Detail::make_unique<Generators<UnderlyingType>>(
7669 generatorExpression() ) );
7670 }
7671
7672 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker->getGenerator() );
7673 return generator.get();
7674 }
7675
7676} // namespace Generators
7677} // namespace Catch
7678
7679#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
7680#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
7681
7682#define GENERATE( ... ) \
7683 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
7684 CATCH_INTERNAL_LINEINFO, \
7685 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
7686#define GENERATE_COPY( ... ) \
7687 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
7688 CATCH_INTERNAL_LINEINFO, \
7689 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
7690#define GENERATE_REF( ... ) \
7691 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
7692 CATCH_INTERNAL_LINEINFO, \
7693 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
7694
7695#endif // CATCH_GENERATORS_HPP_INCLUDED
7696
7697
7698#ifndef CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
7699#define CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
7700
7701
7702#include <cassert>
7703
7704namespace Catch {
7705namespace Generators {
7706
7707 template <typename T>
7708 class TakeGenerator final : public IGenerator<T> {
7709 GeneratorWrapper<T> m_generator;
7710 size_t m_returned = 0;
7711 size_t m_target;
7712 public:
7713 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
7714 m_generator(CATCH_MOVE(generator)),
7715 m_target(target)
7716 {
7717 assert(target != 0 && "Empty generators are not allowed");
7718 }
7719 T const& get() const override {
7720 return m_generator.get();
7721 }
7722 bool next() override {
7723 ++m_returned;
7724 if (m_returned >= m_target) {
7725 return false;
7726 }
7727
7728 const auto success = m_generator.next();
7729 // If the underlying generator does not contain enough values
7730 // then we cut short as well
7731 if (!success) {
7732 m_returned = m_target;
7733 }
7734 return success;
7735 }
7736 };
7737
7738 template <typename T>
7739 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
7740 return GeneratorWrapper<T>(Catch::Detail::make_unique<TakeGenerator<T>>(target, CATCH_MOVE(generator)));
7741 }
7742
7743
7744 template <typename T, typename Predicate>
7745 class FilterGenerator final : public IGenerator<T> {
7746 GeneratorWrapper<T> m_generator;
7747 Predicate m_predicate;
7748 public:
7749 template <typename P = Predicate>
7750 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
7751 m_generator(CATCH_MOVE(generator)),
7752 m_predicate(CATCH_FORWARD(pred))
7753 {
7754 if (!m_predicate(m_generator.get())) {
7755 // It might happen that there are no values that pass the
7756 // filter. In that case we throw an exception.
7757 auto has_initial_value = next();
7758 if (!has_initial_value) {
7759 Detail::throw_generator_exception("No valid value found in filtered generator");
7760 }
7761 }
7762 }
7763
7764 T const& get() const override {
7765 return m_generator.get();
7766 }
7767
7768 bool next() override {
7769 bool success = m_generator.next();
7770 if (!success) {
7771 return false;
7772 }
7773 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
7774 return success;
7775 }
7776 };
7777
7778
7779 template <typename T, typename Predicate>
7780 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
7781 return GeneratorWrapper<T>(Catch::Detail::make_unique<FilterGenerator<T, Predicate>>(CATCH_FORWARD(pred), CATCH_MOVE(generator)));
7782 }
7783
7784 template <typename T>
7785 class RepeatGenerator final : public IGenerator<T> {
7786 static_assert(!std::is_same<T, bool>::value,
7787 "RepeatGenerator currently does not support bools"
7788 "because of std::vector<bool> specialization");
7789 GeneratorWrapper<T> m_generator;
7790 mutable std::vector<T> m_returned;
7791 size_t m_target_repeats;
7792 size_t m_current_repeat = 0;
7793 size_t m_repeat_index = 0;
7794 public:
7795 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
7796 m_generator(CATCH_MOVE(generator)),
7797 m_target_repeats(repeats)
7798 {
7799 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
7800 }
7801
7802 T const& get() const override {
7803 if (m_current_repeat == 0) {
7804 m_returned.push_back(m_generator.get());
7805 return m_returned.back();
7806 }
7807 return m_returned[m_repeat_index];
7808 }
7809
7810 bool next() override {
7811 // There are 2 basic cases:
7812 // 1) We are still reading the generator
7813 // 2) We are reading our own cache
7814
7815 // In the first case, we need to poke the underlying generator.
7816 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
7817 if (m_current_repeat == 0) {
7818 const auto success = m_generator.next();
7819 if (!success) {
7820 ++m_current_repeat;
7821 }
7822 return m_current_repeat < m_target_repeats;
7823 }
7824
7825 // In the second case, we need to move indices forward and check that we haven't run up against the end
7826 ++m_repeat_index;
7827 if (m_repeat_index == m_returned.size()) {
7828 m_repeat_index = 0;
7829 ++m_current_repeat;
7830 }
7831 return m_current_repeat < m_target_repeats;
7832 }
7833 };
7834
7835 template <typename T>
7836 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
7837 return GeneratorWrapper<T>(Catch::Detail::make_unique<RepeatGenerator<T>>(repeats, CATCH_MOVE(generator)));
7838 }
7839
7840 template <typename T, typename U, typename Func>
7841 class MapGenerator final : public IGenerator<T> {
7842 // TBD: provide static assert for mapping function, for friendly error message
7843 GeneratorWrapper<U> m_generator;
7844 Func m_function;
7845 // To avoid returning dangling reference, we have to save the values
7846 T m_cache;
7847 public:
7848 template <typename F2 = Func>
7849 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
7850 m_generator(CATCH_MOVE(generator)),
7851 m_function(CATCH_FORWARD(function)),
7852 m_cache(m_function(m_generator.get()))
7853 {}
7854
7855 T const& get() const override {
7856 return m_cache;
7857 }
7858 bool next() override {
7859 const auto success = m_generator.next();
7860 if (success) {
7861 m_cache = m_function(m_generator.get());
7862 }
7863 return success;
7864 }
7865 };
7866
7867 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
7868 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
7869 return GeneratorWrapper<T>(
7870 Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
7871 );
7872 }
7873
7874 template <typename T, typename U, typename Func>
7875 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
7876 return GeneratorWrapper<T>(
7877 Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
7878 );
7879 }
7880
7881 template <typename T>
7882 class ChunkGenerator final : public IGenerator<std::vector<T>> {
7883 std::vector<T> m_chunk;
7884 size_t m_chunk_size;
7885 GeneratorWrapper<T> m_generator;
7886 bool m_used_up = false;
7887 public:
7888 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
7889 m_chunk_size(size), m_generator(CATCH_MOVE(generator))
7890 {
7891 m_chunk.reserve(m_chunk_size);
7892 if (m_chunk_size != 0) {
7893 m_chunk.push_back(m_generator.get());
7894 for (size_t i = 1; i < m_chunk_size; ++i) {
7895 if (!m_generator.next()) {
7896 Detail::throw_generator_exception("Not enough values to initialize the first chunk");
7897 }
7898 m_chunk.push_back(m_generator.get());
7899 }
7900 }
7901 }
7902 std::vector<T> const& get() const override {
7903 return m_chunk;
7904 }
7905 bool next() override {
7906 m_chunk.clear();
7907 for (size_t idx = 0; idx < m_chunk_size; ++idx) {
7908 if (!m_generator.next()) {
7909 return false;
7910 }
7911 m_chunk.push_back(m_generator.get());
7912 }
7913 return true;
7914 }
7915 };
7916
7917 template <typename T>
7918 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
7919 return GeneratorWrapper<std::vector<T>>(
7920 Catch::Detail::make_unique<ChunkGenerator<T>>(size, CATCH_MOVE(generator))
7921 );
7922 }
7923
7924} // namespace Generators
7925} // namespace Catch
7926
7927
7928#endif // CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
7929
7930
7931#ifndef CATCH_GENERATORS_RANDOM_HPP_INCLUDED
7932#define CATCH_GENERATORS_RANDOM_HPP_INCLUDED
7933
7934
7935
7936#ifndef CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
7937#define CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
7938
7939#include <cstdint>
7940
7941namespace Catch {
7942
7943 // This is a simple implementation of C++11 Uniform Random Number
7944 // Generator. It does not provide all operators, because Catch2
7945 // does not use it, but it should behave as expected inside stdlib's
7946 // distributions.
7947 // The implementation is based on the PCG family (http://pcg-random.org)
7948 class SimplePcg32 {
7949 using state_type = std::uint64_t;
7950 public:
7951 using result_type = std::uint32_t;
7952 static constexpr result_type (min)() {
7953 return 0;
7954 }
7955 static constexpr result_type (max)() {
7956 return static_cast<result_type>(-1);
7957 }
7958
7959 // Provide some default initial state for the default constructor
7960 SimplePcg32():SimplePcg32(0xed743cc4U) {}
7961
7962 explicit SimplePcg32(result_type seed_);
7963
7964 void seed(result_type seed_);
7965 void discard(uint64_t skip);
7966
7967 result_type operator()();
7968
7969 private:
7970 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
7971 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
7972
7973 // In theory we also need operator<< and operator>>
7974 // In practice we do not use them, so we will skip them for now
7975
7976
7977 std::uint64_t m_state;
7978 // This part of the state determines which "stream" of the numbers
7979 // is chosen -- we take it as a constant for Catch2, so we only
7980 // need to deal with seeding the main state.
7981 // Picked by reading 8 bytes from `/dev/random` :-)
7982 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
7983 };
7984
7985} // end namespace Catch
7986
7987#endif // CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
7988
7989
7990
7991#ifndef CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
7992#define CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
7993
7994
7995
7996
7997#ifndef CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
7998#define CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
7999
8000#include <climits>
8001#include <cstddef>
8002#include <cstdint>
8003#include <type_traits>
8004
8005// Note: We use the usual enable-disable-autodetect dance here even though
8006// we do not support these in CMake configuration options (yet?).
8007// It is highly unlikely that we will need to make these actually
8008// user-configurable, but this will make it simpler if weend up needing
8009// it, and it provides an escape hatch to the users who need it.
8010#if defined( __SIZEOF_INT128__ )
8011# define CATCH_CONFIG_INTERNAL_UINT128
8012// Unlike GCC, MSVC does not polyfill umul as mulh + mul pair on ARM machines.
8013// Currently we do not bother doing this ourselves, but we could if it became
8014// important for perf.
8015#elif defined( _MSC_VER ) && defined( _M_X64 )
8016# define CATCH_CONFIG_INTERNAL_MSVC_UMUL128
8017#endif
8018
8019#if defined( CATCH_CONFIG_INTERNAL_UINT128 ) && \
8020 !defined( CATCH_CONFIG_NO_UINT128 ) && \
8021 !defined( CATCH_CONFIG_UINT128 )
8022#define CATCH_CONFIG_UINT128
8023#endif
8024
8025#if defined( CATCH_CONFIG_INTERNAL_MSVC_UMUL128 ) && \
8026 !defined( CATCH_CONFIG_NO_MSVC_UMUL128 ) && \
8027 !defined( CATCH_CONFIG_MSVC_UMUL128 )
8028# define CATCH_CONFIG_MSVC_UMUL128
8029# include <intrin.h>
8030#endif
8031
8032
8033namespace Catch {
8034 namespace Detail {
8035
8036 template <std::size_t>
8037 struct SizedUnsignedType;
8038#define SizedUnsignedTypeHelper( TYPE ) \
8039 template <> \
8040 struct SizedUnsignedType<sizeof( TYPE )> { \
8041 using type = TYPE; \
8042 }
8043
8044 SizedUnsignedTypeHelper( std::uint8_t );
8045 SizedUnsignedTypeHelper( std::uint16_t );
8046 SizedUnsignedTypeHelper( std::uint32_t );
8047 SizedUnsignedTypeHelper( std::uint64_t );
8048#undef SizedUnsignedTypeHelper
8049
8050 template <std::size_t sz>
8051 using SizedUnsignedType_t = typename SizedUnsignedType<sz>::type;
8052
8053 template <typename T>
8054 using DoubleWidthUnsignedType_t = SizedUnsignedType_t<2 * sizeof( T )>;
8055
8056 template <typename T>
8057 struct ExtendedMultResult {
8058 T upper;
8059 T lower;
8060 constexpr bool operator==( ExtendedMultResult const& rhs ) const {
8061 return upper == rhs.upper && lower == rhs.lower;
8062 }
8063 };
8064
8065 /**
8066 * Returns 128 bit result of lhs * rhs using portable C++ code
8067 *
8068 * This implementation is almost twice as fast as naive long multiplication,
8069 * and unlike intrinsic-based approach, it supports constexpr evaluation.
8070 */
8071 constexpr ExtendedMultResult<std::uint64_t>
8072 extendedMultPortable(std::uint64_t lhs, std::uint64_t rhs) {
8073#define CarryBits( x ) ( x >> 32 )
8074#define Digits( x ) ( x & 0xFF'FF'FF'FF )
8075 std::uint64_t lhs_low = Digits( lhs );
8076 std::uint64_t rhs_low = Digits( rhs );
8077 std::uint64_t low_low = ( lhs_low * rhs_low );
8078 std::uint64_t high_high = CarryBits( lhs ) * CarryBits( rhs );
8079
8080 // We add in carry bits from low-low already
8081 std::uint64_t high_low =
8082 ( CarryBits( lhs ) * rhs_low ) + CarryBits( low_low );
8083 // Note that we can add only low bits from high_low, to avoid
8084 // overflow with large inputs
8085 std::uint64_t low_high =
8086 ( lhs_low * CarryBits( rhs ) ) + Digits( high_low );
8087
8088 return { high_high + CarryBits( high_low ) + CarryBits( low_high ),
8089 ( low_high << 32 ) | Digits( low_low ) };
8090#undef CarryBits
8091#undef Digits
8092 }
8093
8094 //! Returns 128 bit result of lhs * rhs
8095 inline ExtendedMultResult<std::uint64_t>
8096 extendedMult( std::uint64_t lhs, std::uint64_t rhs ) {
8097#if defined( CATCH_CONFIG_UINT128 )
8098 auto result = __uint128_t( lhs ) * __uint128_t( rhs );
8099 return { static_cast<std::uint64_t>( result >> 64 ),
8100 static_cast<std::uint64_t>( result ) };
8101#elif defined( CATCH_CONFIG_MSVC_UMUL128 )
8102 std::uint64_t high;
8103 std::uint64_t low = _umul128( lhs, rhs, &high );
8104 return { high, low };
8105#else
8106 return extendedMultPortable( lhs, rhs );
8107#endif
8108 }
8109
8110
8111 template <typename UInt>
8112 constexpr ExtendedMultResult<UInt> extendedMult( UInt lhs, UInt rhs ) {
8113 static_assert( std::is_unsigned<UInt>::value,
8114 "extendedMult can only handle unsigned integers" );
8115 static_assert( sizeof( UInt ) < sizeof( std::uint64_t ),
8116 "Generic extendedMult can only handle types smaller "
8117 "than uint64_t" );
8118 using WideType = DoubleWidthUnsignedType_t<UInt>;
8119
8120 auto result = WideType( lhs ) * WideType( rhs );
8121 return {
8122 static_cast<UInt>( result >> ( CHAR_BIT * sizeof( UInt ) ) ),
8123 static_cast<UInt>( result & UInt( -1 ) ) };
8124 }
8125
8126
8127 template <typename TargetType,
8128 typename Generator>
8129 std::enable_if_t<sizeof(typename Generator::result_type) >= sizeof(TargetType),
8130 TargetType> fillBitsFrom(Generator& gen) {
8131 using gresult_type = typename Generator::result_type;
8132 static_assert( std::is_unsigned<TargetType>::value, "Only unsigned integers are supported" );
8133 static_assert( Generator::min() == 0 &&
8134 Generator::max() == static_cast<gresult_type>( -1 ),
8135 "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
8136
8137 // We want to return the top bits from a generator, as they are
8138 // usually considered higher quality.
8139 constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
8140 constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
8141
8142 return static_cast<TargetType>( gen() >>
8143 ( generated_bits - return_bits) );
8144 }
8145
8146 template <typename TargetType,
8147 typename Generator>
8148 std::enable_if_t<sizeof(typename Generator::result_type) < sizeof(TargetType),
8149 TargetType> fillBitsFrom(Generator& gen) {
8150 using gresult_type = typename Generator::result_type;
8151 static_assert( std::is_unsigned<TargetType>::value,
8152 "Only unsigned integers are supported" );
8153 static_assert( Generator::min() == 0 &&
8154 Generator::max() == static_cast<gresult_type>( -1 ),
8155 "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
8156
8157 constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
8158 constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
8159 std::size_t filled_bits = 0;
8160 TargetType ret = 0;
8161 do {
8162 ret <<= generated_bits;
8163 ret |= gen();
8164 filled_bits += generated_bits;
8165 } while ( filled_bits < return_bits );
8166
8167 return ret;
8168 }
8169
8170 /*
8171 * Transposes numbers into unsigned type while keeping their ordering
8172 *
8173 * This means that signed types are changed so that the ordering is
8174 * [INT_MIN, ..., -1, 0, ..., INT_MAX], rather than order we would
8175 * get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1])
8176 */
8177 template <typename OriginalType, typename UnsignedType>
8178 constexpr
8179 std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType>
8180 transposeToNaturalOrder( UnsignedType in ) {
8181 static_assert(
8182 sizeof( OriginalType ) == sizeof( UnsignedType ),
8183 "reordering requires the same sized types on both sides" );
8184 static_assert( std::is_unsigned<UnsignedType>::value,
8185 "Input type must be unsigned" );
8186 // Assuming 2s complement (standardized in current C++), the
8187 // positive and negative numbers are already internally ordered,
8188 // and their difference is in the top bit. Swapping it orders
8189 // them the desired way.
8190 constexpr auto highest_bit =
8191 UnsignedType( 1 ) << ( sizeof( UnsignedType ) * CHAR_BIT - 1 );
8192 return static_cast<UnsignedType>( in ^ highest_bit );
8193 }
8194
8195
8196
8197 template <typename OriginalType,
8198 typename UnsignedType>
8199 constexpr
8200 std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType>
8201 transposeToNaturalOrder(UnsignedType in) {
8202 static_assert(
8203 sizeof( OriginalType ) == sizeof( UnsignedType ),
8204 "reordering requires the same sized types on both sides" );
8205 static_assert( std::is_unsigned<UnsignedType>::value, "Input type must be unsigned" );
8206 // No reordering is needed for unsigned -> unsigned
8207 return in;
8208 }
8209 } // namespace Detail
8210} // namespace Catch
8211
8212#endif // CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
8213
8214namespace Catch {
8215
8216/**
8217 * Implementation of uniform distribution on integers.
8218 *
8219 * Unlike `std::uniform_int_distribution`, this implementation supports
8220 * various 1 byte integral types, including bool (but you should not
8221 * actually use it for bools).
8222 *
8223 * The underlying algorithm is based on the one described in "Fast Random
8224 * Integer Generation in an Interval" by Daniel Lemire, but has been
8225 * optimized under the assumption of reuse of the same distribution object.
8226 */
8227template <typename IntegerType>
8228class uniform_integer_distribution {
8229 static_assert(std::is_integral<IntegerType>::value, "...");
8230
8231 using UnsignedIntegerType = Detail::SizedUnsignedType_t<sizeof(IntegerType)>;
8232
8233 // Only the left bound is stored, and we store it converted to its
8234 // unsigned image. This avoids having to do the conversions inside
8235 // the operator(), at the cost of having to do the conversion in
8236 // the a() getter. The right bound is only needed in the b() getter,
8237 // so we recompute it there from other stored data.
8238 UnsignedIntegerType m_a;
8239
8240 // How many different values are there in [a, b]. a == b => 1, can be 0 for distribution over all values in the type.
8241 UnsignedIntegerType m_ab_distance;
8242
8243 // We hoisted this out of the main generation function. Technically,
8244 // this means that using this distribution will be slower than Lemire's
8245 // algorithm if this distribution instance will be used only few times,
8246 // but it will be faster if it is used many times. Since Catch2 uses
8247 // distributions only to implement random generators, we assume that each
8248 // distribution will be reused many times and this is an optimization.
8249 UnsignedIntegerType m_rejection_threshold = 0;
8250
8251 static constexpr UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) {
8252 // This overflows and returns 0 if a == 0 and b == TYPE_MAX.
8253 // We handle that later when generating the number.
8254 return transposeTo(b) - transposeTo(a) + 1;
8255 }
8256
8257 static constexpr UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) {
8258 // distance == 0 means that we will return all possible values from
8259 // the type's range, and that we shouldn't reject anything.
8260 if ( ab_distance == 0 ) { return 0; }
8261 return ( ~ab_distance + 1 ) % ab_distance;
8262 }
8263
8264 static constexpr UnsignedIntegerType transposeTo(IntegerType in) {
8265 return Detail::transposeToNaturalOrder<IntegerType>(
8266 static_cast<UnsignedIntegerType>( in ) );
8267 }
8268 static constexpr IntegerType transposeBack(UnsignedIntegerType in) {
8269 return static_cast<IntegerType>(
8270 Detail::transposeToNaturalOrder<IntegerType>(in) );
8271 }
8272
8273public:
8274 using result_type = IntegerType;
8275
8276 constexpr uniform_integer_distribution( IntegerType a, IntegerType b ):
8277 m_a( transposeTo(a) ),
8278 m_ab_distance( computeDistance(a, b) ),
8279 m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) {
8280 assert( a <= b );
8281 }
8282
8283 template <typename Generator>
8284 constexpr result_type operator()( Generator& g ) {
8285 // All possible values of result_type are valid.
8286 if ( m_ab_distance == 0 ) {
8287 return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) );
8288 }
8289
8290 auto random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
8291 auto emul = Detail::extendedMult( random_number, m_ab_distance );
8292 // Unlike Lemire's algorithm we skip the ab_distance check, since
8293 // we precomputed the rejection threshold, which is always tighter.
8294 while (emul.lower < m_rejection_threshold) {
8295 random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
8296 emul = Detail::extendedMult( random_number, m_ab_distance );
8297 }
8298
8299 return transposeBack(m_a + emul.upper);
8300 }
8301
8302 constexpr result_type a() const { return transposeBack(m_a); }
8303 constexpr result_type b() const { return transposeBack(m_ab_distance + m_a - 1); }
8304};
8305
8306} // end namespace Catch
8307
8308#endif // CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
8309
8310
8311
8312#ifndef CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
8313#define CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
8314
8315
8316
8317
8318#ifndef CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
8319#define CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
8320
8321
8322
8323#ifndef CATCH_POLYFILLS_HPP_INCLUDED
8324#define CATCH_POLYFILLS_HPP_INCLUDED
8325
8326namespace Catch {
8327
8328 bool isnan(float f);
8329 bool isnan(double d);
8330
8331 float nextafter(float x, float y);
8332 double nextafter(double x, double y);
8333
8334}
8335
8336#endif // CATCH_POLYFILLS_HPP_INCLUDED
8337
8338#include <cassert>
8339#include <cmath>
8340#include <cstdint>
8341#include <limits>
8342#include <type_traits>
8343
8344namespace Catch {
8345
8346 namespace Detail {
8347 /**
8348 * Returns the largest magnitude of 1-ULP distance inside the [a, b] range.
8349 *
8350 * Assumes `a < b`.
8351 */
8352 template <typename FloatType>
8353 FloatType gamma(FloatType a, FloatType b) {
8354 static_assert( std::is_floating_point<FloatType>::value,
8355 "gamma returns the largest ULP magnitude within "
8356 "floating point range [a, b]. This only makes sense "
8357 "for floating point types" );
8358 assert( a <= b );
8359
8360 const auto gamma_up = Catch::nextafter( a, std::numeric_limits<FloatType>::infinity() ) - a;
8361 const auto gamma_down = b - Catch::nextafter( b, -std::numeric_limits<FloatType>::infinity() );
8362
8363 return gamma_up < gamma_down ? gamma_down : gamma_up;
8364 }
8365
8366 template <typename FloatingPoint>
8367 struct DistanceTypePicker;
8368 template <>
8369 struct DistanceTypePicker<float> {
8370 using type = std::uint32_t;
8371 };
8372 template <>
8373 struct DistanceTypePicker<double> {
8374 using type = std::uint64_t;
8375 };
8376
8377 template <typename T>
8378 using DistanceType = typename DistanceTypePicker<T>::type;
8379
8380#if defined( __GNUC__ ) || defined( __clang__ )
8381# pragma GCC diagnostic push
8382# pragma GCC diagnostic ignored "-Wfloat-equal"
8383#endif
8384 /**
8385 * Computes the number of equi-distant floats in [a, b]
8386 *
8387 * Since not every range can be split into equidistant floats
8388 * exactly, we actually compute ceil(b/distance - a/distance),
8389 * because in those cases we want to overcount.
8390 *
8391 * Uses modified Dekker's FastTwoSum algorithm to handle rounding.
8392 */
8393 template <typename FloatType>
8394 DistanceType<FloatType>
8395 count_equidistant_floats( FloatType a, FloatType b, FloatType distance ) {
8396 assert( a <= b );
8397 // We get distance as gamma for our uniform float distribution,
8398 // so this will round perfectly.
8399 const auto ag = a / distance;
8400 const auto bg = b / distance;
8401
8402 const auto s = bg - ag;
8403 const auto err = ( std::fabs( a ) <= std::fabs( b ) )
8404 ? -ag - ( s - bg )
8405 : bg - ( s + ag );
8406 const auto ceil_s = static_cast<DistanceType<FloatType>>( std::ceil( s ) );
8407
8408 return ( ceil_s != s ) ? ceil_s : ceil_s + ( err > 0 );
8409 }
8410#if defined( __GNUC__ ) || defined( __clang__ )
8411# pragma GCC diagnostic pop
8412#endif
8413
8414 }
8415
8416} // end namespace Catch
8417
8418#endif // CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
8419
8420#include <cmath>
8421#include <type_traits>
8422
8423namespace Catch {
8424
8425 namespace Detail {
8426#if defined( __GNUC__ ) || defined( __clang__ )
8427# pragma GCC diagnostic push
8428# pragma GCC diagnostic ignored "-Wfloat-equal"
8429#endif
8430 // The issue with overflow only happens with maximal ULP and HUGE
8431 // distance, e.g. when generating numbers in [-inf, inf] for given
8432 // type. So we only check for the largest possible ULP in the
8433 // type, and return something that does not overflow to inf in 1 mult.
8434 constexpr std::uint64_t calculate_max_steps_in_one_go(double gamma) {
8435 if ( gamma == 1.99584030953472e+292 ) { return 9007199254740991; }
8436 return static_cast<std::uint64_t>( -1 );
8437 }
8438 constexpr std::uint32_t calculate_max_steps_in_one_go(float gamma) {
8439 if ( gamma == 2.028241e+31f ) { return 16777215; }
8440 return static_cast<std::uint32_t>( -1 );
8441 }
8442#if defined( __GNUC__ ) || defined( __clang__ )
8443# pragma GCC diagnostic pop
8444#endif
8445 }
8446
8447/**
8448 * Implementation of uniform distribution on floating point numbers.
8449 *
8450 * Note that we support only `float` and `double` types, because these
8451 * usually mean the same thing across different platform. `long double`
8452 * varies wildly by platform and thus we cannot provide reproducible
8453 * implementation. Also note that we don't implement all parts of
8454 * distribution per standard: this distribution is not serializable, nor
8455 * can the range be arbitrarily reset.
8456 *
8457 * The implementation also uses different approach than the one taken by
8458 * `std::uniform_real_distribution`, where instead of generating a number
8459 * between [0, 1) and then multiplying the range bounds with it, we first
8460 * split the [a, b] range into a set of equidistributed floating point
8461 * numbers, and then use uniform int distribution to pick which one to
8462 * return.
8463 *
8464 * This has the advantage of guaranteeing uniformity (the multiplication
8465 * method loses uniformity due to rounding when multiplying floats), except
8466 * for small non-uniformity at one side of the interval, where we have
8467 * to deal with the fact that not every interval is splittable into
8468 * equidistributed floats.
8469 *
8470 * Based on "Drawing random floating-point numbers from an interval" by
8471 * Frederic Goualard.
8472 */
8473template <typename FloatType>
8474class uniform_floating_point_distribution {
8475 static_assert(std::is_floating_point<FloatType>::value, "...");
8476 static_assert(!std::is_same<FloatType, long double>::value,
8477 "We do not support long double due to inconsistent behaviour between platforms");
8478
8479 using WidthType = Detail::DistanceType<FloatType>;
8480
8481 FloatType m_a, m_b;
8482 FloatType m_ulp_magnitude;
8483 WidthType m_floats_in_range;
8484 uniform_integer_distribution<WidthType> m_int_dist;
8485
8486 // In specific cases, we can overflow into `inf` when computing the
8487 // `steps * g` offset. To avoid this, we don't offset by more than this
8488 // in one multiply + addition.
8489 WidthType m_max_steps_in_one_go;
8490 // We don't want to do the magnitude check every call to `operator()`
8491 bool m_a_has_leq_magnitude;
8492
8493public:
8494 using result_type = FloatType;
8495
8496 uniform_floating_point_distribution( FloatType a, FloatType b ):
8497 m_a( a ),
8498 m_b( b ),
8499 m_ulp_magnitude( Detail::gamma( m_a, m_b ) ),
8500 m_floats_in_range( Detail::count_equidistant_floats( m_a, m_b, m_ulp_magnitude ) ),
8501 m_int_dist(0, m_floats_in_range),
8502 m_max_steps_in_one_go( Detail::calculate_max_steps_in_one_go(m_ulp_magnitude)),
8503 m_a_has_leq_magnitude(std::fabs(m_a) <= std::fabs(m_b))
8504 {
8505 assert( a <= b );
8506 }
8507
8508 template <typename Generator>
8509 result_type operator()( Generator& g ) {
8510 WidthType steps = m_int_dist( g );
8511 if ( m_a_has_leq_magnitude ) {
8512 if ( steps == m_floats_in_range ) { return m_a; }
8513 auto b = m_b;
8514 while (steps > m_max_steps_in_one_go) {
8515 b -= m_max_steps_in_one_go * m_ulp_magnitude;
8516 steps -= m_max_steps_in_one_go;
8517 }
8518 return b - steps * m_ulp_magnitude;
8519 } else {
8520 if ( steps == m_floats_in_range ) { return m_b; }
8521 auto a = m_a;
8522 while (steps > m_max_steps_in_one_go) {
8523 a += m_max_steps_in_one_go * m_ulp_magnitude;
8524 steps -= m_max_steps_in_one_go;
8525 }
8526 return a + steps * m_ulp_magnitude;
8527 }
8528 }
8529
8530 result_type a() const { return m_a; }
8531 result_type b() const { return m_b; }
8532};
8533
8534} // end namespace Catch
8535
8536#endif // CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
8537
8538namespace Catch {
8539namespace Generators {
8540namespace Detail {
8541 // Returns a suitable seed for a random floating generator based off
8542 // the primary internal rng. It does so by taking current value from
8543 // the rng and returning it as the seed.
8544 std::uint32_t getSeed();
8545}
8546
8547template <typename Float>
8548class RandomFloatingGenerator final : public IGenerator<Float> {
8549 Catch::SimplePcg32 m_rng;
8550 Catch::uniform_floating_point_distribution<Float> m_dist;
8551 Float m_current_number;
8552public:
8553 RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
8554 m_rng(seed),
8555 m_dist(a, b) {
8556 static_cast<void>(next());
8557 }
8558
8559 Float const& get() const override {
8560 return m_current_number;
8561 }
8562 bool next() override {
8563 m_current_number = m_dist(m_rng);
8564 return true;
8565 }
8566};
8567
8568template <>
8569class RandomFloatingGenerator<long double> final : public IGenerator<long double> {
8570 // We still rely on <random> for this specialization, but we don't
8571 // want to drag it into the header.
8572 struct PImpl;
8573 Catch::Detail::unique_ptr<PImpl> m_pimpl;
8574 long double m_current_number;
8575
8576public:
8577 RandomFloatingGenerator( long double a, long double b, std::uint32_t seed );
8578
8579 long double const& get() const override { return m_current_number; }
8580 bool next() override;
8581
8582 ~RandomFloatingGenerator() override; // = default
8583};
8584
8585template <typename Integer>
8586class RandomIntegerGenerator final : public IGenerator<Integer> {
8587 Catch::SimplePcg32 m_rng;
8588 Catch::uniform_integer_distribution<Integer> m_dist;
8589 Integer m_current_number;
8590public:
8591 RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
8592 m_rng(seed),
8593 m_dist(a, b) {
8594 static_cast<void>(next());
8595 }
8596
8597 Integer const& get() const override {
8598 return m_current_number;
8599 }
8600 bool next() override {
8601 m_current_number = m_dist(m_rng);
8602 return true;
8603 }
8604};
8605
8606template <typename T>
8607std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>>
8608random(T a, T b) {
8609 return GeneratorWrapper<T>(
8610 Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
8611 );
8612}
8613
8614template <typename T>
8615std::enable_if_t<std::is_floating_point<T>::value,
8616GeneratorWrapper<T>>
8617random(T a, T b) {
8618 return GeneratorWrapper<T>(
8619 Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed())
8620 );
8621}
8622
8623
8624} // namespace Generators
8625} // namespace Catch
8626
8627
8628#endif // CATCH_GENERATORS_RANDOM_HPP_INCLUDED
8629
8630
8631#ifndef CATCH_GENERATORS_RANGE_HPP_INCLUDED
8632#define CATCH_GENERATORS_RANGE_HPP_INCLUDED
8633
8634
8635#include <iterator>
8636#include <type_traits>
8637
8638namespace Catch {
8639namespace Generators {
8640
8641
8642template <typename T>
8643class RangeGenerator final : public IGenerator<T> {
8644 T m_current;
8645 T m_end;
8646 T m_step;
8647 bool m_positive;
8648
8649public:
8650 RangeGenerator(T const& start, T const& end, T const& step):
8651 m_current(start),
8652 m_end(end),
8653 m_step(step),
8654 m_positive(m_step > T(0))
8655 {
8656 assert(m_current != m_end && "Range start and end cannot be equal");
8657 assert(m_step != T(0) && "Step size cannot be zero");
8658 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
8659 }
8660
8661 RangeGenerator(T const& start, T const& end):
8662 RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
8663 {}
8664
8665 T const& get() const override {
8666 return m_current;
8667 }
8668
8669 bool next() override {
8670 m_current += m_step;
8671 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
8672 }
8673};
8674
8675template <typename T>
8676GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
8677 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
8678 return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end, step));
8679}
8680
8681template <typename T>
8682GeneratorWrapper<T> range(T const& start, T const& end) {
8683 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
8684 return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end));
8685}
8686
8687
8688template <typename T>
8689class IteratorGenerator final : public IGenerator<T> {
8690 static_assert(!std::is_same<T, bool>::value,
8691 "IteratorGenerator currently does not support bools"
8692 "because of std::vector<bool> specialization");
8693
8694 std::vector<T> m_elems;
8695 size_t m_current = 0;
8696public:
8697 template <typename InputIterator, typename InputSentinel>
8698 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
8699 if (m_elems.empty()) {
8700 Detail::throw_generator_exception("IteratorGenerator received no valid values");
8701 }
8702 }
8703
8704 T const& get() const override {
8705 return m_elems[m_current];
8706 }
8707
8708 bool next() override {
8709 ++m_current;
8710 return m_current != m_elems.size();
8711 }
8712};
8713
8714template <typename InputIterator,
8715 typename InputSentinel,
8716 typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
8717GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
8718 return GeneratorWrapper<ResultType>(Catch::Detail::make_unique<IteratorGenerator<ResultType>>(from, to));
8719}
8720
8721template <typename Container>
8722auto from_range(Container const& cnt) {
8723 using std::begin;
8724 using std::end;
8725 return from_range( begin( cnt ), end( cnt ) );
8726}
8727
8728
8729} // namespace Generators
8730} // namespace Catch
8731
8732
8733#endif // CATCH_GENERATORS_RANGE_HPP_INCLUDED
8734
8735#endif // CATCH_GENERATORS_ALL_HPP_INCLUDED
8736
8737
8738/** \file
8739 * This is a convenience header for Catch2's interfaces. It includes
8740 * **all** of Catch2 headers related to interfaces.
8741 *
8742 * Generally the Catch2 users should use specific includes they need,
8743 * but this header can be used instead for ease-of-experimentation, or
8744 * just plain convenience, at the cost of somewhat increased compilation
8745 * times.
8746 *
8747 * When a new header is added to either the `interfaces` folder, or to
8748 * the corresponding internal subfolder, it should be added here.
8749 */
8750
8751
8752#ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED
8753#define CATCH_INTERFACES_ALL_HPP_INCLUDED
8754
8755
8756
8757#ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED
8758#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED
8759
8760
8761
8762#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
8763#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
8764
8765
8766namespace Catch {
8767
8768 struct TestRunInfo {
8769 constexpr TestRunInfo(StringRef _name) : name(_name) {}
8770 StringRef name;
8771 };
8772
8773} // end namespace Catch
8774
8775#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED
8776
8777#include <map>
8778#include <string>
8779#include <vector>
8780#include <iosfwd>
8781
8782namespace Catch {
8783
8784 struct ReporterDescription;
8785 struct ListenerDescription;
8786 struct TagInfo;
8787 struct TestCaseInfo;
8788 class TestCaseHandle;
8789 class IConfig;
8790 class IStream;
8791 enum class ColourMode : std::uint8_t;
8792
8793 struct ReporterConfig {
8794 ReporterConfig( IConfig const* _fullConfig,
8795 Detail::unique_ptr<IStream> _stream,
8796 ColourMode colourMode,
8797 std::map<std::string, std::string> customOptions );
8798
8799 ReporterConfig( ReporterConfig&& ) = default;
8800 ReporterConfig& operator=( ReporterConfig&& ) = default;
8801 ~ReporterConfig(); // = default
8802
8803 Detail::unique_ptr<IStream> takeStream() &&;
8804 IConfig const* fullConfig() const;
8805 ColourMode colourMode() const;
8806 std::map<std::string, std::string> const& customOptions() const;
8807
8808 private:
8809 Detail::unique_ptr<IStream> m_stream;
8810 IConfig const* m_fullConfig;
8811 ColourMode m_colourMode;
8812 std::map<std::string, std::string> m_customOptions;
8813 };
8814
8815 struct AssertionStats {
8816 AssertionStats( AssertionResult const& _assertionResult,
8817 std::vector<MessageInfo> const& _infoMessages,
8818 Totals const& _totals );
8819
8820 AssertionStats( AssertionStats const& ) = default;
8821 AssertionStats( AssertionStats && ) = default;
8822 AssertionStats& operator = ( AssertionStats const& ) = delete;
8823 AssertionStats& operator = ( AssertionStats && ) = delete;
8824
8825 AssertionResult assertionResult;
8826 std::vector<MessageInfo> infoMessages;
8827 Totals totals;
8828 };
8829
8830 struct SectionStats {
8831 SectionStats( SectionInfo&& _sectionInfo,
8832 Counts const& _assertions,
8833 double _durationInSeconds,
8834 bool _missingAssertions );
8835
8836 SectionInfo sectionInfo;
8837 Counts assertions;
8838 double durationInSeconds;
8839 bool missingAssertions;
8840 };
8841
8842 struct TestCaseStats {
8843 TestCaseStats( TestCaseInfo const& _testInfo,
8844 Totals const& _totals,
8845 std::string&& _stdOut,
8846 std::string&& _stdErr,
8847 bool _aborting );
8848
8849 TestCaseInfo const * testInfo;
8850 Totals totals;
8851 std::string stdOut;
8852 std::string stdErr;
8853 bool aborting;
8854 };
8855
8856 struct TestRunStats {
8857 TestRunStats( TestRunInfo const& _runInfo,
8858 Totals const& _totals,
8859 bool _aborting );
8860
8861 TestRunInfo runInfo;
8862 Totals totals;
8863 bool aborting;
8864 };
8865
8866 //! By setting up its preferences, a reporter can modify Catch2's behaviour
8867 //! in some regards, e.g. it can request Catch2 to capture writes to
8868 //! stdout/stderr during test execution, and pass them to the reporter.
8869 struct ReporterPreferences {
8870 //! Catch2 should redirect writes to stdout and pass them to the
8871 //! reporter
8872 bool shouldRedirectStdOut = false;
8873 //! Catch2 should call `Reporter::assertionEnded` even for passing
8874 //! assertions
8875 bool shouldReportAllAssertions = false;
8876 };
8877
8878 /**
8879 * The common base for all reporters and event listeners
8880 *
8881 * Implementing classes must also implement:
8882 *
8883 * //! User-friendly description of the reporter/listener type
8884 * static std::string getDescription()
8885 *
8886 * Generally shouldn't be derived from by users of Catch2 directly,
8887 * instead they should derive from one of the utility bases that
8888 * derive from this class.
8889 */
8890 class IEventListener {
8891 protected:
8892 //! Derived classes can set up their preferences here
8893 ReporterPreferences m_preferences;
8894 //! The test run's config as filled in from CLI and defaults
8895 IConfig const* m_config;
8896
8897 public:
8898 IEventListener( IConfig const* config ): m_config( config ) {}
8899
8900 virtual ~IEventListener(); // = default;
8901
8902 // Implementing class must also provide the following static methods:
8903 // static std::string getDescription();
8904
8905 ReporterPreferences const& getPreferences() const {
8906 return m_preferences;
8907 }
8908
8909 //! Called when no test cases match provided test spec
8910 virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0;
8911 //! Called for all invalid test specs from the cli
8912 virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0;
8913
8914 /**
8915 * Called once in a testing run before tests are started
8916 *
8917 * Not called if tests won't be run (e.g. only listing will happen)
8918 */
8919 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
8920
8921 //! Called _once_ for each TEST_CASE, no matter how many times it is entered
8922 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
8923 //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
8924 virtual void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) = 0;
8925 //! Called when a `SECTION` is being entered. Not called for skipped sections
8926 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
8927
8928 //! Called when user-code is being probed before the actual benchmark runs
8929 virtual void benchmarkPreparing( StringRef benchmarkName ) = 0;
8930 //! Called after probe but before the user-code is being benchmarked
8931 virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0;
8932 //! Called with the benchmark results if benchmark successfully finishes
8933 virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0;
8934 //! Called if running the benchmarks fails for any reason
8935 virtual void benchmarkFailed( StringRef benchmarkName ) = 0;
8936
8937 //! Called before assertion success/failure is evaluated
8938 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
8939
8940 //! Called after assertion was fully evaluated
8941 virtual void assertionEnded( AssertionStats const& assertionStats ) = 0;
8942
8943 //! Called after a `SECTION` has finished running
8944 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
8945 //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
8946 virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber ) = 0;
8947 //! Called _once_ for each TEST_CASE, no matter how many times it is entered
8948 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
8949 /**
8950 * Called once after all tests in a testing run are finished
8951 *
8952 * Not called if tests weren't run (e.g. only listings happened)
8953 */
8954 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
8955
8956 /**
8957 * Called with test cases that are skipped due to the test run aborting.
8958 * NOT called for test cases that are explicitly skipped using the `SKIP` macro.
8959 *
8960 * Deprecated - will be removed in the next major release.
8961 */
8962 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
8963
8964 //! Called if a fatal error (signal/structured exception) occurred
8965 virtual void fatalErrorEncountered( StringRef error ) = 0;
8966
8967 //! Writes out information about provided reporters using reporter-specific format
8968 virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
8969 //! Writes out the provided listeners descriptions using reporter-specific format
8970 virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0;
8971 //! Writes out information about provided tests using reporter-specific format
8972 virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
8973 //! Writes out information about the provided tags using reporter-specific format
8974 virtual void listTags(std::vector<TagInfo> const& tags) = 0;
8975 };
8976 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
8977
8978} // end namespace Catch
8979
8980#endif // CATCH_INTERFACES_REPORTER_HPP_INCLUDED
8981
8982
8983#ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
8984#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
8985
8986
8987#include <string>
8988
8989namespace Catch {
8990
8991 struct ReporterConfig;
8992 class IConfig;
8993 class IEventListener;
8994 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
8995
8996
8997 class IReporterFactory {
8998 public:
8999 virtual ~IReporterFactory(); // = default
9000
9001 virtual IEventListenerPtr
9002 create( ReporterConfig&& config ) const = 0;
9003 virtual std::string getDescription() const = 0;
9004 };
9005 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
9006
9007 class EventListenerFactory {
9008 public:
9009 virtual ~EventListenerFactory(); // = default
9010 virtual IEventListenerPtr create( IConfig const* config ) const = 0;
9011 //! Return a meaningful name for the listener, e.g. its type name
9012 virtual StringRef getName() const = 0;
9013 //! Return listener's description if available
9014 virtual std::string getDescription() const = 0;
9015 };
9016} // namespace Catch
9017
9018#endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
9019
9020
9021#ifndef CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
9022#define CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
9023
9024#include <string>
9025
9026namespace Catch {
9027
9028 struct TagAlias;
9029
9030 class ITagAliasRegistry {
9031 public:
9032 virtual ~ITagAliasRegistry(); // = default
9033 // Nullptr if not present
9034 virtual TagAlias const* find( std::string const& alias ) const = 0;
9035 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
9036
9037 static ITagAliasRegistry const& get();
9038 };
9039
9040} // end namespace Catch
9041
9042#endif // CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
9043
9044
9045#ifndef CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
9046#define CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
9047
9048#include <vector>
9049
9050namespace Catch {
9051
9052 struct TestCaseInfo;
9053 class TestCaseHandle;
9054 class IConfig;
9055
9056 class ITestCaseRegistry {
9057 public:
9058 virtual ~ITestCaseRegistry(); // = default
9059 // TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later
9060 virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0;
9061 virtual std::vector<TestCaseHandle> const& getAllTests() const = 0;
9062 virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0;
9063 };
9064
9065}
9066
9067#endif // CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
9068
9069#endif // CATCH_INTERFACES_ALL_HPP_INCLUDED
9070
9071
9072#ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
9073#define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
9074
9075
9076namespace Catch {
9077 namespace Detail {
9078 //! Provides case-insensitive `op<` semantics when called
9079 struct CaseInsensitiveLess {
9080 bool operator()( StringRef lhs,
9081 StringRef rhs ) const;
9082 };
9083
9084 //! Provides case-insensitive `op==` semantics when called
9085 struct CaseInsensitiveEqualTo {
9086 bool operator()( StringRef lhs,
9087 StringRef rhs ) const;
9088 };
9089
9090 } // namespace Detail
9091} // namespace Catch
9092
9093#endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
9094
9095
9096
9097/** \file
9098 * Wrapper for ANDROID_LOGWRITE configuration option
9099 *
9100 * We want to default to enabling it when compiled for android, but
9101 * users of the library should also be able to disable it if they want
9102 * to.
9103 */
9104
9105#ifndef CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
9106#define CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
9107
9108
9109#if defined(__ANDROID__)
9110# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
9111#endif
9112
9113
9114#if defined( CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE ) && \
9115 !defined( CATCH_CONFIG_NO_ANDROID_LOGWRITE ) && \
9116 !defined( CATCH_CONFIG_ANDROID_LOGWRITE )
9117# define CATCH_CONFIG_ANDROID_LOGWRITE
9118#endif
9119
9120#endif // CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
9121
9122
9123
9124/** \file
9125 * Wrapper for UNCAUGHT_EXCEPTIONS configuration option
9126 *
9127 * For some functionality, Catch2 requires to know whether there is
9128 * an active exception. Because `std::uncaught_exception` is deprecated
9129 * in C++17, we want to use `std::uncaught_exceptions` if possible.
9130 */
9131
9132#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
9133#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
9134
9135
9136#if defined(_MSC_VER)
9137# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
9138# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
9139# endif
9140#endif
9141
9142
9143#include <exception>
9144
9145#if defined(__cpp_lib_uncaught_exceptions) \
9146 && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
9147
9148# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
9149#endif // __cpp_lib_uncaught_exceptions
9150
9151
9152#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
9153 && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
9154 && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
9155
9156# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
9157#endif
9158
9159
9160#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
9161
9162
9163#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
9164#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
9165
9166
9167#include <iosfwd>
9168#include <cstdint>
9169
9170namespace Catch {
9171
9172 enum class ColourMode : std::uint8_t;
9173 class IStream;
9174
9175 struct Colour {
9176 enum Code {
9177 None = 0,
9178
9179 White,
9180 Red,
9181 Green,
9182 Blue,
9183 Cyan,
9184 Yellow,
9185 Grey,
9186
9187 Bright = 0x10,
9188
9189 BrightRed = Bright | Red,
9190 BrightGreen = Bright | Green,
9191 LightGrey = Bright | Grey,
9192 BrightWhite = Bright | White,
9193 BrightYellow = Bright | Yellow,
9194
9195 // By intention
9196 FileName = LightGrey,
9197 Warning = BrightYellow,
9198 ResultError = BrightRed,
9199 ResultSuccess = BrightGreen,
9200 ResultExpectedFailure = Warning,
9201
9202 Error = BrightRed,
9203 Success = Green,
9204 Skip = LightGrey,
9205
9206 OriginalExpression = Cyan,
9207 ReconstructedExpression = BrightYellow,
9208
9209 SecondaryText = LightGrey,
9210 Headers = White
9211 };
9212 };
9213
9214 class ColourImpl {
9215 protected:
9216 //! The associated stream of this ColourImpl instance
9217 IStream* m_stream;
9218 public:
9219 ColourImpl( IStream* stream ): m_stream( stream ) {}
9220
9221 //! RAII wrapper around writing specific colour of text using specific
9222 //! colour impl into a stream.
9223 class ColourGuard {
9224 ColourImpl const* m_colourImpl;
9225 Colour::Code m_code;
9226 bool m_engaged = false;
9227
9228 public:
9229 //! Does **not** engage the guard/start the colour
9230 ColourGuard( Colour::Code code,
9231 ColourImpl const* colour );
9232
9233 ColourGuard( ColourGuard const& rhs ) = delete;
9234 ColourGuard& operator=( ColourGuard const& rhs ) = delete;
9235
9236 ColourGuard( ColourGuard&& rhs ) noexcept;
9237 ColourGuard& operator=( ColourGuard&& rhs ) noexcept;
9238
9239 //! Removes colour _if_ the guard was engaged
9240 ~ColourGuard();
9241
9242 /**
9243 * Explicitly engages colour for given stream.
9244 *
9245 * The API based on operator<< should be preferred.
9246 */
9247 ColourGuard& engage( std::ostream& stream ) &;
9248 /**
9249 * Explicitly engages colour for given stream.
9250 *
9251 * The API based on operator<< should be preferred.
9252 */
9253 ColourGuard&& engage( std::ostream& stream ) &&;
9254
9255 private:
9256 //! Engages the guard and starts using colour
9257 friend std::ostream& operator<<( std::ostream& lhs,
9258 ColourGuard& guard ) {
9259 guard.engageImpl( lhs );
9260 return lhs;
9261 }
9262 //! Engages the guard and starts using colour
9263 friend std::ostream& operator<<( std::ostream& lhs,
9264 ColourGuard&& guard) {
9265 guard.engageImpl( lhs );
9266 return lhs;
9267 }
9268
9269 void engageImpl( std::ostream& stream );
9270
9271 };
9272
9273 virtual ~ColourImpl(); // = default
9274 /**
9275 * Creates a guard object for given colour and this colour impl
9276 *
9277 * **Important:**
9278 * the guard starts disengaged, and has to be engaged explicitly.
9279 */
9280 ColourGuard guardColour( Colour::Code colourCode );
9281
9282 private:
9283 virtual void use( Colour::Code colourCode ) const = 0;
9284 };
9285
9286 //! Provides ColourImpl based on global config and target compilation platform
9287 Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
9288 IStream* stream );
9289
9290 //! Checks if specific colour impl has been compiled into the binary
9291 bool isColourImplAvailable( ColourMode colourSelection );
9292
9293} // end namespace Catch
9294
9295#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED
9296
9297
9298#ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED
9299#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED
9300
9301// This include must be kept so that user's configured value for CONSOLE_WIDTH
9302// is used before we attempt to provide a default value
9303
9304#ifndef CATCH_CONFIG_CONSOLE_WIDTH
9305#define CATCH_CONFIG_CONSOLE_WIDTH 80
9306#endif
9307
9308#endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED
9309
9310
9311#ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
9312#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
9313
9314
9315#include <cstddef>
9316#include <initializer_list>
9317
9318// We want a simple polyfill over `std::empty`, `std::size` and so on
9319// for C++14 or C++ libraries with incomplete support.
9320// We also have to handle that MSVC std lib will happily provide these
9321// under older standards.
9322#if defined(CATCH_CPP17_OR_GREATER) || defined(_MSC_VER)
9323
9324// We are already using this header either way, so there shouldn't
9325// be much additional overhead in including it to get the feature
9326// test macros
9327#include <string>
9328
9329# if !defined(__cpp_lib_nonmember_container_access)
9330# define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
9331# endif
9332
9333#else
9334#define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
9335#endif
9336
9337
9338
9339namespace Catch {
9340namespace Detail {
9341
9342#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
9343 template <typename Container>
9344 constexpr auto empty(Container const& cont) -> decltype(cont.empty()) {
9345 return cont.empty();
9346 }
9347 template <typename T, std::size_t N>
9348 constexpr bool empty(const T (&)[N]) noexcept {
9349 // GCC < 7 does not support the const T(&)[] parameter syntax
9350 // so we have to ignore the length explicitly
9351 (void)N;
9352 return false;
9353 }
9354 template <typename T>
9355 constexpr bool empty(std::initializer_list<T> list) noexcept {
9356 return list.size() > 0;
9357 }
9358
9359
9360 template <typename Container>
9361 constexpr auto size(Container const& cont) -> decltype(cont.size()) {
9362 return cont.size();
9363 }
9364 template <typename T, std::size_t N>
9365 constexpr std::size_t size(const T(&)[N]) noexcept {
9366 return N;
9367 }
9368#endif // CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
9369
9370} // end namespace Detail
9371} // end namespace Catch
9372
9373
9374
9375#endif // CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
9376
9377
9378#ifndef CATCH_DEBUG_CONSOLE_HPP_INCLUDED
9379#define CATCH_DEBUG_CONSOLE_HPP_INCLUDED
9380
9381#include <string>
9382
9383namespace Catch {
9384 void writeToDebugConsole( std::string const& text );
9385}
9386
9387#endif // CATCH_DEBUG_CONSOLE_HPP_INCLUDED
9388
9389
9390#ifndef CATCH_DEBUGGER_HPP_INCLUDED
9391#define CATCH_DEBUGGER_HPP_INCLUDED
9392
9393
9394namespace Catch {
9395 bool isDebuggerActive();
9396}
9397
9398#ifdef CATCH_PLATFORM_MAC
9399
9400 #if defined(__i386__) || defined(__x86_64__)
9401 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
9402 #elif defined(__aarch64__)
9403 #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
9404 #elif defined(__POWERPC__)
9405 #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
9406 : : : "memory","r0","r3","r4" ) /* NOLINT */
9407 #endif
9408
9409#elif defined(CATCH_PLATFORM_IPHONE)
9410
9411 // use inline assembler
9412 #if defined(__i386__) || defined(__x86_64__)
9413 #define CATCH_TRAP() __asm__("int $3")
9414 #elif defined(__aarch64__)
9415 #define CATCH_TRAP() __asm__(".inst 0xd4200000")
9416 #elif defined(__arm__) && !defined(__thumb__)
9417 #define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
9418 #elif defined(__arm__) && defined(__thumb__)
9419 #define CATCH_TRAP() __asm__(".inst 0xde01")
9420 #endif
9421
9422#elif defined(CATCH_PLATFORM_LINUX)
9423 // If we can use inline assembler, do it because this allows us to break
9424 // directly at the location of the failing check instead of breaking inside
9425 // raise() called from it, i.e. one stack frame below.
9426 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
9427 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
9428 #else // Fall back to the generic way.
9429 #include <signal.h>
9430
9431 #define CATCH_TRAP() raise(SIGTRAP)
9432 #endif
9433#elif defined(_MSC_VER)
9434 #define CATCH_TRAP() __debugbreak()
9435#elif defined(__MINGW32__)
9436 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
9437 #define CATCH_TRAP() DebugBreak()
9438#endif
9439
9440#ifndef CATCH_BREAK_INTO_DEBUGGER
9441 #ifdef CATCH_TRAP
9442 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
9443 #else
9444 #define CATCH_BREAK_INTO_DEBUGGER() []{}()
9445 #endif
9446#endif
9447
9448#endif // CATCH_DEBUGGER_HPP_INCLUDED
9449
9450
9451#ifndef CATCH_ENFORCE_HPP_INCLUDED
9452#define CATCH_ENFORCE_HPP_INCLUDED
9453
9454
9455#include <exception>
9456
9457namespace Catch {
9458#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
9459 template <typename Ex>
9460 [[noreturn]]
9461 void throw_exception(Ex const& e) {
9462 throw e;
9463 }
9464#else // ^^ Exceptions are enabled // Exceptions are disabled vv
9465 [[noreturn]]
9466 void throw_exception(std::exception const& e);
9467#endif
9468
9469 [[noreturn]]
9470 void throw_logic_error(std::string const& msg);
9471 [[noreturn]]
9472 void throw_domain_error(std::string const& msg);
9473 [[noreturn]]
9474 void throw_runtime_error(std::string const& msg);
9475
9476} // namespace Catch;
9477
9478#define CATCH_MAKE_MSG(...) \
9479 (Catch::ReusableStringStream() << __VA_ARGS__).str()
9480
9481#define CATCH_INTERNAL_ERROR(...) \
9482 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
9483
9484#define CATCH_ERROR(...) \
9485 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
9486
9487#define CATCH_RUNTIME_ERROR(...) \
9488 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
9489
9490#define CATCH_ENFORCE( condition, ... ) \
9491 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
9492
9493
9494#endif // CATCH_ENFORCE_HPP_INCLUDED
9495
9496
9497#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
9498#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
9499
9500
9501#include <vector>
9502
9503namespace Catch {
9504
9505 namespace Detail {
9506
9507 Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
9508
9509 class EnumValuesRegistry : public IMutableEnumValuesRegistry {
9510
9511 std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
9512
9513 EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
9514 };
9515
9516 std::vector<StringRef> parseEnums( StringRef enums );
9517
9518 } // Detail
9519
9520} // Catch
9521
9522#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
9523
9524
9525#ifndef CATCH_ERRNO_GUARD_HPP_INCLUDED
9526#define CATCH_ERRNO_GUARD_HPP_INCLUDED
9527
9528namespace Catch {
9529
9530 //! Simple RAII class that stores the value of `errno`
9531 //! at construction and restores it at destruction.
9532 class ErrnoGuard {
9533 public:
9534 // Keep these outlined to avoid dragging in macros from <cerrno>
9535
9536 ErrnoGuard();
9537 ~ErrnoGuard();
9538 private:
9539 int m_oldErrno;
9540 };
9541
9542}
9543
9544#endif // CATCH_ERRNO_GUARD_HPP_INCLUDED
9545
9546
9547#ifndef CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
9548#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
9549
9550
9551#include <vector>
9552#include <string>
9553
9554namespace Catch {
9555
9556 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
9557 public:
9558 ~ExceptionTranslatorRegistry() override;
9559 void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator );
9560 std::string translateActiveException() const override;
9561
9562 private:
9563 ExceptionTranslators m_translators;
9564 };
9565}
9566
9567#endif // CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
9568
9569
9570#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
9571#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
9572
9573#include <cassert>
9574
9575namespace Catch {
9576
9577 /**
9578 * Wrapper for platform-specific fatal error (signals/SEH) handlers
9579 *
9580 * Tries to be cooperative with other handlers, and not step over
9581 * other handlers. This means that unknown structured exceptions
9582 * are passed on, previous signal handlers are called, and so on.
9583 *
9584 * Can only be instantiated once, and assumes that once a signal
9585 * is caught, the binary will end up terminating. Thus, there
9586 */
9587 class FatalConditionHandler {
9588 bool m_started = false;
9589
9590 // Install/disengage implementation for specific platform.
9591 // Should be if-defed to work on current platform, can assume
9592 // engage-disengage 1:1 pairing.
9593 void engage_platform();
9594 void disengage_platform() noexcept;
9595 public:
9596 // Should also have platform-specific implementations as needed
9597 FatalConditionHandler();
9598 ~FatalConditionHandler();
9599
9600 void engage() {
9601 assert(!m_started && "Handler cannot be installed twice.");
9602 m_started = true;
9603 engage_platform();
9604 }
9605
9606 void disengage() noexcept {
9607 assert(m_started && "Handler cannot be uninstalled without being installed first");
9608 m_started = false;
9609 disengage_platform();
9610 }
9611 };
9612
9613 //! Simple RAII guard for (dis)engaging the FatalConditionHandler
9614 class FatalConditionHandlerGuard {
9615 FatalConditionHandler* m_handler;
9616 public:
9617 FatalConditionHandlerGuard(FatalConditionHandler* handler):
9618 m_handler(handler) {
9619 m_handler->engage();
9620 }
9621 ~FatalConditionHandlerGuard() {
9622 m_handler->disengage();
9623 }
9624 };
9625
9626} // end namespace Catch
9627
9628#endif // CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
9629
9630
9631#ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
9632#define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
9633
9634
9635#include <cassert>
9636#include <cmath>
9637#include <cstdint>
9638#include <utility>
9639#include <limits>
9640
9641namespace Catch {
9642 namespace Detail {
9643
9644 uint32_t convertToBits(float f);
9645 uint64_t convertToBits(double d);
9646
9647 // Used when we know we want == comparison of two doubles
9648 // to centralize warning suppression
9649 bool directCompare( float lhs, float rhs );
9650 bool directCompare( double lhs, double rhs );
9651
9652 } // end namespace Detail
9653
9654
9655
9656#if defined( __GNUC__ ) || defined( __clang__ )
9657# pragma GCC diagnostic push
9658 // We do a bunch of direct compensations of floating point numbers,
9659 // because we know what we are doing and actually do want the direct
9660 // comparison behaviour.
9661# pragma GCC diagnostic ignored "-Wfloat-equal"
9662#endif
9663
9664 /**
9665 * Calculates the ULP distance between two floating point numbers
9666 *
9667 * The ULP distance of two floating point numbers is the count of
9668 * valid floating point numbers representable between them.
9669 *
9670 * There are some exceptions between how this function counts the
9671 * distance, and the interpretation of the standard as implemented.
9672 * by e.g. `nextafter`. For this function it always holds that:
9673 * * `(x == y) => ulpDistance(x, y) == 0` (so `ulpDistance(-0, 0) == 0`)
9674 * * `ulpDistance(maxFinite, INF) == 1`
9675 * * `ulpDistance(x, -x) == 2 * ulpDistance(x, 0)`
9676 *
9677 * \pre `!isnan( lhs )`
9678 * \pre `!isnan( rhs )`
9679 * \pre floating point numbers are represented in IEEE-754 format
9680 */
9681 template <typename FP>
9682 uint64_t ulpDistance( FP lhs, FP rhs ) {
9683 assert( std::numeric_limits<FP>::is_iec559 &&
9684 "ulpDistance assumes IEEE-754 format for floating point types" );
9685 assert( !Catch::isnan( lhs ) &&
9686 "Distance between NaN and number is not meaningful" );
9687 assert( !Catch::isnan( rhs ) &&
9688 "Distance between NaN and number is not meaningful" );
9689
9690 // We want X == Y to imply 0 ULP distance even if X and Y aren't
9691 // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
9692 if ( lhs == rhs ) { return 0; }
9693
9694 // We need a properly typed positive zero for type inference.
9695 static constexpr FP positive_zero{};
9696
9697 // We want to ensure that +/- 0 is always represented as positive zero
9698 if ( lhs == positive_zero ) { lhs = positive_zero; }
9699 if ( rhs == positive_zero ) { rhs = positive_zero; }
9700
9701 // If arguments have different signs, we can handle them by summing
9702 // how far are they from 0 each.
9703 if ( std::signbit( lhs ) != std::signbit( rhs ) ) {
9704 return ulpDistance( std::abs( lhs ), positive_zero ) +
9705 ulpDistance( std::abs( rhs ), positive_zero );
9706 }
9707
9708 // When both lhs and rhs are of the same sign, we can just
9709 // read the numbers bitwise as integers, and then subtract them
9710 // (assuming IEEE).
9711 uint64_t lc = Detail::convertToBits( lhs );
9712 uint64_t rc = Detail::convertToBits( rhs );
9713
9714 // The ulp distance between two numbers is symmetric, so to avoid
9715 // dealing with overflows we want the bigger converted number on the lhs
9716 if ( lc < rc ) {
9717 std::swap( lc, rc );
9718 }
9719
9720 return lc - rc;
9721 }
9722
9723#if defined( __GNUC__ ) || defined( __clang__ )
9724# pragma GCC diagnostic pop
9725#endif
9726
9727
9728} // end namespace Catch
9729
9730#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
9731
9732
9733#ifndef CATCH_GETENV_HPP_INCLUDED
9734#define CATCH_GETENV_HPP_INCLUDED
9735
9736namespace Catch {
9737namespace Detail {
9738
9739 //! Wrapper over `std::getenv` that compiles on UWP (and always returns nullptr there)
9740 char const* getEnv(char const* varName);
9741
9742}
9743}
9744
9745#endif // CATCH_GETENV_HPP_INCLUDED
9746
9747
9748#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
9749#define CATCH_IS_PERMUTATION_HPP_INCLUDED
9750
9751#include <algorithm>
9752#include <iterator>
9753
9754namespace Catch {
9755 namespace Detail {
9756
9757 template <typename ForwardIter,
9758 typename Sentinel,
9759 typename T,
9760 typename Comparator>
9761 constexpr
9762 ForwardIter find_sentinel( ForwardIter start,
9763 Sentinel sentinel,
9764 T const& value,
9765 Comparator cmp ) {
9766 while ( start != sentinel ) {
9767 if ( cmp( *start, value ) ) { break; }
9768 ++start;
9769 }
9770 return start;
9771 }
9772
9773 template <typename ForwardIter,
9774 typename Sentinel,
9775 typename T,
9776 typename Comparator>
9777 constexpr
9778 std::ptrdiff_t count_sentinel( ForwardIter start,
9779 Sentinel sentinel,
9780 T const& value,
9781 Comparator cmp ) {
9782 std::ptrdiff_t count = 0;
9783 while ( start != sentinel ) {
9784 if ( cmp( *start, value ) ) { ++count; }
9785 ++start;
9786 }
9787 return count;
9788 }
9789
9790 template <typename ForwardIter, typename Sentinel>
9791 constexpr
9792 std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
9793 std::ptrdiff_t>
9794 sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
9795 std::ptrdiff_t dist = 0;
9796 while ( iter != sentinel ) {
9797 ++iter;
9798 ++dist;
9799 }
9800 return dist;
9801 }
9802
9803 template <typename ForwardIter>
9804 constexpr std::ptrdiff_t sentinel_distance( ForwardIter first,
9805 ForwardIter last ) {
9806 return std::distance( first, last );
9807 }
9808
9809 template <typename ForwardIter1,
9810 typename Sentinel1,
9811 typename ForwardIter2,
9812 typename Sentinel2,
9813 typename Comparator>
9814 constexpr bool check_element_counts( ForwardIter1 first_1,
9815 const Sentinel1 end_1,
9816 ForwardIter2 first_2,
9817 const Sentinel2 end_2,
9818 Comparator cmp ) {
9819 auto cursor = first_1;
9820 while ( cursor != end_1 ) {
9821 if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
9822 cursor ) {
9823 // we haven't checked this element yet
9824 const auto count_in_range_2 =
9825 count_sentinel( first_2, end_2, *cursor, cmp );
9826 // Not a single instance in 2nd range, so it cannot be a
9827 // permutation of 1st range
9828 if ( count_in_range_2 == 0 ) { return false; }
9829
9830 const auto count_in_range_1 =
9831 count_sentinel( cursor, end_1, *cursor, cmp );
9832 if ( count_in_range_1 != count_in_range_2 ) {
9833 return false;
9834 }
9835 }
9836
9837 ++cursor;
9838 }
9839
9840 return true;
9841 }
9842
9843 template <typename ForwardIter1,
9844 typename Sentinel1,
9845 typename ForwardIter2,
9846 typename Sentinel2,
9847 typename Comparator>
9848 constexpr bool is_permutation( ForwardIter1 first_1,
9849 const Sentinel1 end_1,
9850 ForwardIter2 first_2,
9851 const Sentinel2 end_2,
9852 Comparator cmp ) {
9853 // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types
9854 // TODO: Comparator has to be "both sides", e.g. a == b => b == a
9855 // This skips shared prefix of the two ranges
9856 while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
9857 ++first_1;
9858 ++first_2;
9859 }
9860
9861 // We need to handle case where at least one of the ranges has no more elements
9862 if (first_1 == end_1 || first_2 == end_2) {
9863 return first_1 == end_1 && first_2 == end_2;
9864 }
9865
9866 // pair counting is n**2, so we pay linear walk to compare the sizes first
9867 auto dist_1 = sentinel_distance( first_1, end_1 );
9868 auto dist_2 = sentinel_distance( first_2, end_2 );
9869
9870 if (dist_1 != dist_2) { return false; }
9871
9872 // Since we do not try to handle stronger iterators pair (e.g.
9873 // bidir) optimally, the only thing left to do is to check counts in
9874 // the remaining ranges.
9875 return check_element_counts( first_1, end_1, first_2, end_2, cmp );
9876 }
9877
9878 } // namespace Detail
9879} // namespace Catch
9880
9881#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED
9882
9883
9884#ifndef CATCH_ISTREAM_HPP_INCLUDED
9885#define CATCH_ISTREAM_HPP_INCLUDED
9886
9887
9888#include <iosfwd>
9889#include <cstddef>
9890#include <ostream>
9891#include <string>
9892
9893namespace Catch {
9894
9895 class IStream {
9896 public:
9897 virtual ~IStream(); // = default
9898 virtual std::ostream& stream() = 0;
9899 /**
9900 * Best guess on whether the instance is writing to a console (e.g. via stdout/stderr)
9901 *
9902 * This is useful for e.g. Win32 colour support, because the Win32
9903 * API manipulates console directly, unlike POSIX escape codes,
9904 * that can be written anywhere.
9905 *
9906 * Due to variety of ways to change where the stdout/stderr is
9907 * _actually_ being written, users should always assume that
9908 * the answer might be wrong.
9909 */
9910 virtual bool isConsole() const { return false; }
9911 };
9912
9913 /**
9914 * Creates a stream wrapper that writes to specific file.
9915 *
9916 * Also recognizes 4 special filenames
9917 * * `-` for stdout
9918 * * `%stdout` for stdout
9919 * * `%stderr` for stderr
9920 * * `%debug` for platform specific debugging output
9921 *
9922 * \throws if passed an unrecognized %-prefixed stream
9923 */
9924 auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream>;
9925
9926}
9927
9928#endif // CATCH_STREAM_HPP_INCLUDED
9929
9930
9931#ifndef CATCH_JSONWRITER_HPP_INCLUDED
9932#define CATCH_JSONWRITER_HPP_INCLUDED
9933
9934
9935#include <cstdint>
9936#include <sstream>
9937
9938namespace Catch {
9939 class JsonObjectWriter;
9940 class JsonArrayWriter;
9941
9942 struct JsonUtils {
9943 static void indent( std::ostream& os, std::uint64_t level );
9944 static void appendCommaNewline( std::ostream& os,
9945 bool& should_comma,
9946 std::uint64_t level );
9947 };
9948
9949 class JsonValueWriter {
9950 public:
9951 JsonValueWriter( std::ostream& os );
9952 JsonValueWriter( std::ostream& os, std::uint64_t indent_level );
9953
9954 JsonObjectWriter writeObject() &&;
9955 JsonArrayWriter writeArray() &&;
9956
9957 template <typename T>
9958 void write( T const& value ) && {
9959 writeImpl( value, !std::is_arithmetic<T>::value );
9960 }
9961 void write( StringRef value ) &&;
9962 void write( bool value ) &&;
9963
9964 private:
9965 void writeImpl( StringRef value, bool quote );
9966
9967 // Without this SFINAE, this overload is a better match
9968 // for `std::string`, `char const*`, `char const[N]` args.
9969 // While it would still work, it would cause code bloat
9970 // and multiple iteration over the strings
9971 template <typename T,
9972 typename = typename std::enable_if_t<
9973 !std::is_convertible<T, StringRef>::value>>
9974 void writeImpl( T const& value, bool quote_value ) {
9975 m_sstream << value;
9976 writeImpl( m_sstream.str(), quote_value );
9977 }
9978
9979 std::ostream& m_os;
9980 std::stringstream m_sstream;
9981 std::uint64_t m_indent_level;
9982 };
9983
9984 class JsonObjectWriter {
9985 public:
9986 JsonObjectWriter( std::ostream& os );
9987 JsonObjectWriter( std::ostream& os, std::uint64_t indent_level );
9988
9989 JsonObjectWriter( JsonObjectWriter&& source ) noexcept;
9990 JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete;
9991
9992 ~JsonObjectWriter();
9993
9994 JsonValueWriter write( StringRef key );
9995
9996 private:
9997 std::ostream& m_os;
9998 std::uint64_t m_indent_level;
9999 bool m_should_comma = false;
10000 bool m_active = true;
10001 };
10002
10003 class JsonArrayWriter {
10004 public:
10005 JsonArrayWriter( std::ostream& os );
10006 JsonArrayWriter( std::ostream& os, std::uint64_t indent_level );
10007
10008 JsonArrayWriter( JsonArrayWriter&& source ) noexcept;
10009 JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete;
10010
10011 ~JsonArrayWriter();
10012
10013 JsonObjectWriter writeObject();
10014 JsonArrayWriter writeArray();
10015
10016 template <typename T>
10017 JsonArrayWriter& write( T const& value ) {
10018 return writeImpl( value );
10019 }
10020
10021 JsonArrayWriter& write( bool value );
10022
10023 private:
10024 template <typename T>
10025 JsonArrayWriter& writeImpl( T const& value ) {
10026 JsonUtils::appendCommaNewline(
10027 m_os, m_should_comma, m_indent_level + 1 );
10028 JsonValueWriter{ m_os }.write( value );
10029
10030 return *this;
10031 }
10032
10033 std::ostream& m_os;
10034 std::uint64_t m_indent_level;
10035 bool m_should_comma = false;
10036 bool m_active = true;
10037 };
10038
10039} // namespace Catch
10040
10041#endif // CATCH_JSONWRITER_HPP_INCLUDED
10042
10043
10044#ifndef CATCH_LEAK_DETECTOR_HPP_INCLUDED
10045#define CATCH_LEAK_DETECTOR_HPP_INCLUDED
10046
10047namespace Catch {
10048
10049 struct LeakDetector {
10050 LeakDetector();
10051 ~LeakDetector();
10052 };
10053
10054}
10055#endif // CATCH_LEAK_DETECTOR_HPP_INCLUDED
10056
10057
10058#ifndef CATCH_LIST_HPP_INCLUDED
10059#define CATCH_LIST_HPP_INCLUDED
10060
10061
10062#include <set>
10063#include <string>
10064
10065
10066namespace Catch {
10067
10068 class IEventListener;
10069 class Config;
10070
10071
10072 struct ReporterDescription {
10073 std::string name, description;
10074 };
10075 struct ListenerDescription {
10076 StringRef name;
10077 std::string description;
10078 };
10079
10080 struct TagInfo {
10081 void add(StringRef spelling);
10082 std::string all() const;
10083
10084 std::set<StringRef> spellings;
10085 std::size_t count = 0;
10086 };
10087
10088 bool list( IEventListener& reporter, Config const& config );
10089
10090} // end namespace Catch
10091
10092#endif // CATCH_LIST_HPP_INCLUDED
10093
10094
10095#ifndef CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
10096#define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
10097
10098
10099#include <cassert>
10100#include <string>
10101
10102namespace Catch {
10103
10104 class OutputRedirect {
10105 bool m_redirectActive = false;
10106 virtual void activateImpl() = 0;
10107 virtual void deactivateImpl() = 0;
10108 public:
10109 enum Kind {
10110 //! No redirect (noop implementation)
10111 None,
10112 //! Redirect std::cout/std::cerr/std::clog streams internally
10113 Streams,
10114 //! Redirect the stdout/stderr file descriptors into files
10115 FileDescriptors,
10116 };
10117
10118 virtual ~OutputRedirect(); // = default;
10119
10120 // TODO: Do we want to check that redirect is not active before retrieving the output?
10121 virtual std::string getStdout() = 0;
10122 virtual std::string getStderr() = 0;
10123 virtual void clearBuffers() = 0;
10124 bool isActive() const { return m_redirectActive; }
10125 void activate() {
10126 assert( !m_redirectActive && "redirect is already active" );
10127 activateImpl();
10128 m_redirectActive = true;
10129 }
10130 void deactivate() {
10131 assert( m_redirectActive && "redirect is not active" );
10132 deactivateImpl();
10133 m_redirectActive = false;
10134 }
10135 };
10136
10137 bool isRedirectAvailable( OutputRedirect::Kind kind);
10138 Detail::unique_ptr<OutputRedirect> makeOutputRedirect( bool actual );
10139
10140 class RedirectGuard {
10141 OutputRedirect* m_redirect;
10142 bool m_activate;
10143 bool m_previouslyActive;
10144 bool m_moved = false;
10145
10146 public:
10147 RedirectGuard( bool activate, OutputRedirect& redirectImpl );
10148 ~RedirectGuard() noexcept( false );
10149
10150 RedirectGuard( RedirectGuard const& ) = delete;
10151 RedirectGuard& operator=( RedirectGuard const& ) = delete;
10152
10153 // C++14 needs move-able guards to return them from functions
10154 RedirectGuard( RedirectGuard&& rhs ) noexcept;
10155 RedirectGuard& operator=( RedirectGuard&& rhs ) noexcept;
10156 };
10157
10158 RedirectGuard scopedActivate( OutputRedirect& redirectImpl );
10159 RedirectGuard scopedDeactivate( OutputRedirect& redirectImpl );
10160
10161} // end namespace Catch
10162
10163#endif // CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
10164
10165
10166#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED
10167#define CATCH_PARSE_NUMBERS_HPP_INCLUDED
10168
10169
10170#include <string>
10171
10172namespace Catch {
10173
10174 /**
10175 * Parses unsigned int from the input, using provided base
10176 *
10177 * Effectively a wrapper around std::stoul but with better error checking
10178 * e.g. "-1" is rejected, instead of being parsed as UINT_MAX.
10179 */
10180 Optional<unsigned int> parseUInt(std::string const& input, int base = 10);
10181}
10182
10183#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED
10184
10185
10186#ifndef CATCH_REPORTER_REGISTRY_HPP_INCLUDED
10187#define CATCH_REPORTER_REGISTRY_HPP_INCLUDED
10188
10189
10190#include <map>
10191#include <string>
10192#include <vector>
10193
10194namespace Catch {
10195
10196 class IEventListener;
10197 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
10198 class IReporterFactory;
10199 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
10200 struct ReporterConfig;
10201 class EventListenerFactory;
10202
10203 class ReporterRegistry {
10204 struct ReporterRegistryImpl;
10205 Detail::unique_ptr<ReporterRegistryImpl> m_impl;
10206
10207 public:
10208 ReporterRegistry();
10209 ~ReporterRegistry(); // = default;
10210
10211 IEventListenerPtr create( std::string const& name,
10212 ReporterConfig&& config ) const;
10213
10214 void registerReporter( std::string const& name,
10215 IReporterFactoryPtr factory );
10216
10217 void
10218 registerListener( Detail::unique_ptr<EventListenerFactory> factory );
10219
10220 std::map<std::string,
10221 IReporterFactoryPtr,
10222 Detail::CaseInsensitiveLess> const&
10223 getFactories() const;
10224
10225 std::vector<Detail::unique_ptr<EventListenerFactory>> const&
10226 getListeners() const;
10227 };
10228
10229} // end namespace Catch
10230
10231#endif // CATCH_REPORTER_REGISTRY_HPP_INCLUDED
10232
10233
10234#ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED
10235#define CATCH_RUN_CONTEXT_HPP_INCLUDED
10236
10237
10238
10239#ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
10240#define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
10241
10242
10243#include <string>
10244#include <vector>
10245
10246namespace Catch {
10247namespace TestCaseTracking {
10248
10249 struct NameAndLocation {
10250 std::string name;
10251 SourceLineInfo location;
10252
10253 NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
10254 friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
10255 // This is a very cheap check that should have a very high hit rate.
10256 // If we get to SourceLineInfo::operator==, we will redo it, but the
10257 // cost of repeating is trivial at that point (we will be paying
10258 // multiple strcmp/memcmps at that point).
10259 if ( lhs.location.line != rhs.location.line ) { return false; }
10260 return lhs.name == rhs.name && lhs.location == rhs.location;
10261 }
10262 friend bool operator!=(NameAndLocation const& lhs,
10263 NameAndLocation const& rhs) {
10264 return !( lhs == rhs );
10265 }
10266 };
10267
10268 /**
10269 * This is a variant of `NameAndLocation` that does not own the name string
10270 *
10271 * This avoids extra allocations when trying to locate a tracker by its
10272 * name and location, as long as we make sure that trackers only keep
10273 * around the owning variant.
10274 */
10275 struct NameAndLocationRef {
10276 StringRef name;
10277 SourceLineInfo location;
10278
10279 constexpr NameAndLocationRef( StringRef name_,
10280 SourceLineInfo location_ ):
10281 name( name_ ), location( location_ ) {}
10282
10283 friend bool operator==( NameAndLocation const& lhs,
10284 NameAndLocationRef const& rhs ) {
10285 // This is a very cheap check that should have a very high hit rate.
10286 // If we get to SourceLineInfo::operator==, we will redo it, but the
10287 // cost of repeating is trivial at that point (we will be paying
10288 // multiple strcmp/memcmps at that point).
10289 if ( lhs.location.line != rhs.location.line ) { return false; }
10290 return StringRef( lhs.name ) == rhs.name &&
10291 lhs.location == rhs.location;
10292 }
10293 friend bool operator==( NameAndLocationRef const& lhs,
10294 NameAndLocation const& rhs ) {
10295 return rhs == lhs;
10296 }
10297 };
10298
10299 class ITracker;
10300
10301 using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
10302
10303 class ITracker {
10304 NameAndLocation m_nameAndLocation;
10305
10306 using Children = std::vector<ITrackerPtr>;
10307
10308 protected:
10309 enum CycleState {
10310 NotStarted,
10311 Executing,
10312 ExecutingChildren,
10313 NeedsAnotherRun,
10314 CompletedSuccessfully,
10315 Failed
10316 };
10317
10318 ITracker* m_parent = nullptr;
10319 Children m_children;
10320 CycleState m_runState = NotStarted;
10321
10322 public:
10323 ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
10324 m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
10325 m_parent( parent )
10326 {}
10327
10328
10329 // static queries
10330 NameAndLocation const& nameAndLocation() const {
10331 return m_nameAndLocation;
10332 }
10333 ITracker* parent() const {
10334 return m_parent;
10335 }
10336
10337 virtual ~ITracker(); // = default
10338
10339
10340 // dynamic queries
10341
10342 //! Returns true if tracker run to completion (successfully or not)
10343 virtual bool isComplete() const = 0;
10344 //! Returns true if tracker run to completion successfully
10345 bool isSuccessfullyCompleted() const {
10346 return m_runState == CompletedSuccessfully;
10347 }
10348 //! Returns true if tracker has started but hasn't been completed
10349 bool isOpen() const;
10350 //! Returns true iff tracker has started
10351 bool hasStarted() const;
10352
10353 // actions
10354 virtual void close() = 0; // Successfully complete
10355 virtual void fail() = 0;
10356 void markAsNeedingAnotherRun();
10357
10358 //! Register a nested ITracker
10359 void addChild( ITrackerPtr&& child );
10360 /**
10361 * Returns ptr to specific child if register with this tracker.
10362 *
10363 * Returns nullptr if not found.
10364 */
10365 ITracker* findChild( NameAndLocationRef const& nameAndLocation );
10366 //! Have any children been added?
10367 bool hasChildren() const {
10368 return !m_children.empty();
10369 }
10370
10371
10372 //! Marks tracker as executing a child, doing se recursively up the tree
10373 void openChild();
10374
10375 /**
10376 * Returns true if the instance is a section tracker
10377 *
10378 * Subclasses should override to true if they are, replaces RTTI
10379 * for internal debug checks.
10380 */
10381 virtual bool isSectionTracker() const;
10382 /**
10383 * Returns true if the instance is a generator tracker
10384 *
10385 * Subclasses should override to true if they are, replaces RTTI
10386 * for internal debug checks.
10387 */
10388 virtual bool isGeneratorTracker() const;
10389 };
10390
10391 class TrackerContext {
10392
10393 enum RunState {
10394 NotStarted,
10395 Executing,
10396 CompletedCycle
10397 };
10398
10399 ITrackerPtr m_rootTracker;
10400 ITracker* m_currentTracker = nullptr;
10401 RunState m_runState = NotStarted;
10402
10403 public:
10404
10405 ITracker& startRun();
10406
10407 void startCycle() {
10408 m_currentTracker = m_rootTracker.get();
10409 m_runState = Executing;
10410 }
10411 void completeCycle();
10412
10413 bool completedCycle() const;
10414 ITracker& currentTracker() { return *m_currentTracker; }
10415 void setCurrentTracker( ITracker* tracker );
10416 };
10417
10418 class TrackerBase : public ITracker {
10419 protected:
10420
10421 TrackerContext& m_ctx;
10422
10423 public:
10424 TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
10425
10426 bool isComplete() const override;
10427
10428 void open();
10429
10430 void close() override;
10431 void fail() override;
10432
10433 private:
10434 void moveToParent();
10435 void moveToThis();
10436 };
10437
10438 class SectionTracker : public TrackerBase {
10439 std::vector<StringRef> m_filters;
10440 // Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
10441 // Currently it allocates owns the name, so this is safe. If it is later refactored
10442 // to not own the name, the name still has to outlive the `ITracker` parent, so
10443 // this should still be safe.
10444 StringRef m_trimmed_name;
10445 public:
10446 SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
10447
10448 bool isSectionTracker() const override;
10449
10450 bool isComplete() const override;
10451
10452 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
10453
10454 void tryOpen();
10455
10456 void addInitialFilters( std::vector<std::string> const& filters );
10457 void addNextFilters( std::vector<StringRef> const& filters );
10458 //! Returns filters active in this tracker
10459 std::vector<StringRef> const& getFilters() const { return m_filters; }
10460 //! Returns whitespace-trimmed name of the tracked section
10461 StringRef trimmedName() const;
10462 };
10463
10464} // namespace TestCaseTracking
10465
10466using TestCaseTracking::ITracker;
10467using TestCaseTracking::TrackerContext;
10468using TestCaseTracking::SectionTracker;
10469
10470} // namespace Catch
10471
10472#endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
10473
10474#include <string>
10475
10476namespace Catch {
10477
10478 class IGeneratorTracker;
10479 class IConfig;
10480 class IEventListener;
10481 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
10482 class OutputRedirect;
10483
10484 ///////////////////////////////////////////////////////////////////////////
10485
10486 class RunContext final : public IResultCapture {
10487
10488 public:
10489 RunContext( RunContext const& ) = delete;
10490 RunContext& operator =( RunContext const& ) = delete;
10491
10492 explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter );
10493
10494 ~RunContext() override;
10495
10496 Totals runTest(TestCaseHandle const& testCase);
10497
10498 public: // IResultCapture
10499
10500 // Assertion handlers
10501 void handleExpr
10502 ( AssertionInfo const& info,
10503 ITransientExpression const& expr,
10504 AssertionReaction& reaction ) override;
10505 void handleMessage
10506 ( AssertionInfo const& info,
10507 ResultWas::OfType resultType,
10508 std::string&& message,
10509 AssertionReaction& reaction ) override;
10510 void handleUnexpectedExceptionNotThrown
10511 ( AssertionInfo const& info,
10512 AssertionReaction& reaction ) override;
10513 void handleUnexpectedInflightException
10514 ( AssertionInfo const& info,
10515 std::string&& message,
10516 AssertionReaction& reaction ) override;
10517 void handleIncomplete
10518 ( AssertionInfo const& info ) override;
10519 void handleNonExpr
10520 ( AssertionInfo const &info,
10521 ResultWas::OfType resultType,
10522 AssertionReaction &reaction ) override;
10523
10524 void notifyAssertionStarted( AssertionInfo const& info ) override;
10525 bool sectionStarted( StringRef sectionName,
10526 SourceLineInfo const& sectionLineInfo,
10527 Counts& assertions ) override;
10528
10529 void sectionEnded( SectionEndInfo&& endInfo ) override;
10530 void sectionEndedEarly( SectionEndInfo&& endInfo ) override;
10531
10532 IGeneratorTracker*
10533 acquireGeneratorTracker( StringRef generatorName,
10534 SourceLineInfo const& lineInfo ) override;
10535 IGeneratorTracker* createGeneratorTracker(
10536 StringRef generatorName,
10537 SourceLineInfo lineInfo,
10538 Generators::GeneratorBasePtr&& generator ) override;
10539
10540
10541 void benchmarkPreparing( StringRef name ) override;
10542 void benchmarkStarting( BenchmarkInfo const& info ) override;
10543 void benchmarkEnded( BenchmarkStats<> const& stats ) override;
10544 void benchmarkFailed( StringRef error ) override;
10545
10546 void pushScopedMessage( MessageInfo const& message ) override;
10547 void popScopedMessage( MessageInfo const& message ) override;
10548
10549 void emplaceUnscopedMessage( MessageBuilder&& builder ) override;
10550
10551 std::string getCurrentTestName() const override;
10552
10553 const AssertionResult* getLastResult() const override;
10554
10555 void exceptionEarlyReported() override;
10556
10557 void handleFatalErrorCondition( StringRef message ) override;
10558
10559 bool lastAssertionPassed() override;
10560
10561 void assertionPassed() override;
10562
10563 public:
10564 // !TBD We need to do this another way!
10565 bool aborting() const;
10566
10567 private:
10568
10569 void runCurrentTest();
10570 void invokeActiveTestCase();
10571
10572 void resetAssertionInfo();
10573 bool testForMissingAssertions( Counts& assertions );
10574
10575 void assertionEnded( AssertionResult&& result );
10576 void reportExpr
10577 ( AssertionInfo const &info,
10578 ResultWas::OfType resultType,
10579 ITransientExpression const *expr,
10580 bool negated );
10581
10582 void populateReaction( AssertionReaction& reaction );
10583
10584 private:
10585
10586 void handleUnfinishedSections();
10587
10588 TestRunInfo m_runInfo;
10589 TestCaseHandle const* m_activeTestCase = nullptr;
10590 ITracker* m_testCaseTracker = nullptr;
10591 Optional<AssertionResult> m_lastResult;
10592
10593 IConfig const* m_config;
10594 Totals m_totals;
10595 IEventListenerPtr m_reporter;
10596 std::vector<MessageInfo> m_messages;
10597 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
10598 AssertionInfo m_lastAssertionInfo;
10599 std::vector<SectionEndInfo> m_unfinishedSections;
10600 std::vector<ITracker*> m_activeSections;
10601 TrackerContext m_trackerContext;
10602 Detail::unique_ptr<OutputRedirect> m_outputRedirect;
10603 FatalConditionHandler m_fatalConditionhandler;
10604 bool m_lastAssertionPassed = false;
10605 bool m_shouldReportUnexpected = true;
10606 bool m_includeSuccessfulResults;
10607 };
10608
10609 void seedRng(IConfig const& config);
10610 unsigned int rngSeed();
10611} // end namespace Catch
10612
10613#endif // CATCH_RUN_CONTEXT_HPP_INCLUDED
10614
10615
10616#ifndef CATCH_SHARDING_HPP_INCLUDED
10617#define CATCH_SHARDING_HPP_INCLUDED
10618
10619#include <cassert>
10620#include <cmath>
10621#include <algorithm>
10622
10623namespace Catch {
10624
10625 template<typename Container>
10626 Container createShard(Container const& container, std::size_t const shardCount, std::size_t const shardIndex) {
10627 assert(shardCount > shardIndex);
10628
10629 if (shardCount == 1) {
10630 return container;
10631 }
10632
10633 const std::size_t totalTestCount = container.size();
10634
10635 const std::size_t shardSize = totalTestCount / shardCount;
10636 const std::size_t leftoverTests = totalTestCount % shardCount;
10637
10638 const std::size_t startIndex = shardIndex * shardSize + (std::min)(shardIndex, leftoverTests);
10639 const std::size_t endIndex = (shardIndex + 1) * shardSize + (std::min)(shardIndex + 1, leftoverTests);
10640
10641 auto startIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(startIndex));
10642 auto endIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(endIndex));
10643
10644 return Container(startIterator, endIterator);
10645 }
10646
10647}
10648
10649#endif // CATCH_SHARDING_HPP_INCLUDED
10650
10651
10652#ifndef CATCH_SINGLETONS_HPP_INCLUDED
10653#define CATCH_SINGLETONS_HPP_INCLUDED
10654
10655namespace Catch {
10656
10657 struct ISingleton {
10658 virtual ~ISingleton(); // = default
10659 };
10660
10661
10662 void addSingleton( ISingleton* singleton );
10663 void cleanupSingletons();
10664
10665
10666 template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
10667 class Singleton : SingletonImplT, public ISingleton {
10668
10669 static auto getInternal() -> Singleton* {
10670 static Singleton* s_instance = nullptr;
10671 if( !s_instance ) {
10672 s_instance = new Singleton;
10673 addSingleton( s_instance );
10674 }
10675 return s_instance;
10676 }
10677
10678 public:
10679 static auto get() -> InterfaceT const& {
10680 return *getInternal();
10681 }
10682 static auto getMutable() -> MutableInterfaceT& {
10683 return *getInternal();
10684 }
10685 };
10686
10687} // namespace Catch
10688
10689#endif // CATCH_SINGLETONS_HPP_INCLUDED
10690
10691
10692#ifndef CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
10693#define CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
10694
10695
10696#include <vector>
10697#include <exception>
10698
10699namespace Catch {
10700
10701 class StartupExceptionRegistry {
10702#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
10703 public:
10704 void add(std::exception_ptr const& exception) noexcept;
10705 std::vector<std::exception_ptr> const& getExceptions() const noexcept;
10706 private:
10707 std::vector<std::exception_ptr> m_exceptions;
10708#endif
10709 };
10710
10711} // end namespace Catch
10712
10713#endif // CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
10714
10715
10716
10717#ifndef CATCH_STDSTREAMS_HPP_INCLUDED
10718#define CATCH_STDSTREAMS_HPP_INCLUDED
10719
10720#include <iosfwd>
10721
10722namespace Catch {
10723
10724 std::ostream& cout();
10725 std::ostream& cerr();
10726 std::ostream& clog();
10727
10728} // namespace Catch
10729
10730#endif
10731
10732
10733#ifndef CATCH_STRING_MANIP_HPP_INCLUDED
10734#define CATCH_STRING_MANIP_HPP_INCLUDED
10735
10736
10737#include <cstdint>
10738#include <string>
10739#include <iosfwd>
10740#include <vector>
10741
10742namespace Catch {
10743
10744 bool startsWith( std::string const& s, std::string const& prefix );
10745 bool startsWith( StringRef s, char prefix );
10746 bool endsWith( std::string const& s, std::string const& suffix );
10747 bool endsWith( std::string const& s, char suffix );
10748 bool contains( std::string const& s, std::string const& infix );
10749 void toLowerInPlace( std::string& s );
10750 std::string toLower( std::string const& s );
10751 char toLower( char c );
10752 //! Returns a new string without whitespace at the start/end
10753 std::string trim( std::string const& str );
10754 //! Returns a substring of the original ref without whitespace. Beware lifetimes!
10755 StringRef trim(StringRef ref);
10756
10757 // !!! Be aware, returns refs into original string - make sure original string outlives them
10758 std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
10759 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
10760
10761 /**
10762 * Helper for streaming a "count [maybe-plural-of-label]" human-friendly string
10763 *
10764 * Usage example:
10765 * ```cpp
10766 * std::cout << "Found " << pluralise(count, "error") << '\n';
10767 * ```
10768 *
10769 * **Important:** The provided string must outlive the instance
10770 */
10771 class pluralise {
10772 std::uint64_t m_count;
10773 StringRef m_label;
10774
10775 public:
10776 constexpr pluralise(std::uint64_t count, StringRef label):
10777 m_count(count),
10778 m_label(label)
10779 {}
10780
10781 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
10782 };
10783}
10784
10785#endif // CATCH_STRING_MANIP_HPP_INCLUDED
10786
10787
10788#ifndef CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
10789#define CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
10790
10791
10792#include <map>
10793#include <string>
10794
10795namespace Catch {
10796 struct SourceLineInfo;
10797
10798 class TagAliasRegistry : public ITagAliasRegistry {
10799 public:
10800 ~TagAliasRegistry() override;
10801 TagAlias const* find( std::string const& alias ) const override;
10802 std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
10803 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
10804
10805 private:
10806 std::map<std::string, TagAlias> m_registry;
10807 };
10808
10809} // end namespace Catch
10810
10811#endif // CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
10812
10813
10814#ifndef CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
10815#define CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
10816
10817#include <cstdint>
10818
10819namespace Catch {
10820
10821 struct TestCaseInfo;
10822
10823 class TestCaseInfoHasher {
10824 public:
10825 using hash_t = std::uint64_t;
10826 TestCaseInfoHasher( hash_t seed );
10827 uint32_t operator()( TestCaseInfo const& t ) const;
10828
10829 private:
10830 hash_t m_seed;
10831 };
10832
10833} // namespace Catch
10834
10835#endif /* CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED */
10836
10837
10838#ifndef CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
10839#define CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
10840
10841
10842#include <vector>
10843
10844namespace Catch {
10845
10846 class IConfig;
10847 class ITestInvoker;
10848 class TestCaseHandle;
10849 class TestSpec;
10850
10851 std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases );
10852
10853 bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config );
10854
10855 std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
10856 std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
10857
10858 class TestRegistry : public ITestCaseRegistry {
10859 public:
10860 void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
10861
10862 std::vector<TestCaseInfo*> const& getAllInfos() const override;
10863 std::vector<TestCaseHandle> const& getAllTests() const override;
10864 std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override;
10865
10866 ~TestRegistry() override; // = default
10867
10868 private:
10869 std::vector<Detail::unique_ptr<TestCaseInfo>> m_owned_test_infos;
10870 // Keeps a materialized vector for `getAllInfos`.
10871 // We should get rid of that eventually (see interface note)
10872 std::vector<TestCaseInfo*> m_viewed_test_infos;
10873
10874 std::vector<Detail::unique_ptr<ITestInvoker>> m_invokers;
10875 std::vector<TestCaseHandle> m_handles;
10876 mutable TestRunOrder m_currentSortOrder = TestRunOrder::Declared;
10877 mutable std::vector<TestCaseHandle> m_sortedFunctions;
10878 };
10879
10880 ///////////////////////////////////////////////////////////////////////////
10881
10882
10883} // end namespace Catch
10884
10885
10886#endif // CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
10887
10888
10889#ifndef CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
10890#define CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
10891
10892#ifdef __clang__
10893#pragma clang diagnostic push
10894#pragma clang diagnostic ignored "-Wpadded"
10895#endif
10896
10897
10898#include <vector>
10899#include <string>
10900
10901namespace Catch {
10902
10903 class ITagAliasRegistry;
10904
10905 class TestSpecParser {
10906 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
10907 Mode m_mode = None;
10908 Mode lastMode = None;
10909 bool m_exclusion = false;
10910 std::size_t m_pos = 0;
10911 std::size_t m_realPatternPos = 0;
10912 std::string m_arg;
10913 std::string m_substring;
10914 std::string m_patternName;
10915 std::vector<std::size_t> m_escapeChars;
10916 TestSpec::Filter m_currentFilter;
10917 TestSpec m_testSpec;
10918 ITagAliasRegistry const* m_tagAliases = nullptr;
10919
10920 public:
10921 TestSpecParser( ITagAliasRegistry const& tagAliases );
10922
10923 TestSpecParser& parse( std::string const& arg );
10924 TestSpec testSpec();
10925
10926 private:
10927 bool visitChar( char c );
10928 void startNewMode( Mode mode );
10929 bool processNoneChar( char c );
10930 void processNameChar( char c );
10931 bool processOtherChar( char c );
10932 void endMode();
10933 void escape();
10934 bool isControlChar( char c ) const;
10935 void saveLastMode();
10936 void revertBackToLastMode();
10937 void addFilter();
10938 bool separate();
10939
10940 // Handles common preprocessing of the pattern for name/tag patterns
10941 std::string preprocessPattern();
10942 // Adds the current pattern as a test name
10943 void addNamePattern();
10944 // Adds the current pattern as a tag
10945 void addTagPattern();
10946
10947 inline void addCharToPattern(char c) {
10948 m_substring += c;
10949 m_patternName += c;
10950 m_realPatternPos++;
10951 }
10952
10953 };
10954
10955} // namespace Catch
10956
10957#ifdef __clang__
10958#pragma clang diagnostic pop
10959#endif
10960
10961#endif // CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
10962
10963
10964#ifndef CATCH_TEXTFLOW_HPP_INCLUDED
10965#define CATCH_TEXTFLOW_HPP_INCLUDED
10966
10967
10968#include <cassert>
10969#include <string>
10970#include <vector>
10971
10972namespace Catch {
10973 namespace TextFlow {
10974
10975 class Columns;
10976
10977 /**
10978 * Abstraction for a string with ansi escape sequences that
10979 * automatically skips over escapes when iterating. Only graphical
10980 * escape sequences are considered.
10981 *
10982 * Internal representation:
10983 * An escape sequence looks like \033[39;49m
10984 * We need bidirectional iteration and the unbound length of escape
10985 * sequences poses a problem for operator-- To make this work we'll
10986 * replace the last `m` with a 0xff (this is a codepoint that won't have
10987 * any utf-8 meaning).
10988 */
10989 class AnsiSkippingString {
10990 std::string m_string;
10991 std::size_t m_size = 0;
10992
10993 // perform 0xff replacement and calculate m_size
10994 void preprocessString();
10995
10996 public:
10997 class const_iterator;
10998 using iterator = const_iterator;
10999 // note: must be u-suffixed or this will cause a "truncation of
11000 // constant value" warning on MSVC
11001 static constexpr char sentinel = static_cast<char>( 0xffu );
11002
11003 explicit AnsiSkippingString( std::string const& text );
11004 explicit AnsiSkippingString( std::string&& text );
11005
11006 const_iterator begin() const;
11007 const_iterator end() const;
11008
11009 size_t size() const { return m_size; }
11010
11011 std::string substring( const_iterator begin,
11012 const_iterator end ) const;
11013 };
11014
11015 class AnsiSkippingString::const_iterator {
11016 friend AnsiSkippingString;
11017 struct EndTag {};
11018
11019 const std::string* m_string;
11020 std::string::const_iterator m_it;
11021
11022 explicit const_iterator( const std::string& string, EndTag ):
11023 m_string( &string ), m_it( string.end() ) {}
11024
11025 void tryParseAnsiEscapes();
11026 void advance();
11027 void unadvance();
11028
11029 public:
11030 using difference_type = std::ptrdiff_t;
11031 using value_type = char;
11032 using pointer = value_type*;
11033 using reference = value_type&;
11034 using iterator_category = std::bidirectional_iterator_tag;
11035
11036 explicit const_iterator( const std::string& string ):
11037 m_string( &string ), m_it( string.begin() ) {
11038 tryParseAnsiEscapes();
11039 }
11040
11041 char operator*() const { return *m_it; }
11042
11043 const_iterator& operator++() {
11044 advance();
11045 return *this;
11046 }
11047 const_iterator operator++( int ) {
11048 iterator prev( *this );
11049 operator++();
11050 return prev;
11051 }
11052 const_iterator& operator--() {
11053 unadvance();
11054 return *this;
11055 }
11056 const_iterator operator--( int ) {
11057 iterator prev( *this );
11058 operator--();
11059 return prev;
11060 }
11061
11062 bool operator==( const_iterator const& other ) const {
11063 return m_it == other.m_it;
11064 }
11065 bool operator!=( const_iterator const& other ) const {
11066 return !operator==( other );
11067 }
11068 bool operator<=( const_iterator const& other ) const {
11069 return m_it <= other.m_it;
11070 }
11071
11072 const_iterator oneBefore() const {
11073 auto it = *this;
11074 return --it;
11075 }
11076 };
11077
11078 /**
11079 * Represents a column of text with specific width and indentation
11080 *
11081 * When written out to a stream, it will perform linebreaking
11082 * of the provided text so that the written lines fit within
11083 * target width.
11084 */
11085 class Column {
11086 // String to be written out
11087 AnsiSkippingString m_string;
11088 // Width of the column for linebreaking
11089 size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1;
11090 // Indentation of other lines (including first if initial indent is
11091 // unset)
11092 size_t m_indent = 0;
11093 // Indentation of the first line
11094 size_t m_initialIndent = std::string::npos;
11095
11096 public:
11097 /**
11098 * Iterates "lines" in `Column` and returns them
11099 */
11100 class const_iterator {
11101 friend Column;
11102 struct EndTag {};
11103
11104 Column const& m_column;
11105 // Where does the current line start?
11106 AnsiSkippingString::const_iterator m_lineStart;
11107 // How long should the current line be?
11108 AnsiSkippingString::const_iterator m_lineEnd;
11109 // How far have we checked the string to iterate?
11110 AnsiSkippingString::const_iterator m_parsedTo;
11111 // Should a '-' be appended to the line?
11112 bool m_addHyphen = false;
11113
11114 const_iterator( Column const& column, EndTag ):
11115 m_column( column ),
11116 m_lineStart( m_column.m_string.end() ),
11117 m_lineEnd( column.m_string.end() ),
11118 m_parsedTo( column.m_string.end() ) {}
11119
11120 // Calculates the length of the current line
11121 void calcLength();
11122
11123 // Returns current indentation width
11124 size_t indentSize() const;
11125
11126 // Creates an indented and (optionally) suffixed string from
11127 // current iterator position, indentation and length.
11128 std::string addIndentAndSuffix(
11129 AnsiSkippingString::const_iterator start,
11130 AnsiSkippingString::const_iterator end ) const;
11131
11132 public:
11133 using difference_type = std::ptrdiff_t;
11134 using value_type = std::string;
11135 using pointer = value_type*;
11136 using reference = value_type&;
11137 using iterator_category = std::forward_iterator_tag;
11138
11139 explicit const_iterator( Column const& column );
11140
11141 std::string operator*() const;
11142
11143 const_iterator& operator++();
11144 const_iterator operator++( int );
11145
11146 bool operator==( const_iterator const& other ) const {
11147 return m_lineStart == other.m_lineStart &&
11148 &m_column == &other.m_column;
11149 }
11150 bool operator!=( const_iterator const& other ) const {
11151 return !operator==( other );
11152 }
11153 };
11154 using iterator = const_iterator;
11155
11156 explicit Column( std::string const& text ): m_string( text ) {}
11157 explicit Column( std::string&& text ):
11158 m_string( CATCH_MOVE( text ) ) {}
11159
11160 Column& width( size_t newWidth ) & {
11161 assert( newWidth > 0 );
11162 m_width = newWidth;
11163 return *this;
11164 }
11165 Column&& width( size_t newWidth ) && {
11166 assert( newWidth > 0 );
11167 m_width = newWidth;
11168 return CATCH_MOVE( *this );
11169 }
11170 Column& indent( size_t newIndent ) & {
11171 m_indent = newIndent;
11172 return *this;
11173 }
11174 Column&& indent( size_t newIndent ) && {
11175 m_indent = newIndent;
11176 return CATCH_MOVE( *this );
11177 }
11178 Column& initialIndent( size_t newIndent ) & {
11179 m_initialIndent = newIndent;
11180 return *this;
11181 }
11182 Column&& initialIndent( size_t newIndent ) && {
11183 m_initialIndent = newIndent;
11184 return CATCH_MOVE( *this );
11185 }
11186
11187 size_t width() const { return m_width; }
11188 const_iterator begin() const { return const_iterator( *this ); }
11189 const_iterator end() const {
11190 return { *this, const_iterator::EndTag{} };
11191 }
11192
11193 friend std::ostream& operator<<( std::ostream& os,
11194 Column const& col );
11195
11196 friend Columns operator+( Column const& lhs, Column const& rhs );
11197 friend Columns operator+( Column&& lhs, Column&& rhs );
11198 };
11199
11200 //! Creates a column that serves as an empty space of specific width
11201 Column Spacer( size_t spaceWidth );
11202
11203 class Columns {
11204 std::vector<Column> m_columns;
11205
11206 public:
11207 class iterator {
11208 friend Columns;
11209 struct EndTag {};
11210
11211 std::vector<Column> const& m_columns;
11212 std::vector<Column::const_iterator> m_iterators;
11213 size_t m_activeIterators;
11214
11215 iterator( Columns const& columns, EndTag );
11216
11217 public:
11218 using difference_type = std::ptrdiff_t;
11219 using value_type = std::string;
11220 using pointer = value_type*;
11221 using reference = value_type&;
11222 using iterator_category = std::forward_iterator_tag;
11223
11224 explicit iterator( Columns const& columns );
11225
11226 auto operator==( iterator const& other ) const -> bool {
11227 return m_iterators == other.m_iterators;
11228 }
11229 auto operator!=( iterator const& other ) const -> bool {
11230 return m_iterators != other.m_iterators;
11231 }
11232 std::string operator*() const;
11233 iterator& operator++();
11234 iterator operator++( int );
11235 };
11236 using const_iterator = iterator;
11237
11238 iterator begin() const { return iterator( *this ); }
11239 iterator end() const { return { *this, iterator::EndTag() }; }
11240
11241 friend Columns& operator+=( Columns& lhs, Column const& rhs );
11242 friend Columns& operator+=( Columns& lhs, Column&& rhs );
11243 friend Columns operator+( Columns const& lhs, Column const& rhs );
11244 friend Columns operator+( Columns&& lhs, Column&& rhs );
11245
11246 friend std::ostream& operator<<( std::ostream& os,
11247 Columns const& cols );
11248 };
11249
11250 } // namespace TextFlow
11251} // namespace Catch
11252#endif // CATCH_TEXTFLOW_HPP_INCLUDED
11253
11254
11255#ifndef CATCH_TO_STRING_HPP_INCLUDED
11256#define CATCH_TO_STRING_HPP_INCLUDED
11257
11258#include <string>
11259
11260
11261namespace Catch {
11262 template <typename T>
11263 std::string to_string(T const& t) {
11264#if defined(CATCH_CONFIG_CPP11_TO_STRING)
11265 return std::to_string(t);
11266#else
11267 ReusableStringStream rss;
11268 rss << t;
11269 return rss.str();
11270#endif
11271 }
11272} // end namespace Catch
11273
11274#endif // CATCH_TO_STRING_HPP_INCLUDED
11275
11276
11277#ifndef CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
11278#define CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
11279
11280namespace Catch {
11281 bool uncaught_exceptions();
11282} // end namespace Catch
11283
11284#endif // CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
11285
11286
11287#ifndef CATCH_XMLWRITER_HPP_INCLUDED
11288#define CATCH_XMLWRITER_HPP_INCLUDED
11289
11290
11291#include <iosfwd>
11292#include <vector>
11293#include <cstdint>
11294
11295namespace Catch {
11296 enum class XmlFormatting : std::uint8_t {
11297 None = 0x00,
11298 Indent = 0x01,
11299 Newline = 0x02,
11300 };
11301
11302 constexpr XmlFormatting operator|( XmlFormatting lhs, XmlFormatting rhs ) {
11303 return static_cast<XmlFormatting>( static_cast<std::uint8_t>( lhs ) |
11304 static_cast<std::uint8_t>( rhs ) );
11305 }
11306
11307 constexpr XmlFormatting operator&( XmlFormatting lhs, XmlFormatting rhs ) {
11308 return static_cast<XmlFormatting>( static_cast<std::uint8_t>( lhs ) &
11309 static_cast<std::uint8_t>( rhs ) );
11310 }
11311
11312
11313 /**
11314 * Helper for XML-encoding text (escaping angle brackets, quotes, etc)
11315 *
11316 * Note: doesn't take ownership of passed strings, and thus the
11317 * encoded string must outlive the encoding instance.
11318 */
11319 class XmlEncode {
11320 public:
11321 enum ForWhat { ForTextNodes, ForAttributes };
11322
11323 constexpr XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ):
11324 m_str( str ), m_forWhat( forWhat ) {}
11325
11326
11327 void encodeTo( std::ostream& os ) const;
11328
11329 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
11330
11331 private:
11332 StringRef m_str;
11333 ForWhat m_forWhat;
11334 };
11335
11336 class XmlWriter {
11337 public:
11338
11339 class ScopedElement {
11340 public:
11341 ScopedElement( XmlWriter* writer, XmlFormatting fmt );
11342
11343 ScopedElement( ScopedElement&& other ) noexcept;
11344 ScopedElement& operator=( ScopedElement&& other ) noexcept;
11345
11346 ~ScopedElement();
11347
11348 ScopedElement&
11349 writeText( StringRef text,
11350 XmlFormatting fmt = XmlFormatting::Newline |
11351 XmlFormatting::Indent );
11352
11353 ScopedElement& writeAttribute( StringRef name,
11354 StringRef attribute );
11355 template <typename T,
11356 // Without this SFINAE, this overload is a better match
11357 // for `std::string`, `char const*`, `char const[N]` args.
11358 // While it would still work, it would cause code bloat
11359 // and multiple iteration over the strings
11360 typename = typename std::enable_if_t<
11361 !std::is_convertible<T, StringRef>::value>>
11362 ScopedElement& writeAttribute( StringRef name,
11363 T const& attribute ) {
11364 m_writer->writeAttribute( name, attribute );
11365 return *this;
11366 }
11367
11368 private:
11369 XmlWriter* m_writer = nullptr;
11370 XmlFormatting m_fmt;
11371 };
11372
11373 XmlWriter( std::ostream& os );
11374 ~XmlWriter();
11375
11376 XmlWriter( XmlWriter const& ) = delete;
11377 XmlWriter& operator=( XmlWriter const& ) = delete;
11378
11379 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
11380
11381 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
11382
11383 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
11384
11385 //! The attribute content is XML-encoded
11386 XmlWriter& writeAttribute( StringRef name, StringRef attribute );
11387
11388 //! Writes the attribute as "true/false"
11389 XmlWriter& writeAttribute( StringRef name, bool attribute );
11390
11391 //! The attribute content is XML-encoded
11392 XmlWriter& writeAttribute( StringRef name, char const* attribute );
11393
11394 //! The attribute value must provide op<<(ostream&, T). The resulting
11395 //! serialization is XML-encoded
11396 template <typename T,
11397 // Without this SFINAE, this overload is a better match
11398 // for `std::string`, `char const*`, `char const[N]` args.
11399 // While it would still work, it would cause code bloat
11400 // and multiple iteration over the strings
11401 typename = typename std::enable_if_t<
11402 !std::is_convertible<T, StringRef>::value>>
11403 XmlWriter& writeAttribute( StringRef name, T const& attribute ) {
11404 ReusableStringStream rss;
11405 rss << attribute;
11406 return writeAttribute( name, rss.str() );
11407 }
11408
11409 //! Writes escaped `text` in a element
11410 XmlWriter& writeText( StringRef text,
11411 XmlFormatting fmt = XmlFormatting::Newline |
11412 XmlFormatting::Indent );
11413
11414 //! Writes XML comment as "<!-- text -->"
11415 XmlWriter& writeComment( StringRef text,
11416 XmlFormatting fmt = XmlFormatting::Newline |
11417 XmlFormatting::Indent );
11418
11419 void writeStylesheetRef( StringRef url );
11420
11421 void ensureTagClosed();
11422
11423 private:
11424
11425 void applyFormatting(XmlFormatting fmt);
11426
11427 void writeDeclaration();
11428
11429 void newlineIfNecessary();
11430
11431 bool m_tagIsOpen = false;
11432 bool m_needsNewline = false;
11433 std::vector<std::string> m_tags;
11434 std::string m_indent;
11435 std::ostream& m_os;
11436 };
11437
11438}
11439
11440#endif // CATCH_XMLWRITER_HPP_INCLUDED
11441
11442
11443/** \file
11444 * This is a convenience header for Catch2's Matcher support. It includes
11445 * **all** of Catch2 headers related to matchers.
11446 *
11447 * Generally the Catch2 users should use specific includes they need,
11448 * but this header can be used instead for ease-of-experimentation, or
11449 * just plain convenience, at the cost of increased compilation times.
11450 *
11451 * When a new header is added to either the `matchers` folder, or to
11452 * the corresponding internal subfolder, it should be added here.
11453 */
11454
11455#ifndef CATCH_MATCHERS_ALL_HPP_INCLUDED
11456#define CATCH_MATCHERS_ALL_HPP_INCLUDED
11457
11458
11459
11460#ifndef CATCH_MATCHERS_HPP_INCLUDED
11461#define CATCH_MATCHERS_HPP_INCLUDED
11462
11463
11464
11465#ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED
11466#define CATCH_MATCHERS_IMPL_HPP_INCLUDED
11467
11468
11469#include <string>
11470
11471namespace Catch {
11472
11473#ifdef __clang__
11474# pragma clang diagnostic push
11475# pragma clang diagnostic ignored "-Wsign-compare"
11476# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
11477#elif defined __GNUC__
11478# pragma GCC diagnostic push
11479# pragma GCC diagnostic ignored "-Wsign-compare"
11480# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
11481#endif
11482
11483 template<typename ArgT, typename MatcherT>
11484 class MatchExpr : public ITransientExpression {
11485 ArgT && m_arg;
11486 MatcherT const& m_matcher;
11487 public:
11488 constexpr MatchExpr( ArgT && arg, MatcherT const& matcher )
11489 : ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose
11490 m_arg( CATCH_FORWARD(arg) ),
11491 m_matcher( matcher )
11492 {}
11493
11494 void streamReconstructedExpression( std::ostream& os ) const override {
11495 os << Catch::Detail::stringify( m_arg )
11496 << ' '
11497 << m_matcher.toString();
11498 }
11499 };
11500
11501#ifdef __clang__
11502# pragma clang diagnostic pop
11503#elif defined __GNUC__
11504# pragma GCC diagnostic pop
11505#endif
11506
11507
11508 namespace Matchers {
11509 template <typename ArgT>
11510 class MatcherBase;
11511 }
11512
11513 using StringMatcher = Matchers::MatcherBase<std::string>;
11514
11515 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher );
11516
11517 template<typename ArgT, typename MatcherT>
11518 constexpr MatchExpr<ArgT, MatcherT>
11519 makeMatchExpr( ArgT&& arg, MatcherT const& matcher ) {
11520 return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher );
11521 }
11522
11523} // namespace Catch
11524
11525
11526///////////////////////////////////////////////////////////////////////////////
11527#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
11528 do { \
11529 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
11530 INTERNAL_CATCH_TRY { \
11531 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher ) ); \
11532 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
11533 catchAssertionHandler.complete(); \
11534 } while( false )
11535
11536
11537///////////////////////////////////////////////////////////////////////////////
11538#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
11539 do { \
11540 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
11541 if( catchAssertionHandler.allowThrows() ) \
11542 try { \
11543 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
11544 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
11545 static_cast<void>(__VA_ARGS__ ); \
11546 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
11547 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
11548 } \
11549 catch( exceptionType const& ex ) { \
11550 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher ) ); \
11551 } \
11552 catch( ... ) { \
11553 catchAssertionHandler.handleUnexpectedInflightException(); \
11554 } \
11555 else \
11556 catchAssertionHandler.handleThrowingCallSkipped(); \
11557 catchAssertionHandler.complete(); \
11558 } while( false )
11559
11560
11561#endif // CATCH_MATCHERS_IMPL_HPP_INCLUDED
11562
11563#include <string>
11564#include <vector>
11565
11566namespace Catch {
11567namespace Matchers {
11568
11569 class MatcherUntypedBase {
11570 public:
11571 MatcherUntypedBase() = default;
11572
11573 MatcherUntypedBase(MatcherUntypedBase const&) = default;
11574 MatcherUntypedBase(MatcherUntypedBase&&) = default;
11575
11576 MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete;
11577 MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete;
11578
11579 std::string toString() const;
11580
11581 protected:
11582 virtual ~MatcherUntypedBase(); // = default;
11583 virtual std::string describe() const = 0;
11584 mutable std::string m_cachedToString;
11585 };
11586
11587
11588 template<typename T>
11589 class MatcherBase : public MatcherUntypedBase {
11590 public:
11591 virtual bool match( T const& arg ) const = 0;
11592 };
11593
11594 namespace Detail {
11595
11596 template<typename ArgT>
11597 class MatchAllOf final : public MatcherBase<ArgT> {
11598 std::vector<MatcherBase<ArgT> const*> m_matchers;
11599
11600 public:
11601 MatchAllOf() = default;
11602 MatchAllOf(MatchAllOf const&) = delete;
11603 MatchAllOf& operator=(MatchAllOf const&) = delete;
11604 MatchAllOf(MatchAllOf&&) = default;
11605 MatchAllOf& operator=(MatchAllOf&&) = default;
11606
11607
11608 bool match( ArgT const& arg ) const override {
11609 for( auto matcher : m_matchers ) {
11610 if (!matcher->match(arg))
11611 return false;
11612 }
11613 return true;
11614 }
11615 std::string describe() const override {
11616 std::string description;
11617 description.reserve( 4 + m_matchers.size()*32 );
11618 description += "( ";
11619 bool first = true;
11620 for( auto matcher : m_matchers ) {
11621 if( first )
11622 first = false;
11623 else
11624 description += " and ";
11625 description += matcher->toString();
11626 }
11627 description += " )";
11628 return description;
11629 }
11630
11631 friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) {
11632 lhs.m_matchers.push_back(&rhs);
11633 return CATCH_MOVE(lhs);
11634 }
11635 friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) {
11636 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
11637 return CATCH_MOVE(rhs);
11638 }
11639 };
11640
11641 //! lvalue overload is intentionally deleted, users should
11642 //! not be trying to compose stored composition matchers
11643 template<typename ArgT>
11644 MatchAllOf<ArgT> operator&& (MatchAllOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
11645 //! lvalue overload is intentionally deleted, users should
11646 //! not be trying to compose stored composition matchers
11647 template<typename ArgT>
11648 MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete;
11649
11650 template<typename ArgT>
11651 class MatchAnyOf final : public MatcherBase<ArgT> {
11652 std::vector<MatcherBase<ArgT> const*> m_matchers;
11653 public:
11654 MatchAnyOf() = default;
11655 MatchAnyOf(MatchAnyOf const&) = delete;
11656 MatchAnyOf& operator=(MatchAnyOf const&) = delete;
11657 MatchAnyOf(MatchAnyOf&&) = default;
11658 MatchAnyOf& operator=(MatchAnyOf&&) = default;
11659
11660 bool match( ArgT const& arg ) const override {
11661 for( auto matcher : m_matchers ) {
11662 if (matcher->match(arg))
11663 return true;
11664 }
11665 return false;
11666 }
11667 std::string describe() const override {
11668 std::string description;
11669 description.reserve( 4 + m_matchers.size()*32 );
11670 description += "( ";
11671 bool first = true;
11672 for( auto matcher : m_matchers ) {
11673 if( first )
11674 first = false;
11675 else
11676 description += " or ";
11677 description += matcher->toString();
11678 }
11679 description += " )";
11680 return description;
11681 }
11682
11683 friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) {
11684 lhs.m_matchers.push_back(&rhs);
11685 return CATCH_MOVE(lhs);
11686 }
11687 friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) {
11688 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
11689 return CATCH_MOVE(rhs);
11690 }
11691 };
11692
11693 //! lvalue overload is intentionally deleted, users should
11694 //! not be trying to compose stored composition matchers
11695 template<typename ArgT>
11696 MatchAnyOf<ArgT> operator|| (MatchAnyOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
11697 //! lvalue overload is intentionally deleted, users should
11698 //! not be trying to compose stored composition matchers
11699 template<typename ArgT>
11700 MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete;
11701
11702 template<typename ArgT>
11703 class MatchNotOf final : public MatcherBase<ArgT> {
11704 MatcherBase<ArgT> const& m_underlyingMatcher;
11705
11706 public:
11707 explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ):
11708 m_underlyingMatcher( underlyingMatcher )
11709 {}
11710
11711 bool match( ArgT const& arg ) const override {
11712 return !m_underlyingMatcher.match( arg );
11713 }
11714
11715 std::string describe() const override {
11716 return "not " + m_underlyingMatcher.toString();
11717 }
11718 };
11719
11720 } // namespace Detail
11721
11722 template <typename T>
11723 Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
11724 return Detail::MatchAllOf<T>{} && lhs && rhs;
11725 }
11726 template <typename T>
11727 Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
11728 return Detail::MatchAnyOf<T>{} || lhs || rhs;
11729 }
11730
11731 template <typename T>
11732 Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) {
11733 return Detail::MatchNotOf<T>{ matcher };
11734 }
11735
11736
11737} // namespace Matchers
11738} // namespace Catch
11739
11740
11741#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
11742 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11743 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
11744
11745 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11746 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11747
11748 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11749 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11750
11751#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
11752
11753 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
11754 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11755
11756 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
11757 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11758
11759 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
11760 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
11761
11762#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
11763
11764 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11765 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
11766
11767 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11768 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11769
11770 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11771 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11772
11773#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
11774
11775 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
11776 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11777
11778 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
11779 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11780
11781 #define CHECK_THAT( arg, matcher ) (void)(0)
11782 #define REQUIRE_THAT( arg, matcher ) (void)(0)
11783
11784#endif // end of user facing macro declarations
11785
11786#endif // CATCH_MATCHERS_HPP_INCLUDED
11787
11788
11789#ifndef CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
11790#define CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
11791
11792
11793
11794#ifndef CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
11795#define CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
11796
11797
11798#include <array>
11799#include <algorithm>
11800#include <string>
11801#include <type_traits>
11802
11803namespace Catch {
11804namespace Matchers {
11805 class MatcherGenericBase : public MatcherUntypedBase {
11806 public:
11807 MatcherGenericBase() = default;
11808 ~MatcherGenericBase() override; // = default;
11809
11810 MatcherGenericBase(MatcherGenericBase const&) = default;
11811 MatcherGenericBase(MatcherGenericBase&&) = default;
11812
11813 MatcherGenericBase& operator=(MatcherGenericBase const&) = delete;
11814 MatcherGenericBase& operator=(MatcherGenericBase&&) = delete;
11815 };
11816
11817
11818 namespace Detail {
11819 template<std::size_t N, std::size_t M>
11820 std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
11821 std::array<void const*, N + M> arr{};
11822 std::copy_n(lhs.begin(), N, arr.begin());
11823 std::copy_n(rhs.begin(), M, arr.begin() + N);
11824 return arr;
11825 }
11826
11827 template<std::size_t N>
11828 std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
11829 std::array<void const*, N+1> arr{};
11830 std::copy_n(lhs.begin(), N, arr.begin());
11831 arr[N] = rhs;
11832 return arr;
11833 }
11834
11835 template<std::size_t N>
11836 std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
11837 std::array<void const*, N + 1> arr{ {lhs} };
11838 std::copy_n(rhs.begin(), N, arr.begin() + 1);
11839 return arr;
11840 }
11841
11842 template<typename T>
11843 using is_generic_matcher = std::is_base_of<
11844 Catch::Matchers::MatcherGenericBase,
11845 std::remove_cv_t<std::remove_reference_t<T>>
11846 >;
11847
11848 template<typename... Ts>
11849 using are_generic_matchers = Catch::Detail::conjunction<is_generic_matcher<Ts>...>;
11850
11851 template<typename T>
11852 using is_matcher = std::is_base_of<
11853 Catch::Matchers::MatcherUntypedBase,
11854 std::remove_cv_t<std::remove_reference_t<T>>
11855 >;
11856
11857
11858 template<std::size_t N, typename Arg>
11859 bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
11860 return true;
11861 }
11862
11863 template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
11864 bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
11865 return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
11866 }
11867
11868
11869 template<std::size_t N, typename Arg>
11870 bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
11871 return false;
11872 }
11873
11874 template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
11875 bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
11876 return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
11877 }
11878
11879 std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end);
11880
11881 template<typename... MatcherTs, std::size_t... Idx>
11882 std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) {
11883 std::array<std::string, sizeof...(MatcherTs)> descriptions {{
11884 static_cast<MatcherTs const*>(matchers[Idx])->toString()...
11885 }};
11886
11887 return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size());
11888 }
11889
11890
11891 template<typename... MatcherTs>
11892 class MatchAllOfGeneric final : public MatcherGenericBase {
11893 public:
11894 MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
11895 MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
11896 MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
11897 MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
11898
11899 MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
11900 explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
11901
11902 template<typename Arg>
11903 bool match(Arg&& arg) const {
11904 return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
11905 }
11906
11907 std::string describe() const override {
11908 return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
11909 }
11910
11911 // Has to be public to enable the concatenating operators
11912 // below, because they are not friend of the RHS, only LHS,
11913 // and thus cannot access private fields of RHS
11914 std::array<void const*, sizeof...( MatcherTs )> m_matchers;
11915
11916
11917 //! Avoids type nesting for `GenericAllOf && GenericAllOf` case
11918 template<typename... MatchersRHS>
11919 friend
11920 MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
11921 MatchAllOfGeneric<MatcherTs...>&& lhs,
11922 MatchAllOfGeneric<MatchersRHS...>&& rhs) {
11923 return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
11924 }
11925
11926 //! Avoids type nesting for `GenericAllOf && some matcher` case
11927 template<typename MatcherRHS>
11928 friend std::enable_if_t<is_matcher<MatcherRHS>::value,
11929 MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
11930 MatchAllOfGeneric<MatcherTs...>&& lhs,
11931 MatcherRHS const& rhs) {
11932 return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))};
11933 }
11934
11935 //! Avoids type nesting for `some matcher && GenericAllOf` case
11936 template<typename MatcherLHS>
11937 friend std::enable_if_t<is_matcher<MatcherLHS>::value,
11938 MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
11939 MatcherLHS const& lhs,
11940 MatchAllOfGeneric<MatcherTs...>&& rhs) {
11941 return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
11942 }
11943 };
11944
11945
11946 template<typename... MatcherTs>
11947 class MatchAnyOfGeneric final : public MatcherGenericBase {
11948 public:
11949 MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
11950 MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
11951 MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
11952 MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
11953
11954 MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
11955 explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
11956
11957 template<typename Arg>
11958 bool match(Arg&& arg) const {
11959 return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
11960 }
11961
11962 std::string describe() const override {
11963 return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
11964 }
11965
11966
11967 // Has to be public to enable the concatenating operators
11968 // below, because they are not friend of the RHS, only LHS,
11969 // and thus cannot access private fields of RHS
11970 std::array<void const*, sizeof...( MatcherTs )> m_matchers;
11971
11972 //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
11973 template<typename... MatchersRHS>
11974 friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
11975 MatchAnyOfGeneric<MatcherTs...>&& lhs,
11976 MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
11977 return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
11978 }
11979
11980 //! Avoids type nesting for `GenericAnyOf || some matcher` case
11981 template<typename MatcherRHS>
11982 friend std::enable_if_t<is_matcher<MatcherRHS>::value,
11983 MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
11984 MatchAnyOfGeneric<MatcherTs...>&& lhs,
11985 MatcherRHS const& rhs) {
11986 return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
11987 }
11988
11989 //! Avoids type nesting for `some matcher || GenericAnyOf` case
11990 template<typename MatcherLHS>
11991 friend std::enable_if_t<is_matcher<MatcherLHS>::value,
11992 MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
11993 MatcherLHS const& lhs,
11994 MatchAnyOfGeneric<MatcherTs...>&& rhs) {
11995 return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
11996 }
11997 };
11998
11999
12000 template<typename MatcherT>
12001 class MatchNotOfGeneric final : public MatcherGenericBase {
12002 MatcherT const& m_matcher;
12003
12004 public:
12005 MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
12006 MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
12007 MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
12008 MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
12009
12010 explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {}
12011
12012 template<typename Arg>
12013 bool match(Arg&& arg) const {
12014 return !m_matcher.match(arg);
12015 }
12016
12017 std::string describe() const override {
12018 return "not " + m_matcher.toString();
12019 }
12020
12021 //! Negating negation can just unwrap and return underlying matcher
12022 friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
12023 return matcher.m_matcher;
12024 }
12025 };
12026 } // namespace Detail
12027
12028
12029 // compose only generic matchers
12030 template<typename MatcherLHS, typename MatcherRHS>
12031 std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
12032 operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
12033 return { lhs, rhs };
12034 }
12035
12036 template<typename MatcherLHS, typename MatcherRHS>
12037 std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
12038 operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
12039 return { lhs, rhs };
12040 }
12041
12042 //! Wrap provided generic matcher in generic negator
12043 template<typename MatcherT>
12044 std::enable_if_t<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>>
12045 operator ! (MatcherT const& matcher) {
12046 return Detail::MatchNotOfGeneric<MatcherT>{matcher};
12047 }
12048
12049
12050 // compose mixed generic and non-generic matchers
12051 template<typename MatcherLHS, typename ArgRHS>
12052 std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
12053 operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
12054 return { lhs, rhs };
12055 }
12056
12057 template<typename ArgLHS, typename MatcherRHS>
12058 std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
12059 operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
12060 return { lhs, rhs };
12061 }
12062
12063 template<typename MatcherLHS, typename ArgRHS>
12064 std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
12065 operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
12066 return { lhs, rhs };
12067 }
12068
12069 template<typename ArgLHS, typename MatcherRHS>
12070 std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
12071 operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
12072 return { lhs, rhs };
12073 }
12074
12075} // namespace Matchers
12076} // namespace Catch
12077
12078#endif // CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
12079
12080namespace Catch {
12081 namespace Matchers {
12082
12083 class IsEmptyMatcher final : public MatcherGenericBase {
12084 public:
12085 template <typename RangeLike>
12086 bool match(RangeLike&& rng) const {
12087#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
12088 using Catch::Detail::empty;
12089#else
12090 using std::empty;
12091#endif
12092 return empty(rng);
12093 }
12094
12095 std::string describe() const override;
12096 };
12097
12098 class HasSizeMatcher final : public MatcherGenericBase {
12099 std::size_t m_target_size;
12100 public:
12101 explicit HasSizeMatcher(std::size_t target_size):
12102 m_target_size(target_size)
12103 {}
12104
12105 template <typename RangeLike>
12106 bool match(RangeLike&& rng) const {
12107#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
12108 using Catch::Detail::size;
12109#else
12110 using std::size;
12111#endif
12112 return size(rng) == m_target_size;
12113 }
12114
12115 std::string describe() const override;
12116 };
12117
12118 template <typename Matcher>
12119 class SizeMatchesMatcher final : public MatcherGenericBase {
12120 Matcher m_matcher;
12121 public:
12122 explicit SizeMatchesMatcher(Matcher m):
12123 m_matcher(CATCH_MOVE(m))
12124 {}
12125
12126 template <typename RangeLike>
12127 bool match(RangeLike&& rng) const {
12128#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
12129 using Catch::Detail::size;
12130#else
12131 using std::size;
12132#endif
12133 return m_matcher.match(size(rng));
12134 }
12135
12136 std::string describe() const override {
12137 return "size matches " + m_matcher.describe();
12138 }
12139 };
12140
12141
12142 //! Creates a matcher that accepts empty ranges/containers
12143 IsEmptyMatcher IsEmpty();
12144 //! Creates a matcher that accepts ranges/containers with specific size
12145 HasSizeMatcher SizeIs(std::size_t sz);
12146 template <typename Matcher>
12147 std::enable_if_t<Detail::is_matcher<Matcher>::value,
12148 SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) {
12149 return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
12150 }
12151
12152 } // end namespace Matchers
12153} // end namespace Catch
12154
12155#endif // CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
12156
12157
12158#ifndef CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
12159#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
12160
12161
12162#include <algorithm>
12163#include <functional>
12164
12165namespace Catch {
12166 namespace Matchers {
12167 //! Matcher for checking that an element in range is equal to specific element
12168 template <typename T, typename Equality>
12169 class ContainsElementMatcher final : public MatcherGenericBase {
12170 T m_desired;
12171 Equality m_eq;
12172 public:
12173 template <typename T2, typename Equality2>
12174 ContainsElementMatcher(T2&& target, Equality2&& predicate):
12175 m_desired(CATCH_FORWARD(target)),
12176 m_eq(CATCH_FORWARD(predicate))
12177 {}
12178
12179 std::string describe() const override {
12180 return "contains element " + Catch::Detail::stringify(m_desired);
12181 }
12182
12183 template <typename RangeLike>
12184 bool match( RangeLike&& rng ) const {
12185 for ( auto&& elem : rng ) {
12186 if ( m_eq( elem, m_desired ) ) { return true; }
12187 }
12188 return false;
12189 }
12190 };
12191
12192 //! Meta-matcher for checking that an element in a range matches a specific matcher
12193 template <typename Matcher>
12194 class ContainsMatcherMatcher final : public MatcherGenericBase {
12195 Matcher m_matcher;
12196 public:
12197 // Note that we do a copy+move to avoid having to SFINAE this
12198 // constructor (and also avoid some perfect forwarding failure
12199 // cases)
12200 ContainsMatcherMatcher(Matcher matcher):
12201 m_matcher(CATCH_MOVE(matcher))
12202 {}
12203
12204 template <typename RangeLike>
12205 bool match(RangeLike&& rng) const {
12206 for (auto&& elem : rng) {
12207 if (m_matcher.match(elem)) {
12208 return true;
12209 }
12210 }
12211 return false;
12212 }
12213
12214 std::string describe() const override {
12215 return "contains element matching " + m_matcher.describe();
12216 }
12217 };
12218
12219 /**
12220 * Creates a matcher that checks whether a range contains a specific element.
12221 *
12222 * Uses `std::equal_to` to do the comparison
12223 */
12224 template <typename T>
12225 std::enable_if_t<!Detail::is_matcher<T>::value,
12226 ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
12227 return { CATCH_FORWARD(elem), std::equal_to<>{} };
12228 }
12229
12230 //! Creates a matcher that checks whether a range contains element matching a matcher
12231 template <typename Matcher>
12232 std::enable_if_t<Detail::is_matcher<Matcher>::value,
12233 ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
12234 return { CATCH_FORWARD(matcher) };
12235 }
12236
12237 /**
12238 * Creates a matcher that checks whether a range contains a specific element.
12239 *
12240 * Uses `eq` to do the comparisons, the element is provided on the rhs
12241 */
12242 template <typename T, typename Equality>
12243 ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
12244 return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) };
12245 }
12246
12247 }
12248}
12249
12250#endif // CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
12251
12252
12253#ifndef CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
12254#define CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
12255
12256
12257namespace Catch {
12258namespace Matchers {
12259
12260class ExceptionMessageMatcher final : public MatcherBase<std::exception> {
12261 std::string m_message;
12262public:
12263
12264 ExceptionMessageMatcher(std::string const& message):
12265 m_message(message)
12266 {}
12267
12268 bool match(std::exception const& ex) const override;
12269
12270 std::string describe() const override;
12271};
12272
12273//! Creates a matcher that checks whether a std derived exception has the provided message
12274ExceptionMessageMatcher Message(std::string const& message);
12275
12276template <typename StringMatcherType>
12277class ExceptionMessageMatchesMatcher final
12278 : public MatcherBase<std::exception> {
12279 StringMatcherType m_matcher;
12280
12281public:
12282 ExceptionMessageMatchesMatcher( StringMatcherType matcher ):
12283 m_matcher( CATCH_MOVE( matcher ) ) {}
12284
12285 bool match( std::exception const& ex ) const override {
12286 return m_matcher.match( ex.what() );
12287 }
12288
12289 std::string describe() const override {
12290 return " matches \"" + m_matcher.describe() + '"';
12291 }
12292};
12293
12294//! Creates a matcher that checks whether a message from an std derived
12295//! exception matches a provided matcher
12296template <typename StringMatcherType>
12297ExceptionMessageMatchesMatcher<StringMatcherType>
12298MessageMatches( StringMatcherType&& matcher ) {
12299 return { CATCH_FORWARD( matcher ) };
12300}
12301
12302} // namespace Matchers
12303} // namespace Catch
12304
12305#endif // CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
12306
12307
12308#ifndef CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
12309#define CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
12310
12311
12312namespace Catch {
12313namespace Matchers {
12314
12315 namespace Detail {
12316 enum class FloatingPointKind : uint8_t;
12317 }
12318
12319 class WithinAbsMatcher final : public MatcherBase<double> {
12320 public:
12321 WithinAbsMatcher(double target, double margin);
12322 bool match(double const& matchee) const override;
12323 std::string describe() const override;
12324 private:
12325 double m_target;
12326 double m_margin;
12327 };
12328
12329 //! Creates a matcher that accepts numbers within certain range of target
12330 WithinAbsMatcher WithinAbs( double target, double margin );
12331
12332
12333
12334 class WithinUlpsMatcher final : public MatcherBase<double> {
12335 public:
12336 WithinUlpsMatcher( double target,
12337 uint64_t ulps,
12338 Detail::FloatingPointKind baseType );
12339 bool match(double const& matchee) const override;
12340 std::string describe() const override;
12341 private:
12342 double m_target;
12343 uint64_t m_ulps;
12344 Detail::FloatingPointKind m_type;
12345 };
12346
12347 //! Creates a matcher that accepts doubles within certain ULP range of target
12348 WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
12349 //! Creates a matcher that accepts floats within certain ULP range of target
12350 WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
12351
12352
12353
12354 // Given IEEE-754 format for floats and doubles, we can assume
12355 // that float -> double promotion is lossless. Given this, we can
12356 // assume that if we do the standard relative comparison of
12357 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
12358 // the same result if we do this for floats, as if we do this for
12359 // doubles that were promoted from floats.
12360 class WithinRelMatcher final : public MatcherBase<double> {
12361 public:
12362 WithinRelMatcher( double target, double epsilon );
12363 bool match(double const& matchee) const override;
12364 std::string describe() const override;
12365 private:
12366 double m_target;
12367 double m_epsilon;
12368 };
12369
12370 //! Creates a matcher that accepts doubles within certain relative range of target
12371 WithinRelMatcher WithinRel(double target, double eps);
12372 //! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
12373 WithinRelMatcher WithinRel(double target);
12374 //! Creates a matcher that accepts doubles within certain relative range of target
12375 WithinRelMatcher WithinRel(float target, float eps);
12376 //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
12377 WithinRelMatcher WithinRel(float target);
12378
12379
12380
12381 class IsNaNMatcher final : public MatcherBase<double> {
12382 public:
12383 IsNaNMatcher() = default;
12384 bool match( double const& matchee ) const override;
12385 std::string describe() const override;
12386 };
12387
12388 IsNaNMatcher IsNaN();
12389
12390} // namespace Matchers
12391} // namespace Catch
12392
12393#endif // CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
12394
12395
12396#ifndef CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
12397#define CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
12398
12399
12400#include <string>
12401
12402namespace Catch {
12403namespace Matchers {
12404
12405namespace Detail {
12406 std::string finalizeDescription(const std::string& desc);
12407} // namespace Detail
12408
12409template <typename T, typename Predicate>
12410class PredicateMatcher final : public MatcherBase<T> {
12411 Predicate m_predicate;
12412 std::string m_description;
12413public:
12414
12415 PredicateMatcher(Predicate&& elem, std::string const& descr)
12416 :m_predicate(CATCH_FORWARD(elem)),
12417 m_description(Detail::finalizeDescription(descr))
12418 {}
12419
12420 bool match( T const& item ) const override {
12421 return m_predicate(item);
12422 }
12423
12424 std::string describe() const override {
12425 return m_description;
12426 }
12427};
12428
12429 /**
12430 * Creates a matcher that calls delegates `match` to the provided predicate.
12431 *
12432 * The user has to explicitly specify the argument type to the matcher
12433 */
12434 template<typename T, typename Pred>
12435 PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") {
12436 static_assert(is_callable<Pred(T)>::value, "Predicate not callable with argument T");
12437 static_assert(std::is_same<bool, FunctionReturnType<Pred, T>>::value, "Predicate does not return bool");
12438 return PredicateMatcher<T, Pred>(CATCH_FORWARD(predicate), description);
12439 }
12440
12441} // namespace Matchers
12442} // namespace Catch
12443
12444#endif // CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
12445
12446
12447#ifndef CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
12448#define CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
12449
12450
12451namespace Catch {
12452 namespace Matchers {
12453 // Matcher for checking that all elements in range matches a given matcher.
12454 template <typename Matcher>
12455 class AllMatchMatcher final : public MatcherGenericBase {
12456 Matcher m_matcher;
12457 public:
12458 AllMatchMatcher(Matcher matcher):
12459 m_matcher(CATCH_MOVE(matcher))
12460 {}
12461
12462 std::string describe() const override {
12463 return "all match " + m_matcher.describe();
12464 }
12465
12466 template <typename RangeLike>
12467 bool match(RangeLike&& rng) const {
12468 for (auto&& elem : rng) {
12469 if (!m_matcher.match(elem)) {
12470 return false;
12471 }
12472 }
12473 return true;
12474 }
12475 };
12476
12477 // Matcher for checking that no element in range matches a given matcher.
12478 template <typename Matcher>
12479 class NoneMatchMatcher final : public MatcherGenericBase {
12480 Matcher m_matcher;
12481 public:
12482 NoneMatchMatcher(Matcher matcher):
12483 m_matcher(CATCH_MOVE(matcher))
12484 {}
12485
12486 std::string describe() const override {
12487 return "none match " + m_matcher.describe();
12488 }
12489
12490 template <typename RangeLike>
12491 bool match(RangeLike&& rng) const {
12492 for (auto&& elem : rng) {
12493 if (m_matcher.match(elem)) {
12494 return false;
12495 }
12496 }
12497 return true;
12498 }
12499 };
12500
12501 // Matcher for checking that at least one element in range matches a given matcher.
12502 template <typename Matcher>
12503 class AnyMatchMatcher final : public MatcherGenericBase {
12504 Matcher m_matcher;
12505 public:
12506 AnyMatchMatcher(Matcher matcher):
12507 m_matcher(CATCH_MOVE(matcher))
12508 {}
12509
12510 std::string describe() const override {
12511 return "any match " + m_matcher.describe();
12512 }
12513
12514 template <typename RangeLike>
12515 bool match(RangeLike&& rng) const {
12516 for (auto&& elem : rng) {
12517 if (m_matcher.match(elem)) {
12518 return true;
12519 }
12520 }
12521 return false;
12522 }
12523 };
12524
12525 // Matcher for checking that all elements in range are true.
12526 class AllTrueMatcher final : public MatcherGenericBase {
12527 public:
12528 std::string describe() const override;
12529
12530 template <typename RangeLike>
12531 bool match(RangeLike&& rng) const {
12532 for (auto&& elem : rng) {
12533 if (!elem) {
12534 return false;
12535 }
12536 }
12537 return true;
12538 }
12539 };
12540
12541 // Matcher for checking that no element in range is true.
12542 class NoneTrueMatcher final : public MatcherGenericBase {
12543 public:
12544 std::string describe() const override;
12545
12546 template <typename RangeLike>
12547 bool match(RangeLike&& rng) const {
12548 for (auto&& elem : rng) {
12549 if (elem) {
12550 return false;
12551 }
12552 }
12553 return true;
12554 }
12555 };
12556
12557 // Matcher for checking that any element in range is true.
12558 class AnyTrueMatcher final : public MatcherGenericBase {
12559 public:
12560 std::string describe() const override;
12561
12562 template <typename RangeLike>
12563 bool match(RangeLike&& rng) const {
12564 for (auto&& elem : rng) {
12565 if (elem) {
12566 return true;
12567 }
12568 }
12569 return false;
12570 }
12571 };
12572
12573 // Creates a matcher that checks whether all elements in a range match a matcher
12574 template <typename Matcher>
12575 AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
12576 return { CATCH_FORWARD(matcher) };
12577 }
12578
12579 // Creates a matcher that checks whether no element in a range matches a matcher.
12580 template <typename Matcher>
12581 NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
12582 return { CATCH_FORWARD(matcher) };
12583 }
12584
12585 // Creates a matcher that checks whether any element in a range matches a matcher.
12586 template <typename Matcher>
12587 AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
12588 return { CATCH_FORWARD(matcher) };
12589 }
12590
12591 // Creates a matcher that checks whether all elements in a range are true
12592 AllTrueMatcher AllTrue();
12593
12594 // Creates a matcher that checks whether no element in a range is true
12595 NoneTrueMatcher NoneTrue();
12596
12597 // Creates a matcher that checks whether any element in a range is true
12598 AnyTrueMatcher AnyTrue();
12599 }
12600}
12601
12602#endif // CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
12603
12604
12605#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
12606#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
12607
12608
12609#include <algorithm>
12610#include <utility>
12611
12612namespace Catch {
12613 namespace Matchers {
12614
12615 /**
12616 * Matcher for checking that an element contains the same
12617 * elements in the same order
12618 */
12619 template <typename TargetRangeLike, typename Equality>
12620 class RangeEqualsMatcher final : public MatcherGenericBase {
12621 TargetRangeLike m_desired;
12622 Equality m_predicate;
12623
12624 public:
12625 template <typename TargetRangeLike2, typename Equality2>
12626 constexpr
12627 RangeEqualsMatcher( TargetRangeLike2&& range,
12628 Equality2&& predicate ):
12629 m_desired( CATCH_FORWARD( range ) ),
12630 m_predicate( CATCH_FORWARD( predicate ) ) {}
12631
12632 template <typename RangeLike>
12633 constexpr
12634 bool match( RangeLike&& rng ) const {
12635 auto rng_start = begin( rng );
12636 const auto rng_end = end( rng );
12637 auto target_start = begin( m_desired );
12638 const auto target_end = end( m_desired );
12639
12640 while (rng_start != rng_end && target_start != target_end) {
12641 if (!m_predicate(*rng_start, *target_start)) {
12642 return false;
12643 }
12644 ++rng_start;
12645 ++target_start;
12646 }
12647 return rng_start == rng_end && target_start == target_end;
12648 }
12649
12650 std::string describe() const override {
12651 return "elements are " + Catch::Detail::stringify( m_desired );
12652 }
12653 };
12654
12655 /**
12656 * Matcher for checking that an element contains the same
12657 * elements (but not necessarily in the same order)
12658 */
12659 template <typename TargetRangeLike, typename Equality>
12660 class UnorderedRangeEqualsMatcher final : public MatcherGenericBase {
12661 TargetRangeLike m_desired;
12662 Equality m_predicate;
12663
12664 public:
12665 template <typename TargetRangeLike2, typename Equality2>
12666 constexpr
12667 UnorderedRangeEqualsMatcher( TargetRangeLike2&& range,
12668 Equality2&& predicate ):
12669 m_desired( CATCH_FORWARD( range ) ),
12670 m_predicate( CATCH_FORWARD( predicate ) ) {}
12671
12672 template <typename RangeLike>
12673 constexpr
12674 bool match( RangeLike&& rng ) const {
12675 using std::begin;
12676 using std::end;
12677 return Catch::Detail::is_permutation( begin( m_desired ),
12678 end( m_desired ),
12679 begin( rng ),
12680 end( rng ),
12681 m_predicate );
12682 }
12683
12684 std::string describe() const override {
12685 return "unordered elements are " +
12686 ::Catch::Detail::stringify( m_desired );
12687 }
12688 };
12689
12690 /**
12691 * Creates a matcher that checks if all elements in a range are equal
12692 * to all elements in another range.
12693 *
12694 * Uses `std::equal_to` to do the comparison
12695 */
12696 template <typename RangeLike>
12697 constexpr
12698 std::enable_if_t<!Detail::is_matcher<RangeLike>::value,
12699 RangeEqualsMatcher<RangeLike, std::equal_to<>>>
12700 RangeEquals( RangeLike&& range ) {
12701 return { CATCH_FORWARD( range ), std::equal_to<>{} };
12702 }
12703
12704 /**
12705 * Creates a matcher that checks if all elements in a range are equal
12706 * to all elements in another range.
12707 *
12708 * Uses to provided predicate `predicate` to do the comparisons
12709 */
12710 template <typename RangeLike, typename Equality>
12711 constexpr
12712 RangeEqualsMatcher<RangeLike, Equality>
12713 RangeEquals( RangeLike&& range, Equality&& predicate ) {
12714 return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
12715 }
12716
12717 /**
12718 * Creates a matcher that checks if all elements in a range are equal
12719 * to all elements in another range, in some permutation
12720 *
12721 * Uses `std::equal_to` to do the comparison
12722 */
12723 template <typename RangeLike>
12724 constexpr
12725 std::enable_if_t<
12726 !Detail::is_matcher<RangeLike>::value,
12727 UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>>
12728 UnorderedRangeEquals( RangeLike&& range ) {
12729 return { CATCH_FORWARD( range ), std::equal_to<>{} };
12730 }
12731
12732 /**
12733 * Creates a matcher that checks if all elements in a range are equal
12734 * to all elements in another range, in some permutation.
12735 *
12736 * Uses to provided predicate `predicate` to do the comparisons
12737 */
12738 template <typename RangeLike, typename Equality>
12739 constexpr
12740 UnorderedRangeEqualsMatcher<RangeLike, Equality>
12741 UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) {
12742 return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
12743 }
12744 } // namespace Matchers
12745} // namespace Catch
12746
12747#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
12748
12749
12750#ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED
12751#define CATCH_MATCHERS_STRING_HPP_INCLUDED
12752
12753
12754#include <string>
12755
12756namespace Catch {
12757namespace Matchers {
12758
12759 struct CasedString {
12760 CasedString( std::string const& str, CaseSensitive caseSensitivity );
12761 std::string adjustString( std::string const& str ) const;
12762 StringRef caseSensitivitySuffix() const;
12763
12764 CaseSensitive m_caseSensitivity;
12765 std::string m_str;
12766 };
12767
12768 class StringMatcherBase : public MatcherBase<std::string> {
12769 protected:
12770 CasedString m_comparator;
12771 StringRef m_operation;
12772
12773 public:
12774 StringMatcherBase( StringRef operation,
12775 CasedString const& comparator );
12776 std::string describe() const override;
12777 };
12778
12779 class StringEqualsMatcher final : public StringMatcherBase {
12780 public:
12781 StringEqualsMatcher( CasedString const& comparator );
12782 bool match( std::string const& source ) const override;
12783 };
12784 class StringContainsMatcher final : public StringMatcherBase {
12785 public:
12786 StringContainsMatcher( CasedString const& comparator );
12787 bool match( std::string const& source ) const override;
12788 };
12789 class StartsWithMatcher final : public StringMatcherBase {
12790 public:
12791 StartsWithMatcher( CasedString const& comparator );
12792 bool match( std::string const& source ) const override;
12793 };
12794 class EndsWithMatcher final : public StringMatcherBase {
12795 public:
12796 EndsWithMatcher( CasedString const& comparator );
12797 bool match( std::string const& source ) const override;
12798 };
12799
12800 class RegexMatcher final : public MatcherBase<std::string> {
12801 std::string m_regex;
12802 CaseSensitive m_caseSensitivity;
12803
12804 public:
12805 RegexMatcher( std::string regex, CaseSensitive caseSensitivity );
12806 bool match( std::string const& matchee ) const override;
12807 std::string describe() const override;
12808 };
12809
12810 //! Creates matcher that accepts strings that are exactly equal to `str`
12811 StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12812 //! Creates matcher that accepts strings that contain `str`
12813 StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12814 //! Creates matcher that accepts strings that _end_ with `str`
12815 EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12816 //! Creates matcher that accepts strings that _start_ with `str`
12817 StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12818 //! Creates matcher that accepts strings matching `regex`
12819 RegexMatcher Matches( std::string const& regex, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12820
12821} // namespace Matchers
12822} // namespace Catch
12823
12824#endif // CATCH_MATCHERS_STRING_HPP_INCLUDED
12825
12826
12827#ifndef CATCH_MATCHERS_VECTOR_HPP_INCLUDED
12828#define CATCH_MATCHERS_VECTOR_HPP_INCLUDED
12829
12830
12831#include <algorithm>
12832
12833namespace Catch {
12834namespace Matchers {
12835
12836 template<typename T, typename Alloc>
12837 class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> {
12838 T const& m_comparator;
12839
12840 public:
12841 VectorContainsElementMatcher(T const& comparator):
12842 m_comparator(comparator)
12843 {}
12844
12845 bool match(std::vector<T, Alloc> const& v) const override {
12846 for (auto const& el : v) {
12847 if (el == m_comparator) {
12848 return true;
12849 }
12850 }
12851 return false;
12852 }
12853
12854 std::string describe() const override {
12855 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
12856 }
12857 };
12858
12859 template<typename T, typename AllocComp, typename AllocMatch>
12860 class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12861 std::vector<T, AllocComp> const& m_comparator;
12862
12863 public:
12864 ContainsMatcher(std::vector<T, AllocComp> const& comparator):
12865 m_comparator( comparator )
12866 {}
12867
12868 bool match(std::vector<T, AllocMatch> const& v) const override {
12869 // !TBD: see note in EqualsMatcher
12870 if (m_comparator.size() > v.size())
12871 return false;
12872 for (auto const& comparator : m_comparator) {
12873 auto present = false;
12874 for (const auto& el : v) {
12875 if (el == comparator) {
12876 present = true;
12877 break;
12878 }
12879 }
12880 if (!present) {
12881 return false;
12882 }
12883 }
12884 return true;
12885 }
12886 std::string describe() const override {
12887 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
12888 }
12889 };
12890
12891 template<typename T, typename AllocComp, typename AllocMatch>
12892 class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12893 std::vector<T, AllocComp> const& m_comparator;
12894
12895 public:
12896 EqualsMatcher(std::vector<T, AllocComp> const& comparator):
12897 m_comparator( comparator )
12898 {}
12899
12900 bool match(std::vector<T, AllocMatch> const& v) const override {
12901 // !TBD: This currently works if all elements can be compared using !=
12902 // - a more general approach would be via a compare template that defaults
12903 // to using !=. but could be specialised for, e.g. std::vector<T> etc
12904 // - then just call that directly
12905 if ( m_comparator.size() != v.size() ) { return false; }
12906 for ( std::size_t i = 0; i < v.size(); ++i ) {
12907 if ( !( m_comparator[i] == v[i] ) ) { return false; }
12908 }
12909 return true;
12910 }
12911 std::string describe() const override {
12912 return "Equals: " + ::Catch::Detail::stringify( m_comparator );
12913 }
12914 };
12915
12916 template<typename T, typename AllocComp, typename AllocMatch>
12917 class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12918 std::vector<T, AllocComp> const& m_comparator;
12919 mutable Catch::Approx approx = Catch::Approx::custom();
12920
12921 public:
12922 ApproxMatcher(std::vector<T, AllocComp> const& comparator):
12923 m_comparator( comparator )
12924 {}
12925
12926 bool match(std::vector<T, AllocMatch> const& v) const override {
12927 if (m_comparator.size() != v.size())
12928 return false;
12929 for (std::size_t i = 0; i < v.size(); ++i)
12930 if (m_comparator[i] != approx(v[i]))
12931 return false;
12932 return true;
12933 }
12934 std::string describe() const override {
12935 return "is approx: " + ::Catch::Detail::stringify( m_comparator );
12936 }
12937 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
12938 ApproxMatcher& epsilon( T const& newEpsilon ) {
12939 approx.epsilon(static_cast<double>(newEpsilon));
12940 return *this;
12941 }
12942 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
12943 ApproxMatcher& margin( T const& newMargin ) {
12944 approx.margin(static_cast<double>(newMargin));
12945 return *this;
12946 }
12947 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
12948 ApproxMatcher& scale( T const& newScale ) {
12949 approx.scale(static_cast<double>(newScale));
12950 return *this;
12951 }
12952 };
12953
12954 template<typename T, typename AllocComp, typename AllocMatch>
12955 class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12956 std::vector<T, AllocComp> const& m_target;
12957
12958 public:
12959 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target):
12960 m_target(target)
12961 {}
12962 bool match(std::vector<T, AllocMatch> const& vec) const override {
12963 if (m_target.size() != vec.size()) {
12964 return false;
12965 }
12966 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
12967 }
12968
12969 std::string describe() const override {
12970 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
12971 }
12972 };
12973
12974
12975 // The following functions create the actual matcher objects.
12976 // This allows the types to be inferred
12977
12978 //! Creates a matcher that matches vectors that contain all elements in `comparator`
12979 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
12980 ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
12981 return ContainsMatcher<T, AllocComp, AllocMatch>(comparator);
12982 }
12983
12984 //! Creates a matcher that matches vectors that contain `comparator` as an element
12985 template<typename T, typename Alloc = std::allocator<T>>
12986 VectorContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
12987 return VectorContainsElementMatcher<T, Alloc>(comparator);
12988 }
12989
12990 //! Creates a matcher that matches vectors that are exactly equal to `comparator`
12991 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
12992 EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
12993 return EqualsMatcher<T, AllocComp, AllocMatch>(comparator);
12994 }
12995
12996 //! Creates a matcher that matches vectors that `comparator` as an element
12997 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
12998 ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
12999 return ApproxMatcher<T, AllocComp, AllocMatch>(comparator);
13000 }
13001
13002 //! Creates a matcher that matches vectors that is equal to `target` modulo permutation
13003 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
13004 UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
13005 return UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target);
13006 }
13007
13008} // namespace Matchers
13009} // namespace Catch
13010
13011#endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED
13012
13013#endif // CATCH_MATCHERS_ALL_HPP_INCLUDED
13014
13015
13016/** \file
13017 * This is a convenience header for Catch2's Reporter support. It includes
13018 * **all** of Catch2 headers related to reporters, including all reporters.
13019 *
13020 * Generally the Catch2 users should use specific includes they need,
13021 * but this header can be used instead for ease-of-experimentation, or
13022 * just plain convenience, at the cost of (significantly) increased
13023 * compilation times.
13024 *
13025 * When a new header (reporter) is added to either the `reporter` folder,
13026 * or to the corresponding internal subfolder, it should be added here.
13027 */
13028
13029#ifndef CATCH_REPORTERS_ALL_HPP_INCLUDED
13030#define CATCH_REPORTERS_ALL_HPP_INCLUDED
13031
13032
13033
13034#ifndef CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
13035#define CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
13036
13037
13038
13039#ifndef CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
13040#define CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
13041
13042
13043
13044#ifndef CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
13045#define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
13046
13047
13048#include <map>
13049#include <string>
13050
13051namespace Catch {
13052 class ColourImpl;
13053
13054 /**
13055 * This is the base class for all reporters.
13056 *
13057 * If are writing a reporter, you must derive from this type, or one
13058 * of the helper reporter bases that are derived from this type.
13059 *
13060 * ReporterBase centralizes handling of various common tasks in reporters,
13061 * like storing the right stream for the reporters to write to, and
13062 * providing the default implementation of the different listing events.
13063 */
13064 class ReporterBase : public IEventListener {
13065 protected:
13066 //! The stream wrapper as passed to us by outside code
13067 Detail::unique_ptr<IStream> m_wrapped_stream;
13068 //! Cached output stream from `m_wrapped_stream` to reduce
13069 //! number of indirect calls needed to write output.
13070 std::ostream& m_stream;
13071 //! Colour implementation this reporter was configured for
13072 Detail::unique_ptr<ColourImpl> m_colour;
13073 //! The custom reporter options user passed down to the reporter
13074 std::map<std::string, std::string> m_customOptions;
13075
13076 public:
13077 ReporterBase( ReporterConfig&& config );
13078 ~ReporterBase() override; // = default;
13079
13080 /**
13081 * Provides a simple default listing of reporters.
13082 *
13083 * Should look roughly like the reporter listing in v2 and earlier
13084 * versions of Catch2.
13085 */
13086 void listReporters(
13087 std::vector<ReporterDescription> const& descriptions ) override;
13088 /**
13089 * Provides a simple default listing of listeners
13090 *
13091 * Looks similarly to listing of reporters, but with listener type
13092 * instead of reporter name.
13093 */
13094 void listListeners(
13095 std::vector<ListenerDescription> const& descriptions ) override;
13096 /**
13097 * Provides a simple default listing of tests.
13098 *
13099 * Should look roughly like the test listing in v2 and earlier versions
13100 * of Catch2. Especially supports low-verbosity listing that mimics the
13101 * old `--list-test-names-only` output.
13102 */
13103 void listTests( std::vector<TestCaseHandle> const& tests ) override;
13104 /**
13105 * Provides a simple default listing of tags.
13106 *
13107 * Should look roughly like the tag listing in v2 and earlier versions
13108 * of Catch2.
13109 */
13110 void listTags( std::vector<TagInfo> const& tags ) override;
13111 };
13112} // namespace Catch
13113
13114#endif // CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
13115
13116#include <vector>
13117
13118namespace Catch {
13119
13120 class StreamingReporterBase : public ReporterBase {
13121 public:
13122 // GCC5 compat: we cannot use inherited constructor, because it
13123 // doesn't implement backport of P0136
13124 StreamingReporterBase(ReporterConfig&& _config):
13125 ReporterBase(CATCH_MOVE(_config))
13126 {}
13127 ~StreamingReporterBase() override;
13128
13129 void benchmarkPreparing( StringRef ) override {}
13130 void benchmarkStarting( BenchmarkInfo const& ) override {}
13131 void benchmarkEnded( BenchmarkStats<> const& ) override {}
13132 void benchmarkFailed( StringRef ) override {}
13133
13134 void fatalErrorEncountered( StringRef /*error*/ ) override {}
13135 void noMatchingTestCases( StringRef /*unmatchedSpec*/ ) override {}
13136 void reportInvalidTestSpec( StringRef /*invalidArgument*/ ) override {}
13137
13138 void testRunStarting( TestRunInfo const& _testRunInfo ) override;
13139
13140 void testCaseStarting(TestCaseInfo const& _testInfo) override {
13141 currentTestCaseInfo = &_testInfo;
13142 }
13143 void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
13144 void sectionStarting(SectionInfo const& _sectionInfo) override {
13145 m_sectionStack.push_back(_sectionInfo);
13146 }
13147
13148 void assertionStarting( AssertionInfo const& ) override {}
13149 void assertionEnded( AssertionStats const& ) override {}
13150
13151 void sectionEnded(SectionStats const& /* _sectionStats */) override {
13152 m_sectionStack.pop_back();
13153 }
13154 void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
13155 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
13156 currentTestCaseInfo = nullptr;
13157 }
13158 void testRunEnded( TestRunStats const& /* _testRunStats */ ) override;
13159
13160 void skipTest(TestCaseInfo const&) override {
13161 // Don't do anything with this by default.
13162 // It can optionally be overridden in the derived class.
13163 }
13164
13165 protected:
13166 TestRunInfo currentTestRunInfo{ "test run has not started yet"_sr };
13167 TestCaseInfo const* currentTestCaseInfo = nullptr;
13168
13169 //! Stack of all _active_ sections in the _current_ test case
13170 std::vector<SectionInfo> m_sectionStack;
13171 };
13172
13173} // end namespace Catch
13174
13175#endif // CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
13176
13177#include <string>
13178
13179namespace Catch {
13180
13181 class AutomakeReporter final : public StreamingReporterBase {
13182 public:
13183 // GCC5 compat: we cannot use inherited constructor, because it
13184 // doesn't implement backport of P0136
13185 AutomakeReporter(ReporterConfig&& _config):
13186 StreamingReporterBase(CATCH_MOVE(_config))
13187 {}
13188 ~AutomakeReporter() override;
13189
13190 static std::string getDescription() {
13191 using namespace std::string_literals;
13192 return "Reports test results in the format of Automake .trs files"s;
13193 }
13194
13195 void testCaseEnded(TestCaseStats const& _testCaseStats) override;
13196 void skipTest(TestCaseInfo const& testInfo) override;
13197 };
13198
13199} // end namespace Catch
13200
13201#endif // CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
13202
13203
13204#ifndef CATCH_REPORTER_COMPACT_HPP_INCLUDED
13205#define CATCH_REPORTER_COMPACT_HPP_INCLUDED
13206
13207
13208
13209
13210namespace Catch {
13211
13212 class CompactReporter final : public StreamingReporterBase {
13213 public:
13214 using StreamingReporterBase::StreamingReporterBase;
13215
13216 ~CompactReporter() override;
13217
13218 static std::string getDescription();
13219
13220 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13221
13222 void testRunStarting( TestRunInfo const& _testInfo ) override;
13223
13224 void assertionEnded(AssertionStats const& _assertionStats) override;
13225
13226 void sectionEnded(SectionStats const& _sectionStats) override;
13227
13228 void testRunEnded(TestRunStats const& _testRunStats) override;
13229
13230 };
13231
13232} // end namespace Catch
13233
13234#endif // CATCH_REPORTER_COMPACT_HPP_INCLUDED
13235
13236
13237#ifndef CATCH_REPORTER_CONSOLE_HPP_INCLUDED
13238#define CATCH_REPORTER_CONSOLE_HPP_INCLUDED
13239
13240
13241namespace Catch {
13242 // Fwd decls
13243 class TablePrinter;
13244
13245 class ConsoleReporter final : public StreamingReporterBase {
13246 Detail::unique_ptr<TablePrinter> m_tablePrinter;
13247
13248 public:
13249 ConsoleReporter(ReporterConfig&& config);
13250 ~ConsoleReporter() override;
13251 static std::string getDescription();
13252
13253 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13254 void reportInvalidTestSpec( StringRef arg ) override;
13255
13256 void assertionStarting(AssertionInfo const&) override;
13257
13258 void assertionEnded(AssertionStats const& _assertionStats) override;
13259
13260 void sectionStarting(SectionInfo const& _sectionInfo) override;
13261 void sectionEnded(SectionStats const& _sectionStats) override;
13262
13263 void benchmarkPreparing( StringRef name ) override;
13264 void benchmarkStarting(BenchmarkInfo const& info) override;
13265 void benchmarkEnded(BenchmarkStats<> const& stats) override;
13266 void benchmarkFailed( StringRef error ) override;
13267
13268 void testCaseEnded(TestCaseStats const& _testCaseStats) override;
13269 void testRunEnded(TestRunStats const& _testRunStats) override;
13270 void testRunStarting(TestRunInfo const& _testRunInfo) override;
13271
13272 private:
13273 void lazyPrint();
13274
13275 void lazyPrintWithoutClosingBenchmarkTable();
13276 void lazyPrintRunInfo();
13277 void printTestCaseAndSectionHeader();
13278
13279 void printClosedHeader(std::string const& _name);
13280 void printOpenHeader(std::string const& _name);
13281
13282 // if string has a : in first line will set indent to follow it on
13283 // subsequent lines
13284 void printHeaderString(std::string const& _string, std::size_t indent = 0);
13285
13286 void printTotalsDivider(Totals const& totals);
13287
13288 bool m_headerPrinted = false;
13289 bool m_testRunInfoPrinted = false;
13290 };
13291
13292} // end namespace Catch
13293
13294#endif // CATCH_REPORTER_CONSOLE_HPP_INCLUDED
13295
13296
13297#ifndef CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
13298#define CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
13299
13300
13301#include <string>
13302#include <vector>
13303
13304namespace Catch {
13305
13306 namespace Detail {
13307
13308 //! Represents either an assertion or a benchmark result to be handled by cumulative reporter later
13309 class AssertionOrBenchmarkResult {
13310 // This should really be a variant, but this is much faster
13311 // to write and the data layout here is already terrible
13312 // enough that we do not have to care about the object size.
13313 Optional<AssertionStats> m_assertion;
13314 Optional<BenchmarkStats<>> m_benchmark;
13315 public:
13316 AssertionOrBenchmarkResult(AssertionStats const& assertion);
13317 AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark);
13318
13319 bool isAssertion() const;
13320 bool isBenchmark() const;
13321
13322 AssertionStats const& asAssertion() const;
13323 BenchmarkStats<> const& asBenchmark() const;
13324 };
13325 }
13326
13327 /**
13328 * Utility base for reporters that need to handle all results at once
13329 *
13330 * It stores tree of all test cases, sections and assertions, and after the
13331 * test run is finished, calls into `testRunEndedCumulative` to pass the
13332 * control to the deriving class.
13333 *
13334 * If you are deriving from this class and override any testing related
13335 * member functions, you should first call into the base's implementation to
13336 * avoid breaking the tree construction.
13337 *
13338 * Due to the way this base functions, it has to expand assertions up-front,
13339 * even if they are later unused (e.g. because the deriving reporter does
13340 * not report successful assertions, or because the deriving reporter does
13341 * not use assertion expansion at all). Derived classes can use two
13342 * customization points, `m_shouldStoreSuccesfulAssertions` and
13343 * `m_shouldStoreFailedAssertions`, to disable the expansion and gain extra
13344 * performance. **Accessing the assertion expansions if it wasn't stored is
13345 * UB.**
13346 */
13347 class CumulativeReporterBase : public ReporterBase {
13348 public:
13349 template<typename T, typename ChildNodeT>
13350 struct Node {
13351 explicit Node( T const& _value ) : value( _value ) {}
13352
13353 using ChildNodes = std::vector<Detail::unique_ptr<ChildNodeT>>;
13354 T value;
13355 ChildNodes children;
13356 };
13357 struct SectionNode {
13358 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
13359
13360 bool operator == (SectionNode const& other) const {
13361 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
13362 }
13363
13364 bool hasAnyAssertions() const;
13365
13366 SectionStats stats;
13367 std::vector<Detail::unique_ptr<SectionNode>> childSections;
13368 std::vector<Detail::AssertionOrBenchmarkResult> assertionsAndBenchmarks;
13369 std::string stdOut;
13370 std::string stdErr;
13371 };
13372
13373
13374 using TestCaseNode = Node<TestCaseStats, SectionNode>;
13375 using TestRunNode = Node<TestRunStats, TestCaseNode>;
13376
13377 // GCC5 compat: we cannot use inherited constructor, because it
13378 // doesn't implement backport of P0136
13379 CumulativeReporterBase(ReporterConfig&& _config):
13380 ReporterBase(CATCH_MOVE(_config))
13381 {}
13382 ~CumulativeReporterBase() override;
13383
13384 void benchmarkPreparing( StringRef ) override {}
13385 void benchmarkStarting( BenchmarkInfo const& ) override {}
13386 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
13387 void benchmarkFailed( StringRef ) override {}
13388
13389 void noMatchingTestCases( StringRef ) override {}
13390 void reportInvalidTestSpec( StringRef ) override {}
13391 void fatalErrorEncountered( StringRef /*error*/ ) override {}
13392
13393 void testRunStarting( TestRunInfo const& ) override {}
13394
13395 void testCaseStarting( TestCaseInfo const& ) override {}
13396 void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
13397 void sectionStarting( SectionInfo const& sectionInfo ) override;
13398
13399 void assertionStarting( AssertionInfo const& ) override {}
13400
13401 void assertionEnded( AssertionStats const& assertionStats ) override;
13402 void sectionEnded( SectionStats const& sectionStats ) override;
13403 void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
13404 void testCaseEnded( TestCaseStats const& testCaseStats ) override;
13405 void testRunEnded( TestRunStats const& testRunStats ) override;
13406 //! Customization point: called after last test finishes (testRunEnded has been handled)
13407 virtual void testRunEndedCumulative() = 0;
13408
13409 void skipTest(TestCaseInfo const&) override {}
13410
13411 protected:
13412 //! Should the cumulative base store the assertion expansion for successful assertions?
13413 bool m_shouldStoreSuccesfulAssertions = true;
13414 //! Should the cumulative base store the assertion expansion for failed assertions?
13415 bool m_shouldStoreFailedAssertions = true;
13416
13417 // We need lazy construction here. We should probably refactor it
13418 // later, after the events are redone.
13419 //! The root node of the test run tree.
13420 Detail::unique_ptr<TestRunNode> m_testRun;
13421
13422 private:
13423 // Note: We rely on pointer identity being stable, which is why
13424 // we store pointers to the nodes rather than the values.
13425 std::vector<Detail::unique_ptr<TestCaseNode>> m_testCases;
13426 // Root section of the _current_ test case
13427 Detail::unique_ptr<SectionNode> m_rootSection;
13428 // Deepest section of the _current_ test case
13429 SectionNode* m_deepestSection = nullptr;
13430 // Stack of _active_ sections in the _current_ test case
13431 std::vector<SectionNode*> m_sectionStack;
13432 };
13433
13434} // end namespace Catch
13435
13436#endif // CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
13437
13438
13439#ifndef CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
13440#define CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
13441
13442
13443namespace Catch {
13444
13445 /**
13446 * Base class to simplify implementing listeners.
13447 *
13448 * Provides empty default implementation for all IEventListener member
13449 * functions, so that a listener implementation can pick which
13450 * member functions it actually cares about.
13451 */
13452 class EventListenerBase : public IEventListener {
13453 public:
13454 using IEventListener::IEventListener;
13455
13456 void reportInvalidTestSpec( StringRef unmatchedSpec ) override;
13457 void fatalErrorEncountered( StringRef error ) override;
13458
13459 void benchmarkPreparing( StringRef name ) override;
13460 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
13461 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
13462 void benchmarkFailed( StringRef error ) override;
13463
13464 void assertionStarting( AssertionInfo const& assertionInfo ) override;
13465 void assertionEnded( AssertionStats const& assertionStats ) override;
13466
13467 void listReporters(
13468 std::vector<ReporterDescription> const& descriptions ) override;
13469 void listListeners(
13470 std::vector<ListenerDescription> const& descriptions ) override;
13471 void listTests( std::vector<TestCaseHandle> const& tests ) override;
13472 void listTags( std::vector<TagInfo> const& tagInfos ) override;
13473
13474 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13475 void testRunStarting( TestRunInfo const& testRunInfo ) override;
13476 void testCaseStarting( TestCaseInfo const& testInfo ) override;
13477 void testCasePartialStarting( TestCaseInfo const& testInfo,
13478 uint64_t partNumber ) override;
13479 void sectionStarting( SectionInfo const& sectionInfo ) override;
13480 void sectionEnded( SectionStats const& sectionStats ) override;
13481 void testCasePartialEnded( TestCaseStats const& testCaseStats,
13482 uint64_t partNumber ) override;
13483 void testCaseEnded( TestCaseStats const& testCaseStats ) override;
13484 void testRunEnded( TestRunStats const& testRunStats ) override;
13485 void skipTest( TestCaseInfo const& testInfo ) override;
13486 };
13487
13488} // end namespace Catch
13489
13490#endif // CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
13491
13492
13493#ifndef CATCH_REPORTER_HELPERS_HPP_INCLUDED
13494#define CATCH_REPORTER_HELPERS_HPP_INCLUDED
13495
13496#include <iosfwd>
13497#include <string>
13498#include <vector>
13499
13500
13501namespace Catch {
13502
13503 class IConfig;
13504 class TestCaseHandle;
13505 class ColourImpl;
13506
13507 // Returns double formatted as %.3f (format expected on output)
13508 std::string getFormattedDuration( double duration );
13509
13510 //! Should the reporter show duration of test given current configuration?
13511 bool shouldShowDuration( IConfig const& config, double duration );
13512
13513 std::string serializeFilters( std::vector<std::string> const& filters );
13514
13515 struct lineOfChars {
13516 char c;
13517 constexpr lineOfChars( char c_ ): c( c_ ) {}
13518
13519 friend std::ostream& operator<<( std::ostream& out, lineOfChars value );
13520 };
13521
13522 /**
13523 * Lists reporter descriptions to the provided stream in user-friendly
13524 * format
13525 *
13526 * Used as the default listing implementation by the first party reporter
13527 * bases. The output should be backwards compatible with the output of
13528 * Catch2 v2 binaries.
13529 */
13530 void
13531 defaultListReporters( std::ostream& out,
13532 std::vector<ReporterDescription> const& descriptions,
13533 Verbosity verbosity );
13534
13535 /**
13536 * Lists listeners descriptions to the provided stream in user-friendly
13537 * format
13538 */
13539 void defaultListListeners( std::ostream& out,
13540 std::vector<ListenerDescription> const& descriptions );
13541
13542 /**
13543 * Lists tag information to the provided stream in user-friendly format
13544 *
13545 * Used as the default listing implementation by the first party reporter
13546 * bases. The output should be backwards compatible with the output of
13547 * Catch2 v2 binaries.
13548 */
13549 void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered );
13550
13551 /**
13552 * Lists test case information to the provided stream in user-friendly
13553 * format
13554 *
13555 * Used as the default listing implementation by the first party reporter
13556 * bases. The output is backwards compatible with the output of Catch2
13557 * v2 binaries, and also supports the format specific to the old
13558 * `--list-test-names-only` option, for people who used it in integrations.
13559 */
13560 void defaultListTests( std::ostream& out,
13561 ColourImpl* streamColour,
13562 std::vector<TestCaseHandle> const& tests,
13563 bool isFiltered,
13564 Verbosity verbosity );
13565
13566 /**
13567 * Prints test run totals to the provided stream in user-friendly format
13568 *
13569 * Used by the console and compact reporters.
13570 */
13571 void printTestRunTotals( std::ostream& stream,
13572 ColourImpl& streamColour,
13573 Totals const& totals );
13574
13575} // end namespace Catch
13576
13577#endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED
13578
13579
13580
13581#ifndef CATCH_REPORTER_JSON_HPP_INCLUDED
13582#define CATCH_REPORTER_JSON_HPP_INCLUDED
13583
13584
13585#include <stack>
13586
13587namespace Catch {
13588 class JsonReporter : public StreamingReporterBase {
13589 public:
13590 JsonReporter( ReporterConfig&& config );
13591
13592 ~JsonReporter() override;
13593
13594 static std::string getDescription();
13595
13596 public: // StreamingReporterBase
13597 void testRunStarting( TestRunInfo const& runInfo ) override;
13598 void testRunEnded( TestRunStats const& runStats ) override;
13599
13600 void testCaseStarting( TestCaseInfo const& tcInfo ) override;
13601 void testCaseEnded( TestCaseStats const& tcStats ) override;
13602
13603 void testCasePartialStarting( TestCaseInfo const& tcInfo,
13604 uint64_t index ) override;
13605 void testCasePartialEnded( TestCaseStats const& tcStats,
13606 uint64_t index ) override;
13607
13608 void sectionStarting( SectionInfo const& sectionInfo ) override;
13609 void sectionEnded( SectionStats const& sectionStats ) override;
13610
13611 void assertionStarting( AssertionInfo const& assertionInfo ) override;
13612 void assertionEnded( AssertionStats const& assertionStats ) override;
13613
13614 //void testRunEndedCumulative() override;
13615
13616 void benchmarkPreparing( StringRef name ) override;
13617 void benchmarkStarting( BenchmarkInfo const& ) override;
13618 void benchmarkEnded( BenchmarkStats<> const& ) override;
13619 void benchmarkFailed( StringRef error ) override;
13620
13621 void listReporters(
13622 std::vector<ReporterDescription> const& descriptions ) override;
13623 void listListeners(
13624 std::vector<ListenerDescription> const& descriptions ) override;
13625 void listTests( std::vector<TestCaseHandle> const& tests ) override;
13626 void listTags( std::vector<TagInfo> const& tags ) override;
13627
13628 private:
13629 Timer m_testCaseTimer;
13630 enum class Writer {
13631 Object,
13632 Array
13633 };
13634
13635 JsonArrayWriter& startArray();
13636 JsonArrayWriter& startArray( StringRef key );
13637
13638 JsonObjectWriter& startObject();
13639 JsonObjectWriter& startObject( StringRef key );
13640
13641 void endObject();
13642 void endArray();
13643
13644 bool isInside( Writer writer );
13645
13646 void startListing();
13647 void endListing();
13648
13649 // Invariant:
13650 // When m_writers is not empty and its top element is
13651 // - Writer::Object, then m_objectWriters is not be empty
13652 // - Writer::Array, then m_arrayWriters shall not be empty
13653 std::stack<JsonObjectWriter> m_objectWriters{};
13654 std::stack<JsonArrayWriter> m_arrayWriters{};
13655 std::stack<Writer> m_writers{};
13656
13657 bool m_startedListing = false;
13658
13659 // std::size_t m_sectionDepth = 0;
13660 // std::size_t m_sectionStarted = 0;
13661 };
13662} // namespace Catch
13663
13664#endif // CATCH_REPORTER_JSON_HPP_INCLUDED
13665
13666
13667#ifndef CATCH_REPORTER_JUNIT_HPP_INCLUDED
13668#define CATCH_REPORTER_JUNIT_HPP_INCLUDED
13669
13670
13671
13672namespace Catch {
13673
13674 class JunitReporter final : public CumulativeReporterBase {
13675 public:
13676 JunitReporter(ReporterConfig&& _config);
13677
13678 static std::string getDescription();
13679
13680 void testRunStarting(TestRunInfo const& runInfo) override;
13681
13682 void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
13683 void assertionEnded(AssertionStats const& assertionStats) override;
13684
13685 void testCaseEnded(TestCaseStats const& testCaseStats) override;
13686
13687 void testRunEndedCumulative() override;
13688
13689 private:
13690 void writeRun(TestRunNode const& testRunNode, double suiteTime);
13691
13692 void writeTestCase(TestCaseNode const& testCaseNode);
13693
13694 void writeSection( std::string const& className,
13695 std::string const& rootName,
13696 SectionNode const& sectionNode,
13697 bool testOkToFail );
13698
13699 void writeAssertions(SectionNode const& sectionNode);
13700 void writeAssertion(AssertionStats const& stats);
13701
13702 XmlWriter xml;
13703 Timer suiteTimer;
13704 std::string stdOutForSuite;
13705 std::string stdErrForSuite;
13706 unsigned int unexpectedExceptions = 0;
13707 bool m_okToFail = false;
13708 };
13709
13710} // end namespace Catch
13711
13712#endif // CATCH_REPORTER_JUNIT_HPP_INCLUDED
13713
13714
13715#ifndef CATCH_REPORTER_MULTI_HPP_INCLUDED
13716#define CATCH_REPORTER_MULTI_HPP_INCLUDED
13717
13718
13719namespace Catch {
13720
13721 class MultiReporter final : public IEventListener {
13722 /*
13723 * Stores all added reporters and listeners
13724 *
13725 * All Listeners are stored before all reporters, and individual
13726 * listeners/reporters are stored in order of insertion.
13727 */
13728 std::vector<IEventListenerPtr> m_reporterLikes;
13729 bool m_haveNoncapturingReporters = false;
13730
13731 // Keep track of how many listeners we have already inserted,
13732 // so that we can insert them into the main vector at the right place
13733 size_t m_insertedListeners = 0;
13734
13735 void updatePreferences(IEventListener const& reporterish);
13736
13737 public:
13738 using IEventListener::IEventListener;
13739
13740 void addListener( IEventListenerPtr&& listener );
13741 void addReporter( IEventListenerPtr&& reporter );
13742
13743 public: // IEventListener
13744
13745 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13746 void fatalErrorEncountered( StringRef error ) override;
13747 void reportInvalidTestSpec( StringRef arg ) override;
13748
13749 void benchmarkPreparing( StringRef name ) override;
13750 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
13751 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
13752 void benchmarkFailed( StringRef error ) override;
13753
13754 void testRunStarting( TestRunInfo const& testRunInfo ) override;
13755 void testCaseStarting( TestCaseInfo const& testInfo ) override;
13756 void testCasePartialStarting(TestCaseInfo const& testInfo, uint64_t partNumber) override;
13757 void sectionStarting( SectionInfo const& sectionInfo ) override;
13758 void assertionStarting( AssertionInfo const& assertionInfo ) override;
13759
13760 void assertionEnded( AssertionStats const& assertionStats ) override;
13761 void sectionEnded( SectionStats const& sectionStats ) override;
13762 void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override;
13763 void testCaseEnded( TestCaseStats const& testCaseStats ) override;
13764 void testRunEnded( TestRunStats const& testRunStats ) override;
13765
13766 void skipTest( TestCaseInfo const& testInfo ) override;
13767
13768 void listReporters(std::vector<ReporterDescription> const& descriptions) override;
13769 void listListeners(std::vector<ListenerDescription> const& descriptions) override;
13770 void listTests(std::vector<TestCaseHandle> const& tests) override;
13771 void listTags(std::vector<TagInfo> const& tags) override;
13772
13773
13774 };
13775
13776} // end namespace Catch
13777
13778#endif // CATCH_REPORTER_MULTI_HPP_INCLUDED
13779
13780
13781#ifndef CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
13782#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
13783
13784
13785#include <type_traits>
13786
13787namespace Catch {
13788
13789 namespace Detail {
13790
13791 template <typename T, typename = void>
13792 struct has_description : std::false_type {};
13793
13794 template <typename T>
13795 struct has_description<
13796 T,
13797 void_t<decltype( T::getDescription() )>>
13798 : std::true_type {};
13799
13800 //! Indirection for reporter registration, so that the error handling is
13801 //! independent on the reporter's concrete type
13802 void registerReporterImpl( std::string const& name,
13803 IReporterFactoryPtr reporterPtr );
13804 //! Actually registers the factory, independent on listener's concrete type
13805 void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory );
13806 } // namespace Detail
13807
13808 class IEventListener;
13809 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
13810
13811 template <typename T>
13812 class ReporterFactory : public IReporterFactory {
13813
13814 IEventListenerPtr create( ReporterConfig&& config ) const override {
13815 return Detail::make_unique<T>( CATCH_MOVE(config) );
13816 }
13817
13818 std::string getDescription() const override {
13819 return T::getDescription();
13820 }
13821 };
13822
13823
13824 template<typename T>
13825 class ReporterRegistrar {
13826 public:
13827 explicit ReporterRegistrar( std::string const& name ) {
13828 registerReporterImpl( name,
13829 Detail::make_unique<ReporterFactory<T>>() );
13830 }
13831 };
13832
13833 template<typename T>
13834 class ListenerRegistrar {
13835
13836 class TypedListenerFactory : public EventListenerFactory {
13837 StringRef m_listenerName;
13838
13839 std::string getDescriptionImpl( std::true_type ) const {
13840 return T::getDescription();
13841 }
13842
13843 std::string getDescriptionImpl( std::false_type ) const {
13844 return "(No description provided)";
13845 }
13846
13847 public:
13848 TypedListenerFactory( StringRef listenerName ):
13849 m_listenerName( listenerName ) {}
13850
13851 IEventListenerPtr create( IConfig const* config ) const override {
13852 return Detail::make_unique<T>( config );
13853 }
13854
13855 StringRef getName() const override {
13856 return m_listenerName;
13857 }
13858
13859 std::string getDescription() const override {
13860 return getDescriptionImpl( Detail::has_description<T>{} );
13861 }
13862 };
13863
13864 public:
13865 ListenerRegistrar(StringRef listenerName) {
13866 registerListenerImpl( Detail::make_unique<TypedListenerFactory>(listenerName) );
13867 }
13868 };
13869}
13870
13871#if !defined(CATCH_CONFIG_DISABLE)
13872
13873# define CATCH_REGISTER_REPORTER( name, reporterType ) \
13874 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
13875 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
13876 namespace { \
13877 Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \
13878 catch_internal_RegistrarFor )( name ); \
13879 } \
13880 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
13881
13882# define CATCH_REGISTER_LISTENER( listenerType ) \
13883 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
13884 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
13885 namespace { \
13886 Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
13887 catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \
13888 } \
13889 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
13890
13891#else // CATCH_CONFIG_DISABLE
13892
13893#define CATCH_REGISTER_REPORTER(name, reporterType)
13894#define CATCH_REGISTER_LISTENER(listenerType)
13895
13896#endif // CATCH_CONFIG_DISABLE
13897
13898#endif // CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
13899
13900
13901#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
13902#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
13903
13904
13905
13906namespace Catch {
13907
13908 class SonarQubeReporter final : public CumulativeReporterBase {
13909 public:
13910 SonarQubeReporter(ReporterConfig&& config)
13911 : CumulativeReporterBase(CATCH_MOVE(config))
13912 , xml(m_stream) {
13913 m_preferences.shouldRedirectStdOut = true;
13914 m_preferences.shouldReportAllAssertions = false;
13915 m_shouldStoreSuccesfulAssertions = false;
13916 }
13917
13918 static std::string getDescription() {
13919 using namespace std::string_literals;
13920 return "Reports test results in the Generic Test Data SonarQube XML format"s;
13921 }
13922
13923 void testRunStarting( TestRunInfo const& testRunInfo ) override;
13924
13925 void testRunEndedCumulative() override {
13926 writeRun( *m_testRun );
13927 xml.endElement();
13928 }
13929
13930 void writeRun( TestRunNode const& runNode );
13931
13932 void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
13933
13934 void writeTestCase(TestCaseNode const& testCaseNode);
13935
13936 void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail);
13937
13938 void writeAssertions(SectionNode const& sectionNode, bool okToFail);
13939
13940 void writeAssertion(AssertionStats const& stats, bool okToFail);
13941
13942 private:
13943 XmlWriter xml;
13944 };
13945
13946
13947} // end namespace Catch
13948
13949#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
13950
13951
13952#ifndef CATCH_REPORTER_TAP_HPP_INCLUDED
13953#define CATCH_REPORTER_TAP_HPP_INCLUDED
13954
13955
13956namespace Catch {
13957
13958 class TAPReporter final : public StreamingReporterBase {
13959 public:
13960 TAPReporter( ReporterConfig&& config ):
13961 StreamingReporterBase( CATCH_MOVE(config) ) {
13962 m_preferences.shouldReportAllAssertions = true;
13963 }
13964
13965 static std::string getDescription() {
13966 using namespace std::string_literals;
13967 return "Reports test results in TAP format, suitable for test harnesses"s;
13968 }
13969
13970 void testRunStarting( TestRunInfo const& testInfo ) override;
13971
13972 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13973
13974 void assertionEnded(AssertionStats const& _assertionStats) override;
13975
13976 void testRunEnded(TestRunStats const& _testRunStats) override;
13977
13978 private:
13979 std::size_t counter = 0;
13980 };
13981
13982} // end namespace Catch
13983
13984#endif // CATCH_REPORTER_TAP_HPP_INCLUDED
13985
13986
13987#ifndef CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
13988#define CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
13989
13990
13991#include <cstring>
13992
13993#ifdef __clang__
13994# pragma clang diagnostic push
13995# pragma clang diagnostic ignored "-Wpadded"
13996#endif
13997
13998namespace Catch {
13999
14000 class TeamCityReporter final : public StreamingReporterBase {
14001 public:
14002 TeamCityReporter( ReporterConfig&& _config )
14003 : StreamingReporterBase( CATCH_MOVE(_config) )
14004 {
14005 m_preferences.shouldRedirectStdOut = true;
14006 }
14007
14008 ~TeamCityReporter() override;
14009
14010 static std::string getDescription() {
14011 using namespace std::string_literals;
14012 return "Reports test results as TeamCity service messages"s;
14013 }
14014
14015 void testRunStarting( TestRunInfo const& runInfo ) override;
14016 void testRunEnded( TestRunStats const& runStats ) override;
14017
14018
14019 void assertionEnded(AssertionStats const& assertionStats) override;
14020
14021 void sectionStarting(SectionInfo const& sectionInfo) override {
14022 m_headerPrintedForThisSection = false;
14023 StreamingReporterBase::sectionStarting( sectionInfo );
14024 }
14025
14026 void testCaseStarting(TestCaseInfo const& testInfo) override;
14027
14028 void testCaseEnded(TestCaseStats const& testCaseStats) override;
14029
14030 private:
14031 void printSectionHeader(std::ostream& os);
14032
14033 bool m_headerPrintedForThisSection = false;
14034 Timer m_testTimer;
14035 };
14036
14037} // end namespace Catch
14038
14039#ifdef __clang__
14040# pragma clang diagnostic pop
14041#endif
14042
14043#endif // CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
14044
14045
14046#ifndef CATCH_REPORTER_XML_HPP_INCLUDED
14047#define CATCH_REPORTER_XML_HPP_INCLUDED
14048
14049
14050
14051
14052namespace Catch {
14053 class XmlReporter : public StreamingReporterBase {
14054 public:
14055 XmlReporter(ReporterConfig&& _config);
14056
14057 ~XmlReporter() override;
14058
14059 static std::string getDescription();
14060
14061 virtual std::string getStylesheetRef() const;
14062
14063 void writeSourceInfo(SourceLineInfo const& sourceInfo);
14064
14065 public: // StreamingReporterBase
14066
14067 void testRunStarting(TestRunInfo const& testInfo) override;
14068
14069 void testCaseStarting(TestCaseInfo const& testInfo) override;
14070
14071 void sectionStarting(SectionInfo const& sectionInfo) override;
14072
14073 void assertionStarting(AssertionInfo const&) override;
14074
14075 void assertionEnded(AssertionStats const& assertionStats) override;
14076
14077 void sectionEnded(SectionStats const& sectionStats) override;
14078
14079 void testCaseEnded(TestCaseStats const& testCaseStats) override;
14080
14081 void testRunEnded(TestRunStats const& testRunStats) override;
14082
14083 void benchmarkPreparing( StringRef name ) override;
14084 void benchmarkStarting(BenchmarkInfo const&) override;
14085 void benchmarkEnded(BenchmarkStats<> const&) override;
14086 void benchmarkFailed( StringRef error ) override;
14087
14088 void listReporters(std::vector<ReporterDescription> const& descriptions) override;
14089 void listListeners(std::vector<ListenerDescription> const& descriptions) override;
14090 void listTests(std::vector<TestCaseHandle> const& tests) override;
14091 void listTags(std::vector<TagInfo> const& tags) override;
14092
14093 private:
14094 Timer m_testCaseTimer;
14095 XmlWriter m_xml;
14096 int m_sectionDepth = 0;
14097 };
14098
14099} // end namespace Catch
14100
14101#endif // CATCH_REPORTER_XML_HPP_INCLUDED
14102
14103#endif // CATCH_REPORTERS_ALL_HPP_INCLUDED
14104
14105#endif // CATCH_ALL_HPP_INCLUDED
14106#endif // CATCH_AMALGAMATED_HPP_INCLUDED