The open source OpenXR runtime
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.6.0
10// Generated: 2024-05-05 20:53:27.071502
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 IResultCapture* getResultCapture() const { return m_resultCapture; }
559 IConfig const* getConfig() const { return m_config; }
560 void setResultCapture( IResultCapture* resultCapture );
561 void setConfig( IConfig const* config );
562 };
563
564 Context& getCurrentMutableContext();
565
566 inline Context const& getCurrentContext() {
567 // We duplicate the logic from `getCurrentMutableContext` here,
568 // to avoid paying the call overhead in debug mode.
569 if ( !Context::currentContext ) { Context::createContext(); }
570 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
571 return *Context::currentContext;
572 }
573
574 void cleanUpContext();
575
576 class SimplePcg32;
577 SimplePcg32& sharedRng();
578}
579
580#endif // CATCH_CONTEXT_HPP_INCLUDED
581
582
583#ifndef CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
584#define CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
585
586#include <type_traits>
587
588//! Replacement for std::move with better compile time performance
589#define CATCH_MOVE(...) static_cast<std::remove_reference_t<decltype(__VA_ARGS__)>&&>(__VA_ARGS__)
590
591//! Replacement for std::forward with better compile time performance
592#define CATCH_FORWARD(...) static_cast<decltype(__VA_ARGS__)&&>(__VA_ARGS__)
593
594#endif // CATCH_MOVE_AND_FORWARD_HPP_INCLUDED
595
596
597#ifndef CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
598#define CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
599
600namespace Catch {
601
602 //! Used to signal that an assertion macro failed
603 struct TestFailureException{};
604 //! Used to signal that the remainder of a test should be skipped
605 struct TestSkipException {};
606
607 /**
608 * Outlines throwing of `TestFailureException` into a single TU
609 *
610 * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
611 */
612 [[noreturn]] void throw_test_failure_exception();
613
614 /**
615 * Outlines throwing of `TestSkipException` into a single TU
616 *
617 * Also handles `CATCH_CONFIG_DISABLE_EXCEPTIONS` for callers.
618 */
619 [[noreturn]] void throw_test_skip_exception();
620
621} // namespace Catch
622
623#endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED
624
625
626#ifndef CATCH_UNIQUE_NAME_HPP_INCLUDED
627#define CATCH_UNIQUE_NAME_HPP_INCLUDED
628
629
630
631
632/** \file
633 * Wrapper for the CONFIG configuration option
634 *
635 * When generating internal unique names, there are two options. Either
636 * we mix in the current line number, or mix in an incrementing number.
637 * We prefer the latter, using `__COUNTER__`, but users might want to
638 * use the former.
639 */
640
641#ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED
642#define CATCH_CONFIG_COUNTER_HPP_INCLUDED
643
644
645#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
646 #define CATCH_INTERNAL_CONFIG_COUNTER
647#endif
648
649#if defined( CATCH_INTERNAL_CONFIG_COUNTER ) && \
650 !defined( CATCH_CONFIG_NO_COUNTER ) && \
651 !defined( CATCH_CONFIG_COUNTER )
652# define CATCH_CONFIG_COUNTER
653#endif
654
655
656#endif // CATCH_CONFIG_COUNTER_HPP_INCLUDED
657#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
658#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
659#ifdef CATCH_CONFIG_COUNTER
660# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
661#else
662# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
663#endif
664
665#endif // CATCH_UNIQUE_NAME_HPP_INCLUDED
666
667
668#ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
669#define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
670
671#include <string>
672#include <chrono>
673
674
675
676#ifndef CATCH_STRINGREF_HPP_INCLUDED
677#define CATCH_STRINGREF_HPP_INCLUDED
678
679#include <cstddef>
680#include <string>
681#include <iosfwd>
682#include <cassert>
683
684#include <cstring>
685
686namespace Catch {
687
688 /// A non-owning string class (similar to the forthcoming std::string_view)
689 /// Note that, because a StringRef may be a substring of another string,
690 /// it may not be null terminated.
691 class StringRef {
692 public:
693 using size_type = std::size_t;
694 using const_iterator = const char*;
695
696 static constexpr size_type npos{ static_cast<size_type>( -1 ) };
697
698 private:
699 static constexpr char const* const s_empty = "";
700
701 char const* m_start = s_empty;
702 size_type m_size = 0;
703
704 public: // construction
705 constexpr StringRef() noexcept = default;
706
707 StringRef( char const* rawChars ) noexcept;
708
709 constexpr StringRef( char const* rawChars, size_type size ) noexcept
710 : m_start( rawChars ),
711 m_size( size )
712 {}
713
714 StringRef( std::string const& stdString ) noexcept
715 : m_start( stdString.c_str() ),
716 m_size( stdString.size() )
717 {}
718
719 explicit operator std::string() const {
720 return std::string(m_start, m_size);
721 }
722
723 public: // operators
724 auto operator == ( StringRef other ) const noexcept -> bool {
725 return m_size == other.m_size
726 && (std::memcmp( m_start, other.m_start, m_size ) == 0);
727 }
728 auto operator != (StringRef other) const noexcept -> bool {
729 return !(*this == other);
730 }
731
732 constexpr auto operator[] ( size_type index ) const noexcept -> char {
733 assert(index < m_size);
734 return m_start[index];
735 }
736
737 bool operator<(StringRef rhs) const noexcept;
738
739 public: // named queries
740 constexpr auto empty() const noexcept -> bool {
741 return m_size == 0;
742 }
743 constexpr auto size() const noexcept -> size_type {
744 return m_size;
745 }
746
747 // Returns a substring of [start, start + length).
748 // If start + length > size(), then the substring is [start, size()).
749 // If start > size(), then the substring is empty.
750 constexpr StringRef substr(size_type start, size_type length) const noexcept {
751 if (start < m_size) {
752 const auto shortened_size = m_size - start;
753 return StringRef(m_start + start, (shortened_size < length) ? shortened_size : length);
754 } else {
755 return StringRef();
756 }
757 }
758
759 // Returns the current start pointer. May not be null-terminated.
760 constexpr char const* data() const noexcept {
761 return m_start;
762 }
763
764 constexpr const_iterator begin() const { return m_start; }
765 constexpr const_iterator end() const { return m_start + m_size; }
766
767
768 friend std::string& operator += (std::string& lhs, StringRef rhs);
769 friend std::ostream& operator << (std::ostream& os, StringRef str);
770 friend std::string operator+(StringRef lhs, StringRef rhs);
771
772 /**
773 * Provides a three-way comparison with rhs
774 *
775 * Returns negative number if lhs < rhs, 0 if lhs == rhs, and a positive
776 * number if lhs > rhs
777 */
778 int compare( StringRef rhs ) const;
779 };
780
781
782 constexpr auto operator ""_sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
783 return StringRef( rawChars, size );
784 }
785} // namespace Catch
786
787constexpr auto operator ""_catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
788 return Catch::StringRef( rawChars, size );
789}
790
791#endif // CATCH_STRINGREF_HPP_INCLUDED
792
793
794#ifndef CATCH_RESULT_TYPE_HPP_INCLUDED
795#define CATCH_RESULT_TYPE_HPP_INCLUDED
796
797namespace Catch {
798
799 // ResultWas::OfType enum
800 struct ResultWas { enum OfType {
801 Unknown = -1,
802 Ok = 0,
803 Info = 1,
804 Warning = 2,
805 // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit?
806 ExplicitSkip = 4,
807
808 FailureBit = 0x10,
809
810 ExpressionFailed = FailureBit | 1,
811 ExplicitFailure = FailureBit | 2,
812
813 Exception = 0x100 | FailureBit,
814
815 ThrewException = Exception | 1,
816 DidntThrowException = Exception | 2,
817
818 FatalErrorCondition = 0x200 | FailureBit
819
820 }; };
821
822 bool isOk( ResultWas::OfType resultType );
823 bool isJustInfo( int flags );
824
825
826 // ResultDisposition::Flags enum
827 struct ResultDisposition { enum Flags {
828 Normal = 0x01,
829
830 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
831 FalseTest = 0x04, // Prefix expression with !
832 SuppressFail = 0x08 // Failures are reported but do not fail the test
833 }; };
834
835 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
836
837 bool shouldContinueOnFailure( int flags );
838 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
839 bool shouldSuppressFailure( int flags );
840
841} // end namespace Catch
842
843#endif // CATCH_RESULT_TYPE_HPP_INCLUDED
844
845
846#ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED
847#define CATCH_UNIQUE_PTR_HPP_INCLUDED
848
849#include <cassert>
850#include <type_traits>
851
852
853namespace Catch {
854namespace Detail {
855 /**
856 * A reimplementation of `std::unique_ptr` for improved compilation performance
857 *
858 * Does not support arrays nor custom deleters.
859 */
860 template <typename T>
861 class unique_ptr {
862 T* m_ptr;
863 public:
864 constexpr unique_ptr(std::nullptr_t = nullptr):
865 m_ptr{}
866 {}
867 explicit constexpr unique_ptr(T* ptr):
868 m_ptr(ptr)
869 {}
870
871 template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
872 unique_ptr(unique_ptr<U>&& from):
873 m_ptr(from.release())
874 {}
875
876 template <typename U, typename = std::enable_if_t<std::is_base_of<T, U>::value>>
877 unique_ptr& operator=(unique_ptr<U>&& from) {
878 reset(from.release());
879
880 return *this;
881 }
882
883 unique_ptr(unique_ptr const&) = delete;
884 unique_ptr& operator=(unique_ptr const&) = delete;
885
886 unique_ptr(unique_ptr&& rhs) noexcept:
887 m_ptr(rhs.m_ptr) {
888 rhs.m_ptr = nullptr;
889 }
890 unique_ptr& operator=(unique_ptr&& rhs) noexcept {
891 reset(rhs.release());
892
893 return *this;
894 }
895
896 ~unique_ptr() {
897 delete m_ptr;
898 }
899
900 T& operator*() {
901 assert(m_ptr);
902 return *m_ptr;
903 }
904 T const& operator*() const {
905 assert(m_ptr);
906 return *m_ptr;
907 }
908 T* operator->() noexcept {
909 assert(m_ptr);
910 return m_ptr;
911 }
912 T const* operator->() const noexcept {
913 assert(m_ptr);
914 return m_ptr;
915 }
916
917 T* get() { return m_ptr; }
918 T const* get() const { return m_ptr; }
919
920 void reset(T* ptr = nullptr) {
921 delete m_ptr;
922 m_ptr = ptr;
923 }
924
925 T* release() {
926 auto temp = m_ptr;
927 m_ptr = nullptr;
928 return temp;
929 }
930
931 explicit operator bool() const {
932 return m_ptr;
933 }
934
935 friend void swap(unique_ptr& lhs, unique_ptr& rhs) {
936 auto temp = lhs.m_ptr;
937 lhs.m_ptr = rhs.m_ptr;
938 rhs.m_ptr = temp;
939 }
940 };
941
942 //! Specialization to cause compile-time error for arrays
943 template <typename T>
944 class unique_ptr<T[]>;
945
946 template <typename T, typename... Args>
947 unique_ptr<T> make_unique(Args&&... args) {
948 return unique_ptr<T>(new T(CATCH_FORWARD(args)...));
949 }
950
951
952} // end namespace Detail
953} // end namespace Catch
954
955#endif // CATCH_UNIQUE_PTR_HPP_INCLUDED
956
957
958#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
959#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
960
961
962
963// Adapted from donated nonius code.
964
965#ifndef CATCH_CLOCK_HPP_INCLUDED
966#define CATCH_CLOCK_HPP_INCLUDED
967
968#include <chrono>
969
970namespace Catch {
971 namespace Benchmark {
972 using IDuration = std::chrono::nanoseconds;
973 using FDuration = std::chrono::duration<double, std::nano>;
974
975 template <typename Clock>
976 using TimePoint = typename Clock::time_point;
977
978 using default_clock = std::chrono::steady_clock;
979 } // namespace Benchmark
980} // namespace Catch
981
982#endif // CATCH_CLOCK_HPP_INCLUDED
983
984namespace Catch {
985
986 // We cannot forward declare the type with default template argument
987 // multiple times, so it is split out into a separate header so that
988 // we can prevent multiple declarations in dependees
989 template <typename Duration = Benchmark::FDuration>
990 struct BenchmarkStats;
991
992} // end namespace Catch
993
994#endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED
995
996namespace Catch {
997
998 class AssertionResult;
999 struct AssertionInfo;
1000 struct SectionInfo;
1001 struct SectionEndInfo;
1002 struct MessageInfo;
1003 struct MessageBuilder;
1004 struct Counts;
1005 struct AssertionReaction;
1006 struct SourceLineInfo;
1007
1008 class ITransientExpression;
1009 class IGeneratorTracker;
1010
1011 struct BenchmarkInfo;
1012
1013 namespace Generators {
1014 class GeneratorUntypedBase;
1015 using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
1016 }
1017
1018
1019 class IResultCapture {
1020 public:
1021 virtual ~IResultCapture();
1022
1023 virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0;
1024 virtual bool sectionStarted( StringRef sectionName,
1025 SourceLineInfo const& sectionLineInfo,
1026 Counts& assertions ) = 0;
1027 virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0;
1028 virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0;
1029
1030 virtual IGeneratorTracker*
1031 acquireGeneratorTracker( StringRef generatorName,
1032 SourceLineInfo const& lineInfo ) = 0;
1033 virtual IGeneratorTracker*
1034 createGeneratorTracker( StringRef generatorName,
1035 SourceLineInfo lineInfo,
1036 Generators::GeneratorBasePtr&& generator ) = 0;
1037
1038 virtual void benchmarkPreparing( StringRef name ) = 0;
1039 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
1040 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
1041 virtual void benchmarkFailed( StringRef error ) = 0;
1042
1043 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1044 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1045
1046 virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0;
1047
1048 virtual void handleFatalErrorCondition( StringRef message ) = 0;
1049
1050 virtual void handleExpr
1051 ( AssertionInfo const& info,
1052 ITransientExpression const& expr,
1053 AssertionReaction& reaction ) = 0;
1054 virtual void handleMessage
1055 ( AssertionInfo const& info,
1056 ResultWas::OfType resultType,
1057 StringRef message,
1058 AssertionReaction& reaction ) = 0;
1059 virtual void handleUnexpectedExceptionNotThrown
1060 ( AssertionInfo const& info,
1061 AssertionReaction& reaction ) = 0;
1062 virtual void handleUnexpectedInflightException
1063 ( AssertionInfo const& info,
1064 std::string&& message,
1065 AssertionReaction& reaction ) = 0;
1066 virtual void handleIncomplete
1067 ( AssertionInfo const& info ) = 0;
1068 virtual void handleNonExpr
1069 ( AssertionInfo const &info,
1070 ResultWas::OfType resultType,
1071 AssertionReaction &reaction ) = 0;
1072
1073
1074
1075 virtual bool lastAssertionPassed() = 0;
1076 virtual void assertionPassed() = 0;
1077
1078 // Deprecated, do not use:
1079 virtual std::string getCurrentTestName() const = 0;
1080 virtual const AssertionResult* getLastResult() const = 0;
1081 virtual void exceptionEarlyReported() = 0;
1082 };
1083
1084 IResultCapture& getResultCapture();
1085}
1086
1087#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED
1088
1089
1090#ifndef CATCH_INTERFACES_CONFIG_HPP_INCLUDED
1091#define CATCH_INTERFACES_CONFIG_HPP_INCLUDED
1092
1093
1094
1095#ifndef CATCH_NONCOPYABLE_HPP_INCLUDED
1096#define CATCH_NONCOPYABLE_HPP_INCLUDED
1097
1098namespace Catch {
1099 namespace Detail {
1100
1101 //! Deriving classes become noncopyable and nonmovable
1102 class NonCopyable {
1103 NonCopyable( NonCopyable const& ) = delete;
1104 NonCopyable( NonCopyable&& ) = delete;
1105 NonCopyable& operator=( NonCopyable const& ) = delete;
1106 NonCopyable& operator=( NonCopyable&& ) = delete;
1107
1108 protected:
1109 NonCopyable() noexcept = default;
1110 };
1111
1112 } // namespace Detail
1113} // namespace Catch
1114
1115#endif // CATCH_NONCOPYABLE_HPP_INCLUDED
1116
1117#include <chrono>
1118#include <iosfwd>
1119#include <string>
1120#include <vector>
1121
1122namespace Catch {
1123
1124 enum class Verbosity {
1125 Quiet = 0,
1126 Normal,
1127 High
1128 };
1129
1130 struct WarnAbout { enum What {
1131 Nothing = 0x00,
1132 //! A test case or leaf section did not run any assertions
1133 NoAssertions = 0x01,
1134 //! A command line test spec matched no test cases
1135 UnmatchedTestSpec = 0x02,
1136 }; };
1137
1138 enum class ShowDurations {
1139 DefaultForReporter,
1140 Always,
1141 Never
1142 };
1143 enum class TestRunOrder {
1144 Declared,
1145 LexicographicallySorted,
1146 Randomized
1147 };
1148 enum class ColourMode : std::uint8_t {
1149 //! Let Catch2 pick implementation based on platform detection
1150 PlatformDefault,
1151 //! Use ANSI colour code escapes
1152 ANSI,
1153 //! Use Win32 console colour API
1154 Win32,
1155 //! Don't use any colour
1156 None
1157 };
1158 struct WaitForKeypress { enum When {
1159 Never,
1160 BeforeStart = 1,
1161 BeforeExit = 2,
1162 BeforeStartAndExit = BeforeStart | BeforeExit
1163 }; };
1164
1165 class TestSpec;
1166 class IStream;
1167
1168 class IConfig : public Detail::NonCopyable {
1169 public:
1170 virtual ~IConfig();
1171
1172 virtual bool allowThrows() const = 0;
1173 virtual StringRef name() const = 0;
1174 virtual bool includeSuccessfulResults() const = 0;
1175 virtual bool shouldDebugBreak() const = 0;
1176 virtual bool warnAboutMissingAssertions() const = 0;
1177 virtual bool warnAboutUnmatchedTestSpecs() const = 0;
1178 virtual bool zeroTestsCountAsSuccess() const = 0;
1179 virtual int abortAfter() const = 0;
1180 virtual bool showInvisibles() const = 0;
1181 virtual ShowDurations showDurations() const = 0;
1182 virtual double minDuration() const = 0;
1183 virtual TestSpec const& testSpec() const = 0;
1184 virtual bool hasTestFilters() const = 0;
1185 virtual std::vector<std::string> const& getTestsOrTags() const = 0;
1186 virtual TestRunOrder runOrder() const = 0;
1187 virtual uint32_t rngSeed() const = 0;
1188 virtual unsigned int shardCount() const = 0;
1189 virtual unsigned int shardIndex() const = 0;
1190 virtual ColourMode defaultColourMode() const = 0;
1191 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
1192 virtual Verbosity verbosity() const = 0;
1193
1194 virtual bool skipBenchmarks() const = 0;
1195 virtual bool benchmarkNoAnalysis() const = 0;
1196 virtual unsigned int benchmarkSamples() const = 0;
1197 virtual double benchmarkConfidenceInterval() const = 0;
1198 virtual unsigned int benchmarkResamples() const = 0;
1199 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
1200 };
1201}
1202
1203#endif // CATCH_INTERFACES_CONFIG_HPP_INCLUDED
1204
1205
1206#ifndef CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
1207#define CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
1208
1209
1210#include <string>
1211
1212namespace Catch {
1213
1214 class TestCaseHandle;
1215 struct TestCaseInfo;
1216 class ITestCaseRegistry;
1217 class IExceptionTranslatorRegistry;
1218 class IExceptionTranslator;
1219 class ReporterRegistry;
1220 class IReporterFactory;
1221 class ITagAliasRegistry;
1222 class ITestInvoker;
1223 class IMutableEnumValuesRegistry;
1224 struct SourceLineInfo;
1225
1226 class StartupExceptionRegistry;
1227 class EventListenerFactory;
1228
1229 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
1230
1231 class IRegistryHub {
1232 public:
1233 virtual ~IRegistryHub(); // = default
1234
1235 virtual ReporterRegistry const& getReporterRegistry() const = 0;
1236 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
1237 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
1238 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
1239
1240
1241 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
1242 };
1243
1244 class IMutableRegistryHub {
1245 public:
1246 virtual ~IMutableRegistryHub(); // = default
1247 virtual void registerReporter( std::string const& name, IReporterFactoryPtr factory ) = 0;
1248 virtual void registerListener( Detail::unique_ptr<EventListenerFactory> factory ) = 0;
1249 virtual void registerTest(Detail::unique_ptr<TestCaseInfo>&& testInfo, Detail::unique_ptr<ITestInvoker>&& invoker) = 0;
1250 virtual void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) = 0;
1251 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
1252 virtual void registerStartupException() noexcept = 0;
1253 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
1254 };
1255
1256 IRegistryHub const& getRegistryHub();
1257 IMutableRegistryHub& getMutableRegistryHub();
1258 void cleanUp();
1259 std::string translateActiveException();
1260
1261}
1262
1263#endif // CATCH_INTERFACES_REGISTRY_HUB_HPP_INCLUDED
1264
1265
1266#ifndef CATCH_BENCHMARK_STATS_HPP_INCLUDED
1267#define CATCH_BENCHMARK_STATS_HPP_INCLUDED
1268
1269
1270
1271// Adapted from donated nonius code.
1272
1273#ifndef CATCH_ESTIMATE_HPP_INCLUDED
1274#define CATCH_ESTIMATE_HPP_INCLUDED
1275
1276namespace Catch {
1277 namespace Benchmark {
1278 template <typename Type>
1279 struct Estimate {
1280 Type point;
1281 Type lower_bound;
1282 Type upper_bound;
1283 double confidence_interval;
1284 };
1285 } // namespace Benchmark
1286} // namespace Catch
1287
1288#endif // CATCH_ESTIMATE_HPP_INCLUDED
1289
1290
1291// Adapted from donated nonius code.
1292
1293#ifndef CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
1294#define CATCH_OUTLIER_CLASSIFICATION_HPP_INCLUDED
1295
1296namespace Catch {
1297 namespace Benchmark {
1298 struct OutlierClassification {
1299 int samples_seen = 0;
1300 int low_severe = 0; // more than 3 times IQR below Q1
1301 int low_mild = 0; // 1.5 to 3 times IQR below Q1
1302 int high_mild = 0; // 1.5 to 3 times IQR above Q3
1303 int high_severe = 0; // more than 3 times IQR above Q3
1304
1305 int total() const {
1306 return low_severe + low_mild + high_mild + high_severe;
1307 }
1308 };
1309 } // namespace Benchmark
1310} // namespace Catch
1311
1312#endif // CATCH_OUTLIERS_CLASSIFICATION_HPP_INCLUDED
1313// The fwd decl & default specialization needs to be seen by VS2017 before
1314// BenchmarkStats itself, or VS2017 will report compilation error.
1315
1316#include <string>
1317#include <vector>
1318
1319namespace Catch {
1320
1321 struct BenchmarkInfo {
1322 std::string name;
1323 double estimatedDuration;
1324 int iterations;
1325 unsigned int samples;
1326 unsigned int resamples;
1327 double clockResolution;
1328 double clockCost;
1329 };
1330
1331 // We need to keep template parameter for backwards compatibility,
1332 // but we also do not want to use the template paraneter.
1333 template <class Dummy>
1334 struct BenchmarkStats {
1335 BenchmarkInfo info;
1336
1337 std::vector<Benchmark::FDuration> samples;
1338 Benchmark::Estimate<Benchmark::FDuration> mean;
1339 Benchmark::Estimate<Benchmark::FDuration> standardDeviation;
1340 Benchmark::OutlierClassification outliers;
1341 double outlierVariance;
1342 };
1343
1344
1345} // end namespace Catch
1346
1347#endif // CATCH_BENCHMARK_STATS_HPP_INCLUDED
1348
1349
1350// Adapted from donated nonius code.
1351
1352#ifndef CATCH_ENVIRONMENT_HPP_INCLUDED
1353#define CATCH_ENVIRONMENT_HPP_INCLUDED
1354
1355
1356namespace Catch {
1357 namespace Benchmark {
1358 struct EnvironmentEstimate {
1359 FDuration mean;
1360 OutlierClassification outliers;
1361 };
1362 struct Environment {
1363 EnvironmentEstimate clock_resolution;
1364 EnvironmentEstimate clock_cost;
1365 };
1366 } // namespace Benchmark
1367} // namespace Catch
1368
1369#endif // CATCH_ENVIRONMENT_HPP_INCLUDED
1370
1371
1372// Adapted from donated nonius code.
1373
1374#ifndef CATCH_EXECUTION_PLAN_HPP_INCLUDED
1375#define CATCH_EXECUTION_PLAN_HPP_INCLUDED
1376
1377
1378
1379// Adapted from donated nonius code.
1380
1381#ifndef CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
1382#define CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
1383
1384
1385
1386// Adapted from donated nonius code.
1387
1388#ifndef CATCH_CHRONOMETER_HPP_INCLUDED
1389#define CATCH_CHRONOMETER_HPP_INCLUDED
1390
1391
1392
1393// Adapted from donated nonius code.
1394
1395#ifndef CATCH_OPTIMIZER_HPP_INCLUDED
1396#define CATCH_OPTIMIZER_HPP_INCLUDED
1397
1398#if defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
1399# include <atomic> // atomic_thread_fence
1400#endif
1401
1402
1403#include <type_traits>
1404
1405namespace Catch {
1406 namespace Benchmark {
1407#if defined(__GNUC__) || defined(__clang__)
1408 template <typename T>
1409 inline void keep_memory(T* p) {
1410 asm volatile("" : : "g"(p) : "memory");
1411 }
1412 inline void keep_memory() {
1413 asm volatile("" : : : "memory");
1414 }
1415
1416 namespace Detail {
1417 inline void optimizer_barrier() { keep_memory(); }
1418 } // namespace Detail
1419#elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__)
1420
1421#if defined(_MSVC_VER)
1422#pragma optimize("", off)
1423#elif defined(__IAR_SYSTEMS_ICC__)
1424// For IAR the pragma only affects the following function
1425#pragma optimize=disable
1426#endif
1427 template <typename T>
1428 inline void keep_memory(T* p) {
1429 // thanks @milleniumbug
1430 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
1431 }
1432 // TODO equivalent keep_memory()
1433#if defined(_MSVC_VER)
1434#pragma optimize("", on)
1435#endif
1436
1437 namespace Detail {
1438 inline void optimizer_barrier() {
1439 std::atomic_thread_fence(std::memory_order_seq_cst);
1440 }
1441 } // namespace Detail
1442
1443#endif
1444
1445 template <typename T>
1446 inline void deoptimize_value(T&& x) {
1447 keep_memory(&x);
1448 }
1449
1450 template <typename Fn, typename... Args>
1451 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<!std::is_same<void, decltype(fn(args...))>::value> {
1452 deoptimize_value(CATCH_FORWARD(fn) (CATCH_FORWARD(args)...));
1453 }
1454
1455 template <typename Fn, typename... Args>
1456 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> {
1457 CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...);
1458 }
1459 } // namespace Benchmark
1460} // namespace Catch
1461
1462#endif // CATCH_OPTIMIZER_HPP_INCLUDED
1463
1464
1465#ifndef CATCH_META_HPP_INCLUDED
1466#define CATCH_META_HPP_INCLUDED
1467
1468#include <type_traits>
1469
1470namespace Catch {
1471 template <typename>
1472 struct true_given : std::true_type {};
1473
1474 struct is_callable_tester {
1475 template <typename Fun, typename... Args>
1476 static true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> test(int);
1477 template <typename...>
1478 static std::false_type test(...);
1479 };
1480
1481 template <typename T>
1482 struct is_callable;
1483
1484 template <typename Fun, typename... Args>
1485 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
1486
1487
1488#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
1489 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
1490 // replaced with std::invoke_result here.
1491 template <typename Func, typename... U>
1492 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
1493#else
1494 template <typename Func, typename... U>
1495 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::result_of_t<Func(U...)>>>;
1496#endif
1497
1498} // namespace Catch
1499
1500namespace mpl_{
1501 struct na;
1502}
1503
1504#endif // CATCH_META_HPP_INCLUDED
1505
1506namespace Catch {
1507 namespace Benchmark {
1508 namespace Detail {
1509 struct ChronometerConcept {
1510 virtual void start() = 0;
1511 virtual void finish() = 0;
1512 virtual ~ChronometerConcept(); // = default;
1513
1514 ChronometerConcept() = default;
1515 ChronometerConcept(ChronometerConcept const&) = default;
1516 ChronometerConcept& operator=(ChronometerConcept const&) = default;
1517 };
1518 template <typename Clock>
1519 struct ChronometerModel final : public ChronometerConcept {
1520 void start() override { started = Clock::now(); }
1521 void finish() override { finished = Clock::now(); }
1522
1523 IDuration elapsed() const {
1524 return std::chrono::duration_cast<std::chrono::nanoseconds>(
1525 finished - started );
1526 }
1527
1528 TimePoint<Clock> started;
1529 TimePoint<Clock> finished;
1530 };
1531 } // namespace Detail
1532
1533 struct Chronometer {
1534 public:
1535 template <typename Fun>
1536 void measure(Fun&& fun) { measure(CATCH_FORWARD(fun), is_callable<Fun(int)>()); }
1537
1538 int runs() const { return repeats; }
1539
1540 Chronometer(Detail::ChronometerConcept& meter, int repeats_)
1541 : impl(&meter)
1542 , repeats(repeats_) {}
1543
1544 private:
1545 template <typename Fun>
1546 void measure(Fun&& fun, std::false_type) {
1547 measure([&fun](int) { return fun(); }, std::true_type());
1548 }
1549
1550 template <typename Fun>
1551 void measure(Fun&& fun, std::true_type) {
1552 Detail::optimizer_barrier();
1553 impl->start();
1554 for (int i = 0; i < repeats; ++i) invoke_deoptimized(fun, i);
1555 impl->finish();
1556 Detail::optimizer_barrier();
1557 }
1558
1559 Detail::ChronometerConcept* impl;
1560 int repeats;
1561 };
1562 } // namespace Benchmark
1563} // namespace Catch
1564
1565#endif // CATCH_CHRONOMETER_HPP_INCLUDED
1566
1567#include <type_traits>
1568
1569namespace Catch {
1570 namespace Benchmark {
1571 namespace Detail {
1572 template <typename T, typename U>
1573 struct is_related
1574 : std::is_same<std::decay_t<T>, std::decay_t<U>> {};
1575
1576 /// We need to reinvent std::function because every piece of code that might add overhead
1577 /// in a measurement context needs to have consistent performance characteristics so that we
1578 /// can account for it in the measurement.
1579 /// Implementations of std::function with optimizations that aren't always applicable, like
1580 /// small buffer optimizations, are not uncommon.
1581 /// This is effectively an implementation of std::function without any such optimizations;
1582 /// it may be slow, but it is consistently slow.
1583 struct BenchmarkFunction {
1584 private:
1585 struct callable {
1586 virtual void call(Chronometer meter) const = 0;
1587 virtual Catch::Detail::unique_ptr<callable> clone() const = 0;
1588 virtual ~callable(); // = default;
1589
1590 callable() = default;
1591 callable(callable const&) = default;
1592 callable& operator=(callable const&) = default;
1593 };
1594 template <typename Fun>
1595 struct model : public callable {
1596 model(Fun&& fun_) : fun(CATCH_MOVE(fun_)) {}
1597 model(Fun const& fun_) : fun(fun_) {}
1598
1599 Catch::Detail::unique_ptr<callable> clone() const override {
1600 return Catch::Detail::make_unique<model<Fun>>( *this );
1601 }
1602
1603 void call(Chronometer meter) const override {
1604 call(meter, is_callable<Fun(Chronometer)>());
1605 }
1606 void call(Chronometer meter, std::true_type) const {
1607 fun(meter);
1608 }
1609 void call(Chronometer meter, std::false_type) const {
1610 meter.measure(fun);
1611 }
1612
1613 Fun fun;
1614 };
1615
1616 struct do_nothing { void operator()() const {} };
1617
1618 template <typename T>
1619 BenchmarkFunction(model<T>* c) : f(c) {}
1620
1621 public:
1622 BenchmarkFunction()
1623 : f(new model<do_nothing>{ {} }) {}
1624
1625 template <typename Fun,
1626 std::enable_if_t<!is_related<Fun, BenchmarkFunction>::value, int> = 0>
1627 BenchmarkFunction(Fun&& fun)
1628 : f(new model<std::decay_t<Fun>>(CATCH_FORWARD(fun))) {}
1629
1630 BenchmarkFunction( BenchmarkFunction&& that ) noexcept:
1631 f( CATCH_MOVE( that.f ) ) {}
1632
1633 BenchmarkFunction(BenchmarkFunction const& that)
1634 : f(that.f->clone()) {}
1635
1636 BenchmarkFunction&
1637 operator=( BenchmarkFunction&& that ) noexcept {
1638 f = CATCH_MOVE( that.f );
1639 return *this;
1640 }
1641
1642 BenchmarkFunction& operator=(BenchmarkFunction const& that) {
1643 f = that.f->clone();
1644 return *this;
1645 }
1646
1647 void operator()(Chronometer meter) const { f->call(meter); }
1648
1649 private:
1650 Catch::Detail::unique_ptr<callable> f;
1651 };
1652 } // namespace Detail
1653 } // namespace Benchmark
1654} // namespace Catch
1655
1656#endif // CATCH_BENCHMARK_FUNCTION_HPP_INCLUDED
1657
1658
1659// Adapted from donated nonius code.
1660
1661#ifndef CATCH_REPEAT_HPP_INCLUDED
1662#define CATCH_REPEAT_HPP_INCLUDED
1663
1664#include <type_traits>
1665
1666namespace Catch {
1667 namespace Benchmark {
1668 namespace Detail {
1669 template <typename Fun>
1670 struct repeater {
1671 void operator()(int k) const {
1672 for (int i = 0; i < k; ++i) {
1673 fun();
1674 }
1675 }
1676 Fun fun;
1677 };
1678 template <typename Fun>
1679 repeater<std::decay_t<Fun>> repeat(Fun&& fun) {
1680 return { CATCH_FORWARD(fun) };
1681 }
1682 } // namespace Detail
1683 } // namespace Benchmark
1684} // namespace Catch
1685
1686#endif // CATCH_REPEAT_HPP_INCLUDED
1687
1688
1689// Adapted from donated nonius code.
1690
1691#ifndef CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
1692#define CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
1693
1694
1695
1696// Adapted from donated nonius code.
1697
1698#ifndef CATCH_MEASURE_HPP_INCLUDED
1699#define CATCH_MEASURE_HPP_INCLUDED
1700
1701
1702
1703// Adapted from donated nonius code.
1704
1705#ifndef CATCH_COMPLETE_INVOKE_HPP_INCLUDED
1706#define CATCH_COMPLETE_INVOKE_HPP_INCLUDED
1707
1708
1709namespace Catch {
1710 namespace Benchmark {
1711 namespace Detail {
1712 template <typename T>
1713 struct CompleteType { using type = T; };
1714 template <>
1715 struct CompleteType<void> { struct type {}; };
1716
1717 template <typename T>
1718 using CompleteType_t = typename CompleteType<T>::type;
1719
1720 template <typename Result>
1721 struct CompleteInvoker {
1722 template <typename Fun, typename... Args>
1723 static Result invoke(Fun&& fun, Args&&... args) {
1724 return CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
1725 }
1726 };
1727 template <>
1728 struct CompleteInvoker<void> {
1729 template <typename Fun, typename... Args>
1730 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {
1731 CATCH_FORWARD(fun)(CATCH_FORWARD(args)...);
1732 return {};
1733 }
1734 };
1735
1736 // invoke and not return void :(
1737 template <typename Fun, typename... Args>
1738 CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {
1739 return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(CATCH_FORWARD(fun), CATCH_FORWARD(args)...);
1740 }
1741
1742 } // namespace Detail
1743
1744 template <typename Fun>
1745 Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {
1746 return Detail::complete_invoke(CATCH_FORWARD(fun));
1747 }
1748 } // namespace Benchmark
1749} // namespace Catch
1750
1751#endif // CATCH_COMPLETE_INVOKE_HPP_INCLUDED
1752
1753
1754// Adapted from donated nonius code.
1755
1756#ifndef CATCH_TIMING_HPP_INCLUDED
1757#define CATCH_TIMING_HPP_INCLUDED
1758
1759
1760#include <type_traits>
1761
1762namespace Catch {
1763 namespace Benchmark {
1764 template <typename Result>
1765 struct Timing {
1766 IDuration elapsed;
1767 Result result;
1768 int iterations;
1769 };
1770 template <typename Func, typename... Args>
1771 using TimingOf = Timing<Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
1772 } // namespace Benchmark
1773} // namespace Catch
1774
1775#endif // CATCH_TIMING_HPP_INCLUDED
1776
1777namespace Catch {
1778 namespace Benchmark {
1779 namespace Detail {
1780 template <typename Clock, typename Fun, typename... Args>
1781 TimingOf<Fun, Args...> measure(Fun&& fun, Args&&... args) {
1782 auto start = Clock::now();
1783 auto&& r = Detail::complete_invoke(fun, CATCH_FORWARD(args)...);
1784 auto end = Clock::now();
1785 auto delta = end - start;
1786 return { delta, CATCH_FORWARD(r), 1 };
1787 }
1788 } // namespace Detail
1789 } // namespace Benchmark
1790} // namespace Catch
1791
1792#endif // CATCH_MEASURE_HPP_INCLUDED
1793
1794#include <type_traits>
1795
1796namespace Catch {
1797 namespace Benchmark {
1798 namespace Detail {
1799 template <typename Clock, typename Fun>
1800 TimingOf<Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {
1801 return Detail::measure<Clock>(fun, iters);
1802 }
1803 template <typename Clock, typename Fun>
1804 TimingOf<Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {
1805 Detail::ChronometerModel<Clock> meter;
1806 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
1807
1808 return { meter.elapsed(), CATCH_MOVE(result), iters };
1809 }
1810
1811 template <typename Clock, typename Fun>
1812 using run_for_at_least_argument_t = std::conditional_t<is_callable<Fun(Chronometer)>::value, Chronometer, int>;
1813
1814
1815 [[noreturn]]
1816 void throw_optimized_away_error();
1817
1818 template <typename Clock, typename Fun>
1819 TimingOf<Fun, run_for_at_least_argument_t<Clock, Fun>>
1820 run_for_at_least(IDuration how_long,
1821 const int initial_iterations,
1822 Fun&& fun) {
1823 auto iters = initial_iterations;
1824 while (iters < (1 << 30)) {
1825 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
1826
1827 if (Timing.elapsed >= how_long) {
1828 return { Timing.elapsed, CATCH_MOVE(Timing.result), iters };
1829 }
1830 iters *= 2;
1831 }
1832 throw_optimized_away_error();
1833 }
1834 } // namespace Detail
1835 } // namespace Benchmark
1836} // namespace Catch
1837
1838#endif // CATCH_RUN_FOR_AT_LEAST_HPP_INCLUDED
1839
1840#include <vector>
1841
1842namespace Catch {
1843 namespace Benchmark {
1844 struct ExecutionPlan {
1845 int iterations_per_sample;
1846 FDuration estimated_duration;
1847 Detail::BenchmarkFunction benchmark;
1848 FDuration warmup_time;
1849 int warmup_iterations;
1850
1851 template <typename Clock>
1852 std::vector<FDuration> run(const IConfig &cfg, Environment env) const {
1853 // warmup a bit
1854 Detail::run_for_at_least<Clock>(
1855 std::chrono::duration_cast<IDuration>( warmup_time ),
1856 warmup_iterations,
1857 Detail::repeat( []() { return Clock::now(); } )
1858 );
1859
1860 std::vector<FDuration> times;
1861 const auto num_samples = cfg.benchmarkSamples();
1862 times.reserve( num_samples );
1863 for ( size_t i = 0; i < num_samples; ++i ) {
1864 Detail::ChronometerModel<Clock> model;
1865 this->benchmark( Chronometer( model, iterations_per_sample ) );
1866 auto sample_time = model.elapsed() - env.clock_cost.mean;
1867 if ( sample_time < FDuration::zero() ) {
1868 sample_time = FDuration::zero();
1869 }
1870 times.push_back(sample_time / iterations_per_sample);
1871 }
1872 return times;
1873 }
1874 };
1875 } // namespace Benchmark
1876} // namespace Catch
1877
1878#endif // CATCH_EXECUTION_PLAN_HPP_INCLUDED
1879
1880
1881// Adapted from donated nonius code.
1882
1883#ifndef CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
1884#define CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
1885
1886
1887
1888// Adapted from donated nonius code.
1889
1890#ifndef CATCH_STATS_HPP_INCLUDED
1891#define CATCH_STATS_HPP_INCLUDED
1892
1893
1894#include <vector>
1895
1896namespace Catch {
1897 namespace Benchmark {
1898 namespace Detail {
1899 using sample = std::vector<double>;
1900
1901 double weighted_average_quantile( int k,
1902 int q,
1903 double* first,
1904 double* last );
1905
1906 OutlierClassification
1907 classify_outliers( double const* first, double const* last );
1908
1909 double mean( double const* first, double const* last );
1910
1911 double normal_cdf( double x );
1912
1913 double erfc_inv(double x);
1914
1915 double normal_quantile(double p);
1916
1917 Estimate<double>
1918 bootstrap( double confidence_level,
1919 double* first,
1920 double* last,
1921 sample const& resample,
1922 double ( *estimator )( double const*, double const* ) );
1923
1924 struct bootstrap_analysis {
1925 Estimate<double> mean;
1926 Estimate<double> standard_deviation;
1927 double outlier_variance;
1928 };
1929
1930 bootstrap_analysis analyse_samples(double confidence_level,
1931 unsigned int n_resamples,
1932 double* first,
1933 double* last);
1934 } // namespace Detail
1935 } // namespace Benchmark
1936} // namespace Catch
1937
1938#endif // CATCH_STATS_HPP_INCLUDED
1939
1940#include <algorithm>
1941#include <vector>
1942#include <cmath>
1943
1944namespace Catch {
1945 namespace Benchmark {
1946 namespace Detail {
1947 template <typename Clock>
1948 std::vector<double> resolution(int k) {
1949 std::vector<TimePoint<Clock>> times;
1950 times.reserve(static_cast<size_t>(k + 1));
1951 for ( int i = 0; i < k + 1; ++i ) {
1952 times.push_back( Clock::now() );
1953 }
1954
1955 std::vector<double> deltas;
1956 deltas.reserve(static_cast<size_t>(k));
1957 for ( size_t idx = 1; idx < times.size(); ++idx ) {
1958 deltas.push_back( static_cast<double>(
1959 ( times[idx] - times[idx - 1] ).count() ) );
1960 }
1961
1962 return deltas;
1963 }
1964
1965 constexpr auto warmup_iterations = 10000;
1966 constexpr auto warmup_time = std::chrono::milliseconds(100);
1967 constexpr auto minimum_ticks = 1000;
1968 constexpr auto warmup_seed = 10000;
1969 constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
1970 constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
1971 constexpr auto clock_cost_estimation_tick_limit = 100000;
1972 constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10);
1973 constexpr auto clock_cost_estimation_iterations = 10000;
1974
1975 template <typename Clock>
1976 int warmup() {
1977 return run_for_at_least<Clock>(warmup_time, warmup_seed, &resolution<Clock>)
1978 .iterations;
1979 }
1980 template <typename Clock>
1981 EnvironmentEstimate estimate_clock_resolution(int iterations) {
1982 auto r = run_for_at_least<Clock>(clock_resolution_estimation_time, iterations, &resolution<Clock>)
1983 .result;
1984 return {
1985 FDuration(mean(r.data(), r.data() + r.size())),
1986 classify_outliers(r.data(), r.data() + r.size()),
1987 };
1988 }
1989 template <typename Clock>
1990 EnvironmentEstimate estimate_clock_cost(FDuration resolution) {
1991 auto time_limit = (std::min)(
1992 resolution * clock_cost_estimation_tick_limit,
1993 FDuration(clock_cost_estimation_time_limit));
1994 auto time_clock = [](int k) {
1995 return Detail::measure<Clock>([k] {
1996 for (int i = 0; i < k; ++i) {
1997 volatile auto ignored = Clock::now();
1998 (void)ignored;
1999 }
2000 }).elapsed;
2001 };
2002 time_clock(1);
2003 int iters = clock_cost_estimation_iterations;
2004 auto&& r = run_for_at_least<Clock>(clock_cost_estimation_time, iters, time_clock);
2005 std::vector<double> times;
2006 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
2007 times.reserve(static_cast<size_t>(nsamples));
2008 for ( int s = 0; s < nsamples; ++s ) {
2009 times.push_back( static_cast<double>(
2010 ( time_clock( r.iterations ) / r.iterations )
2011 .count() ) );
2012 }
2013 return {
2014 FDuration(mean(times.data(), times.data() + times.size())),
2015 classify_outliers(times.data(), times.data() + times.size()),
2016 };
2017 }
2018
2019 template <typename Clock>
2020 Environment measure_environment() {
2021#if defined(__clang__)
2022# pragma clang diagnostic push
2023# pragma clang diagnostic ignored "-Wexit-time-destructors"
2024#endif
2025 static Catch::Detail::unique_ptr<Environment> env;
2026#if defined(__clang__)
2027# pragma clang diagnostic pop
2028#endif
2029 if (env) {
2030 return *env;
2031 }
2032
2033 auto iters = Detail::warmup<Clock>();
2034 auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
2035 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
2036
2037 env = Catch::Detail::make_unique<Environment>( Environment{resolution, cost} );
2038 return *env;
2039 }
2040 } // namespace Detail
2041 } // namespace Benchmark
2042} // namespace Catch
2043
2044#endif // CATCH_ESTIMATE_CLOCK_HPP_INCLUDED
2045
2046
2047// Adapted from donated nonius code.
2048
2049#ifndef CATCH_ANALYSE_HPP_INCLUDED
2050#define CATCH_ANALYSE_HPP_INCLUDED
2051
2052
2053
2054// Adapted from donated nonius code.
2055
2056#ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
2057#define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
2058
2059
2060#include <vector>
2061
2062namespace Catch {
2063 namespace Benchmark {
2064 struct SampleAnalysis {
2065 std::vector<FDuration> samples;
2066 Estimate<FDuration> mean;
2067 Estimate<FDuration> standard_deviation;
2068 OutlierClassification outliers;
2069 double outlier_variance;
2070 };
2071 } // namespace Benchmark
2072} // namespace Catch
2073
2074#endif // CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED
2075
2076
2077namespace Catch {
2078 class IConfig;
2079
2080 namespace Benchmark {
2081 namespace Detail {
2082 SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last);
2083 } // namespace Detail
2084 } // namespace Benchmark
2085} // namespace Catch
2086
2087#endif // CATCH_ANALYSE_HPP_INCLUDED
2088
2089#include <algorithm>
2090#include <chrono>
2091#include <exception>
2092#include <string>
2093#include <cmath>
2094
2095namespace Catch {
2096 namespace Benchmark {
2097 struct Benchmark {
2098 Benchmark(std::string&& benchmarkName)
2099 : name(CATCH_MOVE(benchmarkName)) {}
2100
2101 template <class FUN>
2102 Benchmark(std::string&& benchmarkName , FUN &&func)
2103 : fun(CATCH_MOVE(func)), name(CATCH_MOVE(benchmarkName)) {}
2104
2105 template <typename Clock>
2106 ExecutionPlan prepare(const IConfig &cfg, Environment env) const {
2107 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
2108 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
2109 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<IDuration>(run_time), 1, fun);
2110 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
2111 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FDuration>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
2112 }
2113
2114 template <typename Clock = default_clock>
2115 void run() {
2116 static_assert( Clock::is_steady,
2117 "Benchmarking clock should be steady" );
2118 auto const* cfg = getCurrentContext().getConfig();
2119
2120 auto env = Detail::measure_environment<Clock>();
2121
2122 getResultCapture().benchmarkPreparing(name);
2123 CATCH_TRY{
2124 auto plan = user_code([&] {
2125 return prepare<Clock>(*cfg, env);
2126 });
2127
2128 BenchmarkInfo info {
2129 CATCH_MOVE(name),
2130 plan.estimated_duration.count(),
2131 plan.iterations_per_sample,
2132 cfg->benchmarkSamples(),
2133 cfg->benchmarkResamples(),
2134 env.clock_resolution.mean.count(),
2135 env.clock_cost.mean.count()
2136 };
2137
2138 getResultCapture().benchmarkStarting(info);
2139
2140 auto samples = user_code([&] {
2141 return plan.template run<Clock>(*cfg, env);
2142 });
2143
2144 auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size());
2145 BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
2146 getResultCapture().benchmarkEnded(stats);
2147 } CATCH_CATCH_ANON (TestFailureException const&) {
2148 getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr);
2149 } CATCH_CATCH_ALL{
2150 getResultCapture().benchmarkFailed(translateActiveException());
2151 // We let the exception go further up so that the
2152 // test case is marked as failed.
2153 std::rethrow_exception(std::current_exception());
2154 }
2155 }
2156
2157 // sets lambda to be used in fun *and* executes benchmark!
2158 template <typename Fun, std::enable_if_t<!Detail::is_related<Fun, Benchmark>::value, int> = 0>
2159 Benchmark & operator=(Fun func) {
2160 auto const* cfg = getCurrentContext().getConfig();
2161 if (!cfg->skipBenchmarks()) {
2162 fun = Detail::BenchmarkFunction(func);
2163 run();
2164 }
2165 return *this;
2166 }
2167
2168 explicit operator bool() {
2169 return true;
2170 }
2171
2172 private:
2173 Detail::BenchmarkFunction fun;
2174 std::string name;
2175 };
2176 }
2177} // namespace Catch
2178
2179#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
2180#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
2181
2182#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
2183 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
2184 BenchmarkName = [&](int benchmarkIndex)
2185
2186#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
2187 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
2188 BenchmarkName = [&]
2189
2190#if defined(CATCH_CONFIG_PREFIX_ALL)
2191
2192#define CATCH_BENCHMARK(...) \
2193 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
2194#define CATCH_BENCHMARK_ADVANCED(name) \
2195 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
2196
2197#else
2198
2199#define BENCHMARK(...) \
2200 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
2201#define BENCHMARK_ADVANCED(name) \
2202 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(CATCH2_INTERNAL_BENCHMARK_), name)
2203
2204#endif
2205
2206#endif // CATCH_BENCHMARK_HPP_INCLUDED
2207
2208
2209// Adapted from donated nonius code.
2210
2211#ifndef CATCH_CONSTRUCTOR_HPP_INCLUDED
2212#define CATCH_CONSTRUCTOR_HPP_INCLUDED
2213
2214
2215#include <type_traits>
2216
2217namespace Catch {
2218 namespace Benchmark {
2219 namespace Detail {
2220 template <typename T, bool Destruct>
2221 struct ObjectStorage
2222 {
2223 ObjectStorage() = default;
2224
2225 ObjectStorage(const ObjectStorage& other)
2226 {
2227 new(&data) T(other.stored_object());
2228 }
2229
2230 ObjectStorage(ObjectStorage&& other)
2231 {
2232 new(data) T(CATCH_MOVE(other.stored_object()));
2233 }
2234
2235 ~ObjectStorage() { destruct_on_exit<T>(); }
2236
2237 template <typename... Args>
2238 void construct(Args&&... args)
2239 {
2240 new (data) T(CATCH_FORWARD(args)...);
2241 }
2242
2243 template <bool AllowManualDestruction = !Destruct>
2244 std::enable_if_t<AllowManualDestruction> destruct()
2245 {
2246 stored_object().~T();
2247 }
2248
2249 private:
2250 // If this is a constructor benchmark, destruct the underlying object
2251 template <typename U>
2252 void destruct_on_exit(std::enable_if_t<Destruct, U>* = nullptr) { destruct<true>(); }
2253 // Otherwise, don't
2254 template <typename U>
2255 void destruct_on_exit(std::enable_if_t<!Destruct, U>* = nullptr) { }
2256
2257#if defined( __GNUC__ ) && __GNUC__ <= 6
2258# pragma GCC diagnostic push
2259# pragma GCC diagnostic ignored "-Wstrict-aliasing"
2260#endif
2261 T& stored_object() { return *reinterpret_cast<T*>( data ); }
2262
2263 T const& stored_object() const {
2264 return *reinterpret_cast<T const*>( data );
2265 }
2266#if defined( __GNUC__ ) && __GNUC__ <= 6
2267# pragma GCC diagnostic pop
2268#endif
2269
2270 alignas( T ) unsigned char data[sizeof( T )]{};
2271 };
2272 } // namespace Detail
2273
2274 template <typename T>
2275 using storage_for = Detail::ObjectStorage<T, true>;
2276
2277 template <typename T>
2278 using destructable_object = Detail::ObjectStorage<T, false>;
2279 } // namespace Benchmark
2280} // namespace Catch
2281
2282#endif // CATCH_CONSTRUCTOR_HPP_INCLUDED
2283
2284#endif // CATCH_BENCHMARK_ALL_HPP_INCLUDED
2285
2286
2287#ifndef CATCH_APPROX_HPP_INCLUDED
2288#define CATCH_APPROX_HPP_INCLUDED
2289
2290
2291
2292#ifndef CATCH_TOSTRING_HPP_INCLUDED
2293#define CATCH_TOSTRING_HPP_INCLUDED
2294
2295
2296#include <vector>
2297#include <cstddef>
2298#include <type_traits>
2299#include <string>
2300
2301
2302
2303
2304/** \file
2305 * Wrapper for the WCHAR configuration option
2306 *
2307 * We want to support platforms that do not provide `wchar_t`, so we
2308 * sometimes have to disable providing wchar_t overloads through Catch2,
2309 * e.g. the StringMaker specialization for `std::wstring`.
2310 */
2311
2312#ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED
2313#define CATCH_CONFIG_WCHAR_HPP_INCLUDED
2314
2315
2316// We assume that WCHAR should be enabled by default, and only disabled
2317// for a shortlist (so far only DJGPP) of compilers.
2318
2319#if defined(__DJGPP__)
2320# define CATCH_INTERNAL_CONFIG_NO_WCHAR
2321#endif // __DJGPP__
2322
2323#if !defined( CATCH_INTERNAL_CONFIG_NO_WCHAR ) && \
2324 !defined( CATCH_CONFIG_NO_WCHAR ) && \
2325 !defined( CATCH_CONFIG_WCHAR )
2326# define CATCH_CONFIG_WCHAR
2327#endif
2328
2329#endif // CATCH_CONFIG_WCHAR_HPP_INCLUDED
2330
2331
2332#ifndef CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
2333#define CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
2334
2335
2336#include <iosfwd>
2337#include <cstddef>
2338#include <ostream>
2339#include <string>
2340
2341namespace Catch {
2342
2343 class ReusableStringStream : Detail::NonCopyable {
2344 std::size_t m_index;
2345 std::ostream* m_oss;
2346 public:
2347 ReusableStringStream();
2348 ~ReusableStringStream();
2349
2350 //! Returns the serialized state
2351 std::string str() const;
2352 //! Sets internal state to `str`
2353 void str(std::string const& str);
2354
2355#if defined(__GNUC__) && !defined(__clang__)
2356#pragma GCC diagnostic push
2357// Old versions of GCC do not understand -Wnonnull-compare
2358#pragma GCC diagnostic ignored "-Wpragmas"
2359// Streaming a function pointer triggers Waddress and Wnonnull-compare
2360// on GCC, because it implicitly converts it to bool and then decides
2361// that the check it uses (a? true : false) is tautological and cannot
2362// be null...
2363#pragma GCC diagnostic ignored "-Waddress"
2364#pragma GCC diagnostic ignored "-Wnonnull-compare"
2365#endif
2366
2367 template<typename T>
2368 auto operator << ( T const& value ) -> ReusableStringStream& {
2369 *m_oss << value;
2370 return *this;
2371 }
2372
2373#if defined(__GNUC__) && !defined(__clang__)
2374#pragma GCC diagnostic pop
2375#endif
2376 auto get() -> std::ostream& { return *m_oss; }
2377 };
2378}
2379
2380#endif // CATCH_REUSABLE_STRING_STREAM_HPP_INCLUDED
2381
2382
2383#ifndef CATCH_VOID_TYPE_HPP_INCLUDED
2384#define CATCH_VOID_TYPE_HPP_INCLUDED
2385
2386
2387namespace Catch {
2388 namespace Detail {
2389
2390 template <typename...>
2391 struct make_void { using type = void; };
2392
2393 template <typename... Ts>
2394 using void_t = typename make_void<Ts...>::type;
2395
2396 } // namespace Detail
2397} // namespace Catch
2398
2399
2400#endif // CATCH_VOID_TYPE_HPP_INCLUDED
2401
2402
2403#ifndef CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
2404#define CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
2405
2406
2407#include <vector>
2408
2409namespace Catch {
2410
2411 namespace Detail {
2412 struct EnumInfo {
2413 StringRef m_name;
2414 std::vector<std::pair<int, StringRef>> m_values;
2415
2416 ~EnumInfo();
2417
2418 StringRef lookup( int value ) const;
2419 };
2420 } // namespace Detail
2421
2422 class IMutableEnumValuesRegistry {
2423 public:
2424 virtual ~IMutableEnumValuesRegistry(); // = default;
2425
2426 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
2427
2428 template<typename E>
2429 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
2430 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
2431 std::vector<int> intValues;
2432 intValues.reserve( values.size() );
2433 for( auto enumValue : values )
2434 intValues.push_back( static_cast<int>( enumValue ) );
2435 return registerEnum( enumName, allEnums, intValues );
2436 }
2437 };
2438
2439} // Catch
2440
2441#endif // CATCH_INTERFACES_ENUM_VALUES_REGISTRY_HPP_INCLUDED
2442
2443#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2444#include <string_view>
2445#endif
2446
2447#ifdef _MSC_VER
2448#pragma warning(push)
2449#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
2450#endif
2451
2452// We need a dummy global operator<< so we can bring it into Catch namespace later
2453struct Catch_global_namespace_dummy{};
2454std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
2455
2456namespace Catch {
2457 // Bring in global namespace operator<< for ADL lookup in
2458 // `IsStreamInsertable` below.
2459 using ::operator<<;
2460
2461 namespace Detail {
2462
2463 inline std::size_t catch_strnlen(const char *str, std::size_t n) {
2464 auto ret = std::char_traits<char>::find(str, n, '\0');
2465 if (ret != nullptr) {
2466 return static_cast<std::size_t>(ret - str);
2467 }
2468 return n;
2469 }
2470
2471 constexpr StringRef unprintableString = "{?}"_sr;
2472
2473 //! Encases `string in quotes, and optionally escapes invisibles
2474 std::string convertIntoString( StringRef string, bool escapeInvisibles );
2475
2476 //! Encases `string` in quotes, and escapes invisibles if user requested
2477 //! it via CLI
2478 std::string convertIntoString( StringRef string );
2479
2480 std::string rawMemoryToString( const void *object, std::size_t size );
2481
2482 template<typename T>
2483 std::string rawMemoryToString( const T& object ) {
2484 return rawMemoryToString( &object, sizeof(object) );
2485 }
2486
2487 template<typename T>
2488 class IsStreamInsertable {
2489 template<typename Stream, typename U>
2490 static auto test(int)
2491 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
2492
2493 template<typename, typename>
2494 static auto test(...)->std::false_type;
2495
2496 public:
2497 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
2498 };
2499
2500 template<typename E>
2501 std::string convertUnknownEnumToString( E e );
2502
2503 template<typename T>
2504 std::enable_if_t<
2505 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
2506 std::string> convertUnstreamable( T const& ) {
2507 return std::string(Detail::unprintableString);
2508 }
2509 template<typename T>
2510 std::enable_if_t<
2511 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
2512 std::string> convertUnstreamable(T const& ex) {
2513 return ex.what();
2514 }
2515
2516
2517 template<typename T>
2518 std::enable_if_t<
2519 std::is_enum<T>::value,
2520 std::string> convertUnstreamable( T const& value ) {
2521 return convertUnknownEnumToString( value );
2522 }
2523
2524#if defined(_MANAGED)
2525 //! Convert a CLR string to a utf8 std::string
2526 template<typename T>
2527 std::string clrReferenceToString( T^ ref ) {
2528 if (ref == nullptr)
2529 return std::string("null");
2530 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
2531 cli::pin_ptr<System::Byte> p = &bytes[0];
2532 return std::string(reinterpret_cast<char const *>(p), bytes->Length);
2533 }
2534#endif
2535
2536 } // namespace Detail
2537
2538
2539 template <typename T, typename = void>
2540 struct StringMaker {
2541 template <typename Fake = T>
2542 static
2543 std::enable_if_t<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
2544 convert(const Fake& value) {
2545 ReusableStringStream rss;
2546 // NB: call using the function-like syntax to avoid ambiguity with
2547 // user-defined templated operator<< under clang.
2548 rss.operator<<(value);
2549 return rss.str();
2550 }
2551
2552 template <typename Fake = T>
2553 static
2554 std::enable_if_t<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
2555 convert( const Fake& value ) {
2556#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
2557 return Detail::convertUnstreamable(value);
2558#else
2559 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
2560#endif
2561 }
2562 };
2563
2564 namespace Detail {
2565
2566 // This function dispatches all stringification requests inside of Catch.
2567 // Should be preferably called fully qualified, like ::Catch::Detail::stringify
2568 template <typename T>
2569 std::string stringify(const T& e) {
2570 return ::Catch::StringMaker<std::remove_cv_t<std::remove_reference_t<T>>>::convert(e);
2571 }
2572
2573 template<typename E>
2574 std::string convertUnknownEnumToString( E e ) {
2575 return ::Catch::Detail::stringify(static_cast<std::underlying_type_t<E>>(e));
2576 }
2577
2578#if defined(_MANAGED)
2579 template <typename T>
2580 std::string stringify( T^ e ) {
2581 return ::Catch::StringMaker<T^>::convert(e);
2582 }
2583#endif
2584
2585 } // namespace Detail
2586
2587 // Some predefined specializations
2588
2589 template<>
2590 struct StringMaker<std::string> {
2591 static std::string convert(const std::string& str);
2592 };
2593
2594#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2595 template<>
2596 struct StringMaker<std::string_view> {
2597 static std::string convert(std::string_view str);
2598 };
2599#endif
2600
2601 template<>
2602 struct StringMaker<char const *> {
2603 static std::string convert(char const * str);
2604 };
2605 template<>
2606 struct StringMaker<char *> {
2607 static std::string convert(char * str);
2608 };
2609
2610#if defined(CATCH_CONFIG_WCHAR)
2611 template<>
2612 struct StringMaker<std::wstring> {
2613 static std::string convert(const std::wstring& wstr);
2614 };
2615
2616# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
2617 template<>
2618 struct StringMaker<std::wstring_view> {
2619 static std::string convert(std::wstring_view str);
2620 };
2621# endif
2622
2623 template<>
2624 struct StringMaker<wchar_t const *> {
2625 static std::string convert(wchar_t const * str);
2626 };
2627 template<>
2628 struct StringMaker<wchar_t *> {
2629 static std::string convert(wchar_t * str);
2630 };
2631#endif // CATCH_CONFIG_WCHAR
2632
2633 template<size_t SZ>
2634 struct StringMaker<char[SZ]> {
2635 static std::string convert(char const* str) {
2636 return Detail::convertIntoString(
2637 StringRef( str, Detail::catch_strnlen( str, SZ ) ) );
2638 }
2639 };
2640 template<size_t SZ>
2641 struct StringMaker<signed char[SZ]> {
2642 static std::string convert(signed char const* str) {
2643 auto reinterpreted = reinterpret_cast<char const*>(str);
2644 return Detail::convertIntoString(
2645 StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
2646 }
2647 };
2648 template<size_t SZ>
2649 struct StringMaker<unsigned char[SZ]> {
2650 static std::string convert(unsigned char const* str) {
2651 auto reinterpreted = reinterpret_cast<char const*>(str);
2652 return Detail::convertIntoString(
2653 StringRef(reinterpreted, Detail::catch_strnlen(reinterpreted, SZ)));
2654 }
2655 };
2656
2657#if defined(CATCH_CONFIG_CPP17_BYTE)
2658 template<>
2659 struct StringMaker<std::byte> {
2660 static std::string convert(std::byte value);
2661 };
2662#endif // defined(CATCH_CONFIG_CPP17_BYTE)
2663 template<>
2664 struct StringMaker<int> {
2665 static std::string convert(int value);
2666 };
2667 template<>
2668 struct StringMaker<long> {
2669 static std::string convert(long value);
2670 };
2671 template<>
2672 struct StringMaker<long long> {
2673 static std::string convert(long long value);
2674 };
2675 template<>
2676 struct StringMaker<unsigned int> {
2677 static std::string convert(unsigned int value);
2678 };
2679 template<>
2680 struct StringMaker<unsigned long> {
2681 static std::string convert(unsigned long value);
2682 };
2683 template<>
2684 struct StringMaker<unsigned long long> {
2685 static std::string convert(unsigned long long value);
2686 };
2687
2688 template<>
2689 struct StringMaker<bool> {
2690 static std::string convert(bool b) {
2691 using namespace std::string_literals;
2692 return b ? "true"s : "false"s;
2693 }
2694 };
2695
2696 template<>
2697 struct StringMaker<char> {
2698 static std::string convert(char c);
2699 };
2700 template<>
2701 struct StringMaker<signed char> {
2702 static std::string convert(signed char value);
2703 };
2704 template<>
2705 struct StringMaker<unsigned char> {
2706 static std::string convert(unsigned char value);
2707 };
2708
2709 template<>
2710 struct StringMaker<std::nullptr_t> {
2711 static std::string convert(std::nullptr_t) {
2712 using namespace std::string_literals;
2713 return "nullptr"s;
2714 }
2715 };
2716
2717 template<>
2718 struct StringMaker<float> {
2719 static std::string convert(float value);
2720 CATCH_EXPORT static int precision;
2721 };
2722
2723 template<>
2724 struct StringMaker<double> {
2725 static std::string convert(double value);
2726 CATCH_EXPORT static int precision;
2727 };
2728
2729 template <typename T>
2730 struct StringMaker<T*> {
2731 template <typename U>
2732 static std::string convert(U* p) {
2733 if (p) {
2734 return ::Catch::Detail::rawMemoryToString(p);
2735 } else {
2736 return "nullptr";
2737 }
2738 }
2739 };
2740
2741 template <typename R, typename C>
2742 struct StringMaker<R C::*> {
2743 static std::string convert(R C::* p) {
2744 if (p) {
2745 return ::Catch::Detail::rawMemoryToString(p);
2746 } else {
2747 return "nullptr";
2748 }
2749 }
2750 };
2751
2752#if defined(_MANAGED)
2753 template <typename T>
2754 struct StringMaker<T^> {
2755 static std::string convert( T^ ref ) {
2756 return ::Catch::Detail::clrReferenceToString(ref);
2757 }
2758 };
2759#endif
2760
2761 namespace Detail {
2762 template<typename InputIterator, typename Sentinel = InputIterator>
2763 std::string rangeToString(InputIterator first, Sentinel last) {
2764 ReusableStringStream rss;
2765 rss << "{ ";
2766 if (first != last) {
2767 rss << ::Catch::Detail::stringify(*first);
2768 for (++first; first != last; ++first)
2769 rss << ", " << ::Catch::Detail::stringify(*first);
2770 }
2771 rss << " }";
2772 return rss.str();
2773 }
2774 }
2775
2776} // namespace Catch
2777
2778//////////////////////////////////////////////////////
2779// Separate std-lib types stringification, so it can be selectively enabled
2780// This means that we do not bring in their headers
2781
2782#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
2783# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
2784# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
2785# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
2786# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
2787#endif
2788
2789// Separate std::pair specialization
2790#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
2791#include <utility>
2792namespace Catch {
2793 template<typename T1, typename T2>
2794 struct StringMaker<std::pair<T1, T2> > {
2795 static std::string convert(const std::pair<T1, T2>& pair) {
2796 ReusableStringStream rss;
2797 rss << "{ "
2798 << ::Catch::Detail::stringify(pair.first)
2799 << ", "
2800 << ::Catch::Detail::stringify(pair.second)
2801 << " }";
2802 return rss.str();
2803 }
2804 };
2805}
2806#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
2807
2808#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
2809#include <optional>
2810namespace Catch {
2811 template<typename T>
2812 struct StringMaker<std::optional<T> > {
2813 static std::string convert(const std::optional<T>& optional) {
2814 if (optional.has_value()) {
2815 return ::Catch::Detail::stringify(*optional);
2816 } else {
2817 return "{ }";
2818 }
2819 }
2820 };
2821 template <>
2822 struct StringMaker<std::nullopt_t> {
2823 static std::string convert(const std::nullopt_t&) {
2824 return "{ }";
2825 }
2826 };
2827}
2828#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
2829
2830// Separate std::tuple specialization
2831#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
2832#include <tuple>
2833namespace Catch {
2834 namespace Detail {
2835 template<
2836 typename Tuple,
2837 std::size_t N = 0,
2838 bool = (N < std::tuple_size<Tuple>::value)
2839 >
2840 struct TupleElementPrinter {
2841 static void print(const Tuple& tuple, std::ostream& os) {
2842 os << (N ? ", " : " ")
2843 << ::Catch::Detail::stringify(std::get<N>(tuple));
2844 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
2845 }
2846 };
2847
2848 template<
2849 typename Tuple,
2850 std::size_t N
2851 >
2852 struct TupleElementPrinter<Tuple, N, false> {
2853 static void print(const Tuple&, std::ostream&) {}
2854 };
2855
2856 }
2857
2858
2859 template<typename ...Types>
2860 struct StringMaker<std::tuple<Types...>> {
2861 static std::string convert(const std::tuple<Types...>& tuple) {
2862 ReusableStringStream rss;
2863 rss << '{';
2864 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
2865 rss << " }";
2866 return rss.str();
2867 }
2868 };
2869}
2870#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
2871
2872#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
2873#include <variant>
2874namespace Catch {
2875 template<>
2876 struct StringMaker<std::monostate> {
2877 static std::string convert(const std::monostate&) {
2878 return "{ }";
2879 }
2880 };
2881
2882 template<typename... Elements>
2883 struct StringMaker<std::variant<Elements...>> {
2884 static std::string convert(const std::variant<Elements...>& variant) {
2885 if (variant.valueless_by_exception()) {
2886 return "{valueless variant}";
2887 } else {
2888 return std::visit(
2889 [](const auto& value) {
2890 return ::Catch::Detail::stringify(value);
2891 },
2892 variant
2893 );
2894 }
2895 }
2896 };
2897}
2898#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
2899
2900namespace Catch {
2901 // Import begin/ end from std here
2902 using std::begin;
2903 using std::end;
2904
2905 namespace Detail {
2906 template <typename T, typename = void>
2907 struct is_range_impl : std::false_type {};
2908
2909 template <typename T>
2910 struct is_range_impl<T, void_t<decltype(begin(std::declval<T>()))>> : std::true_type {};
2911 } // namespace Detail
2912
2913 template <typename T>
2914 struct is_range : Detail::is_range_impl<T> {};
2915
2916#if defined(_MANAGED) // Managed types are never ranges
2917 template <typename T>
2918 struct is_range<T^> {
2919 static const bool value = false;
2920 };
2921#endif
2922
2923 template<typename Range>
2924 std::string rangeToString( Range const& range ) {
2925 return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
2926 }
2927
2928 // Handle vector<bool> specially
2929 template<typename Allocator>
2930 std::string rangeToString( std::vector<bool, Allocator> const& v ) {
2931 ReusableStringStream rss;
2932 rss << "{ ";
2933 bool first = true;
2934 for( bool b : v ) {
2935 if( first )
2936 first = false;
2937 else
2938 rss << ", ";
2939 rss << ::Catch::Detail::stringify( b );
2940 }
2941 rss << " }";
2942 return rss.str();
2943 }
2944
2945 template<typename R>
2946 struct StringMaker<R, std::enable_if_t<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>> {
2947 static std::string convert( R const& range ) {
2948 return rangeToString( range );
2949 }
2950 };
2951
2952 template <typename T, size_t SZ>
2953 struct StringMaker<T[SZ]> {
2954 static std::string convert(T const(&arr)[SZ]) {
2955 return rangeToString(arr);
2956 }
2957 };
2958
2959
2960} // namespace Catch
2961
2962// Separate std::chrono::duration specialization
2963#include <ctime>
2964#include <ratio>
2965#include <chrono>
2966
2967
2968namespace Catch {
2969
2970template <class Ratio>
2971struct ratio_string {
2972 static std::string symbol() {
2973 Catch::ReusableStringStream rss;
2974 rss << '[' << Ratio::num << '/'
2975 << Ratio::den << ']';
2976 return rss.str();
2977 }
2978};
2979
2980template <>
2981struct ratio_string<std::atto> {
2982 static char symbol() { return 'a'; }
2983};
2984template <>
2985struct ratio_string<std::femto> {
2986 static char symbol() { return 'f'; }
2987};
2988template <>
2989struct ratio_string<std::pico> {
2990 static char symbol() { return 'p'; }
2991};
2992template <>
2993struct ratio_string<std::nano> {
2994 static char symbol() { return 'n'; }
2995};
2996template <>
2997struct ratio_string<std::micro> {
2998 static char symbol() { return 'u'; }
2999};
3000template <>
3001struct ratio_string<std::milli> {
3002 static char symbol() { return 'm'; }
3003};
3004
3005 ////////////
3006 // std::chrono::duration specializations
3007 template<typename Value, typename Ratio>
3008 struct StringMaker<std::chrono::duration<Value, Ratio>> {
3009 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
3010 ReusableStringStream rss;
3011 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
3012 return rss.str();
3013 }
3014 };
3015 template<typename Value>
3016 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
3017 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
3018 ReusableStringStream rss;
3019 rss << duration.count() << " s";
3020 return rss.str();
3021 }
3022 };
3023 template<typename Value>
3024 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
3025 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
3026 ReusableStringStream rss;
3027 rss << duration.count() << " m";
3028 return rss.str();
3029 }
3030 };
3031 template<typename Value>
3032 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
3033 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
3034 ReusableStringStream rss;
3035 rss << duration.count() << " h";
3036 return rss.str();
3037 }
3038 };
3039
3040 ////////////
3041 // std::chrono::time_point specialization
3042 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
3043 template<typename Clock, typename Duration>
3044 struct StringMaker<std::chrono::time_point<Clock, Duration>> {
3045 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
3046 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
3047 }
3048 };
3049 // std::chrono::time_point<system_clock> specialization
3050 template<typename Duration>
3051 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
3052 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
3053 auto converted = std::chrono::system_clock::to_time_t(time_point);
3054
3055#ifdef _MSC_VER
3056 std::tm timeInfo = {};
3057 gmtime_s(&timeInfo, &converted);
3058#else
3059 std::tm* timeInfo = std::gmtime(&converted);
3060#endif
3061
3062 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
3063 char timeStamp[timeStampSize];
3064 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
3065
3066#ifdef _MSC_VER
3067 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
3068#else
3069 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
3070#endif
3071 return std::string(timeStamp, timeStampSize - 1);
3072 }
3073 };
3074}
3075
3076
3077#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
3078namespace Catch { \
3079 template<> struct StringMaker<enumName> { \
3080 static std::string convert( enumName value ) { \
3081 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
3082 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
3083 } \
3084 }; \
3085}
3086
3087#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
3088
3089#ifdef _MSC_VER
3090#pragma warning(pop)
3091#endif
3092
3093#endif // CATCH_TOSTRING_HPP_INCLUDED
3094
3095#include <type_traits>
3096
3097namespace Catch {
3098
3099 class Approx {
3100 private:
3101 bool equalityComparisonImpl(double other) const;
3102 // Sets and validates the new margin (margin >= 0)
3103 void setMargin(double margin);
3104 // Sets and validates the new epsilon (0 < epsilon < 1)
3105 void setEpsilon(double epsilon);
3106
3107 public:
3108 explicit Approx ( double value );
3109
3110 static Approx custom();
3111
3112 Approx operator-() const;
3113
3114 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3115 Approx operator()( T const& value ) const {
3116 Approx approx( static_cast<double>(value) );
3117 approx.m_epsilon = m_epsilon;
3118 approx.m_margin = m_margin;
3119 approx.m_scale = m_scale;
3120 return approx;
3121 }
3122
3123 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3124 explicit Approx( T const& value ): Approx(static_cast<double>(value))
3125 {}
3126
3127
3128 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3129 friend bool operator == ( const T& lhs, Approx const& rhs ) {
3130 auto lhs_v = static_cast<double>(lhs);
3131 return rhs.equalityComparisonImpl(lhs_v);
3132 }
3133
3134 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3135 friend bool operator == ( Approx const& lhs, const T& rhs ) {
3136 return operator==( rhs, lhs );
3137 }
3138
3139 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3140 friend bool operator != ( T const& lhs, Approx const& rhs ) {
3141 return !operator==( lhs, rhs );
3142 }
3143
3144 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3145 friend bool operator != ( Approx const& lhs, T const& rhs ) {
3146 return !operator==( rhs, lhs );
3147 }
3148
3149 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3150 friend bool operator <= ( T const& lhs, Approx const& rhs ) {
3151 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
3152 }
3153
3154 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3155 friend bool operator <= ( Approx const& lhs, T const& rhs ) {
3156 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
3157 }
3158
3159 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3160 friend bool operator >= ( T const& lhs, Approx const& rhs ) {
3161 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
3162 }
3163
3164 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3165 friend bool operator >= ( Approx const& lhs, T const& rhs ) {
3166 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
3167 }
3168
3169 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3170 Approx& epsilon( T const& newEpsilon ) {
3171 const auto epsilonAsDouble = static_cast<double>(newEpsilon);
3172 setEpsilon(epsilonAsDouble);
3173 return *this;
3174 }
3175
3176 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3177 Approx& margin( T const& newMargin ) {
3178 const auto marginAsDouble = static_cast<double>(newMargin);
3179 setMargin(marginAsDouble);
3180 return *this;
3181 }
3182
3183 template <typename T, typename = std::enable_if_t<std::is_constructible<double, T>::value>>
3184 Approx& scale( T const& newScale ) {
3185 m_scale = static_cast<double>(newScale);
3186 return *this;
3187 }
3188
3189 std::string toString() const;
3190
3191 private:
3192 double m_epsilon;
3193 double m_margin;
3194 double m_scale;
3195 double m_value;
3196 };
3197
3198namespace literals {
3199 Approx operator ""_a(long double val);
3200 Approx operator ""_a(unsigned long long val);
3201} // end namespace literals
3202
3203template<>
3204struct StringMaker<Catch::Approx> {
3205 static std::string convert(Catch::Approx const& value);
3206};
3207
3208} // end namespace Catch
3209
3210#endif // CATCH_APPROX_HPP_INCLUDED
3211
3212
3213#ifndef CATCH_ASSERTION_INFO_HPP_INCLUDED
3214#define CATCH_ASSERTION_INFO_HPP_INCLUDED
3215
3216
3217
3218#ifndef CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
3219#define CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
3220
3221#include <cstddef>
3222#include <iosfwd>
3223
3224namespace Catch {
3225
3226 struct SourceLineInfo {
3227
3228 SourceLineInfo() = delete;
3229 constexpr SourceLineInfo( char const* _file, std::size_t _line ) noexcept:
3230 file( _file ),
3231 line( _line )
3232 {}
3233
3234 bool operator == ( SourceLineInfo const& other ) const noexcept;
3235 bool operator < ( SourceLineInfo const& other ) const noexcept;
3236
3237 char const* file;
3238 std::size_t line;
3239
3240 friend std::ostream& operator << (std::ostream& os, SourceLineInfo const& info);
3241 };
3242}
3243
3244#define CATCH_INTERNAL_LINEINFO \
3245 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
3246
3247#endif // CATCH_SOURCE_LINE_INFO_HPP_INCLUDED
3248
3249namespace Catch {
3250
3251 struct AssertionInfo {
3252 // AssertionInfo() = delete;
3253
3254 StringRef macroName;
3255 SourceLineInfo lineInfo;
3256 StringRef capturedExpression;
3257 ResultDisposition::Flags resultDisposition;
3258 };
3259
3260} // end namespace Catch
3261
3262#endif // CATCH_ASSERTION_INFO_HPP_INCLUDED
3263
3264
3265#ifndef CATCH_ASSERTION_RESULT_HPP_INCLUDED
3266#define CATCH_ASSERTION_RESULT_HPP_INCLUDED
3267
3268
3269
3270#ifndef CATCH_LAZY_EXPR_HPP_INCLUDED
3271#define CATCH_LAZY_EXPR_HPP_INCLUDED
3272
3273#include <iosfwd>
3274
3275namespace Catch {
3276
3277 class ITransientExpression;
3278
3279 class LazyExpression {
3280 friend class AssertionHandler;
3281 friend struct AssertionStats;
3282 friend class RunContext;
3283
3284 ITransientExpression const* m_transientExpression = nullptr;
3285 bool m_isNegated;
3286 public:
3287 LazyExpression( bool isNegated ):
3288 m_isNegated(isNegated)
3289 {}
3290 LazyExpression(LazyExpression const& other) = default;
3291 LazyExpression& operator = ( LazyExpression const& ) = delete;
3292
3293 explicit operator bool() const {
3294 return m_transientExpression != nullptr;
3295 }
3296
3297 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
3298 };
3299
3300} // namespace Catch
3301
3302#endif // CATCH_LAZY_EXPR_HPP_INCLUDED
3303
3304#include <string>
3305
3306namespace Catch {
3307
3308 struct AssertionResultData
3309 {
3310 AssertionResultData() = delete;
3311
3312 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
3313
3314 std::string message;
3315 mutable std::string reconstructedExpression;
3316 LazyExpression lazyExpression;
3317 ResultWas::OfType resultType;
3318
3319 std::string reconstructExpression() const;
3320 };
3321
3322 class AssertionResult {
3323 public:
3324 AssertionResult() = delete;
3325 AssertionResult( AssertionInfo const& info, AssertionResultData&& data );
3326
3327 bool isOk() const;
3328 bool succeeded() const;
3329 ResultWas::OfType getResultType() const;
3330 bool hasExpression() const;
3331 bool hasMessage() const;
3332 std::string getExpression() const;
3333 std::string getExpressionInMacro() const;
3334 bool hasExpandedExpression() const;
3335 std::string getExpandedExpression() const;
3336 StringRef getMessage() const;
3337 SourceLineInfo getSourceInfo() const;
3338 StringRef getTestMacroName() const;
3339
3340 //protected:
3341 AssertionInfo m_info;
3342 AssertionResultData m_resultData;
3343 };
3344
3345} // end namespace Catch
3346
3347#endif // CATCH_ASSERTION_RESULT_HPP_INCLUDED
3348
3349
3350#ifndef CATCH_CONFIG_HPP_INCLUDED
3351#define CATCH_CONFIG_HPP_INCLUDED
3352
3353
3354
3355#ifndef CATCH_TEST_SPEC_HPP_INCLUDED
3356#define CATCH_TEST_SPEC_HPP_INCLUDED
3357
3358#ifdef __clang__
3359#pragma clang diagnostic push
3360#pragma clang diagnostic ignored "-Wpadded"
3361#endif
3362
3363
3364
3365#ifndef CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3366#define CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3367
3368
3369
3370#ifndef CATCH_CASE_SENSITIVE_HPP_INCLUDED
3371#define CATCH_CASE_SENSITIVE_HPP_INCLUDED
3372
3373namespace Catch {
3374
3375 enum class CaseSensitive { Yes, No };
3376
3377} // namespace Catch
3378
3379#endif // CATCH_CASE_SENSITIVE_HPP_INCLUDED
3380
3381#include <string>
3382
3383namespace Catch
3384{
3385 class WildcardPattern {
3386 enum WildcardPosition {
3387 NoWildcard = 0,
3388 WildcardAtStart = 1,
3389 WildcardAtEnd = 2,
3390 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3391 };
3392
3393 public:
3394
3395 WildcardPattern( std::string const& pattern, CaseSensitive caseSensitivity );
3396 bool matches( std::string const& str ) const;
3397
3398 private:
3399 std::string normaliseString( std::string const& str ) const;
3400 CaseSensitive m_caseSensitivity;
3401 WildcardPosition m_wildcard = NoWildcard;
3402 std::string m_pattern;
3403 };
3404}
3405
3406#endif // CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3407
3408#include <iosfwd>
3409#include <string>
3410#include <vector>
3411
3412namespace Catch {
3413
3414 class IConfig;
3415 struct TestCaseInfo;
3416 class TestCaseHandle;
3417
3418 class TestSpec {
3419
3420 class Pattern {
3421 public:
3422 explicit Pattern( std::string const& name );
3423 virtual ~Pattern();
3424 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3425 std::string const& name() const;
3426 private:
3427 virtual void serializeTo( std::ostream& out ) const = 0;
3428 // Writes string that would be reparsed into the pattern
3429 friend std::ostream& operator<<(std::ostream& out,
3430 Pattern const& pattern) {
3431 pattern.serializeTo( out );
3432 return out;
3433 }
3434
3435 std::string const m_name;
3436 };
3437
3438 class NamePattern : public Pattern {
3439 public:
3440 explicit NamePattern( std::string const& name, std::string const& filterString );
3441 bool matches( TestCaseInfo const& testCase ) const override;
3442 private:
3443 void serializeTo( std::ostream& out ) const override;
3444
3445 WildcardPattern m_wildcardPattern;
3446 };
3447
3448 class TagPattern : public Pattern {
3449 public:
3450 explicit TagPattern( std::string const& tag, std::string const& filterString );
3451 bool matches( TestCaseInfo const& testCase ) const override;
3452 private:
3453 void serializeTo( std::ostream& out ) const override;
3454
3455 std::string m_tag;
3456 };
3457
3458 struct Filter {
3459 std::vector<Detail::unique_ptr<Pattern>> m_required;
3460 std::vector<Detail::unique_ptr<Pattern>> m_forbidden;
3461
3462 //! Serializes this filter into a string that would be parsed into
3463 //! an equivalent filter
3464 void serializeTo( std::ostream& out ) const;
3465 friend std::ostream& operator<<(std::ostream& out, Filter const& f) {
3466 f.serializeTo( out );
3467 return out;
3468 }
3469
3470 bool matches( TestCaseInfo const& testCase ) const;
3471 };
3472
3473 static std::string extractFilterName( Filter const& filter );
3474
3475 public:
3476 struct FilterMatch {
3477 std::string name;
3478 std::vector<TestCaseHandle const*> tests;
3479 };
3480 using Matches = std::vector<FilterMatch>;
3481 using vectorStrings = std::vector<std::string>;
3482
3483 bool hasFilters() const;
3484 bool matches( TestCaseInfo const& testCase ) const;
3485 Matches matchesByFilter( std::vector<TestCaseHandle> const& testCases, IConfig const& config ) const;
3486 const vectorStrings & getInvalidSpecs() const;
3487
3488 private:
3489 std::vector<Filter> m_filters;
3490 std::vector<std::string> m_invalidSpecs;
3491
3492 friend class TestSpecParser;
3493 //! Serializes this test spec into a string that would be parsed into
3494 //! equivalent test spec
3495 void serializeTo( std::ostream& out ) const;
3496 friend std::ostream& operator<<(std::ostream& out,
3497 TestSpec const& spec) {
3498 spec.serializeTo( out );
3499 return out;
3500 }
3501 };
3502}
3503
3504#ifdef __clang__
3505#pragma clang diagnostic pop
3506#endif
3507
3508#endif // CATCH_TEST_SPEC_HPP_INCLUDED
3509
3510
3511#ifndef CATCH_OPTIONAL_HPP_INCLUDED
3512#define CATCH_OPTIONAL_HPP_INCLUDED
3513
3514
3515#include <cassert>
3516
3517namespace Catch {
3518
3519 // An optional type
3520 template<typename T>
3521 class Optional {
3522 public:
3523 Optional(): nullableValue( nullptr ) {}
3524 ~Optional() { reset(); }
3525
3526 Optional( T const& _value ):
3527 nullableValue( new ( storage ) T( _value ) ) {}
3528 Optional( T&& _value ):
3529 nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {}
3530
3531 Optional& operator=( T const& _value ) {
3532 reset();
3533 nullableValue = new ( storage ) T( _value );
3534 return *this;
3535 }
3536 Optional& operator=( T&& _value ) {
3537 reset();
3538 nullableValue = new ( storage ) T( CATCH_MOVE( _value ) );
3539 return *this;
3540 }
3541
3542 Optional( Optional const& _other ):
3543 nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {}
3544 Optional( Optional&& _other ):
3545 nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) )
3546 : nullptr ) {}
3547
3548 Optional& operator=( Optional const& _other ) {
3549 if ( &_other != this ) {
3550 reset();
3551 if ( _other ) { nullableValue = new ( storage ) T( *_other ); }
3552 }
3553 return *this;
3554 }
3555 Optional& operator=( Optional&& _other ) {
3556 if ( &_other != this ) {
3557 reset();
3558 if ( _other ) {
3559 nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) );
3560 }
3561 }
3562 return *this;
3563 }
3564
3565 void reset() {
3566 if ( nullableValue ) { nullableValue->~T(); }
3567 nullableValue = nullptr;
3568 }
3569
3570 T& operator*() {
3571 assert(nullableValue);
3572 return *nullableValue;
3573 }
3574 T const& operator*() const {
3575 assert(nullableValue);
3576 return *nullableValue;
3577 }
3578 T* operator->() {
3579 assert(nullableValue);
3580 return nullableValue;
3581 }
3582 const T* operator->() const {
3583 assert(nullableValue);
3584 return nullableValue;
3585 }
3586
3587 T valueOr( T const& defaultValue ) const {
3588 return nullableValue ? *nullableValue : defaultValue;
3589 }
3590
3591 bool some() const { return nullableValue != nullptr; }
3592 bool none() const { return nullableValue == nullptr; }
3593
3594 bool operator !() const { return nullableValue == nullptr; }
3595 explicit operator bool() const {
3596 return some();
3597 }
3598
3599 friend bool operator==(Optional const& a, Optional const& b) {
3600 if (a.none() && b.none()) {
3601 return true;
3602 } else if (a.some() && b.some()) {
3603 return *a == *b;
3604 } else {
3605 return false;
3606 }
3607 }
3608 friend bool operator!=(Optional const& a, Optional const& b) {
3609 return !( a == b );
3610 }
3611
3612 private:
3613 T* nullableValue;
3614 alignas(alignof(T)) char storage[sizeof(T)];
3615 };
3616
3617} // end namespace Catch
3618
3619#endif // CATCH_OPTIONAL_HPP_INCLUDED
3620
3621
3622#ifndef CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
3623#define CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
3624
3625#include <cstdint>
3626
3627namespace Catch {
3628
3629 enum class GenerateFrom {
3630 Time,
3631 RandomDevice,
3632 //! Currently equivalent to RandomDevice, but can change at any point
3633 Default
3634 };
3635
3636 std::uint32_t generateRandomSeed(GenerateFrom from);
3637
3638} // end namespace Catch
3639
3640#endif // CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED
3641
3642
3643#ifndef CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
3644#define CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
3645
3646
3647#include <map>
3648#include <string>
3649#include <vector>
3650
3651namespace Catch {
3652
3653 enum class ColourMode : std::uint8_t;
3654
3655 namespace Detail {
3656 //! Splits the reporter spec into reporter name and kv-pair options
3657 std::vector<std::string> splitReporterSpec( StringRef reporterSpec );
3658
3659 Optional<ColourMode> stringToColourMode( StringRef colourMode );
3660 }
3661
3662 /**
3663 * Structured reporter spec that a reporter can be created from
3664 *
3665 * Parsing has been validated, but semantics have not. This means e.g.
3666 * that the colour mode is known to Catch2, but it might not be
3667 * compiled into the binary, and the output filename might not be
3668 * openable.
3669 */
3670 class ReporterSpec {
3671 std::string m_name;
3672 Optional<std::string> m_outputFileName;
3673 Optional<ColourMode> m_colourMode;
3674 std::map<std::string, std::string> m_customOptions;
3675
3676 friend bool operator==( ReporterSpec const& lhs,
3677 ReporterSpec const& rhs );
3678 friend bool operator!=( ReporterSpec const& lhs,
3679 ReporterSpec const& rhs ) {
3680 return !( lhs == rhs );
3681 }
3682
3683 public:
3684 ReporterSpec(
3685 std::string name,
3686 Optional<std::string> outputFileName,
3687 Optional<ColourMode> colourMode,
3688 std::map<std::string, std::string> customOptions );
3689
3690 std::string const& name() const { return m_name; }
3691
3692 Optional<std::string> const& outputFile() const {
3693 return m_outputFileName;
3694 }
3695
3696 Optional<ColourMode> const& colourMode() const { return m_colourMode; }
3697
3698 std::map<std::string, std::string> const& customOptions() const {
3699 return m_customOptions;
3700 }
3701 };
3702
3703 /**
3704 * Parses provided reporter spec string into
3705 *
3706 * Returns empty optional on errors, e.g.
3707 * * field that is not first and not a key+value pair
3708 * * duplicated keys in kv pair
3709 * * unknown catch reporter option
3710 * * empty key/value in an custom kv pair
3711 * * ...
3712 */
3713 Optional<ReporterSpec> parseReporterSpec( StringRef reporterSpec );
3714
3715}
3716
3717#endif // CATCH_REPORTER_SPEC_PARSER_HPP_INCLUDED
3718
3719#include <chrono>
3720#include <map>
3721#include <string>
3722#include <vector>
3723
3724namespace Catch {
3725
3726 class IStream;
3727
3728 /**
3729 * `ReporterSpec` but with the defaults filled in.
3730 *
3731 * Like `ReporterSpec`, the semantics are unchecked.
3732 */
3733 struct ProcessedReporterSpec {
3734 std::string name;
3735 std::string outputFilename;
3736 ColourMode colourMode;
3737 std::map<std::string, std::string> customOptions;
3738 friend bool operator==( ProcessedReporterSpec const& lhs,
3739 ProcessedReporterSpec const& rhs );
3740 friend bool operator!=( ProcessedReporterSpec const& lhs,
3741 ProcessedReporterSpec const& rhs ) {
3742 return !( lhs == rhs );
3743 }
3744 };
3745
3746 struct ConfigData {
3747
3748 bool listTests = false;
3749 bool listTags = false;
3750 bool listReporters = false;
3751 bool listListeners = false;
3752
3753 bool showSuccessfulTests = false;
3754 bool shouldDebugBreak = false;
3755 bool noThrow = false;
3756 bool showHelp = false;
3757 bool showInvisibles = false;
3758 bool filenamesAsTags = false;
3759 bool libIdentify = false;
3760 bool allowZeroTests = false;
3761
3762 int abortAfter = -1;
3763 uint32_t rngSeed = generateRandomSeed(GenerateFrom::Default);
3764
3765 unsigned int shardCount = 1;
3766 unsigned int shardIndex = 0;
3767
3768 bool skipBenchmarks = false;
3769 bool benchmarkNoAnalysis = false;
3770 unsigned int benchmarkSamples = 100;
3771 double benchmarkConfidenceInterval = 0.95;
3772 unsigned int benchmarkResamples = 100'000;
3773 std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
3774
3775 Verbosity verbosity = Verbosity::Normal;
3776 WarnAbout::What warnings = WarnAbout::Nothing;
3777 ShowDurations showDurations = ShowDurations::DefaultForReporter;
3778 double minDuration = -1;
3779 TestRunOrder runOrder = TestRunOrder::Declared;
3780 ColourMode defaultColourMode = ColourMode::PlatformDefault;
3781 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
3782
3783 std::string defaultOutputFilename;
3784 std::string name;
3785 std::string processName;
3786 std::vector<ReporterSpec> reporterSpecifications;
3787
3788 std::vector<std::string> testsOrTags;
3789 std::vector<std::string> sectionsToRun;
3790 };
3791
3792
3793 class Config : public IConfig {
3794 public:
3795
3796 Config() = default;
3797 Config( ConfigData const& data );
3798 ~Config() override; // = default in the cpp file
3799
3800 bool listTests() const;
3801 bool listTags() const;
3802 bool listReporters() const;
3803 bool listListeners() const;
3804
3805 std::vector<ReporterSpec> const& getReporterSpecs() const;
3806 std::vector<ProcessedReporterSpec> const&
3807 getProcessedReporterSpecs() const;
3808
3809 std::vector<std::string> const& getTestsOrTags() const override;
3810 std::vector<std::string> const& getSectionsToRun() const override;
3811
3812 TestSpec const& testSpec() const override;
3813 bool hasTestFilters() const override;
3814
3815 bool showHelp() const;
3816
3817 // IConfig interface
3818 bool allowThrows() const override;
3819 StringRef name() const override;
3820 bool includeSuccessfulResults() const override;
3821 bool warnAboutMissingAssertions() const override;
3822 bool warnAboutUnmatchedTestSpecs() const override;
3823 bool zeroTestsCountAsSuccess() const override;
3824 ShowDurations showDurations() const override;
3825 double minDuration() const override;
3826 TestRunOrder runOrder() const override;
3827 uint32_t rngSeed() const override;
3828 unsigned int shardCount() const override;
3829 unsigned int shardIndex() const override;
3830 ColourMode defaultColourMode() const override;
3831 bool shouldDebugBreak() const override;
3832 int abortAfter() const override;
3833 bool showInvisibles() const override;
3834 Verbosity verbosity() const override;
3835 bool skipBenchmarks() const override;
3836 bool benchmarkNoAnalysis() const override;
3837 unsigned int benchmarkSamples() const override;
3838 double benchmarkConfidenceInterval() const override;
3839 unsigned int benchmarkResamples() const override;
3840 std::chrono::milliseconds benchmarkWarmupTime() const override;
3841
3842 private:
3843 // Reads Bazel env vars and applies them to the config
3844 void readBazelEnvVars();
3845
3846 ConfigData m_data;
3847 std::vector<ProcessedReporterSpec> m_processedReporterSpecs;
3848 TestSpec m_testSpec;
3849 bool m_hasTestFilters = false;
3850 };
3851} // end namespace Catch
3852
3853#endif // CATCH_CONFIG_HPP_INCLUDED
3854
3855
3856#ifndef CATCH_GET_RANDOM_SEED_HPP_INCLUDED
3857#define CATCH_GET_RANDOM_SEED_HPP_INCLUDED
3858
3859#include <cstdint>
3860
3861namespace Catch {
3862 //! Returns Catch2's current RNG seed.
3863 std::uint32_t getSeed();
3864}
3865
3866#endif // CATCH_GET_RANDOM_SEED_HPP_INCLUDED
3867
3868
3869#ifndef CATCH_MESSAGE_HPP_INCLUDED
3870#define CATCH_MESSAGE_HPP_INCLUDED
3871
3872
3873
3874
3875/** \file
3876 * Wrapper for the CATCH_CONFIG_PREFIX_MESSAGES configuration option
3877 *
3878 * CATCH_CONFIG_PREFIX_ALL can be used to avoid clashes with other macros
3879 * by prepending CATCH_. This may not be desirable if the only clashes are with
3880 * logger macros such as INFO and WARN. In this cases
3881 * CATCH_CONFIG_PREFIX_MESSAGES can be used to only prefix a small subset
3882 * of relevant macros.
3883 *
3884 */
3885
3886#ifndef CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
3887#define CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
3888
3889
3890#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_PREFIX_MESSAGES)
3891 #define CATCH_CONFIG_PREFIX_MESSAGES
3892#endif
3893
3894#endif // CATCH_CONFIG_PREFIX_MESSAGES_HPP_INCLUDED
3895
3896
3897#ifndef CATCH_STREAM_END_STOP_HPP_INCLUDED
3898#define CATCH_STREAM_END_STOP_HPP_INCLUDED
3899
3900
3901namespace Catch {
3902
3903 // Use this in variadic streaming macros to allow
3904 // << +StreamEndStop
3905 // as well as
3906 // << stuff +StreamEndStop
3907 struct StreamEndStop {
3908 constexpr StringRef operator+() const { return StringRef(); }
3909
3910 template <typename T>
3911 constexpr friend T const& operator+( T const& value, StreamEndStop ) {
3912 return value;
3913 }
3914 };
3915
3916} // namespace Catch
3917
3918#endif // CATCH_STREAM_END_STOP_HPP_INCLUDED
3919
3920
3921#ifndef CATCH_MESSAGE_INFO_HPP_INCLUDED
3922#define CATCH_MESSAGE_INFO_HPP_INCLUDED
3923
3924
3925#include <string>
3926
3927namespace Catch {
3928
3929 struct MessageInfo {
3930 MessageInfo( StringRef _macroName,
3931 SourceLineInfo const& _lineInfo,
3932 ResultWas::OfType _type );
3933
3934 StringRef macroName;
3935 std::string message;
3936 SourceLineInfo lineInfo;
3937 ResultWas::OfType type;
3938 unsigned int sequence;
3939
3940 bool operator == (MessageInfo const& other) const {
3941 return sequence == other.sequence;
3942 }
3943 bool operator < (MessageInfo const& other) const {
3944 return sequence < other.sequence;
3945 }
3946 private:
3947 static unsigned int globalCount;
3948 };
3949
3950} // end namespace Catch
3951
3952#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED
3953
3954#include <string>
3955#include <vector>
3956
3957namespace Catch {
3958
3959 struct SourceLineInfo;
3960 class IResultCapture;
3961
3962 struct MessageStream {
3963
3964 template<typename T>
3965 MessageStream& operator << ( T const& value ) {
3966 m_stream << value;
3967 return *this;
3968 }
3969
3970 ReusableStringStream m_stream;
3971 };
3972
3973 struct MessageBuilder : MessageStream {
3974 MessageBuilder( StringRef macroName,
3975 SourceLineInfo const& lineInfo,
3976 ResultWas::OfType type ):
3977 m_info(macroName, lineInfo, type) {}
3978
3979 template<typename T>
3980 MessageBuilder&& operator << ( T const& value ) && {
3981 m_stream << value;
3982 return CATCH_MOVE(*this);
3983 }
3984
3985 MessageInfo m_info;
3986 };
3987
3988 class ScopedMessage {
3989 public:
3990 explicit ScopedMessage( MessageBuilder&& builder );
3991 ScopedMessage( ScopedMessage& duplicate ) = delete;
3992 ScopedMessage( ScopedMessage&& old ) noexcept;
3993 ~ScopedMessage();
3994
3995 MessageInfo m_info;
3996 bool m_moved = false;
3997 };
3998
3999 class Capturer {
4000 std::vector<MessageInfo> m_messages;
4001 IResultCapture& m_resultCapture;
4002 size_t m_captured = 0;
4003 public:
4004 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
4005
4006 Capturer(Capturer const&) = delete;
4007 Capturer& operator=(Capturer const&) = delete;
4008
4009 ~Capturer();
4010
4011 void captureValue( size_t index, std::string const& value );
4012
4013 template<typename T>
4014 void captureValues( size_t index, T const& value ) {
4015 captureValue( index, Catch::Detail::stringify( value ) );
4016 }
4017
4018 template<typename T, typename... Ts>
4019 void captureValues( size_t index, T const& value, Ts const&... values ) {
4020 captureValue( index, Catch::Detail::stringify(value) );
4021 captureValues( index+1, values... );
4022 }
4023 };
4024
4025} // end namespace Catch
4026
4027///////////////////////////////////////////////////////////////////////////////
4028#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
4029 do { \
4030 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
4031 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
4032 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
4033 } while( false )
4034
4035///////////////////////////////////////////////////////////////////////////////
4036#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
4037 Catch::Capturer varName( macroName##_catch_sr, \
4038 CATCH_INTERNAL_LINEINFO, \
4039 Catch::ResultWas::Info, \
4040 #__VA_ARGS__##_catch_sr ); \
4041 varName.captureValues( 0, __VA_ARGS__ )
4042
4043///////////////////////////////////////////////////////////////////////////////
4044#define INTERNAL_CATCH_INFO( macroName, log ) \
4045 const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
4046
4047///////////////////////////////////////////////////////////////////////////////
4048#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
4049 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
4050
4051
4052#if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
4053
4054 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
4055 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
4056 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
4057 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ )
4058
4059#elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
4060
4061 #define CATCH_INFO( msg ) (void)(0)
4062 #define CATCH_UNSCOPED_INFO( msg ) (void)(0)
4063 #define CATCH_WARN( msg ) (void)(0)
4064 #define CATCH_CAPTURE( ... ) (void)(0)
4065
4066#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE)
4067
4068 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
4069 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
4070 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
4071 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ )
4072
4073#elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE)
4074
4075 #define INFO( msg ) (void)(0)
4076 #define UNSCOPED_INFO( msg ) (void)(0)
4077 #define WARN( msg ) (void)(0)
4078 #define CAPTURE( ... ) (void)(0)
4079
4080#endif // end of user facing macro declarations
4081
4082
4083
4084
4085#endif // CATCH_MESSAGE_HPP_INCLUDED
4086
4087
4088#ifndef CATCH_SECTION_INFO_HPP_INCLUDED
4089#define CATCH_SECTION_INFO_HPP_INCLUDED
4090
4091
4092
4093#ifndef CATCH_TOTALS_HPP_INCLUDED
4094#define CATCH_TOTALS_HPP_INCLUDED
4095
4096#include <cstdint>
4097
4098namespace Catch {
4099
4100 struct Counts {
4101 Counts operator - ( Counts const& other ) const;
4102 Counts& operator += ( Counts const& other );
4103
4104 std::uint64_t total() const;
4105 bool allPassed() const;
4106 bool allOk() const;
4107
4108 std::uint64_t passed = 0;
4109 std::uint64_t failed = 0;
4110 std::uint64_t failedButOk = 0;
4111 std::uint64_t skipped = 0;
4112 };
4113
4114 struct Totals {
4115
4116 Totals operator - ( Totals const& other ) const;
4117 Totals& operator += ( Totals const& other );
4118
4119 Totals delta( Totals const& prevTotals ) const;
4120
4121 Counts assertions;
4122 Counts testCases;
4123 };
4124}
4125
4126#endif // CATCH_TOTALS_HPP_INCLUDED
4127
4128#include <string>
4129
4130namespace Catch {
4131
4132 struct SectionInfo {
4133 // The last argument is ignored, so that people can write
4134 // SECTION("ShortName", "Proper description that is long") and
4135 // still use the `-c` flag comfortably.
4136 SectionInfo( SourceLineInfo const& _lineInfo, std::string _name,
4137 const char* const = nullptr ):
4138 name(CATCH_MOVE(_name)),
4139 lineInfo(_lineInfo)
4140 {}
4141
4142 std::string name;
4143 SourceLineInfo lineInfo;
4144 };
4145
4146 struct SectionEndInfo {
4147 SectionInfo sectionInfo;
4148 Counts prevAssertions;
4149 double durationInSeconds;
4150 };
4151
4152} // end namespace Catch
4153
4154#endif // CATCH_SECTION_INFO_HPP_INCLUDED
4155
4156
4157#ifndef CATCH_SESSION_HPP_INCLUDED
4158#define CATCH_SESSION_HPP_INCLUDED
4159
4160
4161
4162#ifndef CATCH_COMMANDLINE_HPP_INCLUDED
4163#define CATCH_COMMANDLINE_HPP_INCLUDED
4164
4165
4166
4167#ifndef CATCH_CLARA_HPP_INCLUDED
4168#define CATCH_CLARA_HPP_INCLUDED
4169
4170#if defined( __clang__ )
4171# pragma clang diagnostic push
4172# pragma clang diagnostic ignored "-Wweak-vtables"
4173# pragma clang diagnostic ignored "-Wshadow"
4174# pragma clang diagnostic ignored "-Wdeprecated"
4175#endif
4176
4177#if defined( __GNUC__ )
4178# pragma GCC diagnostic push
4179# pragma GCC diagnostic ignored "-Wsign-conversion"
4180#endif
4181
4182#ifndef CLARA_CONFIG_OPTIONAL_TYPE
4183# ifdef __has_include
4184# if __has_include( <optional>) && __cplusplus >= 201703L
4185# include <optional>
4186# define CLARA_CONFIG_OPTIONAL_TYPE std::optional
4187# endif
4188# endif
4189#endif
4190
4191
4192#include <cassert>
4193#include <memory>
4194#include <ostream>
4195#include <sstream>
4196#include <string>
4197#include <type_traits>
4198#include <vector>
4199
4200namespace Catch {
4201 namespace Clara {
4202
4203 class Args;
4204 class Parser;
4205
4206 // enum of result types from a parse
4207 enum class ParseResultType {
4208 Matched,
4209 NoMatch,
4210 ShortCircuitAll,
4211 ShortCircuitSame
4212 };
4213
4214 struct accept_many_t {};
4215 constexpr accept_many_t accept_many {};
4216
4217 namespace Detail {
4218 struct fake_arg {
4219 template <typename T>
4220 operator T();
4221 };
4222
4223 template <typename F, typename = void>
4224 struct is_unary_function : std::false_type {};
4225
4226 template <typename F>
4227 struct is_unary_function<
4228 F,
4229 Catch::Detail::void_t<decltype(
4230 std::declval<F>()( fake_arg() ) )
4231 >
4232 > : std::true_type {};
4233
4234 // Traits for extracting arg and return type of lambdas (for single
4235 // argument lambdas)
4236 template <typename L>
4237 struct UnaryLambdaTraits
4238 : UnaryLambdaTraits<decltype( &L::operator() )> {};
4239
4240 template <typename ClassT, typename ReturnT, typename... Args>
4241 struct UnaryLambdaTraits<ReturnT ( ClassT::* )( Args... ) const> {
4242 static const bool isValid = false;
4243 };
4244
4245 template <typename ClassT, typename ReturnT, typename ArgT>
4246 struct UnaryLambdaTraits<ReturnT ( ClassT::* )( ArgT ) const> {
4247 static const bool isValid = true;
4248 using ArgType = std::remove_const_t<std::remove_reference_t<ArgT>>;
4249 using ReturnType = ReturnT;
4250 };
4251
4252 class TokenStream;
4253
4254 // Wraps a token coming from a token stream. These may not directly
4255 // correspond to strings as a single string may encode an option +
4256 // its argument if the : or = form is used
4257 enum class TokenType { Option, Argument };
4258 struct Token {
4259 TokenType type;
4260 StringRef token;
4261 };
4262
4263 // Abstracts iterators into args as a stream of tokens, with option
4264 // arguments uniformly handled
4265 class TokenStream {
4266 using Iterator = std::vector<StringRef>::const_iterator;
4267 Iterator it;
4268 Iterator itEnd;
4269 std::vector<Token> m_tokenBuffer;
4270 void loadBuffer();
4271
4272 public:
4273 explicit TokenStream( Args const& args );
4274 TokenStream( Iterator it, Iterator itEnd );
4275
4276 explicit operator bool() const {
4277 return !m_tokenBuffer.empty() || it != itEnd;
4278 }
4279
4280 size_t count() const {
4281 return m_tokenBuffer.size() + ( itEnd - it );
4282 }
4283
4284 Token operator*() const {
4285 assert( !m_tokenBuffer.empty() );
4286 return m_tokenBuffer.front();
4287 }
4288
4289 Token const* operator->() const {
4290 assert( !m_tokenBuffer.empty() );
4291 return &m_tokenBuffer.front();
4292 }
4293
4294 TokenStream& operator++();
4295 };
4296
4297 //! Denotes type of a parsing result
4298 enum class ResultType {
4299 Ok, ///< No errors
4300 LogicError, ///< Error in user-specified arguments for
4301 ///< construction
4302 RuntimeError ///< Error in parsing inputs
4303 };
4304
4305 class ResultBase {
4306 protected:
4307 ResultBase( ResultType type ): m_type( type ) {}
4308 virtual ~ResultBase(); // = default;
4309
4310
4311 ResultBase(ResultBase const&) = default;
4312 ResultBase& operator=(ResultBase const&) = default;
4313 ResultBase(ResultBase&&) = default;
4314 ResultBase& operator=(ResultBase&&) = default;
4315
4316 virtual void enforceOk() const = 0;
4317
4318 ResultType m_type;
4319 };
4320
4321 template <typename T>
4322 class ResultValueBase : public ResultBase {
4323 public:
4324 T const& value() const& {
4325 enforceOk();
4326 return m_value;
4327 }
4328 T&& value() && {
4329 enforceOk();
4330 return CATCH_MOVE( m_value );
4331 }
4332
4333 protected:
4334 ResultValueBase( ResultType type ): ResultBase( type ) {}
4335
4336 ResultValueBase( ResultValueBase const& other ):
4337 ResultBase( other ) {
4338 if ( m_type == ResultType::Ok )
4339 new ( &m_value ) T( other.m_value );
4340 }
4341 ResultValueBase( ResultValueBase&& other ):
4342 ResultBase( other ) {
4343 if ( m_type == ResultType::Ok )
4344 new ( &m_value ) T( CATCH_MOVE(other.m_value) );
4345 }
4346
4347
4348 ResultValueBase( ResultType, T const& value ):
4349 ResultBase( ResultType::Ok ) {
4350 new ( &m_value ) T( value );
4351 }
4352 ResultValueBase( ResultType, T&& value ):
4353 ResultBase( ResultType::Ok ) {
4354 new ( &m_value ) T( CATCH_MOVE(value) );
4355 }
4356
4357 ResultValueBase& operator=( ResultValueBase const& other ) {
4358 if ( m_type == ResultType::Ok )
4359 m_value.~T();
4360 ResultBase::operator=( other );
4361 if ( m_type == ResultType::Ok )
4362 new ( &m_value ) T( other.m_value );
4363 return *this;
4364 }
4365 ResultValueBase& operator=( ResultValueBase&& other ) {
4366 if ( m_type == ResultType::Ok ) m_value.~T();
4367 ResultBase::operator=( other );
4368 if ( m_type == ResultType::Ok )
4369 new ( &m_value ) T( CATCH_MOVE(other.m_value) );
4370 return *this;
4371 }
4372
4373
4374 ~ResultValueBase() override {
4375 if ( m_type == ResultType::Ok )
4376 m_value.~T();
4377 }
4378
4379 union {
4380 T m_value;
4381 };
4382 };
4383
4384 template <> class ResultValueBase<void> : public ResultBase {
4385 protected:
4386 using ResultBase::ResultBase;
4387 };
4388
4389 template <typename T = void>
4390 class BasicResult : public ResultValueBase<T> {
4391 public:
4392 template <typename U>
4393 explicit BasicResult( BasicResult<U> const& other ):
4394 ResultValueBase<T>( other.type() ),
4395 m_errorMessage( other.errorMessage() ) {
4396 assert( type() != ResultType::Ok );
4397 }
4398
4399 template <typename U>
4400 static auto ok( U&& value ) -> BasicResult {
4401 return { ResultType::Ok, CATCH_FORWARD(value) };
4402 }
4403 static auto ok() -> BasicResult { return { ResultType::Ok }; }
4404 static auto logicError( std::string&& message )
4405 -> BasicResult {
4406 return { ResultType::LogicError, CATCH_MOVE(message) };
4407 }
4408 static auto runtimeError( std::string&& message )
4409 -> BasicResult {
4410 return { ResultType::RuntimeError, CATCH_MOVE(message) };
4411 }
4412
4413 explicit operator bool() const {
4414 return m_type == ResultType::Ok;
4415 }
4416 auto type() const -> ResultType { return m_type; }
4417 auto errorMessage() const -> std::string const& {
4418 return m_errorMessage;
4419 }
4420
4421 protected:
4422 void enforceOk() const override {
4423
4424 // Errors shouldn't reach this point, but if they do
4425 // the actual error message will be in m_errorMessage
4426 assert( m_type != ResultType::LogicError );
4427 assert( m_type != ResultType::RuntimeError );
4428 if ( m_type != ResultType::Ok )
4429 std::abort();
4430 }
4431
4432 std::string
4433 m_errorMessage; // Only populated if resultType is an error
4434
4435 BasicResult( ResultType type,
4436 std::string&& message ):
4437 ResultValueBase<T>( type ), m_errorMessage( CATCH_MOVE(message) ) {
4438 assert( m_type != ResultType::Ok );
4439 }
4440
4441 using ResultValueBase<T>::ResultValueBase;
4442 using ResultBase::m_type;
4443 };
4444
4445 class ParseState {
4446 public:
4447 ParseState( ParseResultType type,
4448 TokenStream remainingTokens );
4449
4450 ParseResultType type() const { return m_type; }
4451 TokenStream const& remainingTokens() const& {
4452 return m_remainingTokens;
4453 }
4454 TokenStream&& remainingTokens() && {
4455 return CATCH_MOVE( m_remainingTokens );
4456 }
4457
4458 private:
4459 ParseResultType m_type;
4460 TokenStream m_remainingTokens;
4461 };
4462
4463 using Result = BasicResult<void>;
4464 using ParserResult = BasicResult<ParseResultType>;
4465 using InternalParseResult = BasicResult<ParseState>;
4466
4467 struct HelpColumns {
4468 std::string left;
4469 StringRef descriptions;
4470 };
4471
4472 template <typename T>
4473 ParserResult convertInto( std::string const& source, T& target ) {
4474 std::stringstream ss( source );
4475 ss >> target;
4476 if ( ss.fail() ) {
4477 return ParserResult::runtimeError(
4478 "Unable to convert '" + source +
4479 "' to destination type" );
4480 } else {
4481 return ParserResult::ok( ParseResultType::Matched );
4482 }
4483 }
4484 ParserResult convertInto( std::string const& source,
4485 std::string& target );
4486 ParserResult convertInto( std::string const& source, bool& target );
4487
4488#ifdef CLARA_CONFIG_OPTIONAL_TYPE
4489 template <typename T>
4490 auto convertInto( std::string const& source,
4491 CLARA_CONFIG_OPTIONAL_TYPE<T>& target )
4492 -> ParserResult {
4493 T temp;
4494 auto result = convertInto( source, temp );
4495 if ( result )
4496 target = CATCH_MOVE( temp );
4497 return result;
4498 }
4499#endif // CLARA_CONFIG_OPTIONAL_TYPE
4500
4501 struct BoundRef : Catch::Detail::NonCopyable {
4502 virtual ~BoundRef() = default;
4503 virtual bool isContainer() const;
4504 virtual bool isFlag() const;
4505 };
4506 struct BoundValueRefBase : BoundRef {
4507 virtual auto setValue( std::string const& arg )
4508 -> ParserResult = 0;
4509 };
4510 struct BoundFlagRefBase : BoundRef {
4511 virtual auto setFlag( bool flag ) -> ParserResult = 0;
4512 bool isFlag() const override;
4513 };
4514
4515 template <typename T> struct BoundValueRef : BoundValueRefBase {
4516 T& m_ref;
4517
4518 explicit BoundValueRef( T& ref ): m_ref( ref ) {}
4519
4520 ParserResult setValue( std::string const& arg ) override {
4521 return convertInto( arg, m_ref );
4522 }
4523 };
4524
4525 template <typename T>
4526 struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
4527 std::vector<T>& m_ref;
4528
4529 explicit BoundValueRef( std::vector<T>& ref ): m_ref( ref ) {}
4530
4531 auto isContainer() const -> bool override { return true; }
4532
4533 auto setValue( std::string const& arg )
4534 -> ParserResult override {
4535 T temp;
4536 auto result = convertInto( arg, temp );
4537 if ( result )
4538 m_ref.push_back( temp );
4539 return result;
4540 }
4541 };
4542
4543 struct BoundFlagRef : BoundFlagRefBase {
4544 bool& m_ref;
4545
4546 explicit BoundFlagRef( bool& ref ): m_ref( ref ) {}
4547
4548 ParserResult setFlag( bool flag ) override;
4549 };
4550
4551 template <typename ReturnType> struct LambdaInvoker {
4552 static_assert(
4553 std::is_same<ReturnType, ParserResult>::value,
4554 "Lambda must return void or clara::ParserResult" );
4555
4556 template <typename L, typename ArgType>
4557 static auto invoke( L const& lambda, ArgType const& arg )
4558 -> ParserResult {
4559 return lambda( arg );
4560 }
4561 };
4562
4563 template <> struct LambdaInvoker<void> {
4564 template <typename L, typename ArgType>
4565 static auto invoke( L const& lambda, ArgType const& arg )
4566 -> ParserResult {
4567 lambda( arg );
4568 return ParserResult::ok( ParseResultType::Matched );
4569 }
4570 };
4571
4572 template <typename ArgType, typename L>
4573 auto invokeLambda( L const& lambda, std::string const& arg )
4574 -> ParserResult {
4575 ArgType temp{};
4576 auto result = convertInto( arg, temp );
4577 return !result ? result
4578 : LambdaInvoker<typename UnaryLambdaTraits<
4579 L>::ReturnType>::invoke( lambda, temp );
4580 }
4581
4582 template <typename L> struct BoundLambda : BoundValueRefBase {
4583 L m_lambda;
4584
4585 static_assert(
4586 UnaryLambdaTraits<L>::isValid,
4587 "Supplied lambda must take exactly one argument" );
4588 explicit BoundLambda( L const& lambda ): m_lambda( lambda ) {}
4589
4590 auto setValue( std::string const& arg )
4591 -> ParserResult override {
4592 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(
4593 m_lambda, arg );
4594 }
4595 };
4596
4597 template <typename L> struct BoundManyLambda : BoundLambda<L> {
4598 explicit BoundManyLambda( L const& lambda ): BoundLambda<L>( lambda ) {}
4599 bool isContainer() const override { return true; }
4600 };
4601
4602 template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
4603 L m_lambda;
4604
4605 static_assert(
4606 UnaryLambdaTraits<L>::isValid,
4607 "Supplied lambda must take exactly one argument" );
4608 static_assert(
4609 std::is_same<typename UnaryLambdaTraits<L>::ArgType,
4610 bool>::value,
4611 "flags must be boolean" );
4612
4613 explicit BoundFlagLambda( L const& lambda ):
4614 m_lambda( lambda ) {}
4615
4616 auto setFlag( bool flag ) -> ParserResult override {
4617 return LambdaInvoker<typename UnaryLambdaTraits<
4618 L>::ReturnType>::invoke( m_lambda, flag );
4619 }
4620 };
4621
4622 enum class Optionality { Optional, Required };
4623
4624 class ParserBase {
4625 public:
4626 virtual ~ParserBase() = default;
4627 virtual auto validate() const -> Result { return Result::ok(); }
4628 virtual auto parse( std::string const& exeName,
4629 TokenStream tokens ) const
4630 -> InternalParseResult = 0;
4631 virtual size_t cardinality() const;
4632
4633 InternalParseResult parse( Args const& args ) const;
4634 };
4635
4636 template <typename DerivedT>
4637 class ComposableParserImpl : public ParserBase {
4638 public:
4639 template <typename T>
4640 auto operator|( T const& other ) const -> Parser;
4641 };
4642
4643 // Common code and state for Args and Opts
4644 template <typename DerivedT>
4645 class ParserRefImpl : public ComposableParserImpl<DerivedT> {
4646 protected:
4647 Optionality m_optionality = Optionality::Optional;
4648 std::shared_ptr<BoundRef> m_ref;
4649 StringRef m_hint;
4650 StringRef m_description;
4651
4652 explicit ParserRefImpl( std::shared_ptr<BoundRef> const& ref ):
4653 m_ref( ref ) {}
4654
4655 public:
4656 template <typename LambdaT>
4657 ParserRefImpl( accept_many_t,
4658 LambdaT const& ref,
4659 StringRef hint ):
4660 m_ref( std::make_shared<BoundManyLambda<LambdaT>>( ref ) ),
4661 m_hint( hint ) {}
4662
4663 template <typename T,
4664 typename = typename std::enable_if_t<
4665 !Detail::is_unary_function<T>::value>>
4666 ParserRefImpl( T& ref, StringRef hint ):
4667 m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
4668 m_hint( hint ) {}
4669
4670 template <typename LambdaT,
4671 typename = typename std::enable_if_t<
4672 Detail::is_unary_function<LambdaT>::value>>
4673 ParserRefImpl( LambdaT const& ref, StringRef hint ):
4674 m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
4675 m_hint( hint ) {}
4676
4677 DerivedT& operator()( StringRef description ) & {
4678 m_description = description;
4679 return static_cast<DerivedT&>( *this );
4680 }
4681 DerivedT&& operator()( StringRef description ) && {
4682 m_description = description;
4683 return static_cast<DerivedT&&>( *this );
4684 }
4685
4686 auto optional() -> DerivedT& {
4687 m_optionality = Optionality::Optional;
4688 return static_cast<DerivedT&>( *this );
4689 }
4690
4691 auto required() -> DerivedT& {
4692 m_optionality = Optionality::Required;
4693 return static_cast<DerivedT&>( *this );
4694 }
4695
4696 auto isOptional() const -> bool {
4697 return m_optionality == Optionality::Optional;
4698 }
4699
4700 auto cardinality() const -> size_t override {
4701 if ( m_ref->isContainer() )
4702 return 0;
4703 else
4704 return 1;
4705 }
4706
4707 StringRef hint() const { return m_hint; }
4708 };
4709
4710 } // namespace detail
4711
4712
4713 // A parser for arguments
4714 class Arg : public Detail::ParserRefImpl<Arg> {
4715 public:
4716 using ParserRefImpl::ParserRefImpl;
4717 using ParserBase::parse;
4718
4719 Detail::InternalParseResult
4720 parse(std::string const&,
4721 Detail::TokenStream tokens) const override;
4722 };
4723
4724 // A parser for options
4725 class Opt : public Detail::ParserRefImpl<Opt> {
4726 protected:
4727 std::vector<StringRef> m_optNames;
4728
4729 public:
4730 template <typename LambdaT>
4731 explicit Opt(LambdaT const& ref) :
4732 ParserRefImpl(
4733 std::make_shared<Detail::BoundFlagLambda<LambdaT>>(ref)) {}
4734
4735 explicit Opt(bool& ref);
4736
4737 template <typename LambdaT,
4738 typename = typename std::enable_if_t<
4739 Detail::is_unary_function<LambdaT>::value>>
4740 Opt( LambdaT const& ref, StringRef hint ):
4741 ParserRefImpl( ref, hint ) {}
4742
4743 template <typename LambdaT>
4744 Opt( accept_many_t, LambdaT const& ref, StringRef hint ):
4745 ParserRefImpl( accept_many, ref, hint ) {}
4746
4747 template <typename T,
4748 typename = typename std::enable_if_t<
4749 !Detail::is_unary_function<T>::value>>
4750 Opt( T& ref, StringRef hint ):
4751 ParserRefImpl( ref, hint ) {}
4752
4753 Opt& operator[]( StringRef optName ) & {
4754 m_optNames.push_back(optName);
4755 return *this;
4756 }
4757 Opt&& operator[]( StringRef optName ) && {
4758 m_optNames.push_back( optName );
4759 return CATCH_MOVE(*this);
4760 }
4761
4762 Detail::HelpColumns getHelpColumns() const;
4763
4764 bool isMatch(StringRef optToken) const;
4765
4766 using ParserBase::parse;
4767
4768 Detail::InternalParseResult
4769 parse(std::string const&,
4770 Detail::TokenStream tokens) const override;
4771
4772 Detail::Result validate() const override;
4773 };
4774
4775 // Specifies the name of the executable
4776 class ExeName : public Detail::ComposableParserImpl<ExeName> {
4777 std::shared_ptr<std::string> m_name;
4778 std::shared_ptr<Detail::BoundValueRefBase> m_ref;
4779
4780 public:
4781 ExeName();
4782 explicit ExeName(std::string& ref);
4783
4784 template <typename LambdaT>
4785 explicit ExeName(LambdaT const& lambda) : ExeName() {
4786 m_ref = std::make_shared<Detail::BoundLambda<LambdaT>>(lambda);
4787 }
4788
4789 // The exe name is not parsed out of the normal tokens, but is
4790 // handled specially
4791 Detail::InternalParseResult
4792 parse(std::string const&,
4793 Detail::TokenStream tokens) const override;
4794
4795 std::string const& name() const { return *m_name; }
4796 Detail::ParserResult set(std::string const& newName);
4797 };
4798
4799
4800 // A Combined parser
4801 class Parser : Detail::ParserBase {
4802 mutable ExeName m_exeName;
4803 std::vector<Opt> m_options;
4804 std::vector<Arg> m_args;
4805
4806 public:
4807
4808 auto operator|=(ExeName const& exeName) -> Parser& {
4809 m_exeName = exeName;
4810 return *this;
4811 }
4812
4813 auto operator|=(Arg const& arg) -> Parser& {
4814 m_args.push_back(arg);
4815 return *this;
4816 }
4817
4818 friend Parser& operator|=( Parser& p, Opt const& opt ) {
4819 p.m_options.push_back( opt );
4820 return p;
4821 }
4822 friend Parser& operator|=( Parser& p, Opt&& opt ) {
4823 p.m_options.push_back( CATCH_MOVE(opt) );
4824 return p;
4825 }
4826
4827 Parser& operator|=(Parser const& other);
4828
4829 template <typename T>
4830 friend Parser operator|( Parser const& p, T&& rhs ) {
4831 Parser temp( p );
4832 temp |= rhs;
4833 return temp;
4834 }
4835
4836 template <typename T>
4837 friend Parser operator|( Parser&& p, T&& rhs ) {
4838 p |= CATCH_FORWARD(rhs);
4839 return CATCH_MOVE(p);
4840 }
4841
4842 std::vector<Detail::HelpColumns> getHelpColumns() const;
4843
4844 void writeToStream(std::ostream& os) const;
4845
4846 friend auto operator<<(std::ostream& os, Parser const& parser)
4847 -> std::ostream& {
4848 parser.writeToStream(os);
4849 return os;
4850 }
4851
4852 Detail::Result validate() const override;
4853
4854 using ParserBase::parse;
4855 Detail::InternalParseResult
4856 parse(std::string const& exeName,
4857 Detail::TokenStream tokens) const override;
4858 };
4859
4860 /**
4861 * Wrapper over argc + argv, assumes that the inputs outlive it
4862 */
4863 class Args {
4864 friend Detail::TokenStream;
4865 StringRef m_exeName;
4866 std::vector<StringRef> m_args;
4867
4868 public:
4869 Args(int argc, char const* const* argv);
4870 // Helper constructor for testing
4871 Args(std::initializer_list<StringRef> args);
4872
4873 StringRef exeName() const { return m_exeName; }
4874 };
4875
4876
4877 // Convenience wrapper for option parser that specifies the help option
4878 struct Help : Opt {
4879 Help(bool& showHelpFlag);
4880 };
4881
4882 // Result type for parser operation
4883 using Detail::ParserResult;
4884
4885 namespace Detail {
4886 template <typename DerivedT>
4887 template <typename T>
4888 Parser
4889 ComposableParserImpl<DerivedT>::operator|(T const& other) const {
4890 return Parser() | static_cast<DerivedT const&>(*this) | other;
4891 }
4892 }
4893
4894 } // namespace Clara
4895} // namespace Catch
4896
4897#if defined( __clang__ )
4898# pragma clang diagnostic pop
4899#endif
4900
4901#if defined( __GNUC__ )
4902# pragma GCC diagnostic pop
4903#endif
4904
4905#endif // CATCH_CLARA_HPP_INCLUDED
4906
4907namespace Catch {
4908
4909 struct ConfigData;
4910
4911 Clara::Parser makeCommandLineParser( ConfigData& config );
4912
4913} // end namespace Catch
4914
4915#endif // CATCH_COMMANDLINE_HPP_INCLUDED
4916
4917namespace Catch {
4918
4919 class Session : Detail::NonCopyable {
4920 public:
4921
4922 Session();
4923 ~Session();
4924
4925 void showHelp() const;
4926 void libIdentify();
4927
4928 int applyCommandLine( int argc, char const * const * argv );
4929 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
4930 int applyCommandLine( int argc, wchar_t const * const * argv );
4931 #endif
4932
4933 void useConfigData( ConfigData const& configData );
4934
4935 template<typename CharT>
4936 int run(int argc, CharT const * const argv[]) {
4937 if (m_startupExceptions)
4938 return 1;
4939 int returnCode = applyCommandLine(argc, argv);
4940 if (returnCode == 0)
4941 returnCode = run();
4942 return returnCode;
4943 }
4944
4945 int run();
4946
4947 Clara::Parser const& cli() const;
4948 void cli( Clara::Parser const& newParser );
4949 ConfigData& configData();
4950 Config& config();
4951 private:
4952 int runInternal();
4953
4954 Clara::Parser m_cli;
4955 ConfigData m_configData;
4956 Detail::unique_ptr<Config> m_config;
4957 bool m_startupExceptions = false;
4958 };
4959
4960} // end namespace Catch
4961
4962#endif // CATCH_SESSION_HPP_INCLUDED
4963
4964
4965#ifndef CATCH_TAG_ALIAS_HPP_INCLUDED
4966#define CATCH_TAG_ALIAS_HPP_INCLUDED
4967
4968
4969#include <string>
4970
4971namespace Catch {
4972
4973 struct TagAlias {
4974 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo):
4975 tag(_tag),
4976 lineInfo(_lineInfo)
4977 {}
4978
4979 std::string tag;
4980 SourceLineInfo lineInfo;
4981 };
4982
4983} // end namespace Catch
4984
4985#endif // CATCH_TAG_ALIAS_HPP_INCLUDED
4986
4987
4988#ifndef CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
4989#define CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
4990
4991
4992namespace Catch {
4993
4994 struct RegistrarForTagAliases {
4995 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
4996 };
4997
4998} // end namespace Catch
4999
5000#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
5001 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5002 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
5003 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
5004 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5005
5006#endif // CATCH_TAG_ALIAS_AUTOREGISTRAR_HPP_INCLUDED
5007
5008
5009#ifndef CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
5010#define CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
5011
5012// We need this suppression to leak, because it took until GCC 10
5013// for the front end to handle local suppression via _Pragma properly
5014// inside templates (so `TEMPLATE_TEST_CASE` and co).
5015// **THIS IS DIFFERENT FOR STANDARD TESTS, WHERE GCC 9 IS SUFFICIENT**
5016#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ < 10
5017#pragma GCC diagnostic ignored "-Wparentheses"
5018#endif
5019
5020
5021
5022
5023#ifndef CATCH_TEST_MACROS_HPP_INCLUDED
5024#define CATCH_TEST_MACROS_HPP_INCLUDED
5025
5026
5027
5028#ifndef CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
5029#define CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
5030
5031
5032
5033#ifndef CATCH_ASSERTION_HANDLER_HPP_INCLUDED
5034#define CATCH_ASSERTION_HANDLER_HPP_INCLUDED
5035
5036
5037
5038#ifndef CATCH_DECOMPOSER_HPP_INCLUDED
5039#define CATCH_DECOMPOSER_HPP_INCLUDED
5040
5041
5042
5043#ifndef CATCH_COMPARE_TRAITS_HPP_INCLUDED
5044#define CATCH_COMPARE_TRAITS_HPP_INCLUDED
5045
5046
5047#include <type_traits>
5048
5049namespace Catch {
5050 namespace Detail {
5051
5052#if defined( __GNUC__ ) && !defined( __clang__ )
5053# pragma GCC diagnostic push
5054 // GCC likes to complain about comparing bool with 0, in the decltype()
5055 // that defines the comparable traits below.
5056# pragma GCC diagnostic ignored "-Wbool-compare"
5057 // "ordered comparison of pointer with integer zero" same as above,
5058 // but it does not have a separate warning flag to suppress
5059# pragma GCC diagnostic ignored "-Wextra"
5060 // Did you know that comparing floats with `0` directly
5061 // is super-duper dangerous in unevaluated context?
5062# pragma GCC diagnostic ignored "-Wfloat-equal"
5063#endif
5064
5065#if defined( __clang__ )
5066# pragma clang diagnostic push
5067 // Did you know that comparing floats with `0` directly
5068 // is super-duper dangerous in unevaluated context?
5069# pragma clang diagnostic ignored "-Wfloat-equal"
5070#endif
5071
5072#define CATCH_DEFINE_COMPARABLE_TRAIT( id, op ) \
5073 template <typename, typename, typename = void> \
5074 struct is_##id##_comparable : std::false_type {}; \
5075 template <typename T, typename U> \
5076 struct is_##id##_comparable< \
5077 T, \
5078 U, \
5079 void_t<decltype( std::declval<T>() op std::declval<U>() )>> \
5080 : std::true_type {}; \
5081 template <typename, typename = void> \
5082 struct is_##id##_0_comparable : std::false_type {}; \
5083 template <typename T> \
5084 struct is_##id##_0_comparable<T, \
5085 void_t<decltype( std::declval<T>() op 0 )>> \
5086 : std::true_type {};
5087
5088 // We need all 6 pre-spaceship comparison ops: <, <=, >, >=, ==, !=
5089 CATCH_DEFINE_COMPARABLE_TRAIT( lt, < )
5090 CATCH_DEFINE_COMPARABLE_TRAIT( le, <= )
5091 CATCH_DEFINE_COMPARABLE_TRAIT( gt, > )
5092 CATCH_DEFINE_COMPARABLE_TRAIT( ge, >= )
5093 CATCH_DEFINE_COMPARABLE_TRAIT( eq, == )
5094 CATCH_DEFINE_COMPARABLE_TRAIT( ne, != )
5095
5096#undef CATCH_DEFINE_COMPARABLE_TRAIT
5097
5098#if defined( __GNUC__ ) && !defined( __clang__ )
5099# pragma GCC diagnostic pop
5100#endif
5101#if defined( __clang__ )
5102# pragma clang diagnostic pop
5103#endif
5104
5105
5106 } // namespace Detail
5107} // namespace Catch
5108
5109#endif // CATCH_COMPARE_TRAITS_HPP_INCLUDED
5110
5111
5112#ifndef CATCH_LOGICAL_TRAITS_HPP_INCLUDED
5113#define CATCH_LOGICAL_TRAITS_HPP_INCLUDED
5114
5115#include <type_traits>
5116
5117namespace Catch {
5118namespace Detail {
5119
5120#if defined( __cpp_lib_logical_traits ) && __cpp_lib_logical_traits >= 201510
5121
5122 using std::conjunction;
5123 using std::disjunction;
5124 using std::negation;
5125
5126#else
5127
5128 template <class...> struct conjunction : std::true_type {};
5129 template <class B1> struct conjunction<B1> : B1 {};
5130 template <class B1, class... Bn>
5131 struct conjunction<B1, Bn...>
5132 : std::conditional_t<bool( B1::value ), conjunction<Bn...>, B1> {};
5133
5134 template <class...> struct disjunction : std::false_type {};
5135 template <class B1> struct disjunction<B1> : B1 {};
5136 template <class B1, class... Bn>
5137 struct disjunction<B1, Bn...>
5138 : std::conditional_t<bool( B1::value ), B1, disjunction<Bn...>> {};
5139
5140 template <class B>
5141 struct negation : std::integral_constant<bool, !bool(B::value)> {};
5142
5143#endif
5144
5145} // namespace Detail
5146} // namespace Catch
5147
5148#endif // CATCH_LOGICAL_TRAITS_HPP_INCLUDED
5149
5150#include <type_traits>
5151#include <iosfwd>
5152
5153/** \file
5154 * Why does decomposing look the way it does:
5155 *
5156 * Conceptually, decomposing is simple. We change `REQUIRE( a == b )` into
5157 * `Decomposer{} <= a == b`, so that `Decomposer{} <= a` is evaluated first,
5158 * and our custom operator is used for `a == b`, because `a` is transformed
5159 * into `ExprLhs<T&>` and then into `BinaryExpr<T&, U&>`.
5160 *
5161 * In practice, decomposing ends up a mess, because we have to support
5162 * various fun things.
5163 *
5164 * 1) Types that are only comparable with literal 0, and they do this by
5165 * comparing against a magic type with pointer constructor and deleted
5166 * other constructors. Example: `REQUIRE((a <=> b) == 0)` in libstdc++
5167 *
5168 * 2) Types that are only comparable with literal 0, and they do this by
5169 * comparing against a magic type with consteval integer constructor.
5170 * Example: `REQUIRE((a <=> b) == 0)` in current MSVC STL.
5171 *
5172 * 3) Types that have no linkage, and so we cannot form a reference to
5173 * them. Example: some implementations of traits.
5174 *
5175 * 4) Starting with C++20, when the compiler sees `a == b`, it also uses
5176 * `b == a` when constructing the overload set. For us this means that
5177 * when the compiler handles `ExprLhs<T> == b`, it also tries to resolve
5178 * the overload set for `b == ExprLhs<T>`.
5179 *
5180 * To accomodate these use cases, decomposer ended up rather complex.
5181 *
5182 * 1) These types are handled by adding SFINAE overloads to our comparison
5183 * operators, checking whether `T == U` are comparable with the given
5184 * operator, and if not, whether T (or U) are comparable with literal 0.
5185 * If yes, the overload compares T (or U) with 0 literal inline in the
5186 * definition.
5187 *
5188 * Note that for extra correctness, we check that the other type is
5189 * either an `int` (literal 0 is captured as `int` by templates), or
5190 * a `long` (some platforms use 0L for `NULL` and we want to support
5191 * that for pointer comparisons).
5192 *
5193 * 2) For these types, `is_foo_comparable<T, int>` is true, but letting
5194 * them fall into the overload that actually does `T == int` causes
5195 * compilation error. Handling them requires that the decomposition
5196 * is `constexpr`, so that P2564R3 applies and the `consteval` from
5197 * their accompanying magic type is propagated through the `constexpr`
5198 * call stack.
5199 *
5200 * However this is not enough to handle these types automatically,
5201 * because our default is to capture types by reference, to avoid
5202 * runtime copies. While these references cannot become dangling,
5203 * they outlive the constexpr context and thus the default capture
5204 * path cannot be actually constexpr.
5205 *
5206 * The solution is to capture these types by value, by explicitly
5207 * specializing `Catch::capture_by_value` for them. Catch2 provides
5208 * specialization for `std::foo_ordering`s, but users can specialize
5209 * the trait for their own types as well.
5210 *
5211 * 3) If a type has no linkage, we also cannot capture it by reference.
5212 * The solution is once again to capture them by value. We handle
5213 * the common cases by using `std::is_arithmetic` as the default
5214 * for `Catch::capture_by_value`, but that is only a some-effort
5215 * heuristic. But as with 2), users can specialize `capture_by_value`
5216 * for their own types as needed.
5217 *
5218 * 4) To support C++20 and make the SFINAE on our decomposing operators
5219 * work, the SFINAE has to happen in return type, rather than in
5220 * a template type. This is due to our use of logical type traits
5221 * (`conjunction`/`disjunction`/`negation`), that we use to workaround
5222 * an issue in older (9-) versions of GCC. I still blame C++20 for
5223 * this, because without the comparison order switching, the logical
5224 * traits could still be used in template type.
5225 *
5226 * There are also other side concerns, e.g. supporting both `REQUIRE(a)`
5227 * and `REQUIRE(a == b)`, or making `REQUIRE_THAT(a, IsEqual(b))` slot
5228 * nicely into the same expression handling logic, but these are rather
5229 * straightforward and add only a bit of complexity (e.g. common base
5230 * class for decomposed expressions).
5231 */
5232
5233#ifdef _MSC_VER
5234#pragma warning(push)
5235#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
5236#pragma warning(disable:4018) // more "signed/unsigned mismatch"
5237#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
5238#pragma warning(disable:4180) // qualifier applied to function type has no meaning
5239#pragma warning(disable:4800) // Forcing result to true or false
5240#endif
5241
5242#ifdef __clang__
5243# pragma clang diagnostic push
5244# pragma clang diagnostic ignored "-Wsign-compare"
5245# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
5246#elif defined __GNUC__
5247# pragma GCC diagnostic push
5248# pragma GCC diagnostic ignored "-Wsign-compare"
5249# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
5250#endif
5251
5252#if defined(CATCH_CPP20_OR_GREATER) && __has_include(<compare>)
5253# include <compare>
5254# if defined( __cpp_lib_three_way_comparison ) && \
5255 __cpp_lib_three_way_comparison >= 201907L
5256# define CATCH_CONFIG_CPP20_COMPARE_OVERLOADS
5257# endif
5258#endif
5259
5260namespace Catch {
5261
5262 namespace Detail {
5263 // This was added in C++20, but we require only C++14 for now.
5264 template <typename T>
5265 using RemoveCVRef_t = std::remove_cv_t<std::remove_reference_t<T>>;
5266 }
5267
5268 // Note: There is nothing that stops us from extending this,
5269 // e.g. to `std::is_scalar`, but the more encompassing
5270 // traits are usually also more expensive. For now we
5271 // keep this as it used to be and it can be changed later.
5272 template <typename T>
5273 struct capture_by_value
5274 : std::integral_constant<bool, std::is_arithmetic<T>{}> {};
5275
5276#if defined( CATCH_CONFIG_CPP20_COMPARE_OVERLOADS )
5277 template <>
5278 struct capture_by_value<std::strong_ordering> : std::true_type {};
5279 template <>
5280 struct capture_by_value<std::weak_ordering> : std::true_type {};
5281 template <>
5282 struct capture_by_value<std::partial_ordering> : std::true_type {};
5283#endif
5284
5285 template <typename T>
5286 struct always_false : std::false_type {};
5287
5288 class ITransientExpression {
5289 bool m_isBinaryExpression;
5290 bool m_result;
5291
5292 public:
5293 constexpr auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
5294 constexpr auto getResult() const -> bool { return m_result; }
5295 //! This function **has** to be overriden by the derived class.
5296 virtual void streamReconstructedExpression( std::ostream& os ) const;
5297
5298 constexpr ITransientExpression( bool isBinaryExpression, bool result )
5299 : m_isBinaryExpression( isBinaryExpression ),
5300 m_result( result )
5301 {}
5302
5303 ITransientExpression() = default;
5304 ITransientExpression(ITransientExpression const&) = default;
5305 ITransientExpression& operator=(ITransientExpression const&) = default;
5306
5307 friend std::ostream& operator<<(std::ostream& out, ITransientExpression const& expr) {
5308 expr.streamReconstructedExpression(out);
5309 return out;
5310 }
5311
5312 protected:
5313 ~ITransientExpression() = default;
5314 };
5315
5316 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
5317
5318 template<typename LhsT, typename RhsT>
5319 class BinaryExpr : public ITransientExpression {
5320 LhsT m_lhs;
5321 StringRef m_op;
5322 RhsT m_rhs;
5323
5324 void streamReconstructedExpression( std::ostream &os ) const override {
5325 formatReconstructedExpression
5326 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
5327 }
5328
5329 public:
5330 constexpr BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
5331 : ITransientExpression{ true, comparisonResult },
5332 m_lhs( lhs ),
5333 m_op( op ),
5334 m_rhs( rhs )
5335 {}
5336
5337 template<typename T>
5338 auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5339 static_assert(always_false<T>::value,
5340 "chained comparisons are not supported inside assertions, "
5341 "wrap the expression inside parentheses, or decompose it");
5342 }
5343
5344 template<typename T>
5345 auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5346 static_assert(always_false<T>::value,
5347 "chained comparisons are not supported inside assertions, "
5348 "wrap the expression inside parentheses, or decompose it");
5349 }
5350
5351 template<typename T>
5352 auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5353 static_assert(always_false<T>::value,
5354 "chained comparisons are not supported inside assertions, "
5355 "wrap the expression inside parentheses, or decompose it");
5356 }
5357
5358 template<typename T>
5359 auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5360 static_assert(always_false<T>::value,
5361 "chained comparisons are not supported inside assertions, "
5362 "wrap the expression inside parentheses, or decompose it");
5363 }
5364
5365 template<typename T>
5366 auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5367 static_assert(always_false<T>::value,
5368 "chained comparisons are not supported inside assertions, "
5369 "wrap the expression inside parentheses, or decompose it");
5370 }
5371
5372 template<typename T>
5373 auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5374 static_assert(always_false<T>::value,
5375 "chained comparisons are not supported inside assertions, "
5376 "wrap the expression inside parentheses, or decompose it");
5377 }
5378
5379 template<typename T>
5380 auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5381 static_assert(always_false<T>::value,
5382 "chained comparisons are not supported inside assertions, "
5383 "wrap the expression inside parentheses, or decompose it");
5384 }
5385
5386 template<typename T>
5387 auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
5388 static_assert(always_false<T>::value,
5389 "chained comparisons are not supported inside assertions, "
5390 "wrap the expression inside parentheses, or decompose it");
5391 }
5392 };
5393
5394 template<typename LhsT>
5395 class UnaryExpr : public ITransientExpression {
5396 LhsT m_lhs;
5397
5398 void streamReconstructedExpression( std::ostream &os ) const override {
5399 os << Catch::Detail::stringify( m_lhs );
5400 }
5401
5402 public:
5403 explicit constexpr UnaryExpr( LhsT lhs )
5404 : ITransientExpression{ false, static_cast<bool>(lhs) },
5405 m_lhs( lhs )
5406 {}
5407 };
5408
5409
5410 template<typename LhsT>
5411 class ExprLhs {
5412 LhsT m_lhs;
5413 public:
5414 explicit constexpr ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
5415
5416#define CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( id, op ) \
5417 template <typename RhsT> \
5418 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
5419 -> std::enable_if_t< \
5420 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5421 Detail::negation<capture_by_value< \
5422 Detail::RemoveCVRef_t<RhsT>>>>::value, \
5423 BinaryExpr<LhsT, RhsT const&>> { \
5424 return { \
5425 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5426 } \
5427 template <typename RhsT> \
5428 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5429 -> std::enable_if_t< \
5430 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5431 capture_by_value<RhsT>>::value, \
5432 BinaryExpr<LhsT, RhsT>> { \
5433 return { \
5434 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5435 } \
5436 template <typename RhsT> \
5437 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5438 -> std::enable_if_t< \
5439 Detail::conjunction< \
5440 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5441 Detail::is_eq_0_comparable<LhsT>, \
5442 /* We allow long because we want `ptr op NULL` to be accepted */ \
5443 Detail::disjunction<std::is_same<RhsT, int>, \
5444 std::is_same<RhsT, long>>>::value, \
5445 BinaryExpr<LhsT, RhsT>> { \
5446 if ( rhs != 0 ) { throw_test_failure_exception(); } \
5447 return { \
5448 static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
5449 } \
5450 template <typename RhsT> \
5451 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5452 -> std::enable_if_t< \
5453 Detail::conjunction< \
5454 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5455 Detail::is_eq_0_comparable<RhsT>, \
5456 /* We allow long because we want `ptr op NULL` to be accepted */ \
5457 Detail::disjunction<std::is_same<LhsT, int>, \
5458 std::is_same<LhsT, long>>>::value, \
5459 BinaryExpr<LhsT, RhsT>> { \
5460 if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
5461 return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5462 }
5463
5464 CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( eq, == )
5465 CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR( ne, != )
5466
5467 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_EQUALITY_OPERATOR
5468
5469
5470#define CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( id, op ) \
5471 template <typename RhsT> \
5472 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
5473 -> std::enable_if_t< \
5474 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5475 Detail::negation<capture_by_value< \
5476 Detail::RemoveCVRef_t<RhsT>>>>::value, \
5477 BinaryExpr<LhsT, RhsT const&>> { \
5478 return { \
5479 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5480 } \
5481 template <typename RhsT> \
5482 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5483 -> std::enable_if_t< \
5484 Detail::conjunction<Detail::is_##id##_comparable<LhsT, RhsT>, \
5485 capture_by_value<RhsT>>::value, \
5486 BinaryExpr<LhsT, RhsT>> { \
5487 return { \
5488 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5489 } \
5490 template <typename RhsT> \
5491 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5492 -> std::enable_if_t< \
5493 Detail::conjunction< \
5494 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5495 Detail::is_##id##_0_comparable<LhsT>, \
5496 std::is_same<RhsT, int>>::value, \
5497 BinaryExpr<LhsT, RhsT>> { \
5498 if ( rhs != 0 ) { throw_test_failure_exception(); } \
5499 return { \
5500 static_cast<bool>( lhs.m_lhs op 0 ), lhs.m_lhs, #op##_sr, rhs }; \
5501 } \
5502 template <typename RhsT> \
5503 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5504 -> std::enable_if_t< \
5505 Detail::conjunction< \
5506 Detail::negation<Detail::is_##id##_comparable<LhsT, RhsT>>, \
5507 Detail::is_##id##_0_comparable<RhsT>, \
5508 std::is_same<LhsT, int>>::value, \
5509 BinaryExpr<LhsT, RhsT>> { \
5510 if ( lhs.m_lhs != 0 ) { throw_test_failure_exception(); } \
5511 return { static_cast<bool>( 0 op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5512 }
5513
5514 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( lt, < )
5515 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( le, <= )
5516 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( gt, > )
5517 CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR( ge, >= )
5518
5519 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_COMPARISON_OPERATOR
5520
5521
5522#define CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR( op ) \
5523 template <typename RhsT> \
5524 constexpr friend auto operator op( ExprLhs&& lhs, RhsT&& rhs ) \
5525 -> std::enable_if_t< \
5526 !capture_by_value<Detail::RemoveCVRef_t<RhsT>>::value, \
5527 BinaryExpr<LhsT, RhsT const&>> { \
5528 return { \
5529 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5530 } \
5531 template <typename RhsT> \
5532 constexpr friend auto operator op( ExprLhs&& lhs, RhsT rhs ) \
5533 -> std::enable_if_t<capture_by_value<RhsT>::value, \
5534 BinaryExpr<LhsT, RhsT>> { \
5535 return { \
5536 static_cast<bool>( lhs.m_lhs op rhs ), lhs.m_lhs, #op##_sr, rhs }; \
5537 }
5538
5539 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(|)
5540 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(&)
5541 CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR(^)
5542
5543 #undef CATCH_INTERNAL_DEFINE_EXPRESSION_OPERATOR
5544
5545 template<typename RhsT>
5546 friend auto operator && ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
5547 static_assert(always_false<RhsT>::value,
5548 "operator&& is not supported inside assertions, "
5549 "wrap the expression inside parentheses, or decompose it");
5550 }
5551
5552 template<typename RhsT>
5553 friend auto operator || ( ExprLhs &&, RhsT && ) -> BinaryExpr<LhsT, RhsT const&> {
5554 static_assert(always_false<RhsT>::value,
5555 "operator|| is not supported inside assertions, "
5556 "wrap the expression inside parentheses, or decompose it");
5557 }
5558
5559 constexpr auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
5560 return UnaryExpr<LhsT>{ m_lhs };
5561 }
5562 };
5563
5564 struct Decomposer {
5565 template <typename T,
5566 std::enable_if_t<!capture_by_value<Detail::RemoveCVRef_t<T>>::value,
5567 int> = 0>
5568 constexpr friend auto operator <= ( Decomposer &&, T && lhs ) -> ExprLhs<T const&> {
5569 return ExprLhs<const T&>{ lhs };
5570 }
5571
5572 template <typename T,
5573 std::enable_if_t<capture_by_value<T>::value, int> = 0>
5574 constexpr friend auto operator <= ( Decomposer &&, T value ) -> ExprLhs<T> {
5575 return ExprLhs<T>{ value };
5576 }
5577 };
5578
5579} // end namespace Catch
5580
5581#ifdef _MSC_VER
5582#pragma warning(pop)
5583#endif
5584#ifdef __clang__
5585# pragma clang diagnostic pop
5586#elif defined __GNUC__
5587# pragma GCC diagnostic pop
5588#endif
5589
5590#endif // CATCH_DECOMPOSER_HPP_INCLUDED
5591
5592#include <string>
5593
5594namespace Catch {
5595
5596 struct AssertionReaction {
5597 bool shouldDebugBreak = false;
5598 bool shouldThrow = false;
5599 bool shouldSkip = false;
5600 };
5601
5602 class AssertionHandler {
5603 AssertionInfo m_assertionInfo;
5604 AssertionReaction m_reaction;
5605 bool m_completed = false;
5606 IResultCapture& m_resultCapture;
5607
5608 public:
5609 AssertionHandler
5610 ( StringRef macroName,
5611 SourceLineInfo const& lineInfo,
5612 StringRef capturedExpression,
5613 ResultDisposition::Flags resultDisposition );
5614 ~AssertionHandler() {
5615 if ( !m_completed ) {
5616 m_resultCapture.handleIncomplete( m_assertionInfo );
5617 }
5618 }
5619
5620
5621 template<typename T>
5622 void handleExpr( ExprLhs<T> const& expr ) {
5623 handleExpr( expr.makeUnaryExpr() );
5624 }
5625 void handleExpr( ITransientExpression const& expr );
5626
5627 void handleMessage(ResultWas::OfType resultType, StringRef message);
5628
5629 void handleExceptionThrownAsExpected();
5630 void handleUnexpectedExceptionNotThrown();
5631 void handleExceptionNotThrownAsExpected();
5632 void handleThrowingCallSkipped();
5633 void handleUnexpectedInflightException();
5634
5635 void complete();
5636
5637 // query
5638 auto allowThrows() const -> bool;
5639 };
5640
5641 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str );
5642
5643} // namespace Catch
5644
5645#endif // CATCH_ASSERTION_HANDLER_HPP_INCLUDED
5646
5647
5648#ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
5649#define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
5650
5651
5652#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
5653 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr
5654#else
5655 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr
5656#endif
5657
5658#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED
5659
5660// We need this suppression to leak, because it took until GCC 10
5661// for the front end to handle local suppression via _Pragma properly
5662#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && __GNUC__ <= 9
5663 #pragma GCC diagnostic ignored "-Wparentheses"
5664#endif
5665
5666#if !defined(CATCH_CONFIG_DISABLE)
5667
5668#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
5669
5670///////////////////////////////////////////////////////////////////////////////
5671// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
5672// macros.
5673#define INTERNAL_CATCH_TRY
5674#define INTERNAL_CATCH_CATCH( capturer )
5675
5676#else // CATCH_CONFIG_FAST_COMPILE
5677
5678#define INTERNAL_CATCH_TRY try
5679#define INTERNAL_CATCH_CATCH( handler ) catch(...) { (handler).handleUnexpectedInflightException(); }
5680
5681#endif
5682
5683#define INTERNAL_CATCH_REACT( handler ) handler.complete();
5684
5685///////////////////////////////////////////////////////////////////////////////
5686#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
5687 do { /* NOLINT(bugprone-infinite-loop) */ \
5688 /* The expression should not be evaluated, but warnings should hopefully be checked */ \
5689 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
5690 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
5691 INTERNAL_CATCH_TRY { \
5692 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5693 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
5694 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); /* NOLINT(bugprone-chained-comparison) */ \
5695 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5696 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
5697 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
5698 } 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
5699 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
5700
5701///////////////////////////////////////////////////////////////////////////////
5702#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
5703 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
5704 if( Catch::getResultCapture().lastAssertionPassed() )
5705
5706///////////////////////////////////////////////////////////////////////////////
5707#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
5708 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
5709 if( !Catch::getResultCapture().lastAssertionPassed() )
5710
5711///////////////////////////////////////////////////////////////////////////////
5712#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
5713 do { \
5714 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
5715 try { \
5716 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5717 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5718 static_cast<void>(__VA_ARGS__); \
5719 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5720 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
5721 } \
5722 catch( ... ) { \
5723 catchAssertionHandler.handleUnexpectedInflightException(); \
5724 } \
5725 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
5726 } while( false )
5727
5728///////////////////////////////////////////////////////////////////////////////
5729#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
5730 do { \
5731 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
5732 if( catchAssertionHandler.allowThrows() ) \
5733 try { \
5734 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5735 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
5736 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5737 static_cast<void>(__VA_ARGS__); \
5738 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5739 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
5740 } \
5741 catch( ... ) { \
5742 catchAssertionHandler.handleExceptionThrownAsExpected(); \
5743 } \
5744 else \
5745 catchAssertionHandler.handleThrowingCallSkipped(); \
5746 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
5747 } while( false )
5748
5749///////////////////////////////////////////////////////////////////////////////
5750#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
5751 do { \
5752 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
5753 if( catchAssertionHandler.allowThrows() ) \
5754 try { \
5755 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5756 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
5757 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5758 static_cast<void>(expr); \
5759 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5760 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
5761 } \
5762 catch( exceptionType const& ) { \
5763 catchAssertionHandler.handleExceptionThrownAsExpected(); \
5764 } \
5765 catch( ... ) { \
5766 catchAssertionHandler.handleUnexpectedInflightException(); \
5767 } \
5768 else \
5769 catchAssertionHandler.handleThrowingCallSkipped(); \
5770 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
5771 } while( false )
5772
5773
5774
5775///////////////////////////////////////////////////////////////////////////////
5776// Although this is matcher-based, it can be used with just a string
5777#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
5778 do { \
5779 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
5780 if( catchAssertionHandler.allowThrows() ) \
5781 try { \
5782 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5783 CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \
5784 CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \
5785 static_cast<void>(__VA_ARGS__); \
5786 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
5787 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
5788 } \
5789 catch( ... ) { \
5790 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher ); \
5791 } \
5792 else \
5793 catchAssertionHandler.handleThrowingCallSkipped(); \
5794 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
5795 } while( false )
5796
5797#endif // CATCH_CONFIG_DISABLE
5798
5799#endif // CATCH_TEST_MACRO_IMPL_HPP_INCLUDED
5800
5801
5802#ifndef CATCH_SECTION_HPP_INCLUDED
5803#define CATCH_SECTION_HPP_INCLUDED
5804
5805
5806
5807
5808/** \file
5809 * Wrapper for the STATIC_ANALYSIS_SUPPORT configuration option
5810 *
5811 * Some of Catch2's macros can be defined differently to work better with
5812 * static analysis tools, like clang-tidy or coverity.
5813 * Currently the main use case is to show that `SECTION`s are executed
5814 * exclusively, and not all in one run of a `TEST_CASE`.
5815 */
5816
5817#ifndef CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
5818#define CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
5819
5820
5821#if defined(__clang_analyzer__) || defined(__COVERITY__)
5822 #define CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT
5823#endif
5824
5825#if defined( CATCH_INTERNAL_CONFIG_STATIC_ANALYSIS_SUPPORT ) && \
5826 !defined( CATCH_CONFIG_NO_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT ) && \
5827 !defined( CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT )
5828# define CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
5829#endif
5830
5831
5832#endif // CATCH_CONFIG_STATIC_ANALYSIS_SUPPORT_HPP_INCLUDED
5833
5834
5835#ifndef CATCH_TIMER_HPP_INCLUDED
5836#define CATCH_TIMER_HPP_INCLUDED
5837
5838#include <cstdint>
5839
5840namespace Catch {
5841
5842 class Timer {
5843 uint64_t m_nanoseconds = 0;
5844 public:
5845 void start();
5846 auto getElapsedNanoseconds() const -> uint64_t;
5847 auto getElapsedMicroseconds() const -> uint64_t;
5848 auto getElapsedMilliseconds() const -> unsigned int;
5849 auto getElapsedSeconds() const -> double;
5850 };
5851
5852} // namespace Catch
5853
5854#endif // CATCH_TIMER_HPP_INCLUDED
5855
5856namespace Catch {
5857
5858 class Section : Detail::NonCopyable {
5859 public:
5860 Section( SectionInfo&& info );
5861 Section( SourceLineInfo const& _lineInfo,
5862 StringRef _name,
5863 const char* const = nullptr );
5864 ~Section();
5865
5866 // This indicates whether the section should be executed or not
5867 explicit operator bool() const;
5868
5869 private:
5870 SectionInfo m_info;
5871
5872 Counts m_assertions;
5873 bool m_sectionIncluded;
5874 Timer m_timer;
5875 };
5876
5877} // end namespace Catch
5878
5879#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
5880# define INTERNAL_CATCH_SECTION( ... ) \
5881 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5882 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5883 if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \
5884 catch_internal_Section ) = \
5885 Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
5886 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5887
5888# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
5889 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5890 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5891 if ( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( \
5892 catch_internal_Section ) = \
5893 Catch::SectionInfo( \
5894 CATCH_INTERNAL_LINEINFO, \
5895 ( Catch::ReusableStringStream() << __VA_ARGS__ ) \
5896 .str() ) ) \
5897 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5898
5899#else
5900
5901// These section definitions imply that at most one section at one level
5902// will be intered (because only one section's __LINE__ can be equal to
5903// the dummy `catchInternalSectionHint` variable from `TEST_CASE`).
5904
5905namespace Catch {
5906 namespace Detail {
5907 // Intentionally without linkage, as it should only be used as a dummy
5908 // symbol for static analysis.
5909 // The arguments are used as a dummy for checking warnings in the passed
5910 // expressions.
5911 int GetNewSectionHint( StringRef, const char* const = nullptr );
5912 } // namespace Detail
5913} // namespace Catch
5914
5915
5916# define INTERNAL_CATCH_SECTION( ... ) \
5917 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5918 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5919 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
5920 if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
5921 catchInternalSectionHint, \
5922 catchInternalSectionHint = \
5923 Catch::Detail::GetNewSectionHint(__VA_ARGS__); \
5924 catchInternalPreviousSectionHint == __LINE__ ) \
5925 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5926
5927# define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
5928 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
5929 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
5930 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
5931 if ( [[maybe_unused]] const int catchInternalPreviousSectionHint = \
5932 catchInternalSectionHint, \
5933 catchInternalSectionHint = Catch::Detail::GetNewSectionHint( \
5934 ( Catch::ReusableStringStream() << __VA_ARGS__ ).str()); \
5935 catchInternalPreviousSectionHint == __LINE__ ) \
5936 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
5937
5938#endif
5939
5940
5941#endif // CATCH_SECTION_HPP_INCLUDED
5942
5943
5944#ifndef CATCH_TEST_REGISTRY_HPP_INCLUDED
5945#define CATCH_TEST_REGISTRY_HPP_INCLUDED
5946
5947
5948
5949#ifndef CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
5950#define CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
5951
5952namespace Catch {
5953
5954 class ITestInvoker {
5955 public:
5956 virtual void invoke() const = 0;
5957 virtual ~ITestInvoker(); // = default
5958 };
5959
5960} // namespace Catch
5961
5962#endif // CATCH_INTERFACES_TEST_INVOKER_HPP_INCLUDED
5963
5964
5965#ifndef CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
5966#define CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
5967
5968#define INTERNAL_CATCH_EXPAND1( param ) INTERNAL_CATCH_EXPAND2( param )
5969#define INTERNAL_CATCH_EXPAND2( ... ) INTERNAL_CATCH_NO##__VA_ARGS__
5970#define INTERNAL_CATCH_DEF( ... ) INTERNAL_CATCH_DEF __VA_ARGS__
5971#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
5972
5973#define INTERNAL_CATCH_REMOVE_PARENS( ... ) \
5974 INTERNAL_CATCH_EXPAND1( INTERNAL_CATCH_DEF __VA_ARGS__ )
5975
5976#endif // CATCH_PREPROCESSOR_REMOVE_PARENS_HPP_INCLUDED
5977
5978// GCC 5 and older do not properly handle disabling unused-variable warning
5979// with a _Pragma. This means that we have to leak the suppression to the
5980// user code as well :-(
5981#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
5982#pragma GCC diagnostic ignored "-Wunused-variable"
5983#endif
5984
5985
5986
5987namespace Catch {
5988
5989template<typename C>
5990class TestInvokerAsMethod : public ITestInvoker {
5991 void (C::*m_testAsMethod)();
5992public:
5993 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
5994
5995 void invoke() const override {
5996 C obj;
5997 (obj.*m_testAsMethod)();
5998 }
5999};
6000
6001Detail::unique_ptr<ITestInvoker> makeTestInvoker( void(*testAsFunction)() );
6002
6003template<typename C>
6004Detail::unique_ptr<ITestInvoker> makeTestInvoker( void (C::*testAsMethod)() ) {
6005 return Detail::make_unique<TestInvokerAsMethod<C>>( testAsMethod );
6006}
6007
6008struct NameAndTags {
6009 constexpr NameAndTags( StringRef name_ = StringRef(),
6010 StringRef tags_ = StringRef() ) noexcept:
6011 name( name_ ), tags( tags_ ) {}
6012 StringRef name;
6013 StringRef tags;
6014};
6015
6016struct AutoReg : Detail::NonCopyable {
6017 AutoReg( Detail::unique_ptr<ITestInvoker> invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
6018};
6019
6020} // end namespace Catch
6021
6022#if defined(CATCH_CONFIG_DISABLE)
6023 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
6024 static inline void TestName()
6025 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
6026 namespace{ \
6027 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
6028 void test(); \
6029 }; \
6030 } \
6031 void TestName::test()
6032#endif
6033
6034
6035#if !defined(CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT)
6036
6037 ///////////////////////////////////////////////////////////////////////////////
6038 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
6039 static void TestName(); \
6040 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6041 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6042 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6043 namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
6044 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6045 static void TestName()
6046 #define INTERNAL_CATCH_TESTCASE( ... ) \
6047 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__ )
6048
6049#else // ^^ !CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT | vv CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
6050
6051
6052// Dummy registrator for the dumy test case macros
6053namespace Catch {
6054 namespace Detail {
6055 struct DummyUse {
6056 DummyUse( void ( * )( int ), Catch::NameAndTags const& );
6057 };
6058 } // namespace Detail
6059} // namespace Catch
6060
6061// Note that both the presence of the argument and its exact name are
6062// necessary for the section support.
6063
6064// We provide a shadowed variable so that a `SECTION` inside non-`TEST_CASE`
6065// tests can compile. The redefined `TEST_CASE` shadows this with param.
6066static int catchInternalSectionHint = 0;
6067
6068# define INTERNAL_CATCH_TESTCASE2( fname, ... ) \
6069 static void fname( int ); \
6070 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6071 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6072 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6073 static const Catch::Detail::DummyUse INTERNAL_CATCH_UNIQUE_NAME( \
6074 dummyUser )( &(fname), Catch::NameAndTags{ __VA_ARGS__ } ); \
6075 CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \
6076 static void fname( [[maybe_unused]] int catchInternalSectionHint ) \
6077 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6078# define INTERNAL_CATCH_TESTCASE( ... ) \
6079 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( dummyFunction ), __VA_ARGS__ )
6080
6081
6082#endif // CATCH_CONFIG_EXPERIMENTAL_STATIC_ANALYSIS_SUPPORT
6083
6084 ///////////////////////////////////////////////////////////////////////////////
6085 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
6086 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6087 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6088 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6089 namespace{ \
6090 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
6091 void test(); \
6092 }; \
6093 const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
6094 Catch::makeTestInvoker( &TestName::test ), \
6095 CATCH_INTERNAL_LINEINFO, \
6096 #ClassName##_catch_sr, \
6097 Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
6098 } \
6099 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6100 void TestName::test()
6101 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
6102 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), ClassName, __VA_ARGS__ )
6103
6104
6105 ///////////////////////////////////////////////////////////////////////////////
6106 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
6107 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6108 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6109 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6110 namespace { \
6111 const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( \
6112 Catch::makeTestInvoker( &QualifiedMethod ), \
6113 CATCH_INTERNAL_LINEINFO, \
6114 "&" #QualifiedMethod##_catch_sr, \
6115 Catch::NameAndTags{ __VA_ARGS__ } ); \
6116 } /* NOLINT */ \
6117 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6118
6119
6120 ///////////////////////////////////////////////////////////////////////////////
6121 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
6122 do { \
6123 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6124 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6125 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6126 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
6127 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6128 } while(false)
6129
6130
6131#endif // CATCH_TEST_REGISTRY_HPP_INCLUDED
6132
6133
6134// All of our user-facing macros support configuration toggle, that
6135// forces them to be defined prefixed with CATCH_. We also like to
6136// support another toggle that can minimize (disable) their implementation.
6137// Given this, we have 4 different configuration options below
6138
6139#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
6140
6141 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6142 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6143
6144 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6145 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
6146 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6147
6148 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6149 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6150 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6151 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6152 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6153
6154 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6155 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
6156 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6157
6158 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
6159 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
6160 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
6161 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
6162 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
6163 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
6164 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6165 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6166 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6167 #define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6168
6169
6170 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
6171 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
6172 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
6173 #define CATCH_STATIC_CHECK( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
6174 #define CATCH_STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
6175 #else
6176 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ )
6177 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
6178 #define CATCH_STATIC_CHECK( ... ) CATCH_CHECK( __VA_ARGS__ )
6179 #define CATCH_STATIC_CHECK_FALSE( ... ) CATCH_CHECK_FALSE( __VA_ARGS__ )
6180 #endif
6181
6182
6183 // "BDD-style" convenience wrappers
6184 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
6185 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
6186 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
6187 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
6188 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
6189 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
6190 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
6191 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
6192
6193#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, implemented | vv prefixed, disabled
6194
6195 #define CATCH_REQUIRE( ... ) (void)(0)
6196 #define CATCH_REQUIRE_FALSE( ... ) (void)(0)
6197
6198 #define CATCH_REQUIRE_THROWS( ... ) (void)(0)
6199 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
6200 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
6201
6202 #define CATCH_CHECK( ... ) (void)(0)
6203 #define CATCH_CHECK_FALSE( ... ) (void)(0)
6204 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
6205 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
6206 #define CATCH_CHECK_NOFAIL( ... ) (void)(0)
6207
6208 #define CATCH_CHECK_THROWS( ... ) (void)(0)
6209 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
6210 #define CATCH_CHECK_NOTHROW( ... ) (void)(0)
6211
6212 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6213 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6214 #define CATCH_METHOD_AS_TEST_CASE( method, ... )
6215 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
6216 #define CATCH_SECTION( ... )
6217 #define CATCH_DYNAMIC_SECTION( ... )
6218 #define CATCH_FAIL( ... ) (void)(0)
6219 #define CATCH_FAIL_CHECK( ... ) (void)(0)
6220 #define CATCH_SUCCEED( ... ) (void)(0)
6221 #define CATCH_SKIP( ... ) (void)(0)
6222
6223 #define CATCH_STATIC_REQUIRE( ... ) (void)(0)
6224 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
6225 #define CATCH_STATIC_CHECK( ... ) (void)(0)
6226 #define CATCH_STATIC_CHECK_FALSE( ... ) (void)(0)
6227
6228 // "BDD-style" convenience wrappers
6229 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6230 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
6231 #define CATCH_GIVEN( desc )
6232 #define CATCH_AND_GIVEN( desc )
6233 #define CATCH_WHEN( desc )
6234 #define CATCH_AND_WHEN( desc )
6235 #define CATCH_THEN( desc )
6236 #define CATCH_AND_THEN( desc )
6237
6238#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) // ^^ prefixed, disabled | vv unprefixed, implemented
6239
6240 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6241 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6242
6243 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6244 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
6245 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
6246
6247 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6248 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
6249 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6250 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6251 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
6252
6253 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6254 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
6255 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6256
6257 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
6258 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
6259 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
6260 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
6261 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
6262 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
6263 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6264 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6265 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
6266 #define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ )
6267
6268
6269 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
6270 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
6271 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
6272 #define STATIC_CHECK( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
6273 #define STATIC_CHECK_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
6274 #else
6275 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ )
6276 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
6277 #define STATIC_CHECK( ... ) CHECK( __VA_ARGS__ )
6278 #define STATIC_CHECK_FALSE( ... ) CHECK_FALSE( __VA_ARGS__ )
6279 #endif
6280
6281 // "BDD-style" convenience wrappers
6282 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
6283 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
6284 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
6285 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
6286 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
6287 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
6288 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
6289 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
6290
6291#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) // ^^ unprefixed, implemented | vv unprefixed, disabled
6292
6293 #define REQUIRE( ... ) (void)(0)
6294 #define REQUIRE_FALSE( ... ) (void)(0)
6295
6296 #define REQUIRE_THROWS( ... ) (void)(0)
6297 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
6298 #define REQUIRE_NOTHROW( ... ) (void)(0)
6299
6300 #define CHECK( ... ) (void)(0)
6301 #define CHECK_FALSE( ... ) (void)(0)
6302 #define CHECKED_IF( ... ) if (__VA_ARGS__)
6303 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
6304 #define CHECK_NOFAIL( ... ) (void)(0)
6305
6306 #define CHECK_THROWS( ... ) (void)(0)
6307 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
6308 #define CHECK_NOTHROW( ... ) (void)(0)
6309
6310 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), __VA_ARGS__)
6311 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ))
6312 #define METHOD_AS_TEST_CASE( method, ... )
6313 #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
6314 #define SECTION( ... )
6315 #define DYNAMIC_SECTION( ... )
6316 #define FAIL( ... ) (void)(0)
6317 #define FAIL_CHECK( ... ) (void)(0)
6318 #define SUCCEED( ... ) (void)(0)
6319 #define SKIP( ... ) (void)(0)
6320
6321 #define STATIC_REQUIRE( ... ) (void)(0)
6322 #define STATIC_REQUIRE_FALSE( ... ) (void)(0)
6323 #define STATIC_CHECK( ... ) (void)(0)
6324 #define STATIC_CHECK_FALSE( ... ) (void)(0)
6325
6326 // "BDD-style" convenience wrappers
6327 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ) )
6328 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className )
6329
6330 #define GIVEN( desc )
6331 #define AND_GIVEN( desc )
6332 #define WHEN( desc )
6333 #define AND_WHEN( desc )
6334 #define THEN( desc )
6335 #define AND_THEN( desc )
6336
6337#endif // ^^ unprefixed, disabled
6338
6339// end of user facing macros
6340
6341#endif // CATCH_TEST_MACROS_HPP_INCLUDED
6342
6343
6344#ifndef CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
6345#define CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
6346
6347
6348
6349#ifndef CATCH_PREPROCESSOR_HPP_INCLUDED
6350#define CATCH_PREPROCESSOR_HPP_INCLUDED
6351
6352
6353#if defined(__GNUC__)
6354// We need to silence "empty __VA_ARGS__ warning", and using just _Pragma does not work
6355#pragma GCC system_header
6356#endif
6357
6358
6359#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
6360#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
6361#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
6362#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
6363#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
6364#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
6365
6366#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6367#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
6368// MSVC needs more evaluations
6369#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
6370#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
6371#else
6372#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
6373#endif
6374
6375#define CATCH_REC_END(...)
6376#define CATCH_REC_OUT
6377
6378#define CATCH_EMPTY()
6379#define CATCH_DEFER(id) id CATCH_EMPTY()
6380
6381#define CATCH_REC_GET_END2() 0, CATCH_REC_END
6382#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
6383#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
6384#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
6385#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
6386#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
6387
6388#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
6389#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
6390#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
6391
6392#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__ )
6393#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__ )
6394#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__ )
6395
6396// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
6397// and passes userdata as the first parameter to each invocation,
6398// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
6399#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
6400
6401#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
6402
6403#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
6404#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6405#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
6406#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
6407#else
6408// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
6409#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
6410#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
6411#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
6412#endif
6413
6414#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
6415#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
6416
6417#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6418#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
6419#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
6420#else
6421#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
6422#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
6423#endif
6424
6425#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
6426 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
6427
6428#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
6429#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
6430#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
6431#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)
6432#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)
6433#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)
6434#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)
6435#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)
6436#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)
6437#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)
6438#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)
6439
6440#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
6441
6442#define INTERNAL_CATCH_TYPE_GEN\
6443 template<typename...> struct TypeList {};\
6444 template<typename...Ts>\
6445 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
6446 template<template<typename...> class...> struct TemplateTypeList{};\
6447 template<template<typename...> class...Cs>\
6448 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
6449 template<typename...>\
6450 struct append;\
6451 template<typename...>\
6452 struct rewrap;\
6453 template<template<typename...> class, typename...>\
6454 struct create;\
6455 template<template<typename...> class, typename>\
6456 struct convert;\
6457 \
6458 template<typename T> \
6459 struct append<T> { using type = T; };\
6460 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
6461 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
6462 template< template<typename...> class L1, typename...E1, typename...Rest>\
6463 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
6464 \
6465 template< template<typename...> class Container, template<typename...> class List, typename...elems>\
6466 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
6467 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
6468 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
6469 \
6470 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
6471 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
6472 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
6473 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
6474
6475#define INTERNAL_CATCH_NTTP_1(signature, ...)\
6476 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
6477 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6478 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
6479 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
6480 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
6481 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
6482 \
6483 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6484 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
6485 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
6486 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
6487 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
6488 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
6489
6490#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
6491#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
6492 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6493 static void TestName()
6494#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
6495 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6496 static void TestName()
6497
6498#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
6499#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
6500 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6501 static void TestName()
6502#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
6503 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6504 static void TestName()
6505
6506#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
6507 template<typename Type>\
6508 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
6509 {\
6510 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
6511 }
6512
6513#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
6514 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6515 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
6516 {\
6517 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
6518 }
6519
6520#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
6521 template<typename Type>\
6522 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
6523 {\
6524 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
6525 }
6526
6527#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
6528 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
6529 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
6530 {\
6531 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
6532 }
6533
6534#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
6535#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
6536 template<typename TestType> \
6537 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
6538 void test();\
6539 }
6540
6541#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
6542 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
6543 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
6544 void test();\
6545 }
6546
6547#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
6548#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
6549 template<typename TestType> \
6550 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
6551#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
6552 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
6553 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
6554
6555#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6556#define INTERNAL_CATCH_NTTP_0
6557#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)
6558#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__)
6559#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__)
6560#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__)
6561#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__)
6562#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__)
6563#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__)
6564#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__)
6565#else
6566#define INTERNAL_CATCH_NTTP_0(signature)
6567#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__))
6568#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__))
6569#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__))
6570#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__))
6571#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__))
6572#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__))
6573#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__))
6574#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__))
6575#endif
6576
6577#endif // CATCH_PREPROCESSOR_HPP_INCLUDED
6578
6579
6580// GCC 5 and older do not properly handle disabling unused-variable warning
6581// with a _Pragma. This means that we have to leak the suppression to the
6582// user code as well :-(
6583#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 5
6584#pragma GCC diagnostic ignored "-Wunused-variable"
6585#endif
6586
6587#if defined(CATCH_CONFIG_DISABLE)
6588 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \
6589 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
6590 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
6591 namespace{ \
6592 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
6593 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
6594 } \
6595 } \
6596 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
6597
6598 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6599 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
6600 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__ )
6601 #else
6602 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
6603 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__ ) )
6604 #endif
6605
6606 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6607 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
6608 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__ )
6609 #else
6610 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
6611 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__ ) )
6612 #endif
6613
6614 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6615 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
6616 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__ )
6617 #else
6618 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
6619 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__ ) )
6620 #endif
6621
6622 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6623 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
6624 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__ )
6625 #else
6626 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
6627 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__ ) )
6628 #endif
6629#endif
6630
6631
6632 ///////////////////////////////////////////////////////////////////////////////
6633 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
6634 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6635 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6636 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6637 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6638 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6639 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6640 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
6641 namespace {\
6642 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
6643 INTERNAL_CATCH_TYPE_GEN\
6644 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6645 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6646 template<typename...Types> \
6647 struct TestName{\
6648 TestName(){\
6649 size_t index = 0; \
6650 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) */\
6651 using expander = size_t[]; /* NOLINT(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,hicpp-avoid-c-arrays) */\
6652 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
6653 }\
6654 };\
6655 static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6656 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
6657 return 0;\
6658 }();\
6659 }\
6660 }\
6661 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6662 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
6663
6664#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6665 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
6666 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__ )
6667#else
6668 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
6669 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__ ) )
6670#endif
6671
6672#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6673 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
6674 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__ )
6675#else
6676 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
6677 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__ ) )
6678#endif
6679
6680 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
6681 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6682 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6683 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6684 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6685 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6686 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6687 template<typename TestType> static void TestFuncName(); \
6688 namespace {\
6689 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
6690 INTERNAL_CATCH_TYPE_GEN \
6691 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
6692 template<typename... Types> \
6693 struct TestName { \
6694 void reg_tests() { \
6695 size_t index = 0; \
6696 using expander = size_t[]; \
6697 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
6698 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
6699 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
6700 (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 */\
6701 } \
6702 }; \
6703 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
6704 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; \
6705 TestInit t; \
6706 t.reg_tests(); \
6707 return 0; \
6708 }(); \
6709 } \
6710 } \
6711 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6712 template<typename TestType> \
6713 static void TestFuncName()
6714
6715#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6716 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
6717 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__)
6718#else
6719 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
6720 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__ ) )
6721#endif
6722
6723#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6724 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
6725 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__)
6726#else
6727 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
6728 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__ ) )
6729#endif
6730
6731 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
6732 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6733 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6734 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6735 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6736 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6737 template<typename TestType> static void TestFunc(); \
6738 namespace {\
6739 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
6740 INTERNAL_CATCH_TYPE_GEN\
6741 template<typename... Types> \
6742 struct TestName { \
6743 void reg_tests() { \
6744 size_t index = 0; \
6745 using expander = size_t[]; \
6746 (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 */\
6747 } \
6748 };\
6749 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
6750 using TestInit = typename convert<TestName, TmplList>::type; \
6751 TestInit t; \
6752 t.reg_tests(); \
6753 return 0; \
6754 }(); \
6755 }}\
6756 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6757 template<typename TestType> \
6758 static void TestFunc()
6759
6760 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
6761 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 )
6762
6763
6764 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
6765 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6766 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6767 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6768 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6769 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6770 namespace {\
6771 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
6772 INTERNAL_CATCH_TYPE_GEN\
6773 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6774 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
6775 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6776 template<typename...Types> \
6777 struct TestNameClass{\
6778 TestNameClass(){\
6779 size_t index = 0; \
6780 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
6781 using expander = size_t[];\
6782 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
6783 }\
6784 };\
6785 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6786 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
6787 return 0;\
6788 }();\
6789 }\
6790 }\
6791 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6792 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
6793
6794#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6795 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
6796 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__ )
6797#else
6798 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
6799 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__ ) )
6800#endif
6801
6802#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6803 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
6804 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__ )
6805#else
6806 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
6807 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__ ) )
6808#endif
6809
6810 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
6811 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6812 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6813 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
6814 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6815 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6816 template<typename TestType> \
6817 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
6818 void test();\
6819 };\
6820 namespace {\
6821 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
6822 INTERNAL_CATCH_TYPE_GEN \
6823 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
6824 template<typename...Types>\
6825 struct TestNameClass{\
6826 void reg_tests(){\
6827 std::size_t index = 0;\
6828 using expander = std::size_t[];\
6829 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
6830 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
6831 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
6832 (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 */ \
6833 }\
6834 };\
6835 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6836 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;\
6837 TestInit t;\
6838 t.reg_tests();\
6839 return 0;\
6840 }(); \
6841 }\
6842 }\
6843 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6844 template<typename TestType> \
6845 void TestName<TestType>::test()
6846
6847#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6848 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
6849 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__ )
6850#else
6851 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
6852 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__ ) )
6853#endif
6854
6855#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6856 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
6857 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__ )
6858#else
6859 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
6860 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__ ) )
6861#endif
6862
6863 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
6864 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6865 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6866 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
6867 CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \
6868 CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \
6869 template<typename TestType> \
6870 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
6871 void test();\
6872 };\
6873 namespace {\
6874 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
6875 INTERNAL_CATCH_TYPE_GEN\
6876 template<typename...Types>\
6877 struct TestNameClass{\
6878 void reg_tests(){\
6879 size_t index = 0;\
6880 using expander = size_t[];\
6881 (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 */ \
6882 }\
6883 };\
6884 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
6885 using TestInit = typename convert<TestNameClass, TmplList>::type;\
6886 TestInit t;\
6887 t.reg_tests();\
6888 return 0;\
6889 }(); \
6890 }}\
6891 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
6892 template<typename TestType> \
6893 void TestName<TestType>::test()
6894
6895#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
6896 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 )
6897
6898
6899#endif // CATCH_TEMPLATE_TEST_REGISTRY_HPP_INCLUDED
6900
6901
6902#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
6903
6904 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6905 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
6906 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
6907 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6908 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
6909 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
6910 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
6911 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
6912 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
6913 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
6914 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
6915 #else
6916 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
6917 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
6918 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6919 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
6920 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
6921 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
6922 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6923 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
6924 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
6925 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6926 #endif
6927
6928#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
6929
6930 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6931 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
6932 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
6933 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
6934 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
6935 #else
6936 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
6937 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
6938 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
6939 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
6940 #endif
6941
6942 // When disabled, these can be shared between proper preprocessor and MSVC preprocessor
6943 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
6944 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
6945 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6946 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6947 #define CATCH_TEMPLATE_LIST_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
6948 #define CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6949
6950#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
6951
6952 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
6953 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
6954 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
6955 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6956 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
6957 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
6958 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
6959 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
6960 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
6961 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
6962 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
6963 #else
6964 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
6965 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
6966 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6967 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
6968 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
6969 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
6970 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
6971 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
6972 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
6973 #define 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 TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
6980 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
6981 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
6982 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
6983 #else
6984 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
6985 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
6986 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
6987 #define 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 TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
6992 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
6993 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6994 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6995 #define TEMPLATE_LIST_TEST_CASE( ... ) TEMPLATE_TEST_CASE(__VA_ARGS__)
6996 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
6997
6998#endif // end of user facing macro declarations
6999
7000
7001#endif // CATCH_TEMPLATE_TEST_MACROS_HPP_INCLUDED
7002
7003
7004#ifndef CATCH_TEST_CASE_INFO_HPP_INCLUDED
7005#define CATCH_TEST_CASE_INFO_HPP_INCLUDED
7006
7007
7008
7009#include <cstdint>
7010#include <string>
7011#include <vector>
7012
7013#ifdef __clang__
7014#pragma clang diagnostic push
7015#pragma clang diagnostic ignored "-Wpadded"
7016#endif
7017
7018namespace Catch {
7019
7020 /**
7021 * A **view** of a tag string that provides case insensitive comparisons
7022 *
7023 * Note that in Catch2 internals, the square brackets around tags are
7024 * not a part of tag's representation, so e.g. "[cool-tag]" is represented
7025 * as "cool-tag" internally.
7026 */
7027 struct Tag {
7028 constexpr Tag(StringRef original_):
7029 original(original_)
7030 {}
7031 StringRef original;
7032
7033 friend bool operator< ( Tag const& lhs, Tag const& rhs );
7034 friend bool operator==( Tag const& lhs, Tag const& rhs );
7035 };
7036
7037 class ITestInvoker;
7038 struct NameAndTags;
7039
7040 enum class TestCaseProperties : uint8_t {
7041 None = 0,
7042 IsHidden = 1 << 1,
7043 ShouldFail = 1 << 2,
7044 MayFail = 1 << 3,
7045 Throws = 1 << 4,
7046 NonPortable = 1 << 5,
7047 Benchmark = 1 << 6
7048 };
7049
7050 /**
7051 * Various metadata about the test case.
7052 *
7053 * A test case is uniquely identified by its (class)name and tags
7054 * combination, with source location being ignored, and other properties
7055 * being determined from tags.
7056 *
7057 * Tags are kept sorted.
7058 */
7059 struct TestCaseInfo : Detail::NonCopyable {
7060
7061 TestCaseInfo(StringRef _className,
7062 NameAndTags const& _nameAndTags,
7063 SourceLineInfo const& _lineInfo);
7064
7065 bool isHidden() const;
7066 bool throws() const;
7067 bool okToFail() const;
7068 bool expectedToFail() const;
7069
7070 // Adds the tag(s) with test's filename (for the -# flag)
7071 void addFilenameTag();
7072
7073 //! Orders by name, classname and tags
7074 friend bool operator<( TestCaseInfo const& lhs,
7075 TestCaseInfo const& rhs );
7076
7077
7078 std::string tagsAsString() const;
7079
7080 std::string name;
7081 StringRef className;
7082 private:
7083 std::string backingTags;
7084 // Internally we copy tags to the backing storage and then add
7085 // refs to this storage to the tags vector.
7086 void internalAppendTag(StringRef tagString);
7087 public:
7088 std::vector<Tag> tags;
7089 SourceLineInfo lineInfo;
7090 TestCaseProperties properties = TestCaseProperties::None;
7091 };
7092
7093 /**
7094 * Wrapper over the test case information and the test case invoker
7095 *
7096 * Does not own either, and is specifically made to be cheap
7097 * to copy around.
7098 */
7099 class TestCaseHandle {
7100 TestCaseInfo* m_info;
7101 ITestInvoker* m_invoker;
7102 public:
7103 TestCaseHandle(TestCaseInfo* info, ITestInvoker* invoker) :
7104 m_info(info), m_invoker(invoker) {}
7105
7106 void invoke() const {
7107 m_invoker->invoke();
7108 }
7109
7110 TestCaseInfo const& getTestCaseInfo() const;
7111 };
7112
7113 Detail::unique_ptr<TestCaseInfo>
7114 makeTestCaseInfo( StringRef className,
7115 NameAndTags const& nameAndTags,
7116 SourceLineInfo const& lineInfo );
7117}
7118
7119#ifdef __clang__
7120#pragma clang diagnostic pop
7121#endif
7122
7123#endif // CATCH_TEST_CASE_INFO_HPP_INCLUDED
7124
7125
7126#ifndef CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
7127#define CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
7128
7129
7130
7131#ifndef CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
7132#define CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
7133
7134
7135#include <string>
7136#include <vector>
7137
7138namespace Catch {
7139 using exceptionTranslateFunction = std::string(*)();
7140
7141 class IExceptionTranslator;
7142 using ExceptionTranslators = std::vector<Detail::unique_ptr<IExceptionTranslator const>>;
7143
7144 class IExceptionTranslator {
7145 public:
7146 virtual ~IExceptionTranslator(); // = default
7147 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
7148 };
7149
7150 class IExceptionTranslatorRegistry {
7151 public:
7152 virtual ~IExceptionTranslatorRegistry(); // = default
7153 virtual std::string translateActiveException() const = 0;
7154 };
7155
7156} // namespace Catch
7157
7158#endif // CATCH_INTERFACES_EXCEPTION_HPP_INCLUDED
7159
7160#include <exception>
7161
7162namespace Catch {
7163 namespace Detail {
7164 void registerTranslatorImpl(
7165 Detail::unique_ptr<IExceptionTranslator>&& translator );
7166 }
7167
7168 class ExceptionTranslatorRegistrar {
7169 template<typename T>
7170 class ExceptionTranslator : public IExceptionTranslator {
7171 public:
7172
7173 ExceptionTranslator( std::string(*translateFunction)( T const& ) )
7174 : m_translateFunction( translateFunction )
7175 {}
7176
7177 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
7178#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
7179 try {
7180 if( it == itEnd )
7181 std::rethrow_exception(std::current_exception());
7182 else
7183 return (*it)->translate( it+1, itEnd );
7184 }
7185 catch( T const& ex ) {
7186 return m_translateFunction( ex );
7187 }
7188#else
7189 return "You should never get here!";
7190#endif
7191 }
7192
7193 protected:
7194 std::string(*m_translateFunction)( T const& );
7195 };
7196
7197 public:
7198 template<typename T>
7199 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T const& ) ) {
7200 Detail::registerTranslatorImpl(
7201 Detail::make_unique<ExceptionTranslator<T>>(
7202 translateFunction ) );
7203 }
7204 };
7205
7206} // namespace Catch
7207
7208///////////////////////////////////////////////////////////////////////////////
7209#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
7210 static std::string translatorName( signature ); \
7211 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
7212 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
7213 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
7214 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
7215 static std::string translatorName( signature )
7216
7217#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
7218
7219#if defined(CATCH_CONFIG_DISABLE)
7220 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
7221 static std::string translatorName( signature )
7222#endif
7223
7224
7225// This macro is always prefixed
7226#if !defined(CATCH_CONFIG_DISABLE)
7227#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
7228#else
7229#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
7230#endif
7231
7232
7233#endif // CATCH_TRANSLATE_EXCEPTION_HPP_INCLUDED
7234
7235
7236#ifndef CATCH_VERSION_HPP_INCLUDED
7237#define CATCH_VERSION_HPP_INCLUDED
7238
7239#include <iosfwd>
7240
7241namespace Catch {
7242
7243 // Versioning information
7244 struct Version {
7245 Version( Version const& ) = delete;
7246 Version& operator=( Version const& ) = delete;
7247 Version( unsigned int _majorVersion,
7248 unsigned int _minorVersion,
7249 unsigned int _patchNumber,
7250 char const * const _branchName,
7251 unsigned int _buildNumber );
7252
7253 unsigned int const majorVersion;
7254 unsigned int const minorVersion;
7255 unsigned int const patchNumber;
7256
7257 // buildNumber is only used if branchName is not null
7258 char const * const branchName;
7259 unsigned int const buildNumber;
7260
7261 friend std::ostream& operator << ( std::ostream& os, Version const& version );
7262 };
7263
7264 Version const& libraryVersion();
7265}
7266
7267#endif // CATCH_VERSION_HPP_INCLUDED
7268
7269
7270#ifndef CATCH_VERSION_MACROS_HPP_INCLUDED
7271#define CATCH_VERSION_MACROS_HPP_INCLUDED
7272
7273#define CATCH_VERSION_MAJOR 3
7274#define CATCH_VERSION_MINOR 6
7275#define CATCH_VERSION_PATCH 0
7276
7277#endif // CATCH_VERSION_MACROS_HPP_INCLUDED
7278
7279
7280/** \file
7281 * This is a convenience header for Catch2's Generator support. It includes
7282 * **all** of Catch2 headers related to generators.
7283 *
7284 * Generally the Catch2 users should use specific includes they need,
7285 * but this header can be used instead for ease-of-experimentation, or
7286 * just plain convenience, at the cost of (significantly) increased
7287 * compilation times.
7288 *
7289 * When a new header is added to either the `generators` folder,
7290 * or to the corresponding internal subfolder, it should be added here.
7291 */
7292
7293#ifndef CATCH_GENERATORS_ALL_HPP_INCLUDED
7294#define CATCH_GENERATORS_ALL_HPP_INCLUDED
7295
7296
7297
7298#ifndef CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
7299#define CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
7300
7301#include <exception>
7302
7303namespace Catch {
7304
7305 // Exception type to be thrown when a Generator runs into an error,
7306 // e.g. it cannot initialize the first return value based on
7307 // runtime information
7308 class GeneratorException : public std::exception {
7309 const char* const m_msg = "";
7310
7311 public:
7312 GeneratorException(const char* msg):
7313 m_msg(msg)
7314 {}
7315
7316 const char* what() const noexcept override final;
7317 };
7318
7319} // end namespace Catch
7320
7321#endif // CATCH_GENERATOR_EXCEPTION_HPP_INCLUDED
7322
7323
7324#ifndef CATCH_GENERATORS_HPP_INCLUDED
7325#define CATCH_GENERATORS_HPP_INCLUDED
7326
7327
7328
7329#ifndef CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
7330#define CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
7331
7332
7333#include <string>
7334
7335namespace Catch {
7336
7337 namespace Generators {
7338 class GeneratorUntypedBase {
7339 // Caches result from `toStringImpl`, assume that when it is an
7340 // empty string, the cache is invalidated.
7341 mutable std::string m_stringReprCache;
7342
7343 // Counts based on `next` returning true
7344 std::size_t m_currentElementIndex = 0;
7345
7346 /**
7347 * Attempts to move the generator to the next element
7348 *
7349 * Returns true iff the move succeeded (and a valid element
7350 * can be retrieved).
7351 */
7352 virtual bool next() = 0;
7353
7354 //! Customization point for `currentElementAsString`
7355 virtual std::string stringifyImpl() const = 0;
7356
7357 public:
7358 GeneratorUntypedBase() = default;
7359 // Generation of copy ops is deprecated (and Clang will complain)
7360 // if there is a user destructor defined
7361 GeneratorUntypedBase(GeneratorUntypedBase const&) = default;
7362 GeneratorUntypedBase& operator=(GeneratorUntypedBase const&) = default;
7363
7364 virtual ~GeneratorUntypedBase(); // = default;
7365
7366 /**
7367 * Attempts to move the generator to the next element
7368 *
7369 * Serves as a non-virtual interface to `next`, so that the
7370 * top level interface can provide sanity checking and shared
7371 * features.
7372 *
7373 * As with `next`, returns true iff the move succeeded and
7374 * the generator has new valid element to provide.
7375 */
7376 bool countedNext();
7377
7378 std::size_t currentElementIndex() const { return m_currentElementIndex; }
7379
7380 /**
7381 * Returns generator's current element as user-friendly string.
7382 *
7383 * By default returns string equivalent to calling
7384 * `Catch::Detail::stringify` on the current element, but generators
7385 * can customize their implementation as needed.
7386 *
7387 * Not thread-safe due to internal caching.
7388 *
7389 * The returned ref is valid only until the generator instance
7390 * is destructed, or it moves onto the next element, whichever
7391 * comes first.
7392 */
7393 StringRef currentElementAsString() const;
7394 };
7395 using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>;
7396
7397 } // namespace Generators
7398
7399 class IGeneratorTracker {
7400 public:
7401 virtual ~IGeneratorTracker(); // = default;
7402 virtual auto hasGenerator() const -> bool = 0;
7403 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
7404 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
7405 };
7406
7407} // namespace Catch
7408
7409#endif // CATCH_INTERFACES_GENERATORTRACKER_HPP_INCLUDED
7410
7411#include <vector>
7412#include <tuple>
7413
7414namespace Catch {
7415
7416namespace Generators {
7417
7418namespace Detail {
7419
7420 //! Throws GeneratorException with the provided message
7421 [[noreturn]]
7422 void throw_generator_exception(char const * msg);
7423
7424} // end namespace detail
7425
7426 template<typename T>
7427 class IGenerator : public GeneratorUntypedBase {
7428 std::string stringifyImpl() const override {
7429 return ::Catch::Detail::stringify( get() );
7430 }
7431
7432 public:
7433 // Returns the current element of the generator
7434 //
7435 // \Precondition The generator is either freshly constructed,
7436 // or the last call to `next()` returned true
7437 virtual T const& get() const = 0;
7438 using type = T;
7439 };
7440
7441 template <typename T>
7442 using GeneratorPtr = Catch::Detail::unique_ptr<IGenerator<T>>;
7443
7444 template <typename T>
7445 class GeneratorWrapper final {
7446 GeneratorPtr<T> m_generator;
7447 public:
7448 //! Takes ownership of the passed pointer.
7449 GeneratorWrapper(IGenerator<T>* generator):
7450 m_generator(generator) {}
7451 GeneratorWrapper(GeneratorPtr<T> generator):
7452 m_generator(CATCH_MOVE(generator)) {}
7453
7454 T const& get() const {
7455 return m_generator->get();
7456 }
7457 bool next() {
7458 return m_generator->countedNext();
7459 }
7460 };
7461
7462
7463 template<typename T>
7464 class SingleValueGenerator final : public IGenerator<T> {
7465 T m_value;
7466 public:
7467 SingleValueGenerator(T const& value) :
7468 m_value(value)
7469 {}
7470 SingleValueGenerator(T&& value):
7471 m_value(CATCH_MOVE(value))
7472 {}
7473
7474 T const& get() const override {
7475 return m_value;
7476 }
7477 bool next() override {
7478 return false;
7479 }
7480 };
7481
7482 template<typename T>
7483 class FixedValuesGenerator final : public IGenerator<T> {
7484 static_assert(!std::is_same<T, bool>::value,
7485 "FixedValuesGenerator does not support bools because of std::vector<bool>"
7486 "specialization, use SingleValue Generator instead.");
7487 std::vector<T> m_values;
7488 size_t m_idx = 0;
7489 public:
7490 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
7491
7492 T const& get() const override {
7493 return m_values[m_idx];
7494 }
7495 bool next() override {
7496 ++m_idx;
7497 return m_idx < m_values.size();
7498 }
7499 };
7500
7501 template <typename T, typename DecayedT = std::decay_t<T>>
7502 GeneratorWrapper<DecayedT> value( T&& value ) {
7503 return GeneratorWrapper<DecayedT>(
7504 Catch::Detail::make_unique<SingleValueGenerator<DecayedT>>(
7505 CATCH_FORWARD( value ) ) );
7506 }
7507 template <typename T>
7508 GeneratorWrapper<T> values(std::initializer_list<T> values) {
7509 return GeneratorWrapper<T>(Catch::Detail::make_unique<FixedValuesGenerator<T>>(values));
7510 }
7511
7512 template<typename T>
7513 class Generators : public IGenerator<T> {
7514 std::vector<GeneratorWrapper<T>> m_generators;
7515 size_t m_current = 0;
7516
7517 void add_generator( GeneratorWrapper<T>&& generator ) {
7518 m_generators.emplace_back( CATCH_MOVE( generator ) );
7519 }
7520 void add_generator( T const& val ) {
7521 m_generators.emplace_back( value( val ) );
7522 }
7523 void add_generator( T&& val ) {
7524 m_generators.emplace_back( value( CATCH_MOVE( val ) ) );
7525 }
7526 template <typename U>
7527 std::enable_if_t<!std::is_same<std::decay_t<U>, T>::value>
7528 add_generator( U&& val ) {
7529 add_generator( T( CATCH_FORWARD( val ) ) );
7530 }
7531
7532 template <typename U> void add_generators( U&& valueOrGenerator ) {
7533 add_generator( CATCH_FORWARD( valueOrGenerator ) );
7534 }
7535
7536 template <typename U, typename... Gs>
7537 void add_generators( U&& valueOrGenerator, Gs&&... moreGenerators ) {
7538 add_generator( CATCH_FORWARD( valueOrGenerator ) );
7539 add_generators( CATCH_FORWARD( moreGenerators )... );
7540 }
7541
7542 public:
7543 template <typename... Gs>
7544 Generators(Gs &&... moreGenerators) {
7545 m_generators.reserve(sizeof...(Gs));
7546 add_generators(CATCH_FORWARD(moreGenerators)...);
7547 }
7548
7549 T const& get() const override {
7550 return m_generators[m_current].get();
7551 }
7552
7553 bool next() override {
7554 if (m_current >= m_generators.size()) {
7555 return false;
7556 }
7557 const bool current_status = m_generators[m_current].next();
7558 if (!current_status) {
7559 ++m_current;
7560 }
7561 return m_current < m_generators.size();
7562 }
7563 };
7564
7565
7566 template <typename... Ts>
7567 GeneratorWrapper<std::tuple<std::decay_t<Ts>...>>
7568 table( std::initializer_list<std::tuple<std::decay_t<Ts>...>> tuples ) {
7569 return values<std::tuple<Ts...>>( tuples );
7570 }
7571
7572 // Tag type to signal that a generator sequence should convert arguments to a specific type
7573 template <typename T>
7574 struct as {};
7575
7576 template<typename T, typename... Gs>
7577 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
7578 return Generators<T>(CATCH_MOVE(generator), CATCH_FORWARD(moreGenerators)...);
7579 }
7580 template<typename T>
7581 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
7582 return Generators<T>(CATCH_MOVE(generator));
7583 }
7584 template<typename T, typename... Gs>
7585 auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<std::decay_t<T>> {
7586 return makeGenerators( value( CATCH_FORWARD( val ) ), CATCH_FORWARD( moreGenerators )... );
7587 }
7588 template<typename T, typename U, typename... Gs>
7589 auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
7590 return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... );
7591 }
7592
7593 IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName,
7594 SourceLineInfo const& lineInfo );
7595 IGeneratorTracker* createGeneratorTracker( StringRef generatorName,
7596 SourceLineInfo lineInfo,
7597 GeneratorBasePtr&& generator );
7598
7599 template<typename L>
7600 auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type {
7601 using UnderlyingType = typename decltype(generatorExpression())::type;
7602
7603 IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo );
7604 // Creation of tracker is delayed after generator creation, so
7605 // that constructing generator can fail without breaking everything.
7606 if (!tracker) {
7607 tracker = createGeneratorTracker(
7608 generatorName,
7609 lineInfo,
7610 Catch::Detail::make_unique<Generators<UnderlyingType>>(
7611 generatorExpression() ) );
7612 }
7613
7614 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker->getGenerator() );
7615 return generator.get();
7616 }
7617
7618} // namespace Generators
7619} // namespace Catch
7620
7621#define CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL( ... ) #__VA_ARGS__##_catch_sr
7622#define CATCH_INTERNAL_GENERATOR_STRINGIZE(...) CATCH_INTERNAL_GENERATOR_STRINGIZE_IMPL(__VA_ARGS__)
7623
7624#define GENERATE( ... ) \
7625 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
7626 CATCH_INTERNAL_LINEINFO, \
7627 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
7628#define GENERATE_COPY( ... ) \
7629 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
7630 CATCH_INTERNAL_LINEINFO, \
7631 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
7632#define GENERATE_REF( ... ) \
7633 Catch::Generators::generate( CATCH_INTERNAL_GENERATOR_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
7634 CATCH_INTERNAL_LINEINFO, \
7635 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
7636
7637#endif // CATCH_GENERATORS_HPP_INCLUDED
7638
7639
7640#ifndef CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
7641#define CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
7642
7643
7644#include <cassert>
7645
7646namespace Catch {
7647namespace Generators {
7648
7649 template <typename T>
7650 class TakeGenerator final : public IGenerator<T> {
7651 GeneratorWrapper<T> m_generator;
7652 size_t m_returned = 0;
7653 size_t m_target;
7654 public:
7655 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
7656 m_generator(CATCH_MOVE(generator)),
7657 m_target(target)
7658 {
7659 assert(target != 0 && "Empty generators are not allowed");
7660 }
7661 T const& get() const override {
7662 return m_generator.get();
7663 }
7664 bool next() override {
7665 ++m_returned;
7666 if (m_returned >= m_target) {
7667 return false;
7668 }
7669
7670 const auto success = m_generator.next();
7671 // If the underlying generator does not contain enough values
7672 // then we cut short as well
7673 if (!success) {
7674 m_returned = m_target;
7675 }
7676 return success;
7677 }
7678 };
7679
7680 template <typename T>
7681 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
7682 return GeneratorWrapper<T>(Catch::Detail::make_unique<TakeGenerator<T>>(target, CATCH_MOVE(generator)));
7683 }
7684
7685
7686 template <typename T, typename Predicate>
7687 class FilterGenerator final : public IGenerator<T> {
7688 GeneratorWrapper<T> m_generator;
7689 Predicate m_predicate;
7690 public:
7691 template <typename P = Predicate>
7692 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
7693 m_generator(CATCH_MOVE(generator)),
7694 m_predicate(CATCH_FORWARD(pred))
7695 {
7696 if (!m_predicate(m_generator.get())) {
7697 // It might happen that there are no values that pass the
7698 // filter. In that case we throw an exception.
7699 auto has_initial_value = next();
7700 if (!has_initial_value) {
7701 Detail::throw_generator_exception("No valid value found in filtered generator");
7702 }
7703 }
7704 }
7705
7706 T const& get() const override {
7707 return m_generator.get();
7708 }
7709
7710 bool next() override {
7711 bool success = m_generator.next();
7712 if (!success) {
7713 return false;
7714 }
7715 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
7716 return success;
7717 }
7718 };
7719
7720
7721 template <typename T, typename Predicate>
7722 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
7723 return GeneratorWrapper<T>(Catch::Detail::make_unique<FilterGenerator<T, Predicate>>(CATCH_FORWARD(pred), CATCH_MOVE(generator)));
7724 }
7725
7726 template <typename T>
7727 class RepeatGenerator final : public IGenerator<T> {
7728 static_assert(!std::is_same<T, bool>::value,
7729 "RepeatGenerator currently does not support bools"
7730 "because of std::vector<bool> specialization");
7731 GeneratorWrapper<T> m_generator;
7732 mutable std::vector<T> m_returned;
7733 size_t m_target_repeats;
7734 size_t m_current_repeat = 0;
7735 size_t m_repeat_index = 0;
7736 public:
7737 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
7738 m_generator(CATCH_MOVE(generator)),
7739 m_target_repeats(repeats)
7740 {
7741 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
7742 }
7743
7744 T const& get() const override {
7745 if (m_current_repeat == 0) {
7746 m_returned.push_back(m_generator.get());
7747 return m_returned.back();
7748 }
7749 return m_returned[m_repeat_index];
7750 }
7751
7752 bool next() override {
7753 // There are 2 basic cases:
7754 // 1) We are still reading the generator
7755 // 2) We are reading our own cache
7756
7757 // In the first case, we need to poke the underlying generator.
7758 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
7759 if (m_current_repeat == 0) {
7760 const auto success = m_generator.next();
7761 if (!success) {
7762 ++m_current_repeat;
7763 }
7764 return m_current_repeat < m_target_repeats;
7765 }
7766
7767 // In the second case, we need to move indices forward and check that we haven't run up against the end
7768 ++m_repeat_index;
7769 if (m_repeat_index == m_returned.size()) {
7770 m_repeat_index = 0;
7771 ++m_current_repeat;
7772 }
7773 return m_current_repeat < m_target_repeats;
7774 }
7775 };
7776
7777 template <typename T>
7778 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
7779 return GeneratorWrapper<T>(Catch::Detail::make_unique<RepeatGenerator<T>>(repeats, CATCH_MOVE(generator)));
7780 }
7781
7782 template <typename T, typename U, typename Func>
7783 class MapGenerator final : public IGenerator<T> {
7784 // TBD: provide static assert for mapping function, for friendly error message
7785 GeneratorWrapper<U> m_generator;
7786 Func m_function;
7787 // To avoid returning dangling reference, we have to save the values
7788 T m_cache;
7789 public:
7790 template <typename F2 = Func>
7791 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
7792 m_generator(CATCH_MOVE(generator)),
7793 m_function(CATCH_FORWARD(function)),
7794 m_cache(m_function(m_generator.get()))
7795 {}
7796
7797 T const& get() const override {
7798 return m_cache;
7799 }
7800 bool next() override {
7801 const auto success = m_generator.next();
7802 if (success) {
7803 m_cache = m_function(m_generator.get());
7804 }
7805 return success;
7806 }
7807 };
7808
7809 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
7810 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
7811 return GeneratorWrapper<T>(
7812 Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
7813 );
7814 }
7815
7816 template <typename T, typename U, typename Func>
7817 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
7818 return GeneratorWrapper<T>(
7819 Catch::Detail::make_unique<MapGenerator<T, U, Func>>(CATCH_FORWARD(function), CATCH_MOVE(generator))
7820 );
7821 }
7822
7823 template <typename T>
7824 class ChunkGenerator final : public IGenerator<std::vector<T>> {
7825 std::vector<T> m_chunk;
7826 size_t m_chunk_size;
7827 GeneratorWrapper<T> m_generator;
7828 bool m_used_up = false;
7829 public:
7830 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
7831 m_chunk_size(size), m_generator(CATCH_MOVE(generator))
7832 {
7833 m_chunk.reserve(m_chunk_size);
7834 if (m_chunk_size != 0) {
7835 m_chunk.push_back(m_generator.get());
7836 for (size_t i = 1; i < m_chunk_size; ++i) {
7837 if (!m_generator.next()) {
7838 Detail::throw_generator_exception("Not enough values to initialize the first chunk");
7839 }
7840 m_chunk.push_back(m_generator.get());
7841 }
7842 }
7843 }
7844 std::vector<T> const& get() const override {
7845 return m_chunk;
7846 }
7847 bool next() override {
7848 m_chunk.clear();
7849 for (size_t idx = 0; idx < m_chunk_size; ++idx) {
7850 if (!m_generator.next()) {
7851 return false;
7852 }
7853 m_chunk.push_back(m_generator.get());
7854 }
7855 return true;
7856 }
7857 };
7858
7859 template <typename T>
7860 GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
7861 return GeneratorWrapper<std::vector<T>>(
7862 Catch::Detail::make_unique<ChunkGenerator<T>>(size, CATCH_MOVE(generator))
7863 );
7864 }
7865
7866} // namespace Generators
7867} // namespace Catch
7868
7869
7870#endif // CATCH_GENERATORS_ADAPTERS_HPP_INCLUDED
7871
7872
7873#ifndef CATCH_GENERATORS_RANDOM_HPP_INCLUDED
7874#define CATCH_GENERATORS_RANDOM_HPP_INCLUDED
7875
7876
7877
7878#ifndef CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
7879#define CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
7880
7881#include <cstdint>
7882
7883namespace Catch {
7884
7885 // This is a simple implementation of C++11 Uniform Random Number
7886 // Generator. It does not provide all operators, because Catch2
7887 // does not use it, but it should behave as expected inside stdlib's
7888 // distributions.
7889 // The implementation is based on the PCG family (http://pcg-random.org)
7890 class SimplePcg32 {
7891 using state_type = std::uint64_t;
7892 public:
7893 using result_type = std::uint32_t;
7894 static constexpr result_type (min)() {
7895 return 0;
7896 }
7897 static constexpr result_type (max)() {
7898 return static_cast<result_type>(-1);
7899 }
7900
7901 // Provide some default initial state for the default constructor
7902 SimplePcg32():SimplePcg32(0xed743cc4U) {}
7903
7904 explicit SimplePcg32(result_type seed_);
7905
7906 void seed(result_type seed_);
7907 void discard(uint64_t skip);
7908
7909 result_type operator()();
7910
7911 private:
7912 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
7913 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
7914
7915 // In theory we also need operator<< and operator>>
7916 // In practice we do not use them, so we will skip them for now
7917
7918
7919 std::uint64_t m_state;
7920 // This part of the state determines which "stream" of the numbers
7921 // is chosen -- we take it as a constant for Catch2, so we only
7922 // need to deal with seeding the main state.
7923 // Picked by reading 8 bytes from `/dev/random` :-)
7924 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
7925 };
7926
7927} // end namespace Catch
7928
7929#endif // CATCH_RANDOM_NUMBER_GENERATOR_HPP_INCLUDED
7930
7931
7932
7933#ifndef CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
7934#define CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
7935
7936
7937
7938
7939#ifndef CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
7940#define CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
7941
7942#include <climits>
7943#include <cstddef>
7944#include <cstdint>
7945#include <type_traits>
7946
7947// Note: We use the usual enable-disable-autodetect dance here even though
7948// we do not support these in CMake configuration options (yet?).
7949// It is highly unlikely that we will need to make these actually
7950// user-configurable, but this will make it simpler if weend up needing
7951// it, and it provides an escape hatch to the users who need it.
7952#if defined( __SIZEOF_INT128__ )
7953# define CATCH_CONFIG_INTERNAL_UINT128
7954// Unlike GCC, MSVC does not polyfill umul as mulh + mul pair on ARM machines.
7955// Currently we do not bother doing this ourselves, but we could if it became
7956// important for perf.
7957#elif defined( _MSC_VER ) && defined( _M_X64 )
7958# define CATCH_CONFIG_INTERNAL_MSVC_UMUL128
7959#endif
7960
7961#if defined( CATCH_CONFIG_INTERNAL_UINT128 ) && \
7962 !defined( CATCH_CONFIG_NO_UINT128 ) && \
7963 !defined( CATCH_CONFIG_UINT128 )
7964#define CATCH_CONFIG_UINT128
7965#endif
7966
7967#if defined( CATCH_CONFIG_INTERNAL_MSVC_UMUL128 ) && \
7968 !defined( CATCH_CONFIG_NO_MSVC_UMUL128 ) && \
7969 !defined( CATCH_CONFIG_MSVC_UMUL128 )
7970# define CATCH_CONFIG_MSVC_UMUL128
7971# include <intrin.h>
7972#endif
7973
7974
7975namespace Catch {
7976 namespace Detail {
7977
7978 template <std::size_t>
7979 struct SizedUnsignedType;
7980#define SizedUnsignedTypeHelper( TYPE ) \
7981 template <> \
7982 struct SizedUnsignedType<sizeof( TYPE )> { \
7983 using type = TYPE; \
7984 }
7985
7986 SizedUnsignedTypeHelper( std::uint8_t );
7987 SizedUnsignedTypeHelper( std::uint16_t );
7988 SizedUnsignedTypeHelper( std::uint32_t );
7989 SizedUnsignedTypeHelper( std::uint64_t );
7990#undef SizedUnsignedTypeHelper
7991
7992 template <std::size_t sz>
7993 using SizedUnsignedType_t = typename SizedUnsignedType<sz>::type;
7994
7995 template <typename T>
7996 using DoubleWidthUnsignedType_t = SizedUnsignedType_t<2 * sizeof( T )>;
7997
7998 template <typename T>
7999 struct ExtendedMultResult {
8000 T upper;
8001 T lower;
8002 bool operator==( ExtendedMultResult const& rhs ) const {
8003 return upper == rhs.upper && lower == rhs.lower;
8004 }
8005 };
8006
8007 /**
8008 * Returns 128 bit result of lhs * rhs using portable C++ code
8009 *
8010 * This implementation is almost twice as fast as naive long multiplication,
8011 * and unlike intrinsic-based approach, it supports constexpr evaluation.
8012 */
8013 constexpr ExtendedMultResult<std::uint64_t>
8014 extendedMultPortable(std::uint64_t lhs, std::uint64_t rhs) {
8015#define CarryBits( x ) ( x >> 32 )
8016#define Digits( x ) ( x & 0xFF'FF'FF'FF )
8017 std::uint64_t lhs_low = Digits( lhs );
8018 std::uint64_t rhs_low = Digits( rhs );
8019 std::uint64_t low_low = ( lhs_low * rhs_low );
8020 std::uint64_t high_high = CarryBits( lhs ) * CarryBits( rhs );
8021
8022 // We add in carry bits from low-low already
8023 std::uint64_t high_low =
8024 ( CarryBits( lhs ) * rhs_low ) + CarryBits( low_low );
8025 // Note that we can add only low bits from high_low, to avoid
8026 // overflow with large inputs
8027 std::uint64_t low_high =
8028 ( lhs_low * CarryBits( rhs ) ) + Digits( high_low );
8029
8030 return { high_high + CarryBits( high_low ) + CarryBits( low_high ),
8031 ( low_high << 32 ) | Digits( low_low ) };
8032#undef CarryBits
8033#undef Digits
8034 }
8035
8036 //! Returns 128 bit result of lhs * rhs
8037 inline ExtendedMultResult<std::uint64_t>
8038 extendedMult( std::uint64_t lhs, std::uint64_t rhs ) {
8039#if defined( CATCH_CONFIG_UINT128 )
8040 auto result = __uint128_t( lhs ) * __uint128_t( rhs );
8041 return { static_cast<std::uint64_t>( result >> 64 ),
8042 static_cast<std::uint64_t>( result ) };
8043#elif defined( CATCH_CONFIG_MSVC_UMUL128 )
8044 std::uint64_t high;
8045 std::uint64_t low = _umul128( lhs, rhs, &high );
8046 return { high, low };
8047#else
8048 return extendedMultPortable( lhs, rhs );
8049#endif
8050 }
8051
8052
8053 template <typename UInt>
8054 constexpr ExtendedMultResult<UInt> extendedMult( UInt lhs, UInt rhs ) {
8055 static_assert( std::is_unsigned<UInt>::value,
8056 "extendedMult can only handle unsigned integers" );
8057 static_assert( sizeof( UInt ) < sizeof( std::uint64_t ),
8058 "Generic extendedMult can only handle types smaller "
8059 "than uint64_t" );
8060 using WideType = DoubleWidthUnsignedType_t<UInt>;
8061
8062 auto result = WideType( lhs ) * WideType( rhs );
8063 return {
8064 static_cast<UInt>( result >> ( CHAR_BIT * sizeof( UInt ) ) ),
8065 static_cast<UInt>( result & UInt( -1 ) ) };
8066 }
8067
8068
8069 template <typename TargetType,
8070 typename Generator>
8071 std::enable_if_t<sizeof(typename Generator::result_type) >= sizeof(TargetType),
8072 TargetType> fillBitsFrom(Generator& gen) {
8073 using gresult_type = typename Generator::result_type;
8074 static_assert( std::is_unsigned<TargetType>::value, "Only unsigned integers are supported" );
8075 static_assert( Generator::min() == 0 &&
8076 Generator::max() == static_cast<gresult_type>( -1 ),
8077 "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
8078
8079 // We want to return the top bits from a generator, as they are
8080 // usually considered higher quality.
8081 constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
8082 constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
8083
8084 return static_cast<TargetType>( gen() >>
8085 ( generated_bits - return_bits) );
8086 }
8087
8088 template <typename TargetType,
8089 typename Generator>
8090 std::enable_if_t<sizeof(typename Generator::result_type) < sizeof(TargetType),
8091 TargetType> fillBitsFrom(Generator& gen) {
8092 using gresult_type = typename Generator::result_type;
8093 static_assert( std::is_unsigned<TargetType>::value,
8094 "Only unsigned integers are supported" );
8095 static_assert( Generator::min() == 0 &&
8096 Generator::max() == static_cast<gresult_type>( -1 ),
8097 "Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
8098
8099 constexpr auto generated_bits = sizeof( gresult_type ) * CHAR_BIT;
8100 constexpr auto return_bits = sizeof( TargetType ) * CHAR_BIT;
8101 std::size_t filled_bits = 0;
8102 TargetType ret = 0;
8103 do {
8104 ret <<= generated_bits;
8105 ret |= gen();
8106 filled_bits += generated_bits;
8107 } while ( filled_bits < return_bits );
8108
8109 return ret;
8110 }
8111
8112 /*
8113 * Transposes numbers into unsigned type while keeping their ordering
8114 *
8115 * This means that signed types are changed so that the ordering is
8116 * [INT_MIN, ..., -1, 0, ..., INT_MAX], rather than order we would
8117 * get by simple casting ([0, ..., INT_MAX, INT_MIN, ..., -1])
8118 */
8119 template <typename OriginalType, typename UnsignedType>
8120 std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType>
8121 transposeToNaturalOrder( UnsignedType in ) {
8122 static_assert(
8123 sizeof( OriginalType ) == sizeof( UnsignedType ),
8124 "reordering requires the same sized types on both sides" );
8125 static_assert( std::is_unsigned<UnsignedType>::value,
8126 "Input type must be unsigned" );
8127 // Assuming 2s complement (standardized in current C++), the
8128 // positive and negative numbers are already internally ordered,
8129 // and their difference is in the top bit. Swapping it orders
8130 // them the desired way.
8131 constexpr auto highest_bit =
8132 UnsignedType( 1 ) << ( sizeof( UnsignedType ) * CHAR_BIT - 1 );
8133 return static_cast<UnsignedType>( in ^ highest_bit );
8134 }
8135
8136
8137
8138 template <typename OriginalType,
8139 typename UnsignedType>
8140 std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType>
8141 transposeToNaturalOrder(UnsignedType in) {
8142 static_assert(
8143 sizeof( OriginalType ) == sizeof( UnsignedType ),
8144 "reordering requires the same sized types on both sides" );
8145 static_assert( std::is_unsigned<UnsignedType>::value, "Input type must be unsigned" );
8146 // No reordering is needed for unsigned -> unsigned
8147 return in;
8148 }
8149 } // namespace Detail
8150} // namespace Catch
8151
8152#endif // CATCH_RANDOM_INTEGER_HELPERS_HPP_INCLUDED
8153
8154namespace Catch {
8155
8156/**
8157 * Implementation of uniform distribution on integers.
8158 *
8159 * Unlike `std::uniform_int_distribution`, this implementation supports
8160 * various 1 byte integral types, including bool (but you should not
8161 * actually use it for bools).
8162 *
8163 * The underlying algorithm is based on the one described in "Fast Random
8164 * Integer Generation in an Interval" by Daniel Lemire, but has been
8165 * optimized under the assumption of reuse of the same distribution object.
8166 */
8167template <typename IntegerType>
8168class uniform_integer_distribution {
8169 static_assert(std::is_integral<IntegerType>::value, "...");
8170
8171 using UnsignedIntegerType = Detail::SizedUnsignedType_t<sizeof(IntegerType)>;
8172
8173 // Only the left bound is stored, and we store it converted to its
8174 // unsigned image. This avoids having to do the conversions inside
8175 // the operator(), at the cost of having to do the conversion in
8176 // the a() getter. The right bound is only needed in the b() getter,
8177 // so we recompute it there from other stored data.
8178 UnsignedIntegerType m_a;
8179
8180 // How many different values are there in [a, b]. a == b => 1, can be 0 for distribution over all values in the type.
8181 UnsignedIntegerType m_ab_distance;
8182
8183 // We hoisted this out of the main generation function. Technically,
8184 // this means that using this distribution will be slower than Lemire's
8185 // algorithm if this distribution instance will be used only few times,
8186 // but it will be faster if it is used many times. Since Catch2 uses
8187 // distributions only to implement random generators, we assume that each
8188 // distribution will be reused many times and this is an optimization.
8189 UnsignedIntegerType m_rejection_threshold = 0;
8190
8191 UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) const {
8192 // This overflows and returns 0 if a == 0 and b == TYPE_MAX.
8193 // We handle that later when generating the number.
8194 return transposeTo(b) - transposeTo(a) + 1;
8195 }
8196
8197 static UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) {
8198 // distance == 0 means that we will return all possible values from
8199 // the type's range, and that we shouldn't reject anything.
8200 if ( ab_distance == 0 ) { return 0; }
8201 return ( ~ab_distance + 1 ) % ab_distance;
8202 }
8203
8204 static UnsignedIntegerType transposeTo(IntegerType in) {
8205 return Detail::transposeToNaturalOrder<IntegerType>(
8206 static_cast<UnsignedIntegerType>( in ) );
8207 }
8208 static IntegerType transposeBack(UnsignedIntegerType in) {
8209 return static_cast<IntegerType>(
8210 Detail::transposeToNaturalOrder<IntegerType>(in) );
8211 }
8212
8213public:
8214 using result_type = IntegerType;
8215
8216 uniform_integer_distribution( IntegerType a, IntegerType b ):
8217 m_a( transposeTo(a) ),
8218 m_ab_distance( computeDistance(a, b) ),
8219 m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) {
8220 assert( a <= b );
8221 }
8222
8223 template <typename Generator>
8224 result_type operator()( Generator& g ) {
8225 // All possible values of result_type are valid.
8226 if ( m_ab_distance == 0 ) {
8227 return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) );
8228 }
8229
8230 auto random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
8231 auto emul = Detail::extendedMult( random_number, m_ab_distance );
8232 // Unlike Lemire's algorithm we skip the ab_distance check, since
8233 // we precomputed the rejection threshold, which is always tighter.
8234 while (emul.lower < m_rejection_threshold) {
8235 random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
8236 emul = Detail::extendedMult( random_number, m_ab_distance );
8237 }
8238
8239 return transposeBack(m_a + emul.upper);
8240 }
8241
8242 result_type a() const { return transposeBack(m_a); }
8243 result_type b() const { return transposeBack(m_ab_distance + m_a - 1); }
8244};
8245
8246} // end namespace Catch
8247
8248#endif // CATCH_UNIFORM_INTEGER_DISTRIBUTION_HPP_INCLUDED
8249
8250
8251
8252#ifndef CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
8253#define CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
8254
8255
8256
8257
8258#ifndef CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
8259#define CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
8260
8261
8262
8263#ifndef CATCH_POLYFILLS_HPP_INCLUDED
8264#define CATCH_POLYFILLS_HPP_INCLUDED
8265
8266namespace Catch {
8267
8268 bool isnan(float f);
8269 bool isnan(double d);
8270
8271 float nextafter(float x, float y);
8272 double nextafter(double x, double y);
8273
8274}
8275
8276#endif // CATCH_POLYFILLS_HPP_INCLUDED
8277
8278#include <cassert>
8279#include <cmath>
8280#include <cstdint>
8281#include <limits>
8282#include <type_traits>
8283
8284namespace Catch {
8285
8286 namespace Detail {
8287 /**
8288 * Returns the largest magnitude of 1-ULP distance inside the [a, b] range.
8289 *
8290 * Assumes `a < b`.
8291 */
8292 template <typename FloatType>
8293 FloatType gamma(FloatType a, FloatType b) {
8294 static_assert( std::is_floating_point<FloatType>::value,
8295 "gamma returns the largest ULP magnitude within "
8296 "floating point range [a, b]. This only makes sense "
8297 "for floating point types" );
8298 assert( a <= b );
8299
8300 const auto gamma_up = Catch::nextafter( a, std::numeric_limits<FloatType>::infinity() ) - a;
8301 const auto gamma_down = b - Catch::nextafter( b, -std::numeric_limits<FloatType>::infinity() );
8302
8303 return gamma_up < gamma_down ? gamma_down : gamma_up;
8304 }
8305
8306 template <typename FloatingPoint>
8307 struct DistanceTypePicker;
8308 template <>
8309 struct DistanceTypePicker<float> {
8310 using type = std::uint32_t;
8311 };
8312 template <>
8313 struct DistanceTypePicker<double> {
8314 using type = std::uint64_t;
8315 };
8316
8317 template <typename T>
8318 using DistanceType = typename DistanceTypePicker<T>::type;
8319
8320#if defined( __GNUC__ ) || defined( __clang__ )
8321# pragma GCC diagnostic push
8322# pragma GCC diagnostic ignored "-Wfloat-equal"
8323#endif
8324 /**
8325 * Computes the number of equi-distant floats in [a, b]
8326 *
8327 * Since not every range can be split into equidistant floats
8328 * exactly, we actually compute ceil(b/distance - a/distance),
8329 * because in those cases we want to overcount.
8330 *
8331 * Uses modified Dekker's FastTwoSum algorithm to handle rounding.
8332 */
8333 template <typename FloatType>
8334 DistanceType<FloatType>
8335 count_equidistant_floats( FloatType a, FloatType b, FloatType distance ) {
8336 assert( a <= b );
8337 // We get distance as gamma for our uniform float distribution,
8338 // so this will round perfectly.
8339 const auto ag = a / distance;
8340 const auto bg = b / distance;
8341
8342 const auto s = bg - ag;
8343 const auto err = ( std::fabs( a ) <= std::fabs( b ) )
8344 ? -ag - ( s - bg )
8345 : bg - ( s + ag );
8346 const auto ceil_s = static_cast<DistanceType<FloatType>>( std::ceil( s ) );
8347
8348 return ( ceil_s != s ) ? ceil_s : ceil_s + ( err > 0 );
8349 }
8350#if defined( __GNUC__ ) || defined( __clang__ )
8351# pragma GCC diagnostic pop
8352#endif
8353
8354 }
8355
8356} // end namespace Catch
8357
8358#endif // CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED
8359
8360#include <cmath>
8361#include <type_traits>
8362
8363namespace Catch {
8364
8365 namespace Detail {
8366#if defined( __GNUC__ ) || defined( __clang__ )
8367# pragma GCC diagnostic push
8368# pragma GCC diagnostic ignored "-Wfloat-equal"
8369#endif
8370 // The issue with overflow only happens with maximal ULP and HUGE
8371 // distance, e.g. when generating numbers in [-inf, inf] for given
8372 // type. So we only check for the largest possible ULP in the
8373 // type, and return something that does not overflow to inf in 1 mult.
8374 constexpr std::uint64_t calculate_max_steps_in_one_go(double gamma) {
8375 if ( gamma == 1.99584030953472e+292 ) { return 9007199254740991; }
8376 return static_cast<std::uint64_t>( -1 );
8377 }
8378 constexpr std::uint32_t calculate_max_steps_in_one_go(float gamma) {
8379 if ( gamma == 2.028241e+31f ) { return 16777215; }
8380 return static_cast<std::uint32_t>( -1 );
8381 }
8382#if defined( __GNUC__ ) || defined( __clang__ )
8383# pragma GCC diagnostic pop
8384#endif
8385 }
8386
8387/**
8388 * Implementation of uniform distribution on floating point numbers.
8389 *
8390 * Note that we support only `float` and `double` types, because these
8391 * usually mean the same thing across different platform. `long double`
8392 * varies wildly by platform and thus we cannot provide reproducible
8393 * implementation. Also note that we don't implement all parts of
8394 * distribution per standard: this distribution is not serializable, nor
8395 * can the range be arbitrarily reset.
8396 *
8397 * The implementation also uses different approach than the one taken by
8398 * `std::uniform_real_distribution`, where instead of generating a number
8399 * between [0, 1) and then multiplying the range bounds with it, we first
8400 * split the [a, b] range into a set of equidistributed floating point
8401 * numbers, and then use uniform int distribution to pick which one to
8402 * return.
8403 *
8404 * This has the advantage of guaranteeing uniformity (the multiplication
8405 * method loses uniformity due to rounding when multiplying floats), except
8406 * for small non-uniformity at one side of the interval, where we have
8407 * to deal with the fact that not every interval is splittable into
8408 * equidistributed floats.
8409 *
8410 * Based on "Drawing random floating-point numbers from an interval" by
8411 * Frederic Goualard.
8412 */
8413template <typename FloatType>
8414class uniform_floating_point_distribution {
8415 static_assert(std::is_floating_point<FloatType>::value, "...");
8416 static_assert(!std::is_same<FloatType, long double>::value,
8417 "We do not support long double due to inconsistent behaviour between platforms");
8418
8419 using WidthType = Detail::DistanceType<FloatType>;
8420
8421 FloatType m_a, m_b;
8422 FloatType m_ulp_magnitude;
8423 WidthType m_floats_in_range;
8424 uniform_integer_distribution<WidthType> m_int_dist;
8425
8426 // In specific cases, we can overflow into `inf` when computing the
8427 // `steps * g` offset. To avoid this, we don't offset by more than this
8428 // in one multiply + addition.
8429 WidthType m_max_steps_in_one_go;
8430 // We don't want to do the magnitude check every call to `operator()`
8431 bool m_a_has_leq_magnitude;
8432
8433public:
8434 using result_type = FloatType;
8435
8436 uniform_floating_point_distribution( FloatType a, FloatType b ):
8437 m_a( a ),
8438 m_b( b ),
8439 m_ulp_magnitude( Detail::gamma( m_a, m_b ) ),
8440 m_floats_in_range( Detail::count_equidistant_floats( m_a, m_b, m_ulp_magnitude ) ),
8441 m_int_dist(0, m_floats_in_range),
8442 m_max_steps_in_one_go( Detail::calculate_max_steps_in_one_go(m_ulp_magnitude)),
8443 m_a_has_leq_magnitude(std::fabs(m_a) <= std::fabs(m_b))
8444 {
8445 assert( a <= b );
8446 }
8447
8448 template <typename Generator>
8449 result_type operator()( Generator& g ) {
8450 WidthType steps = m_int_dist( g );
8451 if ( m_a_has_leq_magnitude ) {
8452 if ( steps == m_floats_in_range ) { return m_a; }
8453 auto b = m_b;
8454 while (steps > m_max_steps_in_one_go) {
8455 b -= m_max_steps_in_one_go * m_ulp_magnitude;
8456 steps -= m_max_steps_in_one_go;
8457 }
8458 return b - steps * m_ulp_magnitude;
8459 } else {
8460 if ( steps == m_floats_in_range ) { return m_b; }
8461 auto a = m_a;
8462 while (steps > m_max_steps_in_one_go) {
8463 a += m_max_steps_in_one_go * m_ulp_magnitude;
8464 steps -= m_max_steps_in_one_go;
8465 }
8466 return a + steps * m_ulp_magnitude;
8467 }
8468 }
8469
8470 result_type a() const { return m_a; }
8471 result_type b() const { return m_b; }
8472};
8473
8474} // end namespace Catch
8475
8476#endif // CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED
8477
8478namespace Catch {
8479namespace Generators {
8480namespace Detail {
8481 // Returns a suitable seed for a random floating generator based off
8482 // the primary internal rng. It does so by taking current value from
8483 // the rng and returning it as the seed.
8484 std::uint32_t getSeed();
8485}
8486
8487template <typename Float>
8488class RandomFloatingGenerator final : public IGenerator<Float> {
8489 Catch::SimplePcg32 m_rng;
8490 Catch::uniform_floating_point_distribution<Float> m_dist;
8491 Float m_current_number;
8492public:
8493 RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ):
8494 m_rng(seed),
8495 m_dist(a, b) {
8496 static_cast<void>(next());
8497 }
8498
8499 Float const& get() const override {
8500 return m_current_number;
8501 }
8502 bool next() override {
8503 m_current_number = m_dist(m_rng);
8504 return true;
8505 }
8506};
8507
8508template <>
8509class RandomFloatingGenerator<long double> final : public IGenerator<long double> {
8510 // We still rely on <random> for this specialization, but we don't
8511 // want to drag it into the header.
8512 struct PImpl;
8513 Catch::Detail::unique_ptr<PImpl> m_pimpl;
8514 long double m_current_number;
8515
8516public:
8517 RandomFloatingGenerator( long double a, long double b, std::uint32_t seed );
8518
8519 long double const& get() const override { return m_current_number; }
8520 bool next() override;
8521
8522 ~RandomFloatingGenerator() override; // = default
8523};
8524
8525template <typename Integer>
8526class RandomIntegerGenerator final : public IGenerator<Integer> {
8527 Catch::SimplePcg32 m_rng;
8528 Catch::uniform_integer_distribution<Integer> m_dist;
8529 Integer m_current_number;
8530public:
8531 RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ):
8532 m_rng(seed),
8533 m_dist(a, b) {
8534 static_cast<void>(next());
8535 }
8536
8537 Integer const& get() const override {
8538 return m_current_number;
8539 }
8540 bool next() override {
8541 m_current_number = m_dist(m_rng);
8542 return true;
8543 }
8544};
8545
8546template <typename T>
8547std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>>
8548random(T a, T b) {
8549 return GeneratorWrapper<T>(
8550 Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed())
8551 );
8552}
8553
8554template <typename T>
8555std::enable_if_t<std::is_floating_point<T>::value,
8556GeneratorWrapper<T>>
8557random(T a, T b) {
8558 return GeneratorWrapper<T>(
8559 Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed())
8560 );
8561}
8562
8563
8564} // namespace Generators
8565} // namespace Catch
8566
8567
8568#endif // CATCH_GENERATORS_RANDOM_HPP_INCLUDED
8569
8570
8571#ifndef CATCH_GENERATORS_RANGE_HPP_INCLUDED
8572#define CATCH_GENERATORS_RANGE_HPP_INCLUDED
8573
8574
8575#include <iterator>
8576#include <type_traits>
8577
8578namespace Catch {
8579namespace Generators {
8580
8581
8582template <typename T>
8583class RangeGenerator final : public IGenerator<T> {
8584 T m_current;
8585 T m_end;
8586 T m_step;
8587 bool m_positive;
8588
8589public:
8590 RangeGenerator(T const& start, T const& end, T const& step):
8591 m_current(start),
8592 m_end(end),
8593 m_step(step),
8594 m_positive(m_step > T(0))
8595 {
8596 assert(m_current != m_end && "Range start and end cannot be equal");
8597 assert(m_step != T(0) && "Step size cannot be zero");
8598 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
8599 }
8600
8601 RangeGenerator(T const& start, T const& end):
8602 RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
8603 {}
8604
8605 T const& get() const override {
8606 return m_current;
8607 }
8608
8609 bool next() override {
8610 m_current += m_step;
8611 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
8612 }
8613};
8614
8615template <typename T>
8616GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
8617 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
8618 return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end, step));
8619}
8620
8621template <typename T>
8622GeneratorWrapper<T> range(T const& start, T const& end) {
8623 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
8624 return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end));
8625}
8626
8627
8628template <typename T>
8629class IteratorGenerator final : public IGenerator<T> {
8630 static_assert(!std::is_same<T, bool>::value,
8631 "IteratorGenerator currently does not support bools"
8632 "because of std::vector<bool> specialization");
8633
8634 std::vector<T> m_elems;
8635 size_t m_current = 0;
8636public:
8637 template <typename InputIterator, typename InputSentinel>
8638 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
8639 if (m_elems.empty()) {
8640 Detail::throw_generator_exception("IteratorGenerator received no valid values");
8641 }
8642 }
8643
8644 T const& get() const override {
8645 return m_elems[m_current];
8646 }
8647
8648 bool next() override {
8649 ++m_current;
8650 return m_current != m_elems.size();
8651 }
8652};
8653
8654template <typename InputIterator,
8655 typename InputSentinel,
8656 typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
8657GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
8658 return GeneratorWrapper<ResultType>(Catch::Detail::make_unique<IteratorGenerator<ResultType>>(from, to));
8659}
8660
8661template <typename Container>
8662auto from_range(Container const& cnt) {
8663 using std::begin;
8664 using std::end;
8665 return from_range( begin( cnt ), end( cnt ) );
8666}
8667
8668
8669} // namespace Generators
8670} // namespace Catch
8671
8672
8673#endif // CATCH_GENERATORS_RANGE_HPP_INCLUDED
8674
8675#endif // CATCH_GENERATORS_ALL_HPP_INCLUDED
8676
8677
8678/** \file
8679 * This is a convenience header for Catch2's interfaces. It includes
8680 * **all** of Catch2 headers related to interfaces.
8681 *
8682 * Generally the Catch2 users should use specific includes they need,
8683 * but this header can be used instead for ease-of-experimentation, or
8684 * just plain convenience, at the cost of somewhat increased compilation
8685 * times.
8686 *
8687 * When a new header is added to either the `interfaces` folder, or to
8688 * the corresponding internal subfolder, it should be added here.
8689 */
8690
8691
8692#ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED
8693#define CATCH_INTERFACES_ALL_HPP_INCLUDED
8694
8695
8696
8697#ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED
8698#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED
8699
8700
8701
8702#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED
8703#define CATCH_TEST_RUN_INFO_HPP_INCLUDED
8704
8705
8706namespace Catch {
8707
8708 struct TestRunInfo {
8709 constexpr TestRunInfo(StringRef _name) : name(_name) {}
8710 StringRef name;
8711 };
8712
8713} // end namespace Catch
8714
8715#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED
8716
8717#include <map>
8718#include <string>
8719#include <vector>
8720#include <iosfwd>
8721
8722namespace Catch {
8723
8724 struct ReporterDescription;
8725 struct ListenerDescription;
8726 struct TagInfo;
8727 struct TestCaseInfo;
8728 class TestCaseHandle;
8729 class IConfig;
8730 class IStream;
8731 enum class ColourMode : std::uint8_t;
8732
8733 struct ReporterConfig {
8734 ReporterConfig( IConfig const* _fullConfig,
8735 Detail::unique_ptr<IStream> _stream,
8736 ColourMode colourMode,
8737 std::map<std::string, std::string> customOptions );
8738
8739 ReporterConfig( ReporterConfig&& ) = default;
8740 ReporterConfig& operator=( ReporterConfig&& ) = default;
8741 ~ReporterConfig(); // = default
8742
8743 Detail::unique_ptr<IStream> takeStream() &&;
8744 IConfig const* fullConfig() const;
8745 ColourMode colourMode() const;
8746 std::map<std::string, std::string> const& customOptions() const;
8747
8748 private:
8749 Detail::unique_ptr<IStream> m_stream;
8750 IConfig const* m_fullConfig;
8751 ColourMode m_colourMode;
8752 std::map<std::string, std::string> m_customOptions;
8753 };
8754
8755 struct AssertionStats {
8756 AssertionStats( AssertionResult const& _assertionResult,
8757 std::vector<MessageInfo> const& _infoMessages,
8758 Totals const& _totals );
8759
8760 AssertionStats( AssertionStats const& ) = default;
8761 AssertionStats( AssertionStats && ) = default;
8762 AssertionStats& operator = ( AssertionStats const& ) = delete;
8763 AssertionStats& operator = ( AssertionStats && ) = delete;
8764
8765 AssertionResult assertionResult;
8766 std::vector<MessageInfo> infoMessages;
8767 Totals totals;
8768 };
8769
8770 struct SectionStats {
8771 SectionStats( SectionInfo&& _sectionInfo,
8772 Counts const& _assertions,
8773 double _durationInSeconds,
8774 bool _missingAssertions );
8775
8776 SectionInfo sectionInfo;
8777 Counts assertions;
8778 double durationInSeconds;
8779 bool missingAssertions;
8780 };
8781
8782 struct TestCaseStats {
8783 TestCaseStats( TestCaseInfo const& _testInfo,
8784 Totals const& _totals,
8785 std::string&& _stdOut,
8786 std::string&& _stdErr,
8787 bool _aborting );
8788
8789 TestCaseInfo const * testInfo;
8790 Totals totals;
8791 std::string stdOut;
8792 std::string stdErr;
8793 bool aborting;
8794 };
8795
8796 struct TestRunStats {
8797 TestRunStats( TestRunInfo const& _runInfo,
8798 Totals const& _totals,
8799 bool _aborting );
8800
8801 TestRunInfo runInfo;
8802 Totals totals;
8803 bool aborting;
8804 };
8805
8806 //! By setting up its preferences, a reporter can modify Catch2's behaviour
8807 //! in some regards, e.g. it can request Catch2 to capture writes to
8808 //! stdout/stderr during test execution, and pass them to the reporter.
8809 struct ReporterPreferences {
8810 //! Catch2 should redirect writes to stdout and pass them to the
8811 //! reporter
8812 bool shouldRedirectStdOut = false;
8813 //! Catch2 should call `Reporter::assertionEnded` even for passing
8814 //! assertions
8815 bool shouldReportAllAssertions = false;
8816 };
8817
8818 /**
8819 * The common base for all reporters and event listeners
8820 *
8821 * Implementing classes must also implement:
8822 *
8823 * //! User-friendly description of the reporter/listener type
8824 * static std::string getDescription()
8825 *
8826 * Generally shouldn't be derived from by users of Catch2 directly,
8827 * instead they should derive from one of the utility bases that
8828 * derive from this class.
8829 */
8830 class IEventListener {
8831 protected:
8832 //! Derived classes can set up their preferences here
8833 ReporterPreferences m_preferences;
8834 //! The test run's config as filled in from CLI and defaults
8835 IConfig const* m_config;
8836
8837 public:
8838 IEventListener( IConfig const* config ): m_config( config ) {}
8839
8840 virtual ~IEventListener(); // = default;
8841
8842 // Implementing class must also provide the following static methods:
8843 // static std::string getDescription();
8844
8845 ReporterPreferences const& getPreferences() const {
8846 return m_preferences;
8847 }
8848
8849 //! Called when no test cases match provided test spec
8850 virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0;
8851 //! Called for all invalid test specs from the cli
8852 virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0;
8853
8854 /**
8855 * Called once in a testing run before tests are started
8856 *
8857 * Not called if tests won't be run (e.g. only listing will happen)
8858 */
8859 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
8860
8861 //! Called _once_ for each TEST_CASE, no matter how many times it is entered
8862 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
8863 //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
8864 virtual void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) = 0;
8865 //! Called when a `SECTION` is being entered. Not called for skipped sections
8866 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
8867
8868 //! Called when user-code is being probed before the actual benchmark runs
8869 virtual void benchmarkPreparing( StringRef benchmarkName ) = 0;
8870 //! Called after probe but before the user-code is being benchmarked
8871 virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0;
8872 //! Called with the benchmark results if benchmark successfully finishes
8873 virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0;
8874 //! Called if running the benchmarks fails for any reason
8875 virtual void benchmarkFailed( StringRef benchmarkName ) = 0;
8876
8877 //! Called before assertion success/failure is evaluated
8878 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
8879
8880 //! Called after assertion was fully evaluated
8881 virtual void assertionEnded( AssertionStats const& assertionStats ) = 0;
8882
8883 //! Called after a `SECTION` has finished running
8884 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
8885 //! Called _every time_ a TEST_CASE is entered, including repeats (due to sections)
8886 virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber ) = 0;
8887 //! Called _once_ for each TEST_CASE, no matter how many times it is entered
8888 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
8889 /**
8890 * Called once after all tests in a testing run are finished
8891 *
8892 * Not called if tests weren't run (e.g. only listings happened)
8893 */
8894 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
8895
8896 /**
8897 * Called with test cases that are skipped due to the test run aborting.
8898 * NOT called for test cases that are explicitly skipped using the `SKIP` macro.
8899 *
8900 * Deprecated - will be removed in the next major release.
8901 */
8902 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
8903
8904 //! Called if a fatal error (signal/structured exception) occurred
8905 virtual void fatalErrorEncountered( StringRef error ) = 0;
8906
8907 //! Writes out information about provided reporters using reporter-specific format
8908 virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0;
8909 //! Writes out the provided listeners descriptions using reporter-specific format
8910 virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0;
8911 //! Writes out information about provided tests using reporter-specific format
8912 virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0;
8913 //! Writes out information about the provided tags using reporter-specific format
8914 virtual void listTags(std::vector<TagInfo> const& tags) = 0;
8915 };
8916 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
8917
8918} // end namespace Catch
8919
8920#endif // CATCH_INTERFACES_REPORTER_HPP_INCLUDED
8921
8922
8923#ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
8924#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
8925
8926
8927#include <string>
8928
8929namespace Catch {
8930
8931 struct ReporterConfig;
8932 class IConfig;
8933 class IEventListener;
8934 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
8935
8936
8937 class IReporterFactory {
8938 public:
8939 virtual ~IReporterFactory(); // = default
8940
8941 virtual IEventListenerPtr
8942 create( ReporterConfig&& config ) const = 0;
8943 virtual std::string getDescription() const = 0;
8944 };
8945 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
8946
8947 class EventListenerFactory {
8948 public:
8949 virtual ~EventListenerFactory(); // = default
8950 virtual IEventListenerPtr create( IConfig const* config ) const = 0;
8951 //! Return a meaningful name for the listener, e.g. its type name
8952 virtual StringRef getName() const = 0;
8953 //! Return listener's description if available
8954 virtual std::string getDescription() const = 0;
8955 };
8956} // namespace Catch
8957
8958#endif // CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED
8959
8960
8961#ifndef CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8962#define CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8963
8964#include <string>
8965
8966namespace Catch {
8967
8968 struct TagAlias;
8969
8970 class ITagAliasRegistry {
8971 public:
8972 virtual ~ITagAliasRegistry(); // = default
8973 // Nullptr if not present
8974 virtual TagAlias const* find( std::string const& alias ) const = 0;
8975 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
8976
8977 static ITagAliasRegistry const& get();
8978 };
8979
8980} // end namespace Catch
8981
8982#endif // CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8983
8984
8985#ifndef CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
8986#define CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
8987
8988#include <vector>
8989
8990namespace Catch {
8991
8992 struct TestCaseInfo;
8993 class TestCaseHandle;
8994 class IConfig;
8995
8996 class ITestCaseRegistry {
8997 public:
8998 virtual ~ITestCaseRegistry(); // = default
8999 // TODO: this exists only for adding filenames to test cases -- let's expose this in a saner way later
9000 virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0;
9001 virtual std::vector<TestCaseHandle> const& getAllTests() const = 0;
9002 virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0;
9003 };
9004
9005}
9006
9007#endif // CATCH_INTERFACES_TESTCASE_HPP_INCLUDED
9008
9009#endif // CATCH_INTERFACES_ALL_HPP_INCLUDED
9010
9011
9012#ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
9013#define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
9014
9015
9016namespace Catch {
9017 namespace Detail {
9018 //! Provides case-insensitive `op<` semantics when called
9019 struct CaseInsensitiveLess {
9020 bool operator()( StringRef lhs,
9021 StringRef rhs ) const;
9022 };
9023
9024 //! Provides case-insensitive `op==` semantics when called
9025 struct CaseInsensitiveEqualTo {
9026 bool operator()( StringRef lhs,
9027 StringRef rhs ) const;
9028 };
9029
9030 } // namespace Detail
9031} // namespace Catch
9032
9033#endif // CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED
9034
9035
9036
9037/** \file
9038 * Wrapper for ANDROID_LOGWRITE configuration option
9039 *
9040 * We want to default to enabling it when compiled for android, but
9041 * users of the library should also be able to disable it if they want
9042 * to.
9043 */
9044
9045#ifndef CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
9046#define CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
9047
9048
9049#if defined(__ANDROID__)
9050# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
9051#endif
9052
9053
9054#if defined( CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE ) && \
9055 !defined( CATCH_CONFIG_NO_ANDROID_LOGWRITE ) && \
9056 !defined( CATCH_CONFIG_ANDROID_LOGWRITE )
9057# define CATCH_CONFIG_ANDROID_LOGWRITE
9058#endif
9059
9060#endif // CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED
9061
9062
9063
9064/** \file
9065 * Wrapper for UNCAUGHT_EXCEPTIONS configuration option
9066 *
9067 * For some functionality, Catch2 requires to know whether there is
9068 * an active exception. Because `std::uncaught_exception` is deprecated
9069 * in C++17, we want to use `std::uncaught_exceptions` if possible.
9070 */
9071
9072#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
9073#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
9074
9075
9076#if defined(_MSC_VER)
9077# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
9078# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
9079# endif
9080#endif
9081
9082
9083#include <exception>
9084
9085#if defined(__cpp_lib_uncaught_exceptions) \
9086 && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
9087
9088# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
9089#endif // __cpp_lib_uncaught_exceptions
9090
9091
9092#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
9093 && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
9094 && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
9095
9096# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
9097#endif
9098
9099
9100#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
9101
9102
9103#ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED
9104#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED
9105
9106
9107#include <iosfwd>
9108#include <cstdint>
9109
9110namespace Catch {
9111
9112 enum class ColourMode : std::uint8_t;
9113 class IStream;
9114
9115 struct Colour {
9116 enum Code {
9117 None = 0,
9118
9119 White,
9120 Red,
9121 Green,
9122 Blue,
9123 Cyan,
9124 Yellow,
9125 Grey,
9126
9127 Bright = 0x10,
9128
9129 BrightRed = Bright | Red,
9130 BrightGreen = Bright | Green,
9131 LightGrey = Bright | Grey,
9132 BrightWhite = Bright | White,
9133 BrightYellow = Bright | Yellow,
9134
9135 // By intention
9136 FileName = LightGrey,
9137 Warning = BrightYellow,
9138 ResultError = BrightRed,
9139 ResultSuccess = BrightGreen,
9140 ResultExpectedFailure = Warning,
9141
9142 Error = BrightRed,
9143 Success = Green,
9144 Skip = LightGrey,
9145
9146 OriginalExpression = Cyan,
9147 ReconstructedExpression = BrightYellow,
9148
9149 SecondaryText = LightGrey,
9150 Headers = White
9151 };
9152 };
9153
9154 class ColourImpl {
9155 protected:
9156 //! The associated stream of this ColourImpl instance
9157 IStream* m_stream;
9158 public:
9159 ColourImpl( IStream* stream ): m_stream( stream ) {}
9160
9161 //! RAII wrapper around writing specific colour of text using specific
9162 //! colour impl into a stream.
9163 class ColourGuard {
9164 ColourImpl const* m_colourImpl;
9165 Colour::Code m_code;
9166 bool m_engaged = false;
9167
9168 public:
9169 //! Does **not** engage the guard/start the colour
9170 ColourGuard( Colour::Code code,
9171 ColourImpl const* colour );
9172
9173 ColourGuard( ColourGuard const& rhs ) = delete;
9174 ColourGuard& operator=( ColourGuard const& rhs ) = delete;
9175
9176 ColourGuard( ColourGuard&& rhs ) noexcept;
9177 ColourGuard& operator=( ColourGuard&& rhs ) noexcept;
9178
9179 //! Removes colour _if_ the guard was engaged
9180 ~ColourGuard();
9181
9182 /**
9183 * Explicitly engages colour for given stream.
9184 *
9185 * The API based on operator<< should be preferred.
9186 */
9187 ColourGuard& engage( std::ostream& stream ) &;
9188 /**
9189 * Explicitly engages colour for given stream.
9190 *
9191 * The API based on operator<< should be preferred.
9192 */
9193 ColourGuard&& engage( std::ostream& stream ) &&;
9194
9195 private:
9196 //! Engages the guard and starts using colour
9197 friend std::ostream& operator<<( std::ostream& lhs,
9198 ColourGuard& guard ) {
9199 guard.engageImpl( lhs );
9200 return lhs;
9201 }
9202 //! Engages the guard and starts using colour
9203 friend std::ostream& operator<<( std::ostream& lhs,
9204 ColourGuard&& guard) {
9205 guard.engageImpl( lhs );
9206 return lhs;
9207 }
9208
9209 void engageImpl( std::ostream& stream );
9210
9211 };
9212
9213 virtual ~ColourImpl(); // = default
9214 /**
9215 * Creates a guard object for given colour and this colour impl
9216 *
9217 * **Important:**
9218 * the guard starts disengaged, and has to be engaged explicitly.
9219 */
9220 ColourGuard guardColour( Colour::Code colourCode );
9221
9222 private:
9223 virtual void use( Colour::Code colourCode ) const = 0;
9224 };
9225
9226 //! Provides ColourImpl based on global config and target compilation platform
9227 Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection,
9228 IStream* stream );
9229
9230 //! Checks if specific colour impl has been compiled into the binary
9231 bool isColourImplAvailable( ColourMode colourSelection );
9232
9233} // end namespace Catch
9234
9235#endif // CATCH_CONSOLE_COLOUR_HPP_INCLUDED
9236
9237
9238#ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED
9239#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED
9240
9241// This include must be kept so that user's configured value for CONSOLE_WIDTH
9242// is used before we attempt to provide a default value
9243
9244#ifndef CATCH_CONFIG_CONSOLE_WIDTH
9245#define CATCH_CONFIG_CONSOLE_WIDTH 80
9246#endif
9247
9248#endif // CATCH_CONSOLE_WIDTH_HPP_INCLUDED
9249
9250
9251#ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
9252#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
9253
9254
9255#include <cstddef>
9256#include <initializer_list>
9257
9258// We want a simple polyfill over `std::empty`, `std::size` and so on
9259// for C++14 or C++ libraries with incomplete support.
9260// We also have to handle that MSVC std lib will happily provide these
9261// under older standards.
9262#if defined(CATCH_CPP17_OR_GREATER) || defined(_MSC_VER)
9263
9264// We are already using this header either way, so there shouldn't
9265// be much additional overhead in including it to get the feature
9266// test macros
9267#include <string>
9268
9269# if !defined(__cpp_lib_nonmember_container_access)
9270# define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
9271# endif
9272
9273#else
9274#define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
9275#endif
9276
9277
9278
9279namespace Catch {
9280namespace Detail {
9281
9282#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
9283 template <typename Container>
9284 constexpr auto empty(Container const& cont) -> decltype(cont.empty()) {
9285 return cont.empty();
9286 }
9287 template <typename T, std::size_t N>
9288 constexpr bool empty(const T (&)[N]) noexcept {
9289 // GCC < 7 does not support the const T(&)[] parameter syntax
9290 // so we have to ignore the length explicitly
9291 (void)N;
9292 return false;
9293 }
9294 template <typename T>
9295 constexpr bool empty(std::initializer_list<T> list) noexcept {
9296 return list.size() > 0;
9297 }
9298
9299
9300 template <typename Container>
9301 constexpr auto size(Container const& cont) -> decltype(cont.size()) {
9302 return cont.size();
9303 }
9304 template <typename T, std::size_t N>
9305 constexpr std::size_t size(const T(&)[N]) noexcept {
9306 return N;
9307 }
9308#endif // CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS
9309
9310} // end namespace Detail
9311} // end namespace Catch
9312
9313
9314
9315#endif // CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED
9316
9317
9318#ifndef CATCH_DEBUG_CONSOLE_HPP_INCLUDED
9319#define CATCH_DEBUG_CONSOLE_HPP_INCLUDED
9320
9321#include <string>
9322
9323namespace Catch {
9324 void writeToDebugConsole( std::string const& text );
9325}
9326
9327#endif // CATCH_DEBUG_CONSOLE_HPP_INCLUDED
9328
9329
9330#ifndef CATCH_DEBUGGER_HPP_INCLUDED
9331#define CATCH_DEBUGGER_HPP_INCLUDED
9332
9333
9334namespace Catch {
9335 bool isDebuggerActive();
9336}
9337
9338#ifdef CATCH_PLATFORM_MAC
9339
9340 #if defined(__i386__) || defined(__x86_64__)
9341 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
9342 #elif defined(__aarch64__)
9343 #define CATCH_TRAP() __asm__(".inst 0xd43e0000")
9344 #elif defined(__POWERPC__)
9345 #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
9346 : : : "memory","r0","r3","r4" ) /* NOLINT */
9347 #endif
9348
9349#elif defined(CATCH_PLATFORM_IPHONE)
9350
9351 // use inline assembler
9352 #if defined(__i386__) || defined(__x86_64__)
9353 #define CATCH_TRAP() __asm__("int $3")
9354 #elif defined(__aarch64__)
9355 #define CATCH_TRAP() __asm__(".inst 0xd4200000")
9356 #elif defined(__arm__) && !defined(__thumb__)
9357 #define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
9358 #elif defined(__arm__) && defined(__thumb__)
9359 #define CATCH_TRAP() __asm__(".inst 0xde01")
9360 #endif
9361
9362#elif defined(CATCH_PLATFORM_LINUX)
9363 // If we can use inline assembler, do it because this allows us to break
9364 // directly at the location of the failing check instead of breaking inside
9365 // raise() called from it, i.e. one stack frame below.
9366 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
9367 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
9368 #else // Fall back to the generic way.
9369 #include <signal.h>
9370
9371 #define CATCH_TRAP() raise(SIGTRAP)
9372 #endif
9373#elif defined(_MSC_VER)
9374 #define CATCH_TRAP() __debugbreak()
9375#elif defined(__MINGW32__)
9376 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
9377 #define CATCH_TRAP() DebugBreak()
9378#endif
9379
9380#ifndef CATCH_BREAK_INTO_DEBUGGER
9381 #ifdef CATCH_TRAP
9382 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
9383 #else
9384 #define CATCH_BREAK_INTO_DEBUGGER() []{}()
9385 #endif
9386#endif
9387
9388#endif // CATCH_DEBUGGER_HPP_INCLUDED
9389
9390
9391#ifndef CATCH_ENFORCE_HPP_INCLUDED
9392#define CATCH_ENFORCE_HPP_INCLUDED
9393
9394
9395#include <exception>
9396
9397namespace Catch {
9398#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
9399 template <typename Ex>
9400 [[noreturn]]
9401 void throw_exception(Ex const& e) {
9402 throw e;
9403 }
9404#else // ^^ Exceptions are enabled // Exceptions are disabled vv
9405 [[noreturn]]
9406 void throw_exception(std::exception const& e);
9407#endif
9408
9409 [[noreturn]]
9410 void throw_logic_error(std::string const& msg);
9411 [[noreturn]]
9412 void throw_domain_error(std::string const& msg);
9413 [[noreturn]]
9414 void throw_runtime_error(std::string const& msg);
9415
9416} // namespace Catch;
9417
9418#define CATCH_MAKE_MSG(...) \
9419 (Catch::ReusableStringStream() << __VA_ARGS__).str()
9420
9421#define CATCH_INTERNAL_ERROR(...) \
9422 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
9423
9424#define CATCH_ERROR(...) \
9425 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
9426
9427#define CATCH_RUNTIME_ERROR(...) \
9428 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
9429
9430#define CATCH_ENFORCE( condition, ... ) \
9431 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
9432
9433
9434#endif // CATCH_ENFORCE_HPP_INCLUDED
9435
9436
9437#ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
9438#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
9439
9440
9441#include <vector>
9442
9443namespace Catch {
9444
9445 namespace Detail {
9446
9447 Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
9448
9449 class EnumValuesRegistry : public IMutableEnumValuesRegistry {
9450
9451 std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos;
9452
9453 EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override;
9454 };
9455
9456 std::vector<StringRef> parseEnums( StringRef enums );
9457
9458 } // Detail
9459
9460} // Catch
9461
9462#endif // CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED
9463
9464
9465#ifndef CATCH_ERRNO_GUARD_HPP_INCLUDED
9466#define CATCH_ERRNO_GUARD_HPP_INCLUDED
9467
9468namespace Catch {
9469
9470 //! Simple RAII class that stores the value of `errno`
9471 //! at construction and restores it at destruction.
9472 class ErrnoGuard {
9473 public:
9474 // Keep these outlined to avoid dragging in macros from <cerrno>
9475
9476 ErrnoGuard();
9477 ~ErrnoGuard();
9478 private:
9479 int m_oldErrno;
9480 };
9481
9482}
9483
9484#endif // CATCH_ERRNO_GUARD_HPP_INCLUDED
9485
9486
9487#ifndef CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
9488#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
9489
9490
9491#include <vector>
9492#include <string>
9493
9494namespace Catch {
9495
9496 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
9497 public:
9498 ~ExceptionTranslatorRegistry() override;
9499 void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator );
9500 std::string translateActiveException() const override;
9501
9502 private:
9503 ExceptionTranslators m_translators;
9504 };
9505}
9506
9507#endif // CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
9508
9509
9510#ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
9511#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
9512
9513#include <cassert>
9514
9515namespace Catch {
9516
9517 /**
9518 * Wrapper for platform-specific fatal error (signals/SEH) handlers
9519 *
9520 * Tries to be cooperative with other handlers, and not step over
9521 * other handlers. This means that unknown structured exceptions
9522 * are passed on, previous signal handlers are called, and so on.
9523 *
9524 * Can only be instantiated once, and assumes that once a signal
9525 * is caught, the binary will end up terminating. Thus, there
9526 */
9527 class FatalConditionHandler {
9528 bool m_started = false;
9529
9530 // Install/disengage implementation for specific platform.
9531 // Should be if-defed to work on current platform, can assume
9532 // engage-disengage 1:1 pairing.
9533 void engage_platform();
9534 void disengage_platform() noexcept;
9535 public:
9536 // Should also have platform-specific implementations as needed
9537 FatalConditionHandler();
9538 ~FatalConditionHandler();
9539
9540 void engage() {
9541 assert(!m_started && "Handler cannot be installed twice.");
9542 m_started = true;
9543 engage_platform();
9544 }
9545
9546 void disengage() noexcept {
9547 assert(m_started && "Handler cannot be uninstalled without being installed first");
9548 m_started = false;
9549 disengage_platform();
9550 }
9551 };
9552
9553 //! Simple RAII guard for (dis)engaging the FatalConditionHandler
9554 class FatalConditionHandlerGuard {
9555 FatalConditionHandler* m_handler;
9556 public:
9557 FatalConditionHandlerGuard(FatalConditionHandler* handler):
9558 m_handler(handler) {
9559 m_handler->engage();
9560 }
9561 ~FatalConditionHandlerGuard() {
9562 m_handler->disengage();
9563 }
9564 };
9565
9566} // end namespace Catch
9567
9568#endif // CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED
9569
9570
9571#ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
9572#define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
9573
9574
9575#include <cassert>
9576#include <cmath>
9577#include <cstdint>
9578#include <utility>
9579#include <limits>
9580
9581namespace Catch {
9582 namespace Detail {
9583
9584 uint32_t convertToBits(float f);
9585 uint64_t convertToBits(double d);
9586
9587 // Used when we know we want == comparison of two doubles
9588 // to centralize warning suppression
9589 bool directCompare( float lhs, float rhs );
9590 bool directCompare( double lhs, double rhs );
9591
9592 } // end namespace Detail
9593
9594
9595
9596#if defined( __GNUC__ ) || defined( __clang__ )
9597# pragma GCC diagnostic push
9598 // We do a bunch of direct compensations of floating point numbers,
9599 // because we know what we are doing and actually do want the direct
9600 // comparison behaviour.
9601# pragma GCC diagnostic ignored "-Wfloat-equal"
9602#endif
9603
9604 /**
9605 * Calculates the ULP distance between two floating point numbers
9606 *
9607 * The ULP distance of two floating point numbers is the count of
9608 * valid floating point numbers representable between them.
9609 *
9610 * There are some exceptions between how this function counts the
9611 * distance, and the interpretation of the standard as implemented.
9612 * by e.g. `nextafter`. For this function it always holds that:
9613 * * `(x == y) => ulpDistance(x, y) == 0` (so `ulpDistance(-0, 0) == 0`)
9614 * * `ulpDistance(maxFinite, INF) == 1`
9615 * * `ulpDistance(x, -x) == 2 * ulpDistance(x, 0)`
9616 *
9617 * \pre `!isnan( lhs )`
9618 * \pre `!isnan( rhs )`
9619 * \pre floating point numbers are represented in IEEE-754 format
9620 */
9621 template <typename FP>
9622 uint64_t ulpDistance( FP lhs, FP rhs ) {
9623 assert( std::numeric_limits<FP>::is_iec559 &&
9624 "ulpDistance assumes IEEE-754 format for floating point types" );
9625 assert( !Catch::isnan( lhs ) &&
9626 "Distance between NaN and number is not meaningful" );
9627 assert( !Catch::isnan( rhs ) &&
9628 "Distance between NaN and number is not meaningful" );
9629
9630 // We want X == Y to imply 0 ULP distance even if X and Y aren't
9631 // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
9632 if ( lhs == rhs ) { return 0; }
9633
9634 // We need a properly typed positive zero for type inference.
9635 static constexpr FP positive_zero{};
9636
9637 // We want to ensure that +/- 0 is always represented as positive zero
9638 if ( lhs == positive_zero ) { lhs = positive_zero; }
9639 if ( rhs == positive_zero ) { rhs = positive_zero; }
9640
9641 // If arguments have different signs, we can handle them by summing
9642 // how far are they from 0 each.
9643 if ( std::signbit( lhs ) != std::signbit( rhs ) ) {
9644 return ulpDistance( std::abs( lhs ), positive_zero ) +
9645 ulpDistance( std::abs( rhs ), positive_zero );
9646 }
9647
9648 // When both lhs and rhs are of the same sign, we can just
9649 // read the numbers bitwise as integers, and then subtract them
9650 // (assuming IEEE).
9651 uint64_t lc = Detail::convertToBits( lhs );
9652 uint64_t rc = Detail::convertToBits( rhs );
9653
9654 // The ulp distance between two numbers is symmetric, so to avoid
9655 // dealing with overflows we want the bigger converted number on the lhs
9656 if ( lc < rc ) {
9657 std::swap( lc, rc );
9658 }
9659
9660 return lc - rc;
9661 }
9662
9663#if defined( __GNUC__ ) || defined( __clang__ )
9664# pragma GCC diagnostic pop
9665#endif
9666
9667
9668} // end namespace Catch
9669
9670#endif // CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED
9671
9672
9673#ifndef CATCH_GETENV_HPP_INCLUDED
9674#define CATCH_GETENV_HPP_INCLUDED
9675
9676namespace Catch {
9677namespace Detail {
9678
9679 //! Wrapper over `std::getenv` that compiles on UWP (and always returns nullptr there)
9680 char const* getEnv(char const* varName);
9681
9682}
9683}
9684
9685#endif // CATCH_GETENV_HPP_INCLUDED
9686
9687
9688#ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED
9689#define CATCH_IS_PERMUTATION_HPP_INCLUDED
9690
9691#include <algorithm>
9692#include <iterator>
9693
9694namespace Catch {
9695 namespace Detail {
9696
9697 template <typename ForwardIter,
9698 typename Sentinel,
9699 typename T,
9700 typename Comparator>
9701 ForwardIter find_sentinel( ForwardIter start,
9702 Sentinel sentinel,
9703 T const& value,
9704 Comparator cmp ) {
9705 while ( start != sentinel ) {
9706 if ( cmp( *start, value ) ) { break; }
9707 ++start;
9708 }
9709 return start;
9710 }
9711
9712 template <typename ForwardIter,
9713 typename Sentinel,
9714 typename T,
9715 typename Comparator>
9716 std::ptrdiff_t count_sentinel( ForwardIter start,
9717 Sentinel sentinel,
9718 T const& value,
9719 Comparator cmp ) {
9720 std::ptrdiff_t count = 0;
9721 while ( start != sentinel ) {
9722 if ( cmp( *start, value ) ) { ++count; }
9723 ++start;
9724 }
9725 return count;
9726 }
9727
9728 template <typename ForwardIter, typename Sentinel>
9729 std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value,
9730 std::ptrdiff_t>
9731 sentinel_distance( ForwardIter iter, const Sentinel sentinel ) {
9732 std::ptrdiff_t dist = 0;
9733 while ( iter != sentinel ) {
9734 ++iter;
9735 ++dist;
9736 }
9737 return dist;
9738 }
9739
9740 template <typename ForwardIter>
9741 std::ptrdiff_t sentinel_distance( ForwardIter first,
9742 ForwardIter last ) {
9743 return std::distance( first, last );
9744 }
9745
9746 template <typename ForwardIter1,
9747 typename Sentinel1,
9748 typename ForwardIter2,
9749 typename Sentinel2,
9750 typename Comparator>
9751 bool check_element_counts( ForwardIter1 first_1,
9752 const Sentinel1 end_1,
9753 ForwardIter2 first_2,
9754 const Sentinel2 end_2,
9755 Comparator cmp ) {
9756 auto cursor = first_1;
9757 while ( cursor != end_1 ) {
9758 if ( find_sentinel( first_1, cursor, *cursor, cmp ) ==
9759 cursor ) {
9760 // we haven't checked this element yet
9761 const auto count_in_range_2 =
9762 count_sentinel( first_2, end_2, *cursor, cmp );
9763 // Not a single instance in 2nd range, so it cannot be a
9764 // permutation of 1st range
9765 if ( count_in_range_2 == 0 ) { return false; }
9766
9767 const auto count_in_range_1 =
9768 count_sentinel( cursor, end_1, *cursor, cmp );
9769 if ( count_in_range_1 != count_in_range_2 ) {
9770 return false;
9771 }
9772 }
9773
9774 ++cursor;
9775 }
9776
9777 return true;
9778 }
9779
9780 template <typename ForwardIter1,
9781 typename Sentinel1,
9782 typename ForwardIter2,
9783 typename Sentinel2,
9784 typename Comparator>
9785 bool is_permutation( ForwardIter1 first_1,
9786 const Sentinel1 end_1,
9787 ForwardIter2 first_2,
9788 const Sentinel2 end_2,
9789 Comparator cmp ) {
9790 // TODO: no optimization for stronger iterators, because we would also have to constrain on sentinel vs not sentinel types
9791 // TODO: Comparator has to be "both sides", e.g. a == b => b == a
9792 // This skips shared prefix of the two ranges
9793 while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) {
9794 ++first_1;
9795 ++first_2;
9796 }
9797
9798 // We need to handle case where at least one of the ranges has no more elements
9799 if (first_1 == end_1 || first_2 == end_2) {
9800 return first_1 == end_1 && first_2 == end_2;
9801 }
9802
9803 // pair counting is n**2, so we pay linear walk to compare the sizes first
9804 auto dist_1 = sentinel_distance( first_1, end_1 );
9805 auto dist_2 = sentinel_distance( first_2, end_2 );
9806
9807 if (dist_1 != dist_2) { return false; }
9808
9809 // Since we do not try to handle stronger iterators pair (e.g.
9810 // bidir) optimally, the only thing left to do is to check counts in
9811 // the remaining ranges.
9812 return check_element_counts( first_1, end_1, first_2, end_2, cmp );
9813 }
9814
9815 } // namespace Detail
9816} // namespace Catch
9817
9818#endif // CATCH_IS_PERMUTATION_HPP_INCLUDED
9819
9820
9821#ifndef CATCH_ISTREAM_HPP_INCLUDED
9822#define CATCH_ISTREAM_HPP_INCLUDED
9823
9824
9825#include <iosfwd>
9826#include <cstddef>
9827#include <ostream>
9828#include <string>
9829
9830namespace Catch {
9831
9832 class IStream {
9833 public:
9834 virtual ~IStream(); // = default
9835 virtual std::ostream& stream() = 0;
9836 /**
9837 * Best guess on whether the instance is writing to a console (e.g. via stdout/stderr)
9838 *
9839 * This is useful for e.g. Win32 colour support, because the Win32
9840 * API manipulates console directly, unlike POSIX escape codes,
9841 * that can be written anywhere.
9842 *
9843 * Due to variety of ways to change where the stdout/stderr is
9844 * _actually_ being written, users should always assume that
9845 * the answer might be wrong.
9846 */
9847 virtual bool isConsole() const { return false; }
9848 };
9849
9850 /**
9851 * Creates a stream wrapper that writes to specific file.
9852 *
9853 * Also recognizes 4 special filenames
9854 * * `-` for stdout
9855 * * `%stdout` for stdout
9856 * * `%stderr` for stderr
9857 * * `%debug` for platform specific debugging output
9858 *
9859 * \throws if passed an unrecognized %-prefixed stream
9860 */
9861 auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream>;
9862
9863}
9864
9865#endif // CATCH_STREAM_HPP_INCLUDED
9866
9867
9868#ifndef CATCH_JSONWRITER_HPP_INCLUDED
9869#define CATCH_JSONWRITER_HPP_INCLUDED
9870
9871
9872#include <cstdint>
9873#include <sstream>
9874
9875namespace Catch {
9876 class JsonObjectWriter;
9877 class JsonArrayWriter;
9878
9879 struct JsonUtils {
9880 static void indent( std::ostream& os, std::uint64_t level );
9881 static void appendCommaNewline( std::ostream& os,
9882 bool& should_comma,
9883 std::uint64_t level );
9884 };
9885
9886 class JsonValueWriter {
9887 public:
9888 JsonValueWriter( std::ostream& os );
9889 JsonValueWriter( std::ostream& os, std::uint64_t indent_level );
9890
9891 JsonObjectWriter writeObject() &&;
9892 JsonArrayWriter writeArray() &&;
9893
9894 template <typename T>
9895 void write( T const& value ) && {
9896 writeImpl( value, !std::is_arithmetic<T>::value );
9897 }
9898 void write( StringRef value ) &&;
9899 void write( bool value ) &&;
9900
9901 private:
9902 void writeImpl( StringRef value, bool quote );
9903
9904 // Without this SFINAE, this overload is a better match
9905 // for `std::string`, `char const*`, `char const[N]` args.
9906 // While it would still work, it would cause code bloat
9907 // and multiple iteration over the strings
9908 template <typename T,
9909 typename = typename std::enable_if_t<
9910 !std::is_convertible<T, StringRef>::value>>
9911 void writeImpl( T const& value, bool quote_value ) {
9912 m_sstream << value;
9913 writeImpl( m_sstream.str(), quote_value );
9914 }
9915
9916 std::ostream& m_os;
9917 std::stringstream m_sstream;
9918 std::uint64_t m_indent_level;
9919 };
9920
9921 class JsonObjectWriter {
9922 public:
9923 JsonObjectWriter( std::ostream& os );
9924 JsonObjectWriter( std::ostream& os, std::uint64_t indent_level );
9925
9926 JsonObjectWriter( JsonObjectWriter&& source ) noexcept;
9927 JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete;
9928
9929 ~JsonObjectWriter();
9930
9931 JsonValueWriter write( StringRef key );
9932
9933 private:
9934 std::ostream& m_os;
9935 std::uint64_t m_indent_level;
9936 bool m_should_comma = false;
9937 bool m_active = true;
9938 };
9939
9940 class JsonArrayWriter {
9941 public:
9942 JsonArrayWriter( std::ostream& os );
9943 JsonArrayWriter( std::ostream& os, std::uint64_t indent_level );
9944
9945 JsonArrayWriter( JsonArrayWriter&& source ) noexcept;
9946 JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete;
9947
9948 ~JsonArrayWriter();
9949
9950 JsonObjectWriter writeObject();
9951 JsonArrayWriter writeArray();
9952
9953 template <typename T>
9954 JsonArrayWriter& write( T const& value ) {
9955 return writeImpl( value );
9956 }
9957
9958 JsonArrayWriter& write( bool value );
9959
9960 private:
9961 template <typename T>
9962 JsonArrayWriter& writeImpl( T const& value ) {
9963 JsonUtils::appendCommaNewline(
9964 m_os, m_should_comma, m_indent_level + 1 );
9965 JsonValueWriter{ m_os }.write( value );
9966
9967 return *this;
9968 }
9969
9970 std::ostream& m_os;
9971 std::uint64_t m_indent_level;
9972 bool m_should_comma = false;
9973 bool m_active = true;
9974 };
9975
9976} // namespace Catch
9977
9978#endif // CATCH_JSONWRITER_HPP_INCLUDED
9979
9980
9981#ifndef CATCH_LEAK_DETECTOR_HPP_INCLUDED
9982#define CATCH_LEAK_DETECTOR_HPP_INCLUDED
9983
9984namespace Catch {
9985
9986 struct LeakDetector {
9987 LeakDetector();
9988 ~LeakDetector();
9989 };
9990
9991}
9992#endif // CATCH_LEAK_DETECTOR_HPP_INCLUDED
9993
9994
9995#ifndef CATCH_LIST_HPP_INCLUDED
9996#define CATCH_LIST_HPP_INCLUDED
9997
9998
9999#include <set>
10000#include <string>
10001
10002
10003namespace Catch {
10004
10005 class IEventListener;
10006 class Config;
10007
10008
10009 struct ReporterDescription {
10010 std::string name, description;
10011 };
10012 struct ListenerDescription {
10013 StringRef name;
10014 std::string description;
10015 };
10016
10017 struct TagInfo {
10018 void add(StringRef spelling);
10019 std::string all() const;
10020
10021 std::set<StringRef> spellings;
10022 std::size_t count = 0;
10023 };
10024
10025 bool list( IEventListener& reporter, Config const& config );
10026
10027} // end namespace Catch
10028
10029#endif // CATCH_LIST_HPP_INCLUDED
10030
10031
10032#ifndef CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
10033#define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
10034
10035
10036#include <cstdio>
10037#include <iosfwd>
10038#include <string>
10039
10040namespace Catch {
10041
10042 class RedirectedStream {
10043 std::ostream& m_originalStream;
10044 std::ostream& m_redirectionStream;
10045 std::streambuf* m_prevBuf;
10046
10047 public:
10048 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
10049 ~RedirectedStream();
10050 };
10051
10052 class RedirectedStdOut {
10053 ReusableStringStream m_rss;
10054 RedirectedStream m_cout;
10055 public:
10056 RedirectedStdOut();
10057 auto str() const -> std::string;
10058 };
10059
10060 // StdErr has two constituent streams in C++, std::cerr and std::clog
10061 // This means that we need to redirect 2 streams into 1 to keep proper
10062 // order of writes
10063 class RedirectedStdErr {
10064 ReusableStringStream m_rss;
10065 RedirectedStream m_cerr;
10066 RedirectedStream m_clog;
10067 public:
10068 RedirectedStdErr();
10069 auto str() const -> std::string;
10070 };
10071
10072 class RedirectedStreams {
10073 public:
10074 RedirectedStreams(RedirectedStreams const&) = delete;
10075 RedirectedStreams& operator=(RedirectedStreams const&) = delete;
10076 RedirectedStreams(RedirectedStreams&&) = delete;
10077 RedirectedStreams& operator=(RedirectedStreams&&) = delete;
10078
10079 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
10080 ~RedirectedStreams();
10081 private:
10082 std::string& m_redirectedCout;
10083 std::string& m_redirectedCerr;
10084 RedirectedStdOut m_redirectedStdOut;
10085 RedirectedStdErr m_redirectedStdErr;
10086 };
10087
10088#if defined(CATCH_CONFIG_NEW_CAPTURE)
10089
10090 // Windows's implementation of std::tmpfile is terrible (it tries
10091 // to create a file inside system folder, thus requiring elevated
10092 // privileges for the binary), so we have to use tmpnam(_s) and
10093 // create the file ourselves there.
10094 class TempFile {
10095 public:
10096 TempFile(TempFile const&) = delete;
10097 TempFile& operator=(TempFile const&) = delete;
10098 TempFile(TempFile&&) = delete;
10099 TempFile& operator=(TempFile&&) = delete;
10100
10101 TempFile();
10102 ~TempFile();
10103
10104 std::FILE* getFile();
10105 std::string getContents();
10106
10107 private:
10108 std::FILE* m_file = nullptr;
10109 #if defined(_MSC_VER)
10110 char m_buffer[L_tmpnam] = { 0 };
10111 #endif
10112 };
10113
10114
10115 class OutputRedirect {
10116 public:
10117 OutputRedirect(OutputRedirect const&) = delete;
10118 OutputRedirect& operator=(OutputRedirect const&) = delete;
10119 OutputRedirect(OutputRedirect&&) = delete;
10120 OutputRedirect& operator=(OutputRedirect&&) = delete;
10121
10122
10123 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
10124 ~OutputRedirect();
10125
10126 private:
10127 int m_originalStdout = -1;
10128 int m_originalStderr = -1;
10129 TempFile m_stdoutFile;
10130 TempFile m_stderrFile;
10131 std::string& m_stdoutDest;
10132 std::string& m_stderrDest;
10133 };
10134
10135#endif
10136
10137} // end namespace Catch
10138
10139#endif // CATCH_OUTPUT_REDIRECT_HPP_INCLUDED
10140
10141
10142#ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED
10143#define CATCH_PARSE_NUMBERS_HPP_INCLUDED
10144
10145
10146#include <string>
10147
10148namespace Catch {
10149
10150 /**
10151 * Parses unsigned int from the input, using provided base
10152 *
10153 * Effectively a wrapper around std::stoul but with better error checking
10154 * e.g. "-1" is rejected, instead of being parsed as UINT_MAX.
10155 */
10156 Optional<unsigned int> parseUInt(std::string const& input, int base = 10);
10157}
10158
10159#endif // CATCH_PARSE_NUMBERS_HPP_INCLUDED
10160
10161
10162#ifndef CATCH_REPORTER_REGISTRY_HPP_INCLUDED
10163#define CATCH_REPORTER_REGISTRY_HPP_INCLUDED
10164
10165
10166#include <map>
10167#include <string>
10168#include <vector>
10169
10170namespace Catch {
10171
10172 class IEventListener;
10173 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
10174 class IReporterFactory;
10175 using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>;
10176 struct ReporterConfig;
10177 class EventListenerFactory;
10178
10179 class ReporterRegistry {
10180 struct ReporterRegistryImpl;
10181 Detail::unique_ptr<ReporterRegistryImpl> m_impl;
10182
10183 public:
10184 ReporterRegistry();
10185 ~ReporterRegistry(); // = default;
10186
10187 IEventListenerPtr create( std::string const& name,
10188 ReporterConfig&& config ) const;
10189
10190 void registerReporter( std::string const& name,
10191 IReporterFactoryPtr factory );
10192
10193 void
10194 registerListener( Detail::unique_ptr<EventListenerFactory> factory );
10195
10196 std::map<std::string,
10197 IReporterFactoryPtr,
10198 Detail::CaseInsensitiveLess> const&
10199 getFactories() const;
10200
10201 std::vector<Detail::unique_ptr<EventListenerFactory>> const&
10202 getListeners() const;
10203 };
10204
10205} // end namespace Catch
10206
10207#endif // CATCH_REPORTER_REGISTRY_HPP_INCLUDED
10208
10209
10210#ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED
10211#define CATCH_RUN_CONTEXT_HPP_INCLUDED
10212
10213
10214
10215#ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
10216#define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
10217
10218
10219#include <string>
10220#include <vector>
10221
10222namespace Catch {
10223namespace TestCaseTracking {
10224
10225 struct NameAndLocation {
10226 std::string name;
10227 SourceLineInfo location;
10228
10229 NameAndLocation( std::string&& _name, SourceLineInfo const& _location );
10230 friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {
10231 // This is a very cheap check that should have a very high hit rate.
10232 // If we get to SourceLineInfo::operator==, we will redo it, but the
10233 // cost of repeating is trivial at that point (we will be paying
10234 // multiple strcmp/memcmps at that point).
10235 if ( lhs.location.line != rhs.location.line ) { return false; }
10236 return lhs.name == rhs.name && lhs.location == rhs.location;
10237 }
10238 friend bool operator!=(NameAndLocation const& lhs,
10239 NameAndLocation const& rhs) {
10240 return !( lhs == rhs );
10241 }
10242 };
10243
10244 /**
10245 * This is a variant of `NameAndLocation` that does not own the name string
10246 *
10247 * This avoids extra allocations when trying to locate a tracker by its
10248 * name and location, as long as we make sure that trackers only keep
10249 * around the owning variant.
10250 */
10251 struct NameAndLocationRef {
10252 StringRef name;
10253 SourceLineInfo location;
10254
10255 constexpr NameAndLocationRef( StringRef name_,
10256 SourceLineInfo location_ ):
10257 name( name_ ), location( location_ ) {}
10258
10259 friend bool operator==( NameAndLocation const& lhs,
10260 NameAndLocationRef const& rhs ) {
10261 // This is a very cheap check that should have a very high hit rate.
10262 // If we get to SourceLineInfo::operator==, we will redo it, but the
10263 // cost of repeating is trivial at that point (we will be paying
10264 // multiple strcmp/memcmps at that point).
10265 if ( lhs.location.line != rhs.location.line ) { return false; }
10266 return StringRef( lhs.name ) == rhs.name &&
10267 lhs.location == rhs.location;
10268 }
10269 friend bool operator==( NameAndLocationRef const& lhs,
10270 NameAndLocation const& rhs ) {
10271 return rhs == lhs;
10272 }
10273 };
10274
10275 class ITracker;
10276
10277 using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>;
10278
10279 class ITracker {
10280 NameAndLocation m_nameAndLocation;
10281
10282 using Children = std::vector<ITrackerPtr>;
10283
10284 protected:
10285 enum CycleState {
10286 NotStarted,
10287 Executing,
10288 ExecutingChildren,
10289 NeedsAnotherRun,
10290 CompletedSuccessfully,
10291 Failed
10292 };
10293
10294 ITracker* m_parent = nullptr;
10295 Children m_children;
10296 CycleState m_runState = NotStarted;
10297
10298 public:
10299 ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ):
10300 m_nameAndLocation( CATCH_MOVE(nameAndLoc) ),
10301 m_parent( parent )
10302 {}
10303
10304
10305 // static queries
10306 NameAndLocation const& nameAndLocation() const {
10307 return m_nameAndLocation;
10308 }
10309 ITracker* parent() const {
10310 return m_parent;
10311 }
10312
10313 virtual ~ITracker(); // = default
10314
10315
10316 // dynamic queries
10317
10318 //! Returns true if tracker run to completion (successfully or not)
10319 virtual bool isComplete() const = 0;
10320 //! Returns true if tracker run to completion successfully
10321 bool isSuccessfullyCompleted() const {
10322 return m_runState == CompletedSuccessfully;
10323 }
10324 //! Returns true if tracker has started but hasn't been completed
10325 bool isOpen() const;
10326 //! Returns true iff tracker has started
10327 bool hasStarted() const;
10328
10329 // actions
10330 virtual void close() = 0; // Successfully complete
10331 virtual void fail() = 0;
10332 void markAsNeedingAnotherRun();
10333
10334 //! Register a nested ITracker
10335 void addChild( ITrackerPtr&& child );
10336 /**
10337 * Returns ptr to specific child if register with this tracker.
10338 *
10339 * Returns nullptr if not found.
10340 */
10341 ITracker* findChild( NameAndLocationRef const& nameAndLocation );
10342 //! Have any children been added?
10343 bool hasChildren() const {
10344 return !m_children.empty();
10345 }
10346
10347
10348 //! Marks tracker as executing a child, doing se recursively up the tree
10349 void openChild();
10350
10351 /**
10352 * Returns true if the instance is a section tracker
10353 *
10354 * Subclasses should override to true if they are, replaces RTTI
10355 * for internal debug checks.
10356 */
10357 virtual bool isSectionTracker() const;
10358 /**
10359 * Returns true if the instance is a generator tracker
10360 *
10361 * Subclasses should override to true if they are, replaces RTTI
10362 * for internal debug checks.
10363 */
10364 virtual bool isGeneratorTracker() const;
10365 };
10366
10367 class TrackerContext {
10368
10369 enum RunState {
10370 NotStarted,
10371 Executing,
10372 CompletedCycle
10373 };
10374
10375 ITrackerPtr m_rootTracker;
10376 ITracker* m_currentTracker = nullptr;
10377 RunState m_runState = NotStarted;
10378
10379 public:
10380
10381 ITracker& startRun();
10382
10383 void startCycle() {
10384 m_currentTracker = m_rootTracker.get();
10385 m_runState = Executing;
10386 }
10387 void completeCycle();
10388
10389 bool completedCycle() const;
10390 ITracker& currentTracker() { return *m_currentTracker; }
10391 void setCurrentTracker( ITracker* tracker );
10392 };
10393
10394 class TrackerBase : public ITracker {
10395 protected:
10396
10397 TrackerContext& m_ctx;
10398
10399 public:
10400 TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
10401
10402 bool isComplete() const override;
10403
10404 void open();
10405
10406 void close() override;
10407 void fail() override;
10408
10409 private:
10410 void moveToParent();
10411 void moveToThis();
10412 };
10413
10414 class SectionTracker : public TrackerBase {
10415 std::vector<StringRef> m_filters;
10416 // Note that lifetime-wise we piggy back off the name stored in the `ITracker` parent`.
10417 // Currently it allocates owns the name, so this is safe. If it is later refactored
10418 // to not own the name, the name still has to outlive the `ITracker` parent, so
10419 // this should still be safe.
10420 StringRef m_trimmed_name;
10421 public:
10422 SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent );
10423
10424 bool isSectionTracker() const override;
10425
10426 bool isComplete() const override;
10427
10428 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation );
10429
10430 void tryOpen();
10431
10432 void addInitialFilters( std::vector<std::string> const& filters );
10433 void addNextFilters( std::vector<StringRef> const& filters );
10434 //! Returns filters active in this tracker
10435 std::vector<StringRef> const& getFilters() const { return m_filters; }
10436 //! Returns whitespace-trimmed name of the tracked section
10437 StringRef trimmedName() const;
10438 };
10439
10440} // namespace TestCaseTracking
10441
10442using TestCaseTracking::ITracker;
10443using TestCaseTracking::TrackerContext;
10444using TestCaseTracking::SectionTracker;
10445
10446} // namespace Catch
10447
10448#endif // CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
10449
10450#include <string>
10451
10452namespace Catch {
10453
10454 class IGeneratorTracker;
10455 class IConfig;
10456 class IEventListener;
10457 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
10458
10459 ///////////////////////////////////////////////////////////////////////////
10460
10461 class RunContext final : public IResultCapture {
10462
10463 public:
10464 RunContext( RunContext const& ) = delete;
10465 RunContext& operator =( RunContext const& ) = delete;
10466
10467 explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter );
10468
10469 ~RunContext() override;
10470
10471 Totals runTest(TestCaseHandle const& testCase);
10472
10473 public: // IResultCapture
10474
10475 // Assertion handlers
10476 void handleExpr
10477 ( AssertionInfo const& info,
10478 ITransientExpression const& expr,
10479 AssertionReaction& reaction ) override;
10480 void handleMessage
10481 ( AssertionInfo const& info,
10482 ResultWas::OfType resultType,
10483 StringRef message,
10484 AssertionReaction& reaction ) override;
10485 void handleUnexpectedExceptionNotThrown
10486 ( AssertionInfo const& info,
10487 AssertionReaction& reaction ) override;
10488 void handleUnexpectedInflightException
10489 ( AssertionInfo const& info,
10490 std::string&& message,
10491 AssertionReaction& reaction ) override;
10492 void handleIncomplete
10493 ( AssertionInfo const& info ) override;
10494 void handleNonExpr
10495 ( AssertionInfo const &info,
10496 ResultWas::OfType resultType,
10497 AssertionReaction &reaction ) override;
10498
10499 void notifyAssertionStarted( AssertionInfo const& info ) override;
10500 bool sectionStarted( StringRef sectionName,
10501 SourceLineInfo const& sectionLineInfo,
10502 Counts& assertions ) override;
10503
10504 void sectionEnded( SectionEndInfo&& endInfo ) override;
10505 void sectionEndedEarly( SectionEndInfo&& endInfo ) override;
10506
10507 IGeneratorTracker*
10508 acquireGeneratorTracker( StringRef generatorName,
10509 SourceLineInfo const& lineInfo ) override;
10510 IGeneratorTracker* createGeneratorTracker(
10511 StringRef generatorName,
10512 SourceLineInfo lineInfo,
10513 Generators::GeneratorBasePtr&& generator ) override;
10514
10515
10516 void benchmarkPreparing( StringRef name ) override;
10517 void benchmarkStarting( BenchmarkInfo const& info ) override;
10518 void benchmarkEnded( BenchmarkStats<> const& stats ) override;
10519 void benchmarkFailed( StringRef error ) override;
10520
10521 void pushScopedMessage( MessageInfo const& message ) override;
10522 void popScopedMessage( MessageInfo const& message ) override;
10523
10524 void emplaceUnscopedMessage( MessageBuilder&& builder ) override;
10525
10526 std::string getCurrentTestName() const override;
10527
10528 const AssertionResult* getLastResult() const override;
10529
10530 void exceptionEarlyReported() override;
10531
10532 void handleFatalErrorCondition( StringRef message ) override;
10533
10534 bool lastAssertionPassed() override;
10535
10536 void assertionPassed() override;
10537
10538 public:
10539 // !TBD We need to do this another way!
10540 bool aborting() const;
10541
10542 private:
10543
10544 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
10545 void invokeActiveTestCase();
10546
10547 void resetAssertionInfo();
10548 bool testForMissingAssertions( Counts& assertions );
10549
10550 void assertionEnded( AssertionResult&& result );
10551 void reportExpr
10552 ( AssertionInfo const &info,
10553 ResultWas::OfType resultType,
10554 ITransientExpression const *expr,
10555 bool negated );
10556
10557 void populateReaction( AssertionReaction& reaction );
10558
10559 private:
10560
10561 void handleUnfinishedSections();
10562
10563 TestRunInfo m_runInfo;
10564 TestCaseHandle const* m_activeTestCase = nullptr;
10565 ITracker* m_testCaseTracker = nullptr;
10566 Optional<AssertionResult> m_lastResult;
10567
10568 IConfig const* m_config;
10569 Totals m_totals;
10570 IEventListenerPtr m_reporter;
10571 std::vector<MessageInfo> m_messages;
10572 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
10573 AssertionInfo m_lastAssertionInfo;
10574 std::vector<SectionEndInfo> m_unfinishedSections;
10575 std::vector<ITracker*> m_activeSections;
10576 TrackerContext m_trackerContext;
10577 FatalConditionHandler m_fatalConditionhandler;
10578 bool m_lastAssertionPassed = false;
10579 bool m_shouldReportUnexpected = true;
10580 bool m_includeSuccessfulResults;
10581 };
10582
10583 void seedRng(IConfig const& config);
10584 unsigned int rngSeed();
10585} // end namespace Catch
10586
10587#endif // CATCH_RUN_CONTEXT_HPP_INCLUDED
10588
10589
10590#ifndef CATCH_SHARDING_HPP_INCLUDED
10591#define CATCH_SHARDING_HPP_INCLUDED
10592
10593#include <cassert>
10594#include <cmath>
10595#include <algorithm>
10596
10597namespace Catch {
10598
10599 template<typename Container>
10600 Container createShard(Container const& container, std::size_t const shardCount, std::size_t const shardIndex) {
10601 assert(shardCount > shardIndex);
10602
10603 if (shardCount == 1) {
10604 return container;
10605 }
10606
10607 const std::size_t totalTestCount = container.size();
10608
10609 const std::size_t shardSize = totalTestCount / shardCount;
10610 const std::size_t leftoverTests = totalTestCount % shardCount;
10611
10612 const std::size_t startIndex = shardIndex * shardSize + (std::min)(shardIndex, leftoverTests);
10613 const std::size_t endIndex = (shardIndex + 1) * shardSize + (std::min)(shardIndex + 1, leftoverTests);
10614
10615 auto startIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(startIndex));
10616 auto endIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(endIndex));
10617
10618 return Container(startIterator, endIterator);
10619 }
10620
10621}
10622
10623#endif // CATCH_SHARDING_HPP_INCLUDED
10624
10625
10626#ifndef CATCH_SINGLETONS_HPP_INCLUDED
10627#define CATCH_SINGLETONS_HPP_INCLUDED
10628
10629namespace Catch {
10630
10631 struct ISingleton {
10632 virtual ~ISingleton(); // = default
10633 };
10634
10635
10636 void addSingleton( ISingleton* singleton );
10637 void cleanupSingletons();
10638
10639
10640 template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
10641 class Singleton : SingletonImplT, public ISingleton {
10642
10643 static auto getInternal() -> Singleton* {
10644 static Singleton* s_instance = nullptr;
10645 if( !s_instance ) {
10646 s_instance = new Singleton;
10647 addSingleton( s_instance );
10648 }
10649 return s_instance;
10650 }
10651
10652 public:
10653 static auto get() -> InterfaceT const& {
10654 return *getInternal();
10655 }
10656 static auto getMutable() -> MutableInterfaceT& {
10657 return *getInternal();
10658 }
10659 };
10660
10661} // namespace Catch
10662
10663#endif // CATCH_SINGLETONS_HPP_INCLUDED
10664
10665
10666#ifndef CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
10667#define CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
10668
10669
10670#include <vector>
10671#include <exception>
10672
10673namespace Catch {
10674
10675 class StartupExceptionRegistry {
10676#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
10677 public:
10678 void add(std::exception_ptr const& exception) noexcept;
10679 std::vector<std::exception_ptr> const& getExceptions() const noexcept;
10680 private:
10681 std::vector<std::exception_ptr> m_exceptions;
10682#endif
10683 };
10684
10685} // end namespace Catch
10686
10687#endif // CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED
10688
10689
10690
10691#ifndef CATCH_STDSTREAMS_HPP_INCLUDED
10692#define CATCH_STDSTREAMS_HPP_INCLUDED
10693
10694#include <iosfwd>
10695
10696namespace Catch {
10697
10698 std::ostream& cout();
10699 std::ostream& cerr();
10700 std::ostream& clog();
10701
10702} // namespace Catch
10703
10704#endif
10705
10706
10707#ifndef CATCH_STRING_MANIP_HPP_INCLUDED
10708#define CATCH_STRING_MANIP_HPP_INCLUDED
10709
10710
10711#include <cstdint>
10712#include <string>
10713#include <iosfwd>
10714#include <vector>
10715
10716namespace Catch {
10717
10718 bool startsWith( std::string const& s, std::string const& prefix );
10719 bool startsWith( StringRef s, char prefix );
10720 bool endsWith( std::string const& s, std::string const& suffix );
10721 bool endsWith( std::string const& s, char suffix );
10722 bool contains( std::string const& s, std::string const& infix );
10723 void toLowerInPlace( std::string& s );
10724 std::string toLower( std::string const& s );
10725 char toLower( char c );
10726 //! Returns a new string without whitespace at the start/end
10727 std::string trim( std::string const& str );
10728 //! Returns a substring of the original ref without whitespace. Beware lifetimes!
10729 StringRef trim(StringRef ref);
10730
10731 // !!! Be aware, returns refs into original string - make sure original string outlives them
10732 std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
10733 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
10734
10735 /**
10736 * Helper for streaming a "count [maybe-plural-of-label]" human-friendly string
10737 *
10738 * Usage example:
10739 * ```cpp
10740 * std::cout << "Found " << pluralise(count, "error") << '\n';
10741 * ```
10742 *
10743 * **Important:** The provided string must outlive the instance
10744 */
10745 class pluralise {
10746 std::uint64_t m_count;
10747 StringRef m_label;
10748
10749 public:
10750 constexpr pluralise(std::uint64_t count, StringRef label):
10751 m_count(count),
10752 m_label(label)
10753 {}
10754
10755 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
10756 };
10757}
10758
10759#endif // CATCH_STRING_MANIP_HPP_INCLUDED
10760
10761
10762#ifndef CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
10763#define CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
10764
10765
10766#include <map>
10767#include <string>
10768
10769namespace Catch {
10770 struct SourceLineInfo;
10771
10772 class TagAliasRegistry : public ITagAliasRegistry {
10773 public:
10774 ~TagAliasRegistry() override;
10775 TagAlias const* find( std::string const& alias ) const override;
10776 std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
10777 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
10778
10779 private:
10780 std::map<std::string, TagAlias> m_registry;
10781 };
10782
10783} // end namespace Catch
10784
10785#endif // CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
10786
10787
10788#ifndef CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
10789#define CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED
10790
10791#include <cstdint>
10792
10793namespace Catch {
10794
10795 struct TestCaseInfo;
10796
10797 class TestCaseInfoHasher {
10798 public:
10799 using hash_t = std::uint64_t;
10800 TestCaseInfoHasher( hash_t seed );
10801 uint32_t operator()( TestCaseInfo const& t ) const;
10802
10803 private:
10804 hash_t m_seed;
10805 };
10806
10807} // namespace Catch
10808
10809#endif /* CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED */
10810
10811
10812#ifndef CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
10813#define CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
10814
10815
10816#include <vector>
10817
10818namespace Catch {
10819
10820 class IConfig;
10821 class ITestInvoker;
10822 class TestCaseHandle;
10823 class TestSpec;
10824
10825 std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases );
10826
10827 bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config );
10828
10829 std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config );
10830 std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config );
10831
10832 class TestRegistry : public ITestCaseRegistry {
10833 public:
10834 void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
10835
10836 std::vector<TestCaseInfo*> const& getAllInfos() const override;
10837 std::vector<TestCaseHandle> const& getAllTests() const override;
10838 std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override;
10839
10840 ~TestRegistry() override; // = default
10841
10842 private:
10843 std::vector<Detail::unique_ptr<TestCaseInfo>> m_owned_test_infos;
10844 // Keeps a materialized vector for `getAllInfos`.
10845 // We should get rid of that eventually (see interface note)
10846 std::vector<TestCaseInfo*> m_viewed_test_infos;
10847
10848 std::vector<Detail::unique_ptr<ITestInvoker>> m_invokers;
10849 std::vector<TestCaseHandle> m_handles;
10850 mutable TestRunOrder m_currentSortOrder = TestRunOrder::Declared;
10851 mutable std::vector<TestCaseHandle> m_sortedFunctions;
10852 };
10853
10854 ///////////////////////////////////////////////////////////////////////////
10855
10856
10857} // end namespace Catch
10858
10859
10860#endif // CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
10861
10862
10863#ifndef CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
10864#define CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
10865
10866#ifdef __clang__
10867#pragma clang diagnostic push
10868#pragma clang diagnostic ignored "-Wpadded"
10869#endif
10870
10871
10872#include <vector>
10873#include <string>
10874
10875namespace Catch {
10876
10877 class ITagAliasRegistry;
10878
10879 class TestSpecParser {
10880 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
10881 Mode m_mode = None;
10882 Mode lastMode = None;
10883 bool m_exclusion = false;
10884 std::size_t m_pos = 0;
10885 std::size_t m_realPatternPos = 0;
10886 std::string m_arg;
10887 std::string m_substring;
10888 std::string m_patternName;
10889 std::vector<std::size_t> m_escapeChars;
10890 TestSpec::Filter m_currentFilter;
10891 TestSpec m_testSpec;
10892 ITagAliasRegistry const* m_tagAliases = nullptr;
10893
10894 public:
10895 TestSpecParser( ITagAliasRegistry const& tagAliases );
10896
10897 TestSpecParser& parse( std::string const& arg );
10898 TestSpec testSpec();
10899
10900 private:
10901 bool visitChar( char c );
10902 void startNewMode( Mode mode );
10903 bool processNoneChar( char c );
10904 void processNameChar( char c );
10905 bool processOtherChar( char c );
10906 void endMode();
10907 void escape();
10908 bool isControlChar( char c ) const;
10909 void saveLastMode();
10910 void revertBackToLastMode();
10911 void addFilter();
10912 bool separate();
10913
10914 // Handles common preprocessing of the pattern for name/tag patterns
10915 std::string preprocessPattern();
10916 // Adds the current pattern as a test name
10917 void addNamePattern();
10918 // Adds the current pattern as a tag
10919 void addTagPattern();
10920
10921 inline void addCharToPattern(char c) {
10922 m_substring += c;
10923 m_patternName += c;
10924 m_realPatternPos++;
10925 }
10926
10927 };
10928
10929} // namespace Catch
10930
10931#ifdef __clang__
10932#pragma clang diagnostic pop
10933#endif
10934
10935#endif // CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
10936
10937
10938#ifndef CATCH_TEXTFLOW_HPP_INCLUDED
10939#define CATCH_TEXTFLOW_HPP_INCLUDED
10940
10941
10942#include <cassert>
10943#include <string>
10944#include <vector>
10945
10946namespace Catch {
10947 namespace TextFlow {
10948
10949 class Columns;
10950
10951 /**
10952 * Abstraction for a string with ansi escape sequences that
10953 * automatically skips over escapes when iterating. Only graphical
10954 * escape sequences are considered.
10955 *
10956 * Internal representation:
10957 * An escape sequence looks like \033[39;49m
10958 * We need bidirectional iteration and the unbound length of escape
10959 * sequences poses a problem for operator-- To make this work we'll
10960 * replace the last `m` with a 0xff (this is a codepoint that won't have
10961 * any utf-8 meaning).
10962 */
10963 class AnsiSkippingString {
10964 std::string m_string;
10965 std::size_t m_size = 0;
10966
10967 // perform 0xff replacement and calculate m_size
10968 void preprocessString();
10969
10970 public:
10971 class const_iterator;
10972 using iterator = const_iterator;
10973 // note: must be u-suffixed or this will cause a "truncation of
10974 // constant value" warning on MSVC
10975 static constexpr char sentinel = static_cast<char>( 0xffu );
10976
10977 explicit AnsiSkippingString( std::string const& text );
10978 explicit AnsiSkippingString( std::string&& text );
10979
10980 const_iterator begin() const;
10981 const_iterator end() const;
10982
10983 size_t size() const { return m_size; }
10984
10985 std::string substring( const_iterator begin,
10986 const_iterator end ) const;
10987 };
10988
10989 class AnsiSkippingString::const_iterator {
10990 friend AnsiSkippingString;
10991 struct EndTag {};
10992
10993 const std::string* m_string;
10994 std::string::const_iterator m_it;
10995
10996 explicit const_iterator( const std::string& string, EndTag ):
10997 m_string( &string ), m_it( string.end() ) {}
10998
10999 void tryParseAnsiEscapes();
11000 void advance();
11001 void unadvance();
11002
11003 public:
11004 using difference_type = std::ptrdiff_t;
11005 using value_type = char;
11006 using pointer = value_type*;
11007 using reference = value_type&;
11008 using iterator_category = std::bidirectional_iterator_tag;
11009
11010 explicit const_iterator( const std::string& string ):
11011 m_string( &string ), m_it( string.begin() ) {
11012 tryParseAnsiEscapes();
11013 }
11014
11015 char operator*() const { return *m_it; }
11016
11017 const_iterator& operator++() {
11018 advance();
11019 return *this;
11020 }
11021 const_iterator operator++( int ) {
11022 iterator prev( *this );
11023 operator++();
11024 return prev;
11025 }
11026 const_iterator& operator--() {
11027 unadvance();
11028 return *this;
11029 }
11030 const_iterator operator--( int ) {
11031 iterator prev( *this );
11032 operator--();
11033 return prev;
11034 }
11035
11036 bool operator==( const_iterator const& other ) const {
11037 return m_it == other.m_it;
11038 }
11039 bool operator!=( const_iterator const& other ) const {
11040 return !operator==( other );
11041 }
11042 bool operator<=( const_iterator const& other ) const {
11043 return m_it <= other.m_it;
11044 }
11045
11046 const_iterator oneBefore() const {
11047 auto it = *this;
11048 return --it;
11049 }
11050 };
11051
11052 /**
11053 * Represents a column of text with specific width and indentation
11054 *
11055 * When written out to a stream, it will perform linebreaking
11056 * of the provided text so that the written lines fit within
11057 * target width.
11058 */
11059 class Column {
11060 // String to be written out
11061 AnsiSkippingString m_string;
11062 // Width of the column for linebreaking
11063 size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1;
11064 // Indentation of other lines (including first if initial indent is
11065 // unset)
11066 size_t m_indent = 0;
11067 // Indentation of the first line
11068 size_t m_initialIndent = std::string::npos;
11069
11070 public:
11071 /**
11072 * Iterates "lines" in `Column` and returns them
11073 */
11074 class const_iterator {
11075 friend Column;
11076 struct EndTag {};
11077
11078 Column const& m_column;
11079 // Where does the current line start?
11080 AnsiSkippingString::const_iterator m_lineStart;
11081 // How long should the current line be?
11082 AnsiSkippingString::const_iterator m_lineEnd;
11083 // How far have we checked the string to iterate?
11084 AnsiSkippingString::const_iterator m_parsedTo;
11085 // Should a '-' be appended to the line?
11086 bool m_addHyphen = false;
11087
11088 const_iterator( Column const& column, EndTag ):
11089 m_column( column ),
11090 m_lineStart( m_column.m_string.end() ),
11091 m_lineEnd( column.m_string.end() ),
11092 m_parsedTo( column.m_string.end() ) {}
11093
11094 // Calculates the length of the current line
11095 void calcLength();
11096
11097 // Returns current indentation width
11098 size_t indentSize() const;
11099
11100 // Creates an indented and (optionally) suffixed string from
11101 // current iterator position, indentation and length.
11102 std::string addIndentAndSuffix(
11103 AnsiSkippingString::const_iterator start,
11104 AnsiSkippingString::const_iterator end ) const;
11105
11106 public:
11107 using difference_type = std::ptrdiff_t;
11108 using value_type = std::string;
11109 using pointer = value_type*;
11110 using reference = value_type&;
11111 using iterator_category = std::forward_iterator_tag;
11112
11113 explicit const_iterator( Column const& column );
11114
11115 std::string operator*() const;
11116
11117 const_iterator& operator++();
11118 const_iterator operator++( int );
11119
11120 bool operator==( const_iterator const& other ) const {
11121 return m_lineStart == other.m_lineStart &&
11122 &m_column == &other.m_column;
11123 }
11124 bool operator!=( const_iterator const& other ) const {
11125 return !operator==( other );
11126 }
11127 };
11128 using iterator = const_iterator;
11129
11130 explicit Column( std::string const& text ): m_string( text ) {}
11131 explicit Column( std::string&& text ):
11132 m_string( CATCH_MOVE( text ) ) {}
11133
11134 Column& width( size_t newWidth ) & {
11135 assert( newWidth > 0 );
11136 m_width = newWidth;
11137 return *this;
11138 }
11139 Column&& width( size_t newWidth ) && {
11140 assert( newWidth > 0 );
11141 m_width = newWidth;
11142 return CATCH_MOVE( *this );
11143 }
11144 Column& indent( size_t newIndent ) & {
11145 m_indent = newIndent;
11146 return *this;
11147 }
11148 Column&& indent( size_t newIndent ) && {
11149 m_indent = newIndent;
11150 return CATCH_MOVE( *this );
11151 }
11152 Column& initialIndent( size_t newIndent ) & {
11153 m_initialIndent = newIndent;
11154 return *this;
11155 }
11156 Column&& initialIndent( size_t newIndent ) && {
11157 m_initialIndent = newIndent;
11158 return CATCH_MOVE( *this );
11159 }
11160
11161 size_t width() const { return m_width; }
11162 const_iterator begin() const { return const_iterator( *this ); }
11163 const_iterator end() const {
11164 return { *this, const_iterator::EndTag{} };
11165 }
11166
11167 friend std::ostream& operator<<( std::ostream& os,
11168 Column const& col );
11169
11170 friend Columns operator+( Column const& lhs, Column const& rhs );
11171 friend Columns operator+( Column&& lhs, Column&& rhs );
11172 };
11173
11174 //! Creates a column that serves as an empty space of specific width
11175 Column Spacer( size_t spaceWidth );
11176
11177 class Columns {
11178 std::vector<Column> m_columns;
11179
11180 public:
11181 class iterator {
11182 friend Columns;
11183 struct EndTag {};
11184
11185 std::vector<Column> const& m_columns;
11186 std::vector<Column::const_iterator> m_iterators;
11187 size_t m_activeIterators;
11188
11189 iterator( Columns const& columns, EndTag );
11190
11191 public:
11192 using difference_type = std::ptrdiff_t;
11193 using value_type = std::string;
11194 using pointer = value_type*;
11195 using reference = value_type&;
11196 using iterator_category = std::forward_iterator_tag;
11197
11198 explicit iterator( Columns const& columns );
11199
11200 auto operator==( iterator const& other ) const -> bool {
11201 return m_iterators == other.m_iterators;
11202 }
11203 auto operator!=( iterator const& other ) const -> bool {
11204 return m_iterators != other.m_iterators;
11205 }
11206 std::string operator*() const;
11207 iterator& operator++();
11208 iterator operator++( int );
11209 };
11210 using const_iterator = iterator;
11211
11212 iterator begin() const { return iterator( *this ); }
11213 iterator end() const { return { *this, iterator::EndTag() }; }
11214
11215 friend Columns& operator+=( Columns& lhs, Column const& rhs );
11216 friend Columns& operator+=( Columns& lhs, Column&& rhs );
11217 friend Columns operator+( Columns const& lhs, Column const& rhs );
11218 friend Columns operator+( Columns&& lhs, Column&& rhs );
11219
11220 friend std::ostream& operator<<( std::ostream& os,
11221 Columns const& cols );
11222 };
11223
11224 } // namespace TextFlow
11225} // namespace Catch
11226#endif // CATCH_TEXTFLOW_HPP_INCLUDED
11227
11228
11229#ifndef CATCH_TO_STRING_HPP_INCLUDED
11230#define CATCH_TO_STRING_HPP_INCLUDED
11231
11232#include <string>
11233
11234
11235namespace Catch {
11236 template <typename T>
11237 std::string to_string(T const& t) {
11238#if defined(CATCH_CONFIG_CPP11_TO_STRING)
11239 return std::to_string(t);
11240#else
11241 ReusableStringStream rss;
11242 rss << t;
11243 return rss.str();
11244#endif
11245 }
11246} // end namespace Catch
11247
11248#endif // CATCH_TO_STRING_HPP_INCLUDED
11249
11250
11251#ifndef CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
11252#define CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
11253
11254namespace Catch {
11255 bool uncaught_exceptions();
11256} // end namespace Catch
11257
11258#endif // CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED
11259
11260
11261#ifndef CATCH_XMLWRITER_HPP_INCLUDED
11262#define CATCH_XMLWRITER_HPP_INCLUDED
11263
11264
11265#include <iosfwd>
11266#include <vector>
11267
11268namespace Catch {
11269 enum class XmlFormatting {
11270 None = 0x00,
11271 Indent = 0x01,
11272 Newline = 0x02,
11273 };
11274
11275 XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs);
11276 XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs);
11277
11278 /**
11279 * Helper for XML-encoding text (escaping angle brackets, quotes, etc)
11280 *
11281 * Note: doesn't take ownership of passed strings, and thus the
11282 * encoded string must outlive the encoding instance.
11283 */
11284 class XmlEncode {
11285 public:
11286 enum ForWhat { ForTextNodes, ForAttributes };
11287
11288 XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes );
11289
11290 void encodeTo( std::ostream& os ) const;
11291
11292 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
11293
11294 private:
11295 StringRef m_str;
11296 ForWhat m_forWhat;
11297 };
11298
11299 class XmlWriter {
11300 public:
11301
11302 class ScopedElement {
11303 public:
11304 ScopedElement( XmlWriter* writer, XmlFormatting fmt );
11305
11306 ScopedElement( ScopedElement&& other ) noexcept;
11307 ScopedElement& operator=( ScopedElement&& other ) noexcept;
11308
11309 ~ScopedElement();
11310
11311 ScopedElement&
11312 writeText( StringRef text,
11313 XmlFormatting fmt = XmlFormatting::Newline |
11314 XmlFormatting::Indent );
11315
11316 ScopedElement& writeAttribute( StringRef name,
11317 StringRef attribute );
11318 template <typename T,
11319 // Without this SFINAE, this overload is a better match
11320 // for `std::string`, `char const*`, `char const[N]` args.
11321 // While it would still work, it would cause code bloat
11322 // and multiple iteration over the strings
11323 typename = typename std::enable_if_t<
11324 !std::is_convertible<T, StringRef>::value>>
11325 ScopedElement& writeAttribute( StringRef name,
11326 T const& attribute ) {
11327 m_writer->writeAttribute( name, attribute );
11328 return *this;
11329 }
11330
11331 private:
11332 XmlWriter* m_writer = nullptr;
11333 XmlFormatting m_fmt;
11334 };
11335
11336 XmlWriter( std::ostream& os );
11337 ~XmlWriter();
11338
11339 XmlWriter( XmlWriter const& ) = delete;
11340 XmlWriter& operator=( XmlWriter const& ) = delete;
11341
11342 XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
11343
11344 ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
11345
11346 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
11347
11348 //! The attribute content is XML-encoded
11349 XmlWriter& writeAttribute( StringRef name, StringRef attribute );
11350
11351 //! Writes the attribute as "true/false"
11352 XmlWriter& writeAttribute( StringRef name, bool attribute );
11353
11354 //! The attribute content is XML-encoded
11355 XmlWriter& writeAttribute( StringRef name, char const* attribute );
11356
11357 //! The attribute value must provide op<<(ostream&, T). The resulting
11358 //! serialization is XML-encoded
11359 template <typename T,
11360 // Without this SFINAE, this overload is a better match
11361 // for `std::string`, `char const*`, `char const[N]` args.
11362 // While it would still work, it would cause code bloat
11363 // and multiple iteration over the strings
11364 typename = typename std::enable_if_t<
11365 !std::is_convertible<T, StringRef>::value>>
11366 XmlWriter& writeAttribute( StringRef name, T const& attribute ) {
11367 ReusableStringStream rss;
11368 rss << attribute;
11369 return writeAttribute( name, rss.str() );
11370 }
11371
11372 //! Writes escaped `text` in a element
11373 XmlWriter& writeText( StringRef text,
11374 XmlFormatting fmt = XmlFormatting::Newline |
11375 XmlFormatting::Indent );
11376
11377 //! Writes XML comment as "<!-- text -->"
11378 XmlWriter& writeComment( StringRef text,
11379 XmlFormatting fmt = XmlFormatting::Newline |
11380 XmlFormatting::Indent );
11381
11382 void writeStylesheetRef( StringRef url );
11383
11384 void ensureTagClosed();
11385
11386 private:
11387
11388 void applyFormatting(XmlFormatting fmt);
11389
11390 void writeDeclaration();
11391
11392 void newlineIfNecessary();
11393
11394 bool m_tagIsOpen = false;
11395 bool m_needsNewline = false;
11396 std::vector<std::string> m_tags;
11397 std::string m_indent;
11398 std::ostream& m_os;
11399 };
11400
11401}
11402
11403#endif // CATCH_XMLWRITER_HPP_INCLUDED
11404
11405
11406/** \file
11407 * This is a convenience header for Catch2's Matcher support. It includes
11408 * **all** of Catch2 headers related to matchers.
11409 *
11410 * Generally the Catch2 users should use specific includes they need,
11411 * but this header can be used instead for ease-of-experimentation, or
11412 * just plain convenience, at the cost of increased compilation times.
11413 *
11414 * When a new header is added to either the `matchers` folder, or to
11415 * the corresponding internal subfolder, it should be added here.
11416 */
11417
11418#ifndef CATCH_MATCHERS_ALL_HPP_INCLUDED
11419#define CATCH_MATCHERS_ALL_HPP_INCLUDED
11420
11421
11422
11423#ifndef CATCH_MATCHERS_HPP_INCLUDED
11424#define CATCH_MATCHERS_HPP_INCLUDED
11425
11426
11427
11428#ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED
11429#define CATCH_MATCHERS_IMPL_HPP_INCLUDED
11430
11431
11432#include <string>
11433
11434namespace Catch {
11435
11436#ifdef __clang__
11437# pragma clang diagnostic push
11438# pragma clang diagnostic ignored "-Wsign-compare"
11439# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
11440#elif defined __GNUC__
11441# pragma GCC diagnostic push
11442# pragma GCC diagnostic ignored "-Wsign-compare"
11443# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
11444#endif
11445
11446 template<typename ArgT, typename MatcherT>
11447 class MatchExpr : public ITransientExpression {
11448 ArgT && m_arg;
11449 MatcherT const& m_matcher;
11450 public:
11451 MatchExpr( ArgT && arg, MatcherT const& matcher )
11452 : ITransientExpression{ true, matcher.match( arg ) }, // not forwarding arg here on purpose
11453 m_arg( CATCH_FORWARD(arg) ),
11454 m_matcher( matcher )
11455 {}
11456
11457 void streamReconstructedExpression( std::ostream& os ) const override {
11458 os << Catch::Detail::stringify( m_arg )
11459 << ' '
11460 << m_matcher.toString();
11461 }
11462 };
11463
11464#ifdef __clang__
11465# pragma clang diagnostic pop
11466#elif defined __GNUC__
11467# pragma GCC diagnostic pop
11468#endif
11469
11470
11471 namespace Matchers {
11472 template <typename ArgT>
11473 class MatcherBase;
11474 }
11475
11476 using StringMatcher = Matchers::MatcherBase<std::string>;
11477
11478 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher );
11479
11480 template<typename ArgT, typename MatcherT>
11481 auto makeMatchExpr( ArgT && arg, MatcherT const& matcher ) -> MatchExpr<ArgT, MatcherT> {
11482 return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher );
11483 }
11484
11485} // namespace Catch
11486
11487
11488///////////////////////////////////////////////////////////////////////////////
11489#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
11490 do { \
11491 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
11492 INTERNAL_CATCH_TRY { \
11493 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher ) ); \
11494 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
11495 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
11496 } while( false )
11497
11498
11499///////////////////////////////////////////////////////////////////////////////
11500#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
11501 do { \
11502 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
11503 if( catchAssertionHandler.allowThrows() ) \
11504 try { \
11505 static_cast<void>(__VA_ARGS__ ); \
11506 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
11507 } \
11508 catch( exceptionType const& ex ) { \
11509 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher ) ); \
11510 } \
11511 catch( ... ) { \
11512 catchAssertionHandler.handleUnexpectedInflightException(); \
11513 } \
11514 else \
11515 catchAssertionHandler.handleThrowingCallSkipped(); \
11516 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
11517 } while( false )
11518
11519
11520#endif // CATCH_MATCHERS_IMPL_HPP_INCLUDED
11521
11522#include <string>
11523#include <vector>
11524
11525namespace Catch {
11526namespace Matchers {
11527
11528 class MatcherUntypedBase {
11529 public:
11530 MatcherUntypedBase() = default;
11531
11532 MatcherUntypedBase(MatcherUntypedBase const&) = default;
11533 MatcherUntypedBase(MatcherUntypedBase&&) = default;
11534
11535 MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete;
11536 MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete;
11537
11538 std::string toString() const;
11539
11540 protected:
11541 virtual ~MatcherUntypedBase(); // = default;
11542 virtual std::string describe() const = 0;
11543 mutable std::string m_cachedToString;
11544 };
11545
11546
11547 template<typename T>
11548 class MatcherBase : public MatcherUntypedBase {
11549 public:
11550 virtual bool match( T const& arg ) const = 0;
11551 };
11552
11553 namespace Detail {
11554
11555 template<typename ArgT>
11556 class MatchAllOf final : public MatcherBase<ArgT> {
11557 std::vector<MatcherBase<ArgT> const*> m_matchers;
11558
11559 public:
11560 MatchAllOf() = default;
11561 MatchAllOf(MatchAllOf const&) = delete;
11562 MatchAllOf& operator=(MatchAllOf const&) = delete;
11563 MatchAllOf(MatchAllOf&&) = default;
11564 MatchAllOf& operator=(MatchAllOf&&) = default;
11565
11566
11567 bool match( ArgT const& arg ) const override {
11568 for( auto matcher : m_matchers ) {
11569 if (!matcher->match(arg))
11570 return false;
11571 }
11572 return true;
11573 }
11574 std::string describe() const override {
11575 std::string description;
11576 description.reserve( 4 + m_matchers.size()*32 );
11577 description += "( ";
11578 bool first = true;
11579 for( auto matcher : m_matchers ) {
11580 if( first )
11581 first = false;
11582 else
11583 description += " and ";
11584 description += matcher->toString();
11585 }
11586 description += " )";
11587 return description;
11588 }
11589
11590 friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) {
11591 lhs.m_matchers.push_back(&rhs);
11592 return CATCH_MOVE(lhs);
11593 }
11594 friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) {
11595 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
11596 return CATCH_MOVE(rhs);
11597 }
11598 };
11599
11600 //! lvalue overload is intentionally deleted, users should
11601 //! not be trying to compose stored composition matchers
11602 template<typename ArgT>
11603 MatchAllOf<ArgT> operator&& (MatchAllOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
11604 //! lvalue overload is intentionally deleted, users should
11605 //! not be trying to compose stored composition matchers
11606 template<typename ArgT>
11607 MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete;
11608
11609 template<typename ArgT>
11610 class MatchAnyOf final : public MatcherBase<ArgT> {
11611 std::vector<MatcherBase<ArgT> const*> m_matchers;
11612 public:
11613 MatchAnyOf() = default;
11614 MatchAnyOf(MatchAnyOf const&) = delete;
11615 MatchAnyOf& operator=(MatchAnyOf const&) = delete;
11616 MatchAnyOf(MatchAnyOf&&) = default;
11617 MatchAnyOf& operator=(MatchAnyOf&&) = default;
11618
11619 bool match( ArgT const& arg ) const override {
11620 for( auto matcher : m_matchers ) {
11621 if (matcher->match(arg))
11622 return true;
11623 }
11624 return false;
11625 }
11626 std::string describe() const override {
11627 std::string description;
11628 description.reserve( 4 + m_matchers.size()*32 );
11629 description += "( ";
11630 bool first = true;
11631 for( auto matcher : m_matchers ) {
11632 if( first )
11633 first = false;
11634 else
11635 description += " or ";
11636 description += matcher->toString();
11637 }
11638 description += " )";
11639 return description;
11640 }
11641
11642 friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) {
11643 lhs.m_matchers.push_back(&rhs);
11644 return CATCH_MOVE(lhs);
11645 }
11646 friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) {
11647 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
11648 return CATCH_MOVE(rhs);
11649 }
11650 };
11651
11652 //! lvalue overload is intentionally deleted, users should
11653 //! not be trying to compose stored composition matchers
11654 template<typename ArgT>
11655 MatchAnyOf<ArgT> operator|| (MatchAnyOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete;
11656 //! lvalue overload is intentionally deleted, users should
11657 //! not be trying to compose stored composition matchers
11658 template<typename ArgT>
11659 MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete;
11660
11661 template<typename ArgT>
11662 class MatchNotOf final : public MatcherBase<ArgT> {
11663 MatcherBase<ArgT> const& m_underlyingMatcher;
11664
11665 public:
11666 explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ):
11667 m_underlyingMatcher( underlyingMatcher )
11668 {}
11669
11670 bool match( ArgT const& arg ) const override {
11671 return !m_underlyingMatcher.match( arg );
11672 }
11673
11674 std::string describe() const override {
11675 return "not " + m_underlyingMatcher.toString();
11676 }
11677 };
11678
11679 } // namespace Detail
11680
11681 template <typename T>
11682 Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
11683 return Detail::MatchAllOf<T>{} && lhs && rhs;
11684 }
11685 template <typename T>
11686 Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
11687 return Detail::MatchAnyOf<T>{} || lhs || rhs;
11688 }
11689
11690 template <typename T>
11691 Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) {
11692 return Detail::MatchNotOf<T>{ matcher };
11693 }
11694
11695
11696} // namespace Matchers
11697} // namespace Catch
11698
11699
11700#if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
11701 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11702 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
11703
11704 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11705 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11706
11707 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11708 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11709
11710#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
11711
11712 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
11713 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11714
11715 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
11716 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11717
11718 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
11719 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
11720
11721#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE)
11722
11723 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11724 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
11725
11726 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11727 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11728
11729 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11730 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11731
11732#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE)
11733
11734 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
11735 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11736
11737 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
11738 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
11739
11740 #define CHECK_THAT( arg, matcher ) (void)(0)
11741 #define REQUIRE_THAT( arg, matcher ) (void)(0)
11742
11743#endif // end of user facing macro declarations
11744
11745#endif // CATCH_MATCHERS_HPP_INCLUDED
11746
11747
11748#ifndef CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
11749#define CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
11750
11751
11752
11753#ifndef CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
11754#define CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
11755
11756
11757#include <array>
11758#include <algorithm>
11759#include <string>
11760#include <type_traits>
11761
11762namespace Catch {
11763namespace Matchers {
11764 class MatcherGenericBase : public MatcherUntypedBase {
11765 public:
11766 MatcherGenericBase() = default;
11767 ~MatcherGenericBase() override; // = default;
11768
11769 MatcherGenericBase(MatcherGenericBase const&) = default;
11770 MatcherGenericBase(MatcherGenericBase&&) = default;
11771
11772 MatcherGenericBase& operator=(MatcherGenericBase const&) = delete;
11773 MatcherGenericBase& operator=(MatcherGenericBase&&) = delete;
11774 };
11775
11776
11777 namespace Detail {
11778 template<std::size_t N, std::size_t M>
11779 std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) {
11780 std::array<void const*, N + M> arr{};
11781 std::copy_n(lhs.begin(), N, arr.begin());
11782 std::copy_n(rhs.begin(), M, arr.begin() + N);
11783 return arr;
11784 }
11785
11786 template<std::size_t N>
11787 std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) {
11788 std::array<void const*, N+1> arr{};
11789 std::copy_n(lhs.begin(), N, arr.begin());
11790 arr[N] = rhs;
11791 return arr;
11792 }
11793
11794 template<std::size_t N>
11795 std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) {
11796 std::array<void const*, N + 1> arr{ {lhs} };
11797 std::copy_n(rhs.begin(), N, arr.begin() + 1);
11798 return arr;
11799 }
11800
11801 template<typename T>
11802 using is_generic_matcher = std::is_base_of<
11803 Catch::Matchers::MatcherGenericBase,
11804 std::remove_cv_t<std::remove_reference_t<T>>
11805 >;
11806
11807 template<typename... Ts>
11808 using are_generic_matchers = Catch::Detail::conjunction<is_generic_matcher<Ts>...>;
11809
11810 template<typename T>
11811 using is_matcher = std::is_base_of<
11812 Catch::Matchers::MatcherUntypedBase,
11813 std::remove_cv_t<std::remove_reference_t<T>>
11814 >;
11815
11816
11817 template<std::size_t N, typename Arg>
11818 bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
11819 return true;
11820 }
11821
11822 template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
11823 bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
11824 return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
11825 }
11826
11827
11828 template<std::size_t N, typename Arg>
11829 bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) {
11830 return false;
11831 }
11832
11833 template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices>
11834 bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) {
11835 return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{});
11836 }
11837
11838 std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end);
11839
11840 template<typename... MatcherTs, std::size_t... Idx>
11841 std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) {
11842 std::array<std::string, sizeof...(MatcherTs)> descriptions {{
11843 static_cast<MatcherTs const*>(matchers[Idx])->toString()...
11844 }};
11845
11846 return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size());
11847 }
11848
11849
11850 template<typename... MatcherTs>
11851 class MatchAllOfGeneric final : public MatcherGenericBase {
11852 public:
11853 MatchAllOfGeneric(MatchAllOfGeneric const&) = delete;
11854 MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete;
11855 MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
11856 MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
11857
11858 MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
11859 explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
11860
11861 template<typename Arg>
11862 bool match(Arg&& arg) const {
11863 return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
11864 }
11865
11866 std::string describe() const override {
11867 return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
11868 }
11869
11870 // Has to be public to enable the concatenating operators
11871 // below, because they are not friend of the RHS, only LHS,
11872 // and thus cannot access private fields of RHS
11873 std::array<void const*, sizeof...( MatcherTs )> m_matchers;
11874
11875
11876 //! Avoids type nesting for `GenericAllOf && GenericAllOf` case
11877 template<typename... MatchersRHS>
11878 friend
11879 MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
11880 MatchAllOfGeneric<MatcherTs...>&& lhs,
11881 MatchAllOfGeneric<MatchersRHS...>&& rhs) {
11882 return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
11883 }
11884
11885 //! Avoids type nesting for `GenericAllOf && some matcher` case
11886 template<typename MatcherRHS>
11887 friend std::enable_if_t<is_matcher<MatcherRHS>::value,
11888 MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
11889 MatchAllOfGeneric<MatcherTs...>&& lhs,
11890 MatcherRHS const& rhs) {
11891 return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))};
11892 }
11893
11894 //! Avoids type nesting for `some matcher && GenericAllOf` case
11895 template<typename MatcherLHS>
11896 friend std::enable_if_t<is_matcher<MatcherLHS>::value,
11897 MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
11898 MatcherLHS const& lhs,
11899 MatchAllOfGeneric<MatcherTs...>&& rhs) {
11900 return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
11901 }
11902 };
11903
11904
11905 template<typename... MatcherTs>
11906 class MatchAnyOfGeneric final : public MatcherGenericBase {
11907 public:
11908 MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete;
11909 MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete;
11910 MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
11911 MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
11912
11913 MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
11914 explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
11915
11916 template<typename Arg>
11917 bool match(Arg&& arg) const {
11918 return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{});
11919 }
11920
11921 std::string describe() const override {
11922 return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{});
11923 }
11924
11925
11926 // Has to be public to enable the concatenating operators
11927 // below, because they are not friend of the RHS, only LHS,
11928 // and thus cannot access private fields of RHS
11929 std::array<void const*, sizeof...( MatcherTs )> m_matchers;
11930
11931 //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
11932 template<typename... MatchersRHS>
11933 friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
11934 MatchAnyOfGeneric<MatcherTs...>&& lhs,
11935 MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
11936 return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
11937 }
11938
11939 //! Avoids type nesting for `GenericAnyOf || some matcher` case
11940 template<typename MatcherRHS>
11941 friend std::enable_if_t<is_matcher<MatcherRHS>::value,
11942 MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
11943 MatchAnyOfGeneric<MatcherTs...>&& lhs,
11944 MatcherRHS const& rhs) {
11945 return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
11946 }
11947
11948 //! Avoids type nesting for `some matcher || GenericAnyOf` case
11949 template<typename MatcherLHS>
11950 friend std::enable_if_t<is_matcher<MatcherLHS>::value,
11951 MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
11952 MatcherLHS const& lhs,
11953 MatchAnyOfGeneric<MatcherTs...>&& rhs) {
11954 return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
11955 }
11956 };
11957
11958
11959 template<typename MatcherT>
11960 class MatchNotOfGeneric final : public MatcherGenericBase {
11961 MatcherT const& m_matcher;
11962
11963 public:
11964 MatchNotOfGeneric(MatchNotOfGeneric const&) = delete;
11965 MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete;
11966 MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
11967 MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
11968
11969 explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {}
11970
11971 template<typename Arg>
11972 bool match(Arg&& arg) const {
11973 return !m_matcher.match(arg);
11974 }
11975
11976 std::string describe() const override {
11977 return "not " + m_matcher.toString();
11978 }
11979
11980 //! Negating negation can just unwrap and return underlying matcher
11981 friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
11982 return matcher.m_matcher;
11983 }
11984 };
11985 } // namespace Detail
11986
11987
11988 // compose only generic matchers
11989 template<typename MatcherLHS, typename MatcherRHS>
11990 std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
11991 operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
11992 return { lhs, rhs };
11993 }
11994
11995 template<typename MatcherLHS, typename MatcherRHS>
11996 std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
11997 operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
11998 return { lhs, rhs };
11999 }
12000
12001 //! Wrap provided generic matcher in generic negator
12002 template<typename MatcherT>
12003 std::enable_if_t<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>>
12004 operator ! (MatcherT const& matcher) {
12005 return Detail::MatchNotOfGeneric<MatcherT>{matcher};
12006 }
12007
12008
12009 // compose mixed generic and non-generic matchers
12010 template<typename MatcherLHS, typename ArgRHS>
12011 std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
12012 operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
12013 return { lhs, rhs };
12014 }
12015
12016 template<typename ArgLHS, typename MatcherRHS>
12017 std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
12018 operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
12019 return { lhs, rhs };
12020 }
12021
12022 template<typename MatcherLHS, typename ArgRHS>
12023 std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
12024 operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
12025 return { lhs, rhs };
12026 }
12027
12028 template<typename ArgLHS, typename MatcherRHS>
12029 std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
12030 operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
12031 return { lhs, rhs };
12032 }
12033
12034} // namespace Matchers
12035} // namespace Catch
12036
12037#endif // CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED
12038
12039namespace Catch {
12040 namespace Matchers {
12041
12042 class IsEmptyMatcher final : public MatcherGenericBase {
12043 public:
12044 template <typename RangeLike>
12045 bool match(RangeLike&& rng) const {
12046#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
12047 using Catch::Detail::empty;
12048#else
12049 using std::empty;
12050#endif
12051 return empty(rng);
12052 }
12053
12054 std::string describe() const override;
12055 };
12056
12057 class HasSizeMatcher final : public MatcherGenericBase {
12058 std::size_t m_target_size;
12059 public:
12060 explicit HasSizeMatcher(std::size_t target_size):
12061 m_target_size(target_size)
12062 {}
12063
12064 template <typename RangeLike>
12065 bool match(RangeLike&& rng) const {
12066#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
12067 using Catch::Detail::size;
12068#else
12069 using std::size;
12070#endif
12071 return size(rng) == m_target_size;
12072 }
12073
12074 std::string describe() const override;
12075 };
12076
12077 template <typename Matcher>
12078 class SizeMatchesMatcher final : public MatcherGenericBase {
12079 Matcher m_matcher;
12080 public:
12081 explicit SizeMatchesMatcher(Matcher m):
12082 m_matcher(CATCH_MOVE(m))
12083 {}
12084
12085 template <typename RangeLike>
12086 bool match(RangeLike&& rng) const {
12087#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS)
12088 using Catch::Detail::size;
12089#else
12090 using std::size;
12091#endif
12092 return m_matcher.match(size(rng));
12093 }
12094
12095 std::string describe() const override {
12096 return "size matches " + m_matcher.describe();
12097 }
12098 };
12099
12100
12101 //! Creates a matcher that accepts empty ranges/containers
12102 IsEmptyMatcher IsEmpty();
12103 //! Creates a matcher that accepts ranges/containers with specific size
12104 HasSizeMatcher SizeIs(std::size_t sz);
12105 template <typename Matcher>
12106 std::enable_if_t<Detail::is_matcher<Matcher>::value,
12107 SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) {
12108 return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)};
12109 }
12110
12111 } // end namespace Matchers
12112} // end namespace Catch
12113
12114#endif // CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED
12115
12116
12117#ifndef CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
12118#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
12119
12120
12121#include <algorithm>
12122#include <functional>
12123
12124namespace Catch {
12125 namespace Matchers {
12126 //! Matcher for checking that an element in range is equal to specific element
12127 template <typename T, typename Equality>
12128 class ContainsElementMatcher final : public MatcherGenericBase {
12129 T m_desired;
12130 Equality m_eq;
12131 public:
12132 template <typename T2, typename Equality2>
12133 ContainsElementMatcher(T2&& target, Equality2&& predicate):
12134 m_desired(CATCH_FORWARD(target)),
12135 m_eq(CATCH_FORWARD(predicate))
12136 {}
12137
12138 std::string describe() const override {
12139 return "contains element " + Catch::Detail::stringify(m_desired);
12140 }
12141
12142 template <typename RangeLike>
12143 bool match( RangeLike&& rng ) const {
12144 for ( auto&& elem : rng ) {
12145 if ( m_eq( elem, m_desired ) ) { return true; }
12146 }
12147 return false;
12148 }
12149 };
12150
12151 //! Meta-matcher for checking that an element in a range matches a specific matcher
12152 template <typename Matcher>
12153 class ContainsMatcherMatcher final : public MatcherGenericBase {
12154 Matcher m_matcher;
12155 public:
12156 // Note that we do a copy+move to avoid having to SFINAE this
12157 // constructor (and also avoid some perfect forwarding failure
12158 // cases)
12159 ContainsMatcherMatcher(Matcher matcher):
12160 m_matcher(CATCH_MOVE(matcher))
12161 {}
12162
12163 template <typename RangeLike>
12164 bool match(RangeLike&& rng) const {
12165 for (auto&& elem : rng) {
12166 if (m_matcher.match(elem)) {
12167 return true;
12168 }
12169 }
12170 return false;
12171 }
12172
12173 std::string describe() const override {
12174 return "contains element matching " + m_matcher.describe();
12175 }
12176 };
12177
12178 /**
12179 * Creates a matcher that checks whether a range contains a specific element.
12180 *
12181 * Uses `std::equal_to` to do the comparison
12182 */
12183 template <typename T>
12184 std::enable_if_t<!Detail::is_matcher<T>::value,
12185 ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) {
12186 return { CATCH_FORWARD(elem), std::equal_to<>{} };
12187 }
12188
12189 //! Creates a matcher that checks whether a range contains element matching a matcher
12190 template <typename Matcher>
12191 std::enable_if_t<Detail::is_matcher<Matcher>::value,
12192 ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) {
12193 return { CATCH_FORWARD(matcher) };
12194 }
12195
12196 /**
12197 * Creates a matcher that checks whether a range contains a specific element.
12198 *
12199 * Uses `eq` to do the comparisons, the element is provided on the rhs
12200 */
12201 template <typename T, typename Equality>
12202 ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) {
12203 return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) };
12204 }
12205
12206 }
12207}
12208
12209#endif // CATCH_MATCHERS_CONTAINS_HPP_INCLUDED
12210
12211
12212#ifndef CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
12213#define CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
12214
12215
12216namespace Catch {
12217namespace Matchers {
12218
12219class ExceptionMessageMatcher final : public MatcherBase<std::exception> {
12220 std::string m_message;
12221public:
12222
12223 ExceptionMessageMatcher(std::string const& message):
12224 m_message(message)
12225 {}
12226
12227 bool match(std::exception const& ex) const override;
12228
12229 std::string describe() const override;
12230};
12231
12232//! Creates a matcher that checks whether a std derived exception has the provided message
12233ExceptionMessageMatcher Message(std::string const& message);
12234
12235template <typename StringMatcherType>
12236class ExceptionMessageMatchesMatcher final
12237 : public MatcherBase<std::exception> {
12238 StringMatcherType m_matcher;
12239
12240public:
12241 ExceptionMessageMatchesMatcher( StringMatcherType matcher ):
12242 m_matcher( CATCH_MOVE( matcher ) ) {}
12243
12244 bool match( std::exception const& ex ) const override {
12245 return m_matcher.match( ex.what() );
12246 }
12247
12248 std::string describe() const override {
12249 return " matches \"" + m_matcher.describe() + '"';
12250 }
12251};
12252
12253//! Creates a matcher that checks whether a message from an std derived
12254//! exception matches a provided matcher
12255template <typename StringMatcherType>
12256ExceptionMessageMatchesMatcher<StringMatcherType>
12257MessageMatches( StringMatcherType&& matcher ) {
12258 return { CATCH_FORWARD( matcher ) };
12259}
12260
12261} // namespace Matchers
12262} // namespace Catch
12263
12264#endif // CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
12265
12266
12267#ifndef CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
12268#define CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
12269
12270
12271namespace Catch {
12272namespace Matchers {
12273
12274 namespace Detail {
12275 enum class FloatingPointKind : uint8_t;
12276 }
12277
12278 class WithinAbsMatcher final : public MatcherBase<double> {
12279 public:
12280 WithinAbsMatcher(double target, double margin);
12281 bool match(double const& matchee) const override;
12282 std::string describe() const override;
12283 private:
12284 double m_target;
12285 double m_margin;
12286 };
12287
12288 //! Creates a matcher that accepts numbers within certain range of target
12289 WithinAbsMatcher WithinAbs( double target, double margin );
12290
12291
12292
12293 class WithinUlpsMatcher final : public MatcherBase<double> {
12294 public:
12295 WithinUlpsMatcher( double target,
12296 uint64_t ulps,
12297 Detail::FloatingPointKind baseType );
12298 bool match(double const& matchee) const override;
12299 std::string describe() const override;
12300 private:
12301 double m_target;
12302 uint64_t m_ulps;
12303 Detail::FloatingPointKind m_type;
12304 };
12305
12306 //! Creates a matcher that accepts doubles within certain ULP range of target
12307 WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
12308 //! Creates a matcher that accepts floats within certain ULP range of target
12309 WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
12310
12311
12312
12313 // Given IEEE-754 format for floats and doubles, we can assume
12314 // that float -> double promotion is lossless. Given this, we can
12315 // assume that if we do the standard relative comparison of
12316 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
12317 // the same result if we do this for floats, as if we do this for
12318 // doubles that were promoted from floats.
12319 class WithinRelMatcher final : public MatcherBase<double> {
12320 public:
12321 WithinRelMatcher( double target, double epsilon );
12322 bool match(double const& matchee) const override;
12323 std::string describe() const override;
12324 private:
12325 double m_target;
12326 double m_epsilon;
12327 };
12328
12329 //! Creates a matcher that accepts doubles within certain relative range of target
12330 WithinRelMatcher WithinRel(double target, double eps);
12331 //! Creates a matcher that accepts doubles within 100*DBL_EPS relative range of target
12332 WithinRelMatcher WithinRel(double target);
12333 //! Creates a matcher that accepts doubles within certain relative range of target
12334 WithinRelMatcher WithinRel(float target, float eps);
12335 //! Creates a matcher that accepts floats within 100*FLT_EPS relative range of target
12336 WithinRelMatcher WithinRel(float target);
12337
12338
12339
12340 class IsNaNMatcher final : public MatcherBase<double> {
12341 public:
12342 IsNaNMatcher() = default;
12343 bool match( double const& matchee ) const override;
12344 std::string describe() const override;
12345 };
12346
12347 IsNaNMatcher IsNaN();
12348
12349} // namespace Matchers
12350} // namespace Catch
12351
12352#endif // CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED
12353
12354
12355#ifndef CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
12356#define CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
12357
12358
12359#include <string>
12360
12361namespace Catch {
12362namespace Matchers {
12363
12364namespace Detail {
12365 std::string finalizeDescription(const std::string& desc);
12366} // namespace Detail
12367
12368template <typename T, typename Predicate>
12369class PredicateMatcher final : public MatcherBase<T> {
12370 Predicate m_predicate;
12371 std::string m_description;
12372public:
12373
12374 PredicateMatcher(Predicate&& elem, std::string const& descr)
12375 :m_predicate(CATCH_FORWARD(elem)),
12376 m_description(Detail::finalizeDescription(descr))
12377 {}
12378
12379 bool match( T const& item ) const override {
12380 return m_predicate(item);
12381 }
12382
12383 std::string describe() const override {
12384 return m_description;
12385 }
12386};
12387
12388 /**
12389 * Creates a matcher that calls delegates `match` to the provided predicate.
12390 *
12391 * The user has to explicitly specify the argument type to the matcher
12392 */
12393 template<typename T, typename Pred>
12394 PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") {
12395 static_assert(is_callable<Pred(T)>::value, "Predicate not callable with argument T");
12396 static_assert(std::is_same<bool, FunctionReturnType<Pred, T>>::value, "Predicate does not return bool");
12397 return PredicateMatcher<T, Pred>(CATCH_FORWARD(predicate), description);
12398 }
12399
12400} // namespace Matchers
12401} // namespace Catch
12402
12403#endif // CATCH_MATCHERS_PREDICATE_HPP_INCLUDED
12404
12405
12406#ifndef CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
12407#define CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
12408
12409
12410namespace Catch {
12411 namespace Matchers {
12412 // Matcher for checking that all elements in range matches a given matcher.
12413 template <typename Matcher>
12414 class AllMatchMatcher final : public MatcherGenericBase {
12415 Matcher m_matcher;
12416 public:
12417 AllMatchMatcher(Matcher matcher):
12418 m_matcher(CATCH_MOVE(matcher))
12419 {}
12420
12421 std::string describe() const override {
12422 return "all match " + m_matcher.describe();
12423 }
12424
12425 template <typename RangeLike>
12426 bool match(RangeLike&& rng) const {
12427 for (auto&& elem : rng) {
12428 if (!m_matcher.match(elem)) {
12429 return false;
12430 }
12431 }
12432 return true;
12433 }
12434 };
12435
12436 // Matcher for checking that no element in range matches a given matcher.
12437 template <typename Matcher>
12438 class NoneMatchMatcher final : public MatcherGenericBase {
12439 Matcher m_matcher;
12440 public:
12441 NoneMatchMatcher(Matcher matcher):
12442 m_matcher(CATCH_MOVE(matcher))
12443 {}
12444
12445 std::string describe() const override {
12446 return "none match " + m_matcher.describe();
12447 }
12448
12449 template <typename RangeLike>
12450 bool match(RangeLike&& rng) const {
12451 for (auto&& elem : rng) {
12452 if (m_matcher.match(elem)) {
12453 return false;
12454 }
12455 }
12456 return true;
12457 }
12458 };
12459
12460 // Matcher for checking that at least one element in range matches a given matcher.
12461 template <typename Matcher>
12462 class AnyMatchMatcher final : public MatcherGenericBase {
12463 Matcher m_matcher;
12464 public:
12465 AnyMatchMatcher(Matcher matcher):
12466 m_matcher(CATCH_MOVE(matcher))
12467 {}
12468
12469 std::string describe() const override {
12470 return "any match " + m_matcher.describe();
12471 }
12472
12473 template <typename RangeLike>
12474 bool match(RangeLike&& rng) const {
12475 for (auto&& elem : rng) {
12476 if (m_matcher.match(elem)) {
12477 return true;
12478 }
12479 }
12480 return false;
12481 }
12482 };
12483
12484 // Matcher for checking that all elements in range are true.
12485 class AllTrueMatcher final : public MatcherGenericBase {
12486 public:
12487 std::string describe() const override;
12488
12489 template <typename RangeLike>
12490 bool match(RangeLike&& rng) const {
12491 for (auto&& elem : rng) {
12492 if (!elem) {
12493 return false;
12494 }
12495 }
12496 return true;
12497 }
12498 };
12499
12500 // Matcher for checking that no element in range is true.
12501 class NoneTrueMatcher final : public MatcherGenericBase {
12502 public:
12503 std::string describe() const override;
12504
12505 template <typename RangeLike>
12506 bool match(RangeLike&& rng) const {
12507 for (auto&& elem : rng) {
12508 if (elem) {
12509 return false;
12510 }
12511 }
12512 return true;
12513 }
12514 };
12515
12516 // Matcher for checking that any element in range is true.
12517 class AnyTrueMatcher final : public MatcherGenericBase {
12518 public:
12519 std::string describe() const override;
12520
12521 template <typename RangeLike>
12522 bool match(RangeLike&& rng) const {
12523 for (auto&& elem : rng) {
12524 if (elem) {
12525 return true;
12526 }
12527 }
12528 return false;
12529 }
12530 };
12531
12532 // Creates a matcher that checks whether all elements in a range match a matcher
12533 template <typename Matcher>
12534 AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) {
12535 return { CATCH_FORWARD(matcher) };
12536 }
12537
12538 // Creates a matcher that checks whether no element in a range matches a matcher.
12539 template <typename Matcher>
12540 NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) {
12541 return { CATCH_FORWARD(matcher) };
12542 }
12543
12544 // Creates a matcher that checks whether any element in a range matches a matcher.
12545 template <typename Matcher>
12546 AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) {
12547 return { CATCH_FORWARD(matcher) };
12548 }
12549
12550 // Creates a matcher that checks whether all elements in a range are true
12551 AllTrueMatcher AllTrue();
12552
12553 // Creates a matcher that checks whether no element in a range is true
12554 NoneTrueMatcher NoneTrue();
12555
12556 // Creates a matcher that checks whether any element in a range is true
12557 AnyTrueMatcher AnyTrue();
12558 }
12559}
12560
12561#endif // CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED
12562
12563
12564#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
12565#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
12566
12567
12568#include <algorithm>
12569#include <utility>
12570
12571namespace Catch {
12572 namespace Matchers {
12573
12574 /**
12575 * Matcher for checking that an element contains the same
12576 * elements in the same order
12577 */
12578 template <typename TargetRangeLike, typename Equality>
12579 class RangeEqualsMatcher final : public MatcherGenericBase {
12580 TargetRangeLike m_desired;
12581 Equality m_predicate;
12582
12583 public:
12584 template <typename TargetRangeLike2, typename Equality2>
12585 RangeEqualsMatcher( TargetRangeLike2&& range,
12586 Equality2&& predicate ):
12587 m_desired( CATCH_FORWARD( range ) ),
12588 m_predicate( CATCH_FORWARD( predicate ) ) {}
12589
12590 template <typename RangeLike>
12591 bool match( RangeLike&& rng ) const {
12592 auto rng_start = begin( rng );
12593 const auto rng_end = end( rng );
12594 auto target_start = begin( m_desired );
12595 const auto target_end = end( m_desired );
12596
12597 while (rng_start != rng_end && target_start != target_end) {
12598 if (!m_predicate(*rng_start, *target_start)) {
12599 return false;
12600 }
12601 ++rng_start;
12602 ++target_start;
12603 }
12604 return rng_start == rng_end && target_start == target_end;
12605 }
12606
12607 std::string describe() const override {
12608 return "elements are " + Catch::Detail::stringify( m_desired );
12609 }
12610 };
12611
12612 /**
12613 * Matcher for checking that an element contains the same
12614 * elements (but not necessarily in the same order)
12615 */
12616 template <typename TargetRangeLike, typename Equality>
12617 class UnorderedRangeEqualsMatcher final : public MatcherGenericBase {
12618 TargetRangeLike m_desired;
12619 Equality m_predicate;
12620
12621 public:
12622 template <typename TargetRangeLike2, typename Equality2>
12623 UnorderedRangeEqualsMatcher( TargetRangeLike2&& range,
12624 Equality2&& predicate ):
12625 m_desired( CATCH_FORWARD( range ) ),
12626 m_predicate( CATCH_FORWARD( predicate ) ) {}
12627
12628 template <typename RangeLike>
12629 bool match( RangeLike&& rng ) const {
12630 using std::begin;
12631 using std::end;
12632 return Catch::Detail::is_permutation( begin( m_desired ),
12633 end( m_desired ),
12634 begin( rng ),
12635 end( rng ),
12636 m_predicate );
12637 }
12638
12639 std::string describe() const override {
12640 return "unordered elements are " +
12641 ::Catch::Detail::stringify( m_desired );
12642 }
12643 };
12644
12645 /**
12646 * Creates a matcher that checks if all elements in a range are equal
12647 * to all elements in another range.
12648 *
12649 * Uses `std::equal_to` to do the comparison
12650 */
12651 template <typename RangeLike>
12652 std::enable_if_t<!Detail::is_matcher<RangeLike>::value,
12653 RangeEqualsMatcher<RangeLike, std::equal_to<>>>
12654 RangeEquals( RangeLike&& range ) {
12655 return { CATCH_FORWARD( range ), std::equal_to<>{} };
12656 }
12657
12658 /**
12659 * Creates a matcher that checks if all elements in a range are equal
12660 * to all elements in another range.
12661 *
12662 * Uses to provided predicate `predicate` to do the comparisons
12663 */
12664 template <typename RangeLike, typename Equality>
12665 RangeEqualsMatcher<RangeLike, Equality>
12666 RangeEquals( RangeLike&& range, Equality&& predicate ) {
12667 return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
12668 }
12669
12670 /**
12671 * Creates a matcher that checks if all elements in a range are equal
12672 * to all elements in another range, in some permutation
12673 *
12674 * Uses `std::equal_to` to do the comparison
12675 */
12676 template <typename RangeLike>
12677 std::enable_if_t<
12678 !Detail::is_matcher<RangeLike>::value,
12679 UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>>
12680 UnorderedRangeEquals( RangeLike&& range ) {
12681 return { CATCH_FORWARD( range ), std::equal_to<>{} };
12682 }
12683
12684 /**
12685 * Creates a matcher that checks if all elements in a range are equal
12686 * to all elements in another range, in some permutation.
12687 *
12688 * Uses to provided predicate `predicate` to do the comparisons
12689 */
12690 template <typename RangeLike, typename Equality>
12691 UnorderedRangeEqualsMatcher<RangeLike, Equality>
12692 UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) {
12693 return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) };
12694 }
12695 } // namespace Matchers
12696} // namespace Catch
12697
12698#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED
12699
12700
12701#ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED
12702#define CATCH_MATCHERS_STRING_HPP_INCLUDED
12703
12704
12705#include <string>
12706
12707namespace Catch {
12708namespace Matchers {
12709
12710 struct CasedString {
12711 CasedString( std::string const& str, CaseSensitive caseSensitivity );
12712 std::string adjustString( std::string const& str ) const;
12713 StringRef caseSensitivitySuffix() const;
12714
12715 CaseSensitive m_caseSensitivity;
12716 std::string m_str;
12717 };
12718
12719 class StringMatcherBase : public MatcherBase<std::string> {
12720 protected:
12721 CasedString m_comparator;
12722 StringRef m_operation;
12723
12724 public:
12725 StringMatcherBase( StringRef operation,
12726 CasedString const& comparator );
12727 std::string describe() const override;
12728 };
12729
12730 class StringEqualsMatcher final : public StringMatcherBase {
12731 public:
12732 StringEqualsMatcher( CasedString const& comparator );
12733 bool match( std::string const& source ) const override;
12734 };
12735 class StringContainsMatcher final : public StringMatcherBase {
12736 public:
12737 StringContainsMatcher( CasedString const& comparator );
12738 bool match( std::string const& source ) const override;
12739 };
12740 class StartsWithMatcher final : public StringMatcherBase {
12741 public:
12742 StartsWithMatcher( CasedString const& comparator );
12743 bool match( std::string const& source ) const override;
12744 };
12745 class EndsWithMatcher final : public StringMatcherBase {
12746 public:
12747 EndsWithMatcher( CasedString const& comparator );
12748 bool match( std::string const& source ) const override;
12749 };
12750
12751 class RegexMatcher final : public MatcherBase<std::string> {
12752 std::string m_regex;
12753 CaseSensitive m_caseSensitivity;
12754
12755 public:
12756 RegexMatcher( std::string regex, CaseSensitive caseSensitivity );
12757 bool match( std::string const& matchee ) const override;
12758 std::string describe() const override;
12759 };
12760
12761 //! Creates matcher that accepts strings that are exactly equal to `str`
12762 StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12763 //! Creates matcher that accepts strings that contain `str`
12764 StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12765 //! Creates matcher that accepts strings that _end_ with `str`
12766 EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12767 //! Creates matcher that accepts strings that _start_ with `str`
12768 StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12769 //! Creates matcher that accepts strings matching `regex`
12770 RegexMatcher Matches( std::string const& regex, CaseSensitive caseSensitivity = CaseSensitive::Yes );
12771
12772} // namespace Matchers
12773} // namespace Catch
12774
12775#endif // CATCH_MATCHERS_STRING_HPP_INCLUDED
12776
12777
12778#ifndef CATCH_MATCHERS_VECTOR_HPP_INCLUDED
12779#define CATCH_MATCHERS_VECTOR_HPP_INCLUDED
12780
12781
12782#include <algorithm>
12783
12784namespace Catch {
12785namespace Matchers {
12786
12787 template<typename T, typename Alloc>
12788 class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> {
12789 T const& m_comparator;
12790
12791 public:
12792 VectorContainsElementMatcher(T const& comparator):
12793 m_comparator(comparator)
12794 {}
12795
12796 bool match(std::vector<T, Alloc> const& v) const override {
12797 for (auto const& el : v) {
12798 if (el == m_comparator) {
12799 return true;
12800 }
12801 }
12802 return false;
12803 }
12804
12805 std::string describe() const override {
12806 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
12807 }
12808 };
12809
12810 template<typename T, typename AllocComp, typename AllocMatch>
12811 class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12812 std::vector<T, AllocComp> const& m_comparator;
12813
12814 public:
12815 ContainsMatcher(std::vector<T, AllocComp> const& comparator):
12816 m_comparator( comparator )
12817 {}
12818
12819 bool match(std::vector<T, AllocMatch> const& v) const override {
12820 // !TBD: see note in EqualsMatcher
12821 if (m_comparator.size() > v.size())
12822 return false;
12823 for (auto const& comparator : m_comparator) {
12824 auto present = false;
12825 for (const auto& el : v) {
12826 if (el == comparator) {
12827 present = true;
12828 break;
12829 }
12830 }
12831 if (!present) {
12832 return false;
12833 }
12834 }
12835 return true;
12836 }
12837 std::string describe() const override {
12838 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
12839 }
12840 };
12841
12842 template<typename T, typename AllocComp, typename AllocMatch>
12843 class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12844 std::vector<T, AllocComp> const& m_comparator;
12845
12846 public:
12847 EqualsMatcher(std::vector<T, AllocComp> const& comparator):
12848 m_comparator( comparator )
12849 {}
12850
12851 bool match(std::vector<T, AllocMatch> const& v) const override {
12852 // !TBD: This currently works if all elements can be compared using !=
12853 // - a more general approach would be via a compare template that defaults
12854 // to using !=. but could be specialised for, e.g. std::vector<T> etc
12855 // - then just call that directly
12856 if ( m_comparator.size() != v.size() ) { return false; }
12857 for ( std::size_t i = 0; i < v.size(); ++i ) {
12858 if ( !( m_comparator[i] == v[i] ) ) { return false; }
12859 }
12860 return true;
12861 }
12862 std::string describe() const override {
12863 return "Equals: " + ::Catch::Detail::stringify( m_comparator );
12864 }
12865 };
12866
12867 template<typename T, typename AllocComp, typename AllocMatch>
12868 class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12869 std::vector<T, AllocComp> const& m_comparator;
12870 mutable Catch::Approx approx = Catch::Approx::custom();
12871
12872 public:
12873 ApproxMatcher(std::vector<T, AllocComp> const& comparator):
12874 m_comparator( comparator )
12875 {}
12876
12877 bool match(std::vector<T, AllocMatch> const& v) const override {
12878 if (m_comparator.size() != v.size())
12879 return false;
12880 for (std::size_t i = 0; i < v.size(); ++i)
12881 if (m_comparator[i] != approx(v[i]))
12882 return false;
12883 return true;
12884 }
12885 std::string describe() const override {
12886 return "is approx: " + ::Catch::Detail::stringify( m_comparator );
12887 }
12888 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
12889 ApproxMatcher& epsilon( T const& newEpsilon ) {
12890 approx.epsilon(static_cast<double>(newEpsilon));
12891 return *this;
12892 }
12893 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
12894 ApproxMatcher& margin( T const& newMargin ) {
12895 approx.margin(static_cast<double>(newMargin));
12896 return *this;
12897 }
12898 template <typename = std::enable_if_t<std::is_constructible<double, T>::value>>
12899 ApproxMatcher& scale( T const& newScale ) {
12900 approx.scale(static_cast<double>(newScale));
12901 return *this;
12902 }
12903 };
12904
12905 template<typename T, typename AllocComp, typename AllocMatch>
12906 class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> {
12907 std::vector<T, AllocComp> const& m_target;
12908
12909 public:
12910 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target):
12911 m_target(target)
12912 {}
12913 bool match(std::vector<T, AllocMatch> const& vec) const override {
12914 if (m_target.size() != vec.size()) {
12915 return false;
12916 }
12917 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
12918 }
12919
12920 std::string describe() const override {
12921 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
12922 }
12923 };
12924
12925
12926 // The following functions create the actual matcher objects.
12927 // This allows the types to be inferred
12928
12929 //! Creates a matcher that matches vectors that contain all elements in `comparator`
12930 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
12931 ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
12932 return ContainsMatcher<T, AllocComp, AllocMatch>(comparator);
12933 }
12934
12935 //! Creates a matcher that matches vectors that contain `comparator` as an element
12936 template<typename T, typename Alloc = std::allocator<T>>
12937 VectorContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {
12938 return VectorContainsElementMatcher<T, Alloc>(comparator);
12939 }
12940
12941 //! Creates a matcher that matches vectors that are exactly equal to `comparator`
12942 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
12943 EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
12944 return EqualsMatcher<T, AllocComp, AllocMatch>(comparator);
12945 }
12946
12947 //! Creates a matcher that matches vectors that `comparator` as an element
12948 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
12949 ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
12950 return ApproxMatcher<T, AllocComp, AllocMatch>(comparator);
12951 }
12952
12953 //! Creates a matcher that matches vectors that is equal to `target` modulo permutation
12954 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
12955 UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {
12956 return UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target);
12957 }
12958
12959} // namespace Matchers
12960} // namespace Catch
12961
12962#endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED
12963
12964#endif // CATCH_MATCHERS_ALL_HPP_INCLUDED
12965
12966
12967/** \file
12968 * This is a convenience header for Catch2's Reporter support. It includes
12969 * **all** of Catch2 headers related to reporters, including all reporters.
12970 *
12971 * Generally the Catch2 users should use specific includes they need,
12972 * but this header can be used instead for ease-of-experimentation, or
12973 * just plain convenience, at the cost of (significantly) increased
12974 * compilation times.
12975 *
12976 * When a new header (reporter) is added to either the `reporter` folder,
12977 * or to the corresponding internal subfolder, it should be added here.
12978 */
12979
12980#ifndef CATCH_REPORTERS_ALL_HPP_INCLUDED
12981#define CATCH_REPORTERS_ALL_HPP_INCLUDED
12982
12983
12984
12985#ifndef CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
12986#define CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
12987
12988
12989
12990#ifndef CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
12991#define CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
12992
12993
12994
12995#ifndef CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
12996#define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
12997
12998
12999#include <map>
13000#include <string>
13001
13002namespace Catch {
13003 class ColourImpl;
13004
13005 /**
13006 * This is the base class for all reporters.
13007 *
13008 * If are writing a reporter, you must derive from this type, or one
13009 * of the helper reporter bases that are derived from this type.
13010 *
13011 * ReporterBase centralizes handling of various common tasks in reporters,
13012 * like storing the right stream for the reporters to write to, and
13013 * providing the default implementation of the different listing events.
13014 */
13015 class ReporterBase : public IEventListener {
13016 protected:
13017 //! The stream wrapper as passed to us by outside code
13018 Detail::unique_ptr<IStream> m_wrapped_stream;
13019 //! Cached output stream from `m_wrapped_stream` to reduce
13020 //! number of indirect calls needed to write output.
13021 std::ostream& m_stream;
13022 //! Colour implementation this reporter was configured for
13023 Detail::unique_ptr<ColourImpl> m_colour;
13024 //! The custom reporter options user passed down to the reporter
13025 std::map<std::string, std::string> m_customOptions;
13026
13027 public:
13028 ReporterBase( ReporterConfig&& config );
13029 ~ReporterBase() override; // = default;
13030
13031 /**
13032 * Provides a simple default listing of reporters.
13033 *
13034 * Should look roughly like the reporter listing in v2 and earlier
13035 * versions of Catch2.
13036 */
13037 void listReporters(
13038 std::vector<ReporterDescription> const& descriptions ) override;
13039 /**
13040 * Provides a simple default listing of listeners
13041 *
13042 * Looks similarly to listing of reporters, but with listener type
13043 * instead of reporter name.
13044 */
13045 void listListeners(
13046 std::vector<ListenerDescription> const& descriptions ) override;
13047 /**
13048 * Provides a simple default listing of tests.
13049 *
13050 * Should look roughly like the test listing in v2 and earlier versions
13051 * of Catch2. Especially supports low-verbosity listing that mimics the
13052 * old `--list-test-names-only` output.
13053 */
13054 void listTests( std::vector<TestCaseHandle> const& tests ) override;
13055 /**
13056 * Provides a simple default listing of tags.
13057 *
13058 * Should look roughly like the tag listing in v2 and earlier versions
13059 * of Catch2.
13060 */
13061 void listTags( std::vector<TagInfo> const& tags ) override;
13062 };
13063} // namespace Catch
13064
13065#endif // CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED
13066
13067#include <vector>
13068
13069namespace Catch {
13070
13071 class StreamingReporterBase : public ReporterBase {
13072 public:
13073 // GCC5 compat: we cannot use inherited constructor, because it
13074 // doesn't implement backport of P0136
13075 StreamingReporterBase(ReporterConfig&& _config):
13076 ReporterBase(CATCH_MOVE(_config))
13077 {}
13078 ~StreamingReporterBase() override;
13079
13080 void benchmarkPreparing( StringRef ) override {}
13081 void benchmarkStarting( BenchmarkInfo const& ) override {}
13082 void benchmarkEnded( BenchmarkStats<> const& ) override {}
13083 void benchmarkFailed( StringRef ) override {}
13084
13085 void fatalErrorEncountered( StringRef /*error*/ ) override {}
13086 void noMatchingTestCases( StringRef /*unmatchedSpec*/ ) override {}
13087 void reportInvalidTestSpec( StringRef /*invalidArgument*/ ) override {}
13088
13089 void testRunStarting( TestRunInfo const& _testRunInfo ) override;
13090
13091 void testCaseStarting(TestCaseInfo const& _testInfo) override {
13092 currentTestCaseInfo = &_testInfo;
13093 }
13094 void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
13095 void sectionStarting(SectionInfo const& _sectionInfo) override {
13096 m_sectionStack.push_back(_sectionInfo);
13097 }
13098
13099 void assertionStarting( AssertionInfo const& ) override {}
13100 void assertionEnded( AssertionStats const& ) override {}
13101
13102 void sectionEnded(SectionStats const& /* _sectionStats */) override {
13103 m_sectionStack.pop_back();
13104 }
13105 void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
13106 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
13107 currentTestCaseInfo = nullptr;
13108 }
13109 void testRunEnded( TestRunStats const& /* _testRunStats */ ) override;
13110
13111 void skipTest(TestCaseInfo const&) override {
13112 // Don't do anything with this by default.
13113 // It can optionally be overridden in the derived class.
13114 }
13115
13116 protected:
13117 TestRunInfo currentTestRunInfo{ "test run has not started yet"_sr };
13118 TestCaseInfo const* currentTestCaseInfo = nullptr;
13119
13120 //! Stack of all _active_ sections in the _current_ test case
13121 std::vector<SectionInfo> m_sectionStack;
13122 };
13123
13124} // end namespace Catch
13125
13126#endif // CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED
13127
13128#include <string>
13129
13130namespace Catch {
13131
13132 class AutomakeReporter final : public StreamingReporterBase {
13133 public:
13134 // GCC5 compat: we cannot use inherited constructor, because it
13135 // doesn't implement backport of P0136
13136 AutomakeReporter(ReporterConfig&& _config):
13137 StreamingReporterBase(CATCH_MOVE(_config))
13138 {}
13139 ~AutomakeReporter() override;
13140
13141 static std::string getDescription() {
13142 using namespace std::string_literals;
13143 return "Reports test results in the format of Automake .trs files"s;
13144 }
13145
13146 void testCaseEnded(TestCaseStats const& _testCaseStats) override;
13147 void skipTest(TestCaseInfo const& testInfo) override;
13148 };
13149
13150} // end namespace Catch
13151
13152#endif // CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED
13153
13154
13155#ifndef CATCH_REPORTER_COMPACT_HPP_INCLUDED
13156#define CATCH_REPORTER_COMPACT_HPP_INCLUDED
13157
13158
13159
13160
13161namespace Catch {
13162
13163 class CompactReporter final : public StreamingReporterBase {
13164 public:
13165 using StreamingReporterBase::StreamingReporterBase;
13166
13167 ~CompactReporter() override;
13168
13169 static std::string getDescription();
13170
13171 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13172
13173 void testRunStarting( TestRunInfo const& _testInfo ) override;
13174
13175 void assertionEnded(AssertionStats const& _assertionStats) override;
13176
13177 void sectionEnded(SectionStats const& _sectionStats) override;
13178
13179 void testRunEnded(TestRunStats const& _testRunStats) override;
13180
13181 };
13182
13183} // end namespace Catch
13184
13185#endif // CATCH_REPORTER_COMPACT_HPP_INCLUDED
13186
13187
13188#ifndef CATCH_REPORTER_CONSOLE_HPP_INCLUDED
13189#define CATCH_REPORTER_CONSOLE_HPP_INCLUDED
13190
13191
13192namespace Catch {
13193 // Fwd decls
13194 class TablePrinter;
13195
13196 class ConsoleReporter final : public StreamingReporterBase {
13197 Detail::unique_ptr<TablePrinter> m_tablePrinter;
13198
13199 public:
13200 ConsoleReporter(ReporterConfig&& config);
13201 ~ConsoleReporter() override;
13202 static std::string getDescription();
13203
13204 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13205 void reportInvalidTestSpec( StringRef arg ) override;
13206
13207 void assertionStarting(AssertionInfo const&) override;
13208
13209 void assertionEnded(AssertionStats const& _assertionStats) override;
13210
13211 void sectionStarting(SectionInfo const& _sectionInfo) override;
13212 void sectionEnded(SectionStats const& _sectionStats) override;
13213
13214 void benchmarkPreparing( StringRef name ) override;
13215 void benchmarkStarting(BenchmarkInfo const& info) override;
13216 void benchmarkEnded(BenchmarkStats<> const& stats) override;
13217 void benchmarkFailed( StringRef error ) override;
13218
13219 void testCaseEnded(TestCaseStats const& _testCaseStats) override;
13220 void testRunEnded(TestRunStats const& _testRunStats) override;
13221 void testRunStarting(TestRunInfo const& _testRunInfo) override;
13222
13223 private:
13224 void lazyPrint();
13225
13226 void lazyPrintWithoutClosingBenchmarkTable();
13227 void lazyPrintRunInfo();
13228 void printTestCaseAndSectionHeader();
13229
13230 void printClosedHeader(std::string const& _name);
13231 void printOpenHeader(std::string const& _name);
13232
13233 // if string has a : in first line will set indent to follow it on
13234 // subsequent lines
13235 void printHeaderString(std::string const& _string, std::size_t indent = 0);
13236
13237 void printTotalsDivider(Totals const& totals);
13238
13239 bool m_headerPrinted = false;
13240 bool m_testRunInfoPrinted = false;
13241 };
13242
13243} // end namespace Catch
13244
13245#endif // CATCH_REPORTER_CONSOLE_HPP_INCLUDED
13246
13247
13248#ifndef CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
13249#define CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
13250
13251
13252#include <string>
13253#include <vector>
13254
13255namespace Catch {
13256
13257 namespace Detail {
13258
13259 //! Represents either an assertion or a benchmark result to be handled by cumulative reporter later
13260 class AssertionOrBenchmarkResult {
13261 // This should really be a variant, but this is much faster
13262 // to write and the data layout here is already terrible
13263 // enough that we do not have to care about the object size.
13264 Optional<AssertionStats> m_assertion;
13265 Optional<BenchmarkStats<>> m_benchmark;
13266 public:
13267 AssertionOrBenchmarkResult(AssertionStats const& assertion);
13268 AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark);
13269
13270 bool isAssertion() const;
13271 bool isBenchmark() const;
13272
13273 AssertionStats const& asAssertion() const;
13274 BenchmarkStats<> const& asBenchmark() const;
13275 };
13276 }
13277
13278 /**
13279 * Utility base for reporters that need to handle all results at once
13280 *
13281 * It stores tree of all test cases, sections and assertions, and after the
13282 * test run is finished, calls into `testRunEndedCumulative` to pass the
13283 * control to the deriving class.
13284 *
13285 * If you are deriving from this class and override any testing related
13286 * member functions, you should first call into the base's implementation to
13287 * avoid breaking the tree construction.
13288 *
13289 * Due to the way this base functions, it has to expand assertions up-front,
13290 * even if they are later unused (e.g. because the deriving reporter does
13291 * not report successful assertions, or because the deriving reporter does
13292 * not use assertion expansion at all). Derived classes can use two
13293 * customization points, `m_shouldStoreSuccesfulAssertions` and
13294 * `m_shouldStoreFailedAssertions`, to disable the expansion and gain extra
13295 * performance. **Accessing the assertion expansions if it wasn't stored is
13296 * UB.**
13297 */
13298 class CumulativeReporterBase : public ReporterBase {
13299 public:
13300 template<typename T, typename ChildNodeT>
13301 struct Node {
13302 explicit Node( T const& _value ) : value( _value ) {}
13303
13304 using ChildNodes = std::vector<Detail::unique_ptr<ChildNodeT>>;
13305 T value;
13306 ChildNodes children;
13307 };
13308 struct SectionNode {
13309 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
13310
13311 bool operator == (SectionNode const& other) const {
13312 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
13313 }
13314
13315 bool hasAnyAssertions() const;
13316
13317 SectionStats stats;
13318 std::vector<Detail::unique_ptr<SectionNode>> childSections;
13319 std::vector<Detail::AssertionOrBenchmarkResult> assertionsAndBenchmarks;
13320 std::string stdOut;
13321 std::string stdErr;
13322 };
13323
13324
13325 using TestCaseNode = Node<TestCaseStats, SectionNode>;
13326 using TestRunNode = Node<TestRunStats, TestCaseNode>;
13327
13328 // GCC5 compat: we cannot use inherited constructor, because it
13329 // doesn't implement backport of P0136
13330 CumulativeReporterBase(ReporterConfig&& _config):
13331 ReporterBase(CATCH_MOVE(_config))
13332 {}
13333 ~CumulativeReporterBase() override;
13334
13335 void benchmarkPreparing( StringRef ) override {}
13336 void benchmarkStarting( BenchmarkInfo const& ) override {}
13337 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
13338 void benchmarkFailed( StringRef ) override {}
13339
13340 void noMatchingTestCases( StringRef ) override {}
13341 void reportInvalidTestSpec( StringRef ) override {}
13342 void fatalErrorEncountered( StringRef /*error*/ ) override {}
13343
13344 void testRunStarting( TestRunInfo const& ) override {}
13345
13346 void testCaseStarting( TestCaseInfo const& ) override {}
13347 void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {}
13348 void sectionStarting( SectionInfo const& sectionInfo ) override;
13349
13350 void assertionStarting( AssertionInfo const& ) override {}
13351
13352 void assertionEnded( AssertionStats const& assertionStats ) override;
13353 void sectionEnded( SectionStats const& sectionStats ) override;
13354 void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {}
13355 void testCaseEnded( TestCaseStats const& testCaseStats ) override;
13356 void testRunEnded( TestRunStats const& testRunStats ) override;
13357 //! Customization point: called after last test finishes (testRunEnded has been handled)
13358 virtual void testRunEndedCumulative() = 0;
13359
13360 void skipTest(TestCaseInfo const&) override {}
13361
13362 protected:
13363 //! Should the cumulative base store the assertion expansion for successful assertions?
13364 bool m_shouldStoreSuccesfulAssertions = true;
13365 //! Should the cumulative base store the assertion expansion for failed assertions?
13366 bool m_shouldStoreFailedAssertions = true;
13367
13368 // We need lazy construction here. We should probably refactor it
13369 // later, after the events are redone.
13370 //! The root node of the test run tree.
13371 Detail::unique_ptr<TestRunNode> m_testRun;
13372
13373 private:
13374 // Note: We rely on pointer identity being stable, which is why
13375 // we store pointers to the nodes rather than the values.
13376 std::vector<Detail::unique_ptr<TestCaseNode>> m_testCases;
13377 // Root section of the _current_ test case
13378 Detail::unique_ptr<SectionNode> m_rootSection;
13379 // Deepest section of the _current_ test case
13380 SectionNode* m_deepestSection = nullptr;
13381 // Stack of _active_ sections in the _current_ test case
13382 std::vector<SectionNode*> m_sectionStack;
13383 };
13384
13385} // end namespace Catch
13386
13387#endif // CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED
13388
13389
13390#ifndef CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
13391#define CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
13392
13393
13394namespace Catch {
13395
13396 /**
13397 * Base class to simplify implementing listeners.
13398 *
13399 * Provides empty default implementation for all IEventListener member
13400 * functions, so that a listener implementation can pick which
13401 * member functions it actually cares about.
13402 */
13403 class EventListenerBase : public IEventListener {
13404 public:
13405 using IEventListener::IEventListener;
13406
13407 void reportInvalidTestSpec( StringRef unmatchedSpec ) override;
13408 void fatalErrorEncountered( StringRef error ) override;
13409
13410 void benchmarkPreparing( StringRef name ) override;
13411 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
13412 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
13413 void benchmarkFailed( StringRef error ) override;
13414
13415 void assertionStarting( AssertionInfo const& assertionInfo ) override;
13416 void assertionEnded( AssertionStats const& assertionStats ) override;
13417
13418 void listReporters(
13419 std::vector<ReporterDescription> const& descriptions ) override;
13420 void listListeners(
13421 std::vector<ListenerDescription> const& descriptions ) override;
13422 void listTests( std::vector<TestCaseHandle> const& tests ) override;
13423 void listTags( std::vector<TagInfo> const& tagInfos ) override;
13424
13425 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13426 void testRunStarting( TestRunInfo const& testRunInfo ) override;
13427 void testCaseStarting( TestCaseInfo const& testInfo ) override;
13428 void testCasePartialStarting( TestCaseInfo const& testInfo,
13429 uint64_t partNumber ) override;
13430 void sectionStarting( SectionInfo const& sectionInfo ) override;
13431 void sectionEnded( SectionStats const& sectionStats ) override;
13432 void testCasePartialEnded( TestCaseStats const& testCaseStats,
13433 uint64_t partNumber ) override;
13434 void testCaseEnded( TestCaseStats const& testCaseStats ) override;
13435 void testRunEnded( TestRunStats const& testRunStats ) override;
13436 void skipTest( TestCaseInfo const& testInfo ) override;
13437 };
13438
13439} // end namespace Catch
13440
13441#endif // CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED
13442
13443
13444#ifndef CATCH_REPORTER_HELPERS_HPP_INCLUDED
13445#define CATCH_REPORTER_HELPERS_HPP_INCLUDED
13446
13447#include <iosfwd>
13448#include <string>
13449#include <vector>
13450
13451
13452namespace Catch {
13453
13454 class IConfig;
13455 class TestCaseHandle;
13456 class ColourImpl;
13457
13458 // Returns double formatted as %.3f (format expected on output)
13459 std::string getFormattedDuration( double duration );
13460
13461 //! Should the reporter show duration of test given current configuration?
13462 bool shouldShowDuration( IConfig const& config, double duration );
13463
13464 std::string serializeFilters( std::vector<std::string> const& filters );
13465
13466 struct lineOfChars {
13467 char c;
13468 constexpr lineOfChars( char c_ ): c( c_ ) {}
13469
13470 friend std::ostream& operator<<( std::ostream& out, lineOfChars value );
13471 };
13472
13473 /**
13474 * Lists reporter descriptions to the provided stream in user-friendly
13475 * format
13476 *
13477 * Used as the default listing implementation by the first party reporter
13478 * bases. The output should be backwards compatible with the output of
13479 * Catch2 v2 binaries.
13480 */
13481 void
13482 defaultListReporters( std::ostream& out,
13483 std::vector<ReporterDescription> const& descriptions,
13484 Verbosity verbosity );
13485
13486 /**
13487 * Lists listeners descriptions to the provided stream in user-friendly
13488 * format
13489 */
13490 void defaultListListeners( std::ostream& out,
13491 std::vector<ListenerDescription> const& descriptions );
13492
13493 /**
13494 * Lists tag information to the provided stream in user-friendly format
13495 *
13496 * Used as the default listing implementation by the first party reporter
13497 * bases. The output should be backwards compatible with the output of
13498 * Catch2 v2 binaries.
13499 */
13500 void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered );
13501
13502 /**
13503 * Lists test case information to the provided stream in user-friendly
13504 * format
13505 *
13506 * Used as the default listing implementation by the first party reporter
13507 * bases. The output is backwards compatible with the output of Catch2
13508 * v2 binaries, and also supports the format specific to the old
13509 * `--list-test-names-only` option, for people who used it in integrations.
13510 */
13511 void defaultListTests( std::ostream& out,
13512 ColourImpl* streamColour,
13513 std::vector<TestCaseHandle> const& tests,
13514 bool isFiltered,
13515 Verbosity verbosity );
13516
13517 /**
13518 * Prints test run totals to the provided stream in user-friendly format
13519 *
13520 * Used by the console and compact reporters.
13521 */
13522 void printTestRunTotals( std::ostream& stream,
13523 ColourImpl& streamColour,
13524 Totals const& totals );
13525
13526} // end namespace Catch
13527
13528#endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED
13529
13530
13531
13532#ifndef CATCH_REPORTER_JSON_HPP_INCLUDED
13533#define CATCH_REPORTER_JSON_HPP_INCLUDED
13534
13535
13536#include <stack>
13537
13538namespace Catch {
13539 class JsonReporter : public StreamingReporterBase {
13540 public:
13541 JsonReporter( ReporterConfig&& config );
13542
13543 ~JsonReporter() override;
13544
13545 static std::string getDescription();
13546
13547 public: // StreamingReporterBase
13548 void testRunStarting( TestRunInfo const& runInfo ) override;
13549 void testRunEnded( TestRunStats const& runStats ) override;
13550
13551 void testCaseStarting( TestCaseInfo const& tcInfo ) override;
13552 void testCaseEnded( TestCaseStats const& tcStats ) override;
13553
13554 void testCasePartialStarting( TestCaseInfo const& tcInfo,
13555 uint64_t index ) override;
13556 void testCasePartialEnded( TestCaseStats const& tcStats,
13557 uint64_t index ) override;
13558
13559 void sectionStarting( SectionInfo const& sectionInfo ) override;
13560 void sectionEnded( SectionStats const& sectionStats ) override;
13561
13562 void assertionStarting( AssertionInfo const& assertionInfo ) override;
13563 void assertionEnded( AssertionStats const& assertionStats ) override;
13564
13565 //void testRunEndedCumulative() override;
13566
13567 void benchmarkPreparing( StringRef name ) override;
13568 void benchmarkStarting( BenchmarkInfo const& ) override;
13569 void benchmarkEnded( BenchmarkStats<> const& ) override;
13570 void benchmarkFailed( StringRef error ) override;
13571
13572 void listReporters(
13573 std::vector<ReporterDescription> const& descriptions ) override;
13574 void listListeners(
13575 std::vector<ListenerDescription> const& descriptions ) override;
13576 void listTests( std::vector<TestCaseHandle> const& tests ) override;
13577 void listTags( std::vector<TagInfo> const& tags ) override;
13578
13579 private:
13580 Timer m_testCaseTimer;
13581 enum class Writer {
13582 Object,
13583 Array
13584 };
13585
13586 JsonArrayWriter& startArray();
13587 JsonArrayWriter& startArray( StringRef key );
13588
13589 JsonObjectWriter& startObject();
13590 JsonObjectWriter& startObject( StringRef key );
13591
13592 void endObject();
13593 void endArray();
13594
13595 bool isInside( Writer writer );
13596
13597 void startListing();
13598 void endListing();
13599
13600 // Invariant:
13601 // When m_writers is not empty and its top element is
13602 // - Writer::Object, then m_objectWriters is not be empty
13603 // - Writer::Array, then m_arrayWriters shall not be empty
13604 std::stack<JsonObjectWriter> m_objectWriters{};
13605 std::stack<JsonArrayWriter> m_arrayWriters{};
13606 std::stack<Writer> m_writers{};
13607
13608 bool m_startedListing = false;
13609
13610 // std::size_t m_sectionDepth = 0;
13611 // std::size_t m_sectionStarted = 0;
13612 };
13613} // namespace Catch
13614
13615#endif // CATCH_REPORTER_JSON_HPP_INCLUDED
13616
13617
13618#ifndef CATCH_REPORTER_JUNIT_HPP_INCLUDED
13619#define CATCH_REPORTER_JUNIT_HPP_INCLUDED
13620
13621
13622
13623namespace Catch {
13624
13625 class JunitReporter final : public CumulativeReporterBase {
13626 public:
13627 JunitReporter(ReporterConfig&& _config);
13628
13629 static std::string getDescription();
13630
13631 void testRunStarting(TestRunInfo const& runInfo) override;
13632
13633 void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
13634 void assertionEnded(AssertionStats const& assertionStats) override;
13635
13636 void testCaseEnded(TestCaseStats const& testCaseStats) override;
13637
13638 void testRunEndedCumulative() override;
13639
13640 private:
13641 void writeRun(TestRunNode const& testRunNode, double suiteTime);
13642
13643 void writeTestCase(TestCaseNode const& testCaseNode);
13644
13645 void writeSection( std::string const& className,
13646 std::string const& rootName,
13647 SectionNode const& sectionNode,
13648 bool testOkToFail );
13649
13650 void writeAssertions(SectionNode const& sectionNode);
13651 void writeAssertion(AssertionStats const& stats);
13652
13653 XmlWriter xml;
13654 Timer suiteTimer;
13655 std::string stdOutForSuite;
13656 std::string stdErrForSuite;
13657 unsigned int unexpectedExceptions = 0;
13658 bool m_okToFail = false;
13659 };
13660
13661} // end namespace Catch
13662
13663#endif // CATCH_REPORTER_JUNIT_HPP_INCLUDED
13664
13665
13666#ifndef CATCH_REPORTER_MULTI_HPP_INCLUDED
13667#define CATCH_REPORTER_MULTI_HPP_INCLUDED
13668
13669
13670namespace Catch {
13671
13672 class MultiReporter final : public IEventListener {
13673 /*
13674 * Stores all added reporters and listeners
13675 *
13676 * All Listeners are stored before all reporters, and individual
13677 * listeners/reporters are stored in order of insertion.
13678 */
13679 std::vector<IEventListenerPtr> m_reporterLikes;
13680 bool m_haveNoncapturingReporters = false;
13681
13682 // Keep track of how many listeners we have already inserted,
13683 // so that we can insert them into the main vector at the right place
13684 size_t m_insertedListeners = 0;
13685
13686 void updatePreferences(IEventListener const& reporterish);
13687
13688 public:
13689 using IEventListener::IEventListener;
13690
13691 void addListener( IEventListenerPtr&& listener );
13692 void addReporter( IEventListenerPtr&& reporter );
13693
13694 public: // IEventListener
13695
13696 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13697 void fatalErrorEncountered( StringRef error ) override;
13698 void reportInvalidTestSpec( StringRef arg ) override;
13699
13700 void benchmarkPreparing( StringRef name ) override;
13701 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
13702 void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
13703 void benchmarkFailed( StringRef error ) override;
13704
13705 void testRunStarting( TestRunInfo const& testRunInfo ) override;
13706 void testCaseStarting( TestCaseInfo const& testInfo ) override;
13707 void testCasePartialStarting(TestCaseInfo const& testInfo, uint64_t partNumber) override;
13708 void sectionStarting( SectionInfo const& sectionInfo ) override;
13709 void assertionStarting( AssertionInfo const& assertionInfo ) override;
13710
13711 void assertionEnded( AssertionStats const& assertionStats ) override;
13712 void sectionEnded( SectionStats const& sectionStats ) override;
13713 void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override;
13714 void testCaseEnded( TestCaseStats const& testCaseStats ) override;
13715 void testRunEnded( TestRunStats const& testRunStats ) override;
13716
13717 void skipTest( TestCaseInfo const& testInfo ) override;
13718
13719 void listReporters(std::vector<ReporterDescription> const& descriptions) override;
13720 void listListeners(std::vector<ListenerDescription> const& descriptions) override;
13721 void listTests(std::vector<TestCaseHandle> const& tests) override;
13722 void listTags(std::vector<TagInfo> const& tags) override;
13723
13724
13725 };
13726
13727} // end namespace Catch
13728
13729#endif // CATCH_REPORTER_MULTI_HPP_INCLUDED
13730
13731
13732#ifndef CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
13733#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
13734
13735
13736#include <type_traits>
13737
13738namespace Catch {
13739
13740 namespace Detail {
13741
13742 template <typename T, typename = void>
13743 struct has_description : std::false_type {};
13744
13745 template <typename T>
13746 struct has_description<
13747 T,
13748 void_t<decltype( T::getDescription() )>>
13749 : std::true_type {};
13750
13751 //! Indirection for reporter registration, so that the error handling is
13752 //! independent on the reporter's concrete type
13753 void registerReporterImpl( std::string const& name,
13754 IReporterFactoryPtr reporterPtr );
13755 //! Actually registers the factory, independent on listener's concrete type
13756 void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory );
13757 } // namespace Detail
13758
13759 class IEventListener;
13760 using IEventListenerPtr = Detail::unique_ptr<IEventListener>;
13761
13762 template <typename T>
13763 class ReporterFactory : public IReporterFactory {
13764
13765 IEventListenerPtr create( ReporterConfig&& config ) const override {
13766 return Detail::make_unique<T>( CATCH_MOVE(config) );
13767 }
13768
13769 std::string getDescription() const override {
13770 return T::getDescription();
13771 }
13772 };
13773
13774
13775 template<typename T>
13776 class ReporterRegistrar {
13777 public:
13778 explicit ReporterRegistrar( std::string const& name ) {
13779 registerReporterImpl( name,
13780 Detail::make_unique<ReporterFactory<T>>() );
13781 }
13782 };
13783
13784 template<typename T>
13785 class ListenerRegistrar {
13786
13787 class TypedListenerFactory : public EventListenerFactory {
13788 StringRef m_listenerName;
13789
13790 std::string getDescriptionImpl( std::true_type ) const {
13791 return T::getDescription();
13792 }
13793
13794 std::string getDescriptionImpl( std::false_type ) const {
13795 return "(No description provided)";
13796 }
13797
13798 public:
13799 TypedListenerFactory( StringRef listenerName ):
13800 m_listenerName( listenerName ) {}
13801
13802 IEventListenerPtr create( IConfig const* config ) const override {
13803 return Detail::make_unique<T>( config );
13804 }
13805
13806 StringRef getName() const override {
13807 return m_listenerName;
13808 }
13809
13810 std::string getDescription() const override {
13811 return getDescriptionImpl( Detail::has_description<T>{} );
13812 }
13813 };
13814
13815 public:
13816 ListenerRegistrar(StringRef listenerName) {
13817 registerListenerImpl( Detail::make_unique<TypedListenerFactory>(listenerName) );
13818 }
13819 };
13820}
13821
13822#if !defined(CATCH_CONFIG_DISABLE)
13823
13824# define CATCH_REGISTER_REPORTER( name, reporterType ) \
13825 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
13826 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
13827 namespace { \
13828 Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \
13829 catch_internal_RegistrarFor )( name ); \
13830 } \
13831 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
13832
13833# define CATCH_REGISTER_LISTENER( listenerType ) \
13834 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
13835 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
13836 namespace { \
13837 Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \
13838 catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \
13839 } \
13840 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
13841
13842#else // CATCH_CONFIG_DISABLE
13843
13844#define CATCH_REGISTER_REPORTER(name, reporterType)
13845#define CATCH_REGISTER_LISTENER(listenerType)
13846
13847#endif // CATCH_CONFIG_DISABLE
13848
13849#endif // CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
13850
13851
13852#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
13853#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
13854
13855
13856
13857namespace Catch {
13858
13859 class SonarQubeReporter final : public CumulativeReporterBase {
13860 public:
13861 SonarQubeReporter(ReporterConfig&& config)
13862 : CumulativeReporterBase(CATCH_MOVE(config))
13863 , xml(m_stream) {
13864 m_preferences.shouldRedirectStdOut = true;
13865 m_preferences.shouldReportAllAssertions = true;
13866 m_shouldStoreSuccesfulAssertions = false;
13867 }
13868
13869 static std::string getDescription() {
13870 using namespace std::string_literals;
13871 return "Reports test results in the Generic Test Data SonarQube XML format"s;
13872 }
13873
13874 void testRunStarting( TestRunInfo const& testRunInfo ) override;
13875
13876 void testRunEndedCumulative() override {
13877 writeRun( *m_testRun );
13878 xml.endElement();
13879 }
13880
13881 void writeRun( TestRunNode const& runNode );
13882
13883 void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes);
13884
13885 void writeTestCase(TestCaseNode const& testCaseNode);
13886
13887 void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail);
13888
13889 void writeAssertions(SectionNode const& sectionNode, bool okToFail);
13890
13891 void writeAssertion(AssertionStats const& stats, bool okToFail);
13892
13893 private:
13894 XmlWriter xml;
13895 };
13896
13897
13898} // end namespace Catch
13899
13900#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED
13901
13902
13903#ifndef CATCH_REPORTER_TAP_HPP_INCLUDED
13904#define CATCH_REPORTER_TAP_HPP_INCLUDED
13905
13906
13907namespace Catch {
13908
13909 class TAPReporter final : public StreamingReporterBase {
13910 public:
13911 TAPReporter( ReporterConfig&& config ):
13912 StreamingReporterBase( CATCH_MOVE(config) ) {
13913 m_preferences.shouldReportAllAssertions = true;
13914 }
13915
13916 static std::string getDescription() {
13917 using namespace std::string_literals;
13918 return "Reports test results in TAP format, suitable for test harnesses"s;
13919 }
13920
13921 void testRunStarting( TestRunInfo const& testInfo ) override;
13922
13923 void noMatchingTestCases( StringRef unmatchedSpec ) override;
13924
13925 void assertionEnded(AssertionStats const& _assertionStats) override;
13926
13927 void testRunEnded(TestRunStats const& _testRunStats) override;
13928
13929 private:
13930 std::size_t counter = 0;
13931 };
13932
13933} // end namespace Catch
13934
13935#endif // CATCH_REPORTER_TAP_HPP_INCLUDED
13936
13937
13938#ifndef CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
13939#define CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
13940
13941
13942#include <cstring>
13943
13944#ifdef __clang__
13945# pragma clang diagnostic push
13946# pragma clang diagnostic ignored "-Wpadded"
13947#endif
13948
13949namespace Catch {
13950
13951 class TeamCityReporter final : public StreamingReporterBase {
13952 public:
13953 TeamCityReporter( ReporterConfig&& _config )
13954 : StreamingReporterBase( CATCH_MOVE(_config) )
13955 {
13956 m_preferences.shouldRedirectStdOut = true;
13957 }
13958
13959 ~TeamCityReporter() override;
13960
13961 static std::string getDescription() {
13962 using namespace std::string_literals;
13963 return "Reports test results as TeamCity service messages"s;
13964 }
13965
13966 void testRunStarting( TestRunInfo const& runInfo ) override;
13967 void testRunEnded( TestRunStats const& runStats ) override;
13968
13969
13970 void assertionEnded(AssertionStats const& assertionStats) override;
13971
13972 void sectionStarting(SectionInfo const& sectionInfo) override {
13973 m_headerPrintedForThisSection = false;
13974 StreamingReporterBase::sectionStarting( sectionInfo );
13975 }
13976
13977 void testCaseStarting(TestCaseInfo const& testInfo) override;
13978
13979 void testCaseEnded(TestCaseStats const& testCaseStats) override;
13980
13981 private:
13982 void printSectionHeader(std::ostream& os);
13983
13984 bool m_headerPrintedForThisSection = false;
13985 Timer m_testTimer;
13986 };
13987
13988} // end namespace Catch
13989
13990#ifdef __clang__
13991# pragma clang diagnostic pop
13992#endif
13993
13994#endif // CATCH_REPORTER_TEAMCITY_HPP_INCLUDED
13995
13996
13997#ifndef CATCH_REPORTER_XML_HPP_INCLUDED
13998#define CATCH_REPORTER_XML_HPP_INCLUDED
13999
14000
14001
14002
14003namespace Catch {
14004 class XmlReporter : public StreamingReporterBase {
14005 public:
14006 XmlReporter(ReporterConfig&& _config);
14007
14008 ~XmlReporter() override;
14009
14010 static std::string getDescription();
14011
14012 virtual std::string getStylesheetRef() const;
14013
14014 void writeSourceInfo(SourceLineInfo const& sourceInfo);
14015
14016 public: // StreamingReporterBase
14017
14018 void testRunStarting(TestRunInfo const& testInfo) override;
14019
14020 void testCaseStarting(TestCaseInfo const& testInfo) override;
14021
14022 void sectionStarting(SectionInfo const& sectionInfo) override;
14023
14024 void assertionStarting(AssertionInfo const&) override;
14025
14026 void assertionEnded(AssertionStats const& assertionStats) override;
14027
14028 void sectionEnded(SectionStats const& sectionStats) override;
14029
14030 void testCaseEnded(TestCaseStats const& testCaseStats) override;
14031
14032 void testRunEnded(TestRunStats const& testRunStats) override;
14033
14034 void benchmarkPreparing( StringRef name ) override;
14035 void benchmarkStarting(BenchmarkInfo const&) override;
14036 void benchmarkEnded(BenchmarkStats<> const&) override;
14037 void benchmarkFailed( StringRef error ) override;
14038
14039 void listReporters(std::vector<ReporterDescription> const& descriptions) override;
14040 void listListeners(std::vector<ListenerDescription> const& descriptions) override;
14041 void listTests(std::vector<TestCaseHandle> const& tests) override;
14042 void listTags(std::vector<TagInfo> const& tags) override;
14043
14044 private:
14045 Timer m_testCaseTimer;
14046 XmlWriter m_xml;
14047 int m_sectionDepth = 0;
14048 };
14049
14050} // end namespace Catch
14051
14052#endif // CATCH_REPORTER_XML_HPP_INCLUDED
14053
14054#endif // CATCH_REPORTERS_ALL_HPP_INCLUDED
14055
14056#endif // CATCH_ALL_HPP_INCLUDED
14057#endif // CATCH_AMALGAMATED_HPP_INCLUDED