kblib 0.2.3
General utilities library for modern C++
catch.hpp
Go to the documentation of this file.
1/*
2 * Catch v2.13.10
3 * Generated: 2022-10-16 11:01:23.452308
4 * ----------------------------------------------------------
5 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2022 Two Blue Cubes Ltd. All rights reserved.
7 *
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 */
11#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
13// start catch.hpp
14
15
16#define CATCH_VERSION_MAJOR 2
17#define CATCH_VERSION_MINOR 13
18#define CATCH_VERSION_PATCH 10
19
20#ifdef __clang__
21# pragma clang system_header
22#elif defined __GNUC__
23# pragma GCC system_header
24#endif
25
26// start catch_suppress_warnings.h
27
28#ifdef __clang__
29# ifdef __ICC // icpc defines the __clang__ macro
30# pragma warning(push)
31# pragma warning(disable: 161 1682)
32# else // __ICC
33# pragma clang diagnostic push
34# pragma clang diagnostic ignored "-Wpadded"
35# pragma clang diagnostic ignored "-Wswitch-enum"
36# pragma clang diagnostic ignored "-Wcovered-switch-default"
37# endif
38#elif defined __GNUC__
39 // Because REQUIREs trigger GCC's -Wparentheses, and because still
40 // supported version of g++ have only buggy support for _Pragmas,
41 // Wparentheses have to be suppressed globally.
42# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
43
44# pragma GCC diagnostic push
45# pragma GCC diagnostic ignored "-Wunused-variable"
46# pragma GCC diagnostic ignored "-Wpadded"
47#endif
48// end catch_suppress_warnings.h
49#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
50# define CATCH_IMPL
51# define CATCH_CONFIG_ALL_PARTS
52#endif
53
54// In the impl file, we want to have access to all parts of the headers
55// Can also be used to sanely support PCHs
56#if defined(CATCH_CONFIG_ALL_PARTS)
57# define CATCH_CONFIG_EXTERNAL_INTERFACES
58# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
59# undef CATCH_CONFIG_DISABLE_MATCHERS
60# endif
61# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
62# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
63# endif
64#endif
65
66#if !defined(CATCH_CONFIG_IMPL_ONLY)
67// start catch_platform.h
68
69// See e.g.:
70// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
71#ifdef __APPLE__
72# include <TargetConditionals.h>
73# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
74 (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
75# define CATCH_PLATFORM_MAC
76# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
77# define CATCH_PLATFORM_IPHONE
78# endif
79
80#elif defined(linux) || defined(__linux) || defined(__linux__)
81# define CATCH_PLATFORM_LINUX
82
83#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
84# define CATCH_PLATFORM_WINDOWS
85#endif
86
87// end catch_platform.h
88
89#ifdef CATCH_IMPL
90# ifndef CLARA_CONFIG_MAIN
91# define CLARA_CONFIG_MAIN_NOT_DEFINED
92# define CLARA_CONFIG_MAIN
93# endif
94#endif
95
96// start catch_user_interfaces.h
97
98namespace Catch {
99 unsigned int rngSeed();
100}
101
102// end catch_user_interfaces.h
103// start catch_tag_alias_autoregistrar.h
104
105// start catch_common.h
106
107// start catch_compiler_capabilities.h
108
109// Detect a number of compiler features - by compiler
110// The following features are defined:
111//
112// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
113// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
114// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
115// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
116// ****************
117// Note to maintainers: if new toggles are added please document them
118// in configuration.md, too
119// ****************
120
121// In general each macro has a _NO_<feature name> form
122// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
123// Many features, at point of detection, define an _INTERNAL_ macro, so they
124// can be combined, en-mass, with the _NO_ forms later.
125
126#ifdef __cplusplus
127
128# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
129# define CATCH_CPP14_OR_GREATER
130# endif
131
132# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
133# define CATCH_CPP17_OR_GREATER
134# endif
135
136#endif
137
138// Only GCC compiler should be used in this block, so other compilers trying to
139// mask themselves as GCC should be ignored.
140#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
141# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
142# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
143
144# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
145
146#endif
147
148#if defined(__clang__)
149
150# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
151# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
152
153// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
154// which results in calls to destructors being emitted for each temporary,
155// without a matching initialization. In practice, this can result in something
156// like `std::string::~string` being called on an uninitialized value.
157//
158// For example, this code will likely segfault under IBM XL:
159// ```
160// REQUIRE(std::string("12") + "34" == "1234")
161// ```
162//
163// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
164# if !defined(__ibmxl__) && !defined(__CUDACC__)
165# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
166# endif
167
168# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
169 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
170 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
171
172# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
173 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
174
175# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
176 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
177
178# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
179 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
180
181# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
182 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
183
184#endif // __clang__
185
187// Assume that non-Windows platforms support posix signals by default
188#if !defined(CATCH_PLATFORM_WINDOWS)
189 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
190#endif
191
193// We know some environments not to support full POSIX signals
194#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
195 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
196#endif
197
198#ifdef __OS400__
199# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
200# define CATCH_CONFIG_COLOUR_NONE
201#endif
202
204// Android somehow still does not support std::to_string
205#if defined(__ANDROID__)
206# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
207# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
208#endif
209
211// Not all Windows environments support SEH properly
212#if defined(__MINGW32__)
213# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
214#endif
215
217// PS4
218#if defined(__ORBIS__)
219# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
220#endif
221
223// Cygwin
224#ifdef __CYGWIN__
225
226// Required for some versions of Cygwin to declare gettimeofday
227// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
228# define _BSD_SOURCE
229// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
230// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
231# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
232 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
233
234# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
235
236# endif
237#endif // __CYGWIN__
238
240// Visual C++
241#if defined(_MSC_VER)
242
243// Universal Windows platform does not support SEH
244// Or console colours (or console at all...)
245# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
246# define CATCH_CONFIG_COLOUR_NONE
247# else
248# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
249# endif
250
251# if !defined(__clang__) // Handle Clang masquerading for msvc
252
253// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
254// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
255// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
256# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
257# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
258# endif // MSVC_TRADITIONAL
259
260// Only do this if we're not using clang on Windows, which uses `diagnostic push` & `diagnostic pop`
261# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
262# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
263# endif // __clang__
264
265#endif // _MSC_VER
266
267#if defined(_REENTRANT) || defined(_MSC_VER)
268// Enable async processing, as -pthread is specified or no additional linking is required
269# define CATCH_INTERNAL_CONFIG_USE_ASYNC
270#endif // _MSC_VER
271
273// Check if we are compiled with -fno-exceptions or equivalent
274#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
275# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
276#endif
277
279// DJGPP
280#ifdef __DJGPP__
281# define CATCH_INTERNAL_CONFIG_NO_WCHAR
282#endif // __DJGPP__
283
285// Embarcadero C++Build
286#if defined(__BORLANDC__)
287 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
288#endif
289
291
292// Use of __COUNTER__ is suppressed during code analysis in
293// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
294// handled by it.
295// Otherwise all supported compilers support COUNTER macro,
296// but user still might want to turn it off
297#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
298 #define CATCH_INTERNAL_CONFIG_COUNTER
299#endif
300
302
303// RTX is a special version of Windows that is real time.
304// This means that it is detected as Windows, but does not provide
305// the same set of capabilities as real Windows does.
306#if defined(UNDER_RTSS) || defined(RTX64_BUILD)
307 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
308 #define CATCH_INTERNAL_CONFIG_NO_ASYNC
309 #define CATCH_CONFIG_COLOUR_NONE
310#endif
311
312#if !defined(_GLIBCXX_USE_C99_MATH_TR1)
313#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
314#endif
315
316// Various stdlib support checks that require __has_include
317#if defined(__has_include)
318 // Check if string_view is available and usable
319 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
320 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
321 #endif
322
323 // Check if optional is available and usable
324 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
325 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
326 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
327
328 // Check if byte is available and usable
329 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
330 # include <cstddef>
331 # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
332 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE
333 # endif
334 # endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
335
336 // Check if variant is available and usable
337 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
338 # if defined(__clang__) && (__clang_major__ < 8)
339 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
340 // fix should be in clang 8, workaround in libstdc++ 8.2
341 # include <ciso646>
342 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
343 # define CATCH_CONFIG_NO_CPP17_VARIANT
344 # else
345 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
346 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
347 # else
348 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
349 # endif // defined(__clang__) && (__clang_major__ < 8)
350 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
351#endif // defined(__has_include)
352
353#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
354# define CATCH_CONFIG_COUNTER
355#endif
356#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)
357# define CATCH_CONFIG_WINDOWS_SEH
358#endif
359// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
360#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)
361# define CATCH_CONFIG_POSIX_SIGNALS
362#endif
363// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
364#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
365# define CATCH_CONFIG_WCHAR
366#endif
367
368#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
369# define CATCH_CONFIG_CPP11_TO_STRING
370#endif
371
372#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
373# define CATCH_CONFIG_CPP17_OPTIONAL
374#endif
375
376#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
377# define CATCH_CONFIG_CPP17_STRING_VIEW
378#endif
379
380#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
381# define CATCH_CONFIG_CPP17_VARIANT
382#endif
383
384#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
385# define CATCH_CONFIG_CPP17_BYTE
386#endif
387
388#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
389# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
390#endif
391
392#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)
393# define CATCH_CONFIG_NEW_CAPTURE
394#endif
395
396#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
397# define CATCH_CONFIG_DISABLE_EXCEPTIONS
398#endif
399
400#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
401# define CATCH_CONFIG_POLYFILL_ISNAN
402#endif
403
404#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
405# define CATCH_CONFIG_USE_ASYNC
406#endif
407
408#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
409# define CATCH_CONFIG_ANDROID_LOGWRITE
410#endif
411
412#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
413# define CATCH_CONFIG_GLOBAL_NEXTAFTER
414#endif
415
416// Even if we do not think the compiler has that warning, we still have
417// to provide a macro that can be used by the code.
418#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
419# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
420#endif
421#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
422# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
423#endif
424#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
425# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
426#endif
427#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
428# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
429#endif
430#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
431# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
432#endif
433#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
434# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
435#endif
436
437// The goal of this macro is to avoid evaluation of the arguments, but
438// still have the compiler warn on problems inside...
439#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
440# define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
441#endif
442
443#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
444# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
445#elif defined(__clang__) && (__clang_major__ < 5)
446# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
447#endif
448
449#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
450# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
451#endif
452
453#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
454#define CATCH_TRY if ((true))
455#define CATCH_CATCH_ALL if ((false))
456#define CATCH_CATCH_ANON(type) if ((false))
457#else
458#define CATCH_TRY try
459#define CATCH_CATCH_ALL catch (...)
460#define CATCH_CATCH_ANON(type) catch (type)
461#endif
462
463#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
464#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
465#endif
466
467// end catch_compiler_capabilities.h
468#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
469#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
470#ifdef CATCH_CONFIG_COUNTER
471# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
472#else
473# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
474#endif
475
476#include <iosfwd>
477#include <string>
478#include <cstdint>
479
480// We need a dummy global operator<< so we can bring it into Catch namespace later
482std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
483
484namespace Catch {
485
486 struct CaseSensitive { enum Choice {
488 No
489 }; };
490
492 NonCopyable( NonCopyable const& ) = delete;
493 NonCopyable( NonCopyable && ) = delete;
494 NonCopyable& operator = ( NonCopyable const& ) = delete;
495 NonCopyable& operator = ( NonCopyable && ) = delete;
496
497 protected:
499 virtual ~NonCopyable();
500 };
501
503
504 SourceLineInfo() = delete;
505 SourceLineInfo( char const* _file, std::size_t _line ) noexcept
506 : file( _file ),
507 line( _line )
508 {}
509
510 SourceLineInfo( SourceLineInfo const& other ) = default;
512 SourceLineInfo( SourceLineInfo&& ) noexcept = default;
513 SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
514
515 bool empty() const noexcept { return file[0] == '\0'; }
516 bool operator == ( SourceLineInfo const& other ) const noexcept;
517 bool operator < ( SourceLineInfo const& other ) const noexcept;
518
519 char const* file;
520 std::size_t line;
521 };
522
523 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
524
525 // Bring in operator<< from global namespace into Catch namespace
526 // This is necessary because the overload of operator<< above makes
527 // lookup stop at namespace Catch
528 using ::operator<<;
529
530 // Use this in variadic streaming macros to allow
531 // >> +StreamEndStop
532 // as well as
533 // >> stuff +StreamEndStop
535 std::string operator+() const;
536 };
537 template<typename T>
538 T const& operator + ( T const& value, StreamEndStop ) {
539 return value;
540 }
541}
542
543#define CATCH_INTERNAL_LINEINFO \
544 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
545
546// end catch_common.h
547namespace Catch {
548
550 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
551 };
552
553} // end namespace Catch
554
555#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
556 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
557 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
558 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
559 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
560
561// end catch_tag_alias_autoregistrar.h
562// start catch_test_registry.h
563
564// start catch_interfaces_testcase.h
565
566#include <vector>
567
568namespace Catch {
569
570 class TestSpec;
571
573 virtual void invoke () const = 0;
574 virtual ~ITestInvoker();
575 };
576
577 class TestCase;
578 struct IConfig;
579
582 virtual std::vector<TestCase> const& getAllTests() const = 0;
583 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
584 };
585
586 bool isThrowSafe( TestCase const& testCase, IConfig const& config );
587 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
588 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
589 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
590
591}
592
593// end catch_interfaces_testcase.h
594// start catch_stringref.h
595
596#include <cstddef>
597#include <string>
598#include <iosfwd>
599#include <cassert>
600
601namespace Catch {
602
606 class StringRef {
607 public:
608 using size_type = std::size_t;
609 using const_iterator = const char*;
610
611 private:
612 static constexpr char const* const s_empty = "";
613
614 char const* m_start = s_empty;
615 size_type m_size = 0;
616
617 public: // construction
618 constexpr StringRef() noexcept = default;
619
620 StringRef( char const* rawChars ) noexcept;
621
622 constexpr StringRef( char const* rawChars, size_type size ) noexcept
623 : m_start( rawChars ),
624 m_size( size )
625 {}
626
627 StringRef( std::string const& stdString ) noexcept
628 : m_start( stdString.c_str() ),
629 m_size( stdString.size() )
630 {}
631
632 explicit operator std::string() const {
633 return std::string(m_start, m_size);
634 }
635
636 public: // operators
637 auto operator == ( StringRef const& other ) const noexcept -> bool;
638 auto operator != (StringRef const& other) const noexcept -> bool {
639 return !(*this == other);
640 }
641
642 auto operator[] ( size_type index ) const noexcept -> char {
643 assert(index < m_size);
644 return m_start[index];
645 }
646
647 public: // named queries
648 constexpr auto empty() const noexcept -> bool {
649 return m_size == 0;
650 }
651 constexpr auto size() const noexcept -> size_type {
652 return m_size;
653 }
654
655 // Returns the current start pointer. If the StringRef is not
656 // null-terminated, throws std::domain_exception
657 auto c_str() const -> char const*;
658
659 public: // substrings and searches
660 // Returns a substring of [start, start + length).
661 // If start + length > size(), then the substring is [start, size()).
662 // If start > size(), then the substring is empty.
663 auto substr( size_type start, size_type length ) const noexcept -> StringRef;
664
665 // Returns the current start pointer. May not be null-terminated.
666 auto data() const noexcept -> char const*;
667
668 constexpr auto isNullTerminated() const noexcept -> bool {
669 return m_start[m_size] == '\0';
670 }
671
672 public: // iterators
673 constexpr const_iterator begin() const { return m_start; }
674 constexpr const_iterator end() const { return m_start + m_size; }
675 };
676
677 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
678 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
679
680 constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
681 return StringRef( rawChars, size );
682 }
683} // namespace Catch
684
685constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
686 return Catch::StringRef( rawChars, size );
687}
688
689// end catch_stringref.h
690// start catch_preprocessor.hpp
691
692
693#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
694#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
695#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
696#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
697#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
698#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
699
700#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
701#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
702// MSVC needs more evaluations
703#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
704#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
705#else
706#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
707#endif
708
709#define CATCH_REC_END(...)
710#define CATCH_REC_OUT
711
712#define CATCH_EMPTY()
713#define CATCH_DEFER(id) id CATCH_EMPTY()
714
715#define CATCH_REC_GET_END2() 0, CATCH_REC_END
716#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
717#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
718#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
719#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
720#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
721
722#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
723#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
724#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
725
726#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__ )
727#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__ )
728#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__ )
729
730// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
731// and passes userdata as the first parameter to each invocation,
732// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
733#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
734
735#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
736
737#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
738#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
739#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
740#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
741#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
742#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
743#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
744#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
745#else
746// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
747#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
748#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
749#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
750#endif
751
752#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
753#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
754
755#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
756
757#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
758#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
759#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
760#else
761#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
762#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
763#endif
764
765#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
766 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
767
768#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
769#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
770#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
771#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)
772#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)
773#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)
774#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)
775#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)
776#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)
777#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)
778#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)
779
780#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
781
782#define INTERNAL_CATCH_TYPE_GEN\
783 template<typename...> struct TypeList {};\
784 template<typename...Ts>\
785 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
786 template<template<typename...> class...> struct TemplateTypeList{};\
787 template<template<typename...> class...Cs>\
788 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
789 template<typename...>\
790 struct append;\
791 template<typename...>\
792 struct rewrap;\
793 template<template<typename...> class, typename...>\
794 struct create;\
795 template<template<typename...> class, typename>\
796 struct convert;\
797 \
798 template<typename T> \
799 struct append<T> { using type = T; };\
800 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
801 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
802 template< template<typename...> class L1, typename...E1, typename...Rest>\
803 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
804 \
805 template< template<typename...> class Container, template<typename...> class List, typename...elems>\
806 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
807 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
808 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
809 \
810 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
811 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
812 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
813 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
814
815#define INTERNAL_CATCH_NTTP_1(signature, ...)\
816 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
817 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
818 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
819 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
820 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
821 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
822 \
823 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
824 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
825 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
826 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
827 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
828 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
829
830#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
831#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
832 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
833 static void TestName()
834#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
835 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
836 static void TestName()
837
838#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
839#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
840 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
841 static void TestName()
842#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
843 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
844 static void TestName()
845
846#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
847 template<typename Type>\
848 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
849 {\
850 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
851 }
852
853#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
854 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
855 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
856 {\
857 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
858 }
859
860#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
861 template<typename Type>\
862 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
863 {\
864 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
865 }
866
867#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
868 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
869 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
870 {\
871 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
872 }
873
874#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
875#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
876 template<typename TestType> \
877 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
878 void test();\
879 }
880
881#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
882 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
883 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
884 void test();\
885 }
886
887#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
888#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
889 template<typename TestType> \
890 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
891#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
892 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
893 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
894
895#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
896#define INTERNAL_CATCH_NTTP_0
897#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)
898#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__)
899#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__)
900#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__)
901#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__)
902#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__)
903#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__)
904#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__)
905#else
906#define INTERNAL_CATCH_NTTP_0(signature)
907#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__))
908#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__))
909#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__))
910#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__))
911#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__))
912#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__))
913#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__))
914#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__))
915#endif
916
917// end catch_preprocessor.hpp
918// start catch_meta.hpp
919
920
921#include <type_traits>
922
923namespace Catch {
924 template<typename T>
925 struct always_false : std::false_type {};
926
927 template <typename> struct true_given : std::true_type {};
929 template <typename Fun, typename... Args>
930 true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);
931 template <typename...>
932 std::false_type static test(...);
933 };
934
935 template <typename T>
937
938 template <typename Fun, typename... Args>
939 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
940
941#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
942 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
943 // replaced with std::invoke_result here.
944 template <typename Func, typename... U>
945 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
946#else
947 // Keep ::type here because we still support C++11
948 template <typename Func, typename... U>
949 using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type;
950#endif
951
952} // namespace Catch
953
954namespace mpl_{
955 struct na;
956}
957
958// end catch_meta.hpp
959namespace Catch {
960
961template<typename C>
963 void (C::*m_testAsMethod)();
964public:
965 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
966
967 void invoke() const override {
968 C obj;
969 (obj.*m_testAsMethod)();
970 }
971};
972
973auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
974
975template<typename C>
976auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
977 return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );
978}
979
981 NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
984};
985
987 AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
989};
990
991} // end namespace Catch
992
993#if defined(CATCH_CONFIG_DISABLE)
994 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
995 static void TestName()
996 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
997 namespace{ \
998 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
999 void test(); \
1000 }; \
1001 } \
1002 void TestName::test()
1003 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \
1004 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1005 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
1006 namespace{ \
1007 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
1008 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1009 } \
1010 } \
1011 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1012
1013 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1014 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1015 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
1016 #else
1017 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1018 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
1019 #endif
1020
1021 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1022 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1023 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
1024 #else
1025 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1026 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
1027 #endif
1028
1029 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1030 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
1031 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
1032 #else
1033 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
1034 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
1035 #endif
1036
1037 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1038 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
1039 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
1040 #else
1041 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
1042 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
1043 #endif
1044#endif
1045
1047 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
1048 static void TestName(); \
1049 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1050 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1051 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
1052 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1053 static void TestName()
1054 #define INTERNAL_CATCH_TESTCASE( ... ) \
1055 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ )
1056
1058 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
1059 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1060 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1061 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
1062 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1063
1065 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
1066 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1067 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1068 namespace{ \
1069 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
1070 void test(); \
1071 }; \
1072 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
1073 } \
1074 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1075 void TestName::test()
1076 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
1077 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ )
1078
1080 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
1081 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1082 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1083 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
1084 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1085
1087 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
1088 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1089 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1090 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1091 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1092 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1093 namespace {\
1094 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
1095 INTERNAL_CATCH_TYPE_GEN\
1096 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1097 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1098 template<typename...Types> \
1099 struct TestName{\
1100 TestName(){\
1101 int index = 0; \
1102 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
1103 using expander = int[];\
1104 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
1105 }\
1106 };\
1107 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1108 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
1109 return 0;\
1110 }();\
1111 }\
1112 }\
1113 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1114 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
1115
1116#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1117 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1118 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ )
1119#else
1120 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1121 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
1122#endif
1123
1124#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1125 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1126 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ )
1127#else
1128 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1129 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
1130#endif
1131
1132 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
1133 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1134 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1135 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1136 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1137 template<typename TestType> static void TestFuncName(); \
1138 namespace {\
1139 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
1140 INTERNAL_CATCH_TYPE_GEN \
1141 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1142 template<typename... Types> \
1143 struct TestName { \
1144 void reg_tests() { \
1145 int index = 0; \
1146 using expander = int[]; \
1147 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
1148 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
1149 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
1150 (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 */\
1151 } \
1152 }; \
1153 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
1154 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; \
1155 TestInit t; \
1156 t.reg_tests(); \
1157 return 0; \
1158 }(); \
1159 } \
1160 } \
1161 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1162 template<typename TestType> \
1163 static void TestFuncName()
1164
1165#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1166 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
1167 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T,__VA_ARGS__)
1168#else
1169 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
1170 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, typename T, __VA_ARGS__ ) )
1171#endif
1172
1173#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1174 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
1175 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__)
1176#else
1177 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
1178 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, Signature, __VA_ARGS__ ) )
1179#endif
1180
1181 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
1182 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1183 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1184 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1185 template<typename TestType> static void TestFunc(); \
1186 namespace {\
1187 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
1188 INTERNAL_CATCH_TYPE_GEN\
1189 template<typename... Types> \
1190 struct TestName { \
1191 void reg_tests() { \
1192 int index = 0; \
1193 using expander = int[]; \
1194 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
1195 } \
1196 };\
1197 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
1198 using TestInit = typename convert<TestName, TmplList>::type; \
1199 TestInit t; \
1200 t.reg_tests(); \
1201 return 0; \
1202 }(); \
1203 }}\
1204 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1205 template<typename TestType> \
1206 static void TestFunc()
1207
1208 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
1209 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), Name, Tags, TmplList )
1210
1211 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
1212 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1213 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1214 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1215 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1216 namespace {\
1217 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
1218 INTERNAL_CATCH_TYPE_GEN\
1219 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1220 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1221 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1222 template<typename...Types> \
1223 struct TestNameClass{\
1224 TestNameClass(){\
1225 int index = 0; \
1226 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
1227 using expander = int[];\
1228 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
1229 }\
1230 };\
1231 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1232 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
1233 return 0;\
1234 }();\
1235 }\
1236 }\
1237 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1238 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1239
1240#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1241 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1242 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
1243#else
1244 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1245 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
1246#endif
1247
1248#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1249 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
1250 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
1251#else
1252 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
1253 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_C_L_A_S_S_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
1254#endif
1255
1256 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
1257 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1258 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1259 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1260 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1261 template<typename TestType> \
1262 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
1263 void test();\
1264 };\
1265 namespace {\
1266 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
1267 INTERNAL_CATCH_TYPE_GEN \
1268 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1269 template<typename...Types>\
1270 struct TestNameClass{\
1271 void reg_tests(){\
1272 int index = 0;\
1273 using expander = int[];\
1274 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
1275 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
1276 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
1277 (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 */ \
1278 }\
1279 };\
1280 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1281 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;\
1282 TestInit t;\
1283 t.reg_tests();\
1284 return 0;\
1285 }(); \
1286 }\
1287 }\
1288 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1289 template<typename TestType> \
1290 void TestName<TestType>::test()
1291
1292#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1293 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1294 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
1295#else
1296 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1297 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
1298#endif
1299
1300#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1301 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
1302 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
1303#else
1304 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
1305 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
1306#endif
1307
1308 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
1309 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1310 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1311 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1312 template<typename TestType> \
1313 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
1314 void test();\
1315 };\
1316 namespace {\
1317 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
1318 INTERNAL_CATCH_TYPE_GEN\
1319 template<typename...Types>\
1320 struct TestNameClass{\
1321 void reg_tests(){\
1322 int index = 0;\
1323 using expander = int[];\
1324 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
1325 }\
1326 };\
1327 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1328 using TestInit = typename convert<TestNameClass, TmplList>::type;\
1329 TestInit t;\
1330 t.reg_tests();\
1331 return 0;\
1332 }(); \
1333 }}\
1334 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1335 template<typename TestType> \
1336 void TestName<TestType>::test()
1337
1338#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
1339 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_ ), INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_M_P_L_A_T_E_T_E_S_T_F_U_N_C_ ), ClassName, Name, Tags, TmplList )
1340
1341// end catch_test_registry.h
1342// start catch_capture.hpp
1343
1344// start catch_assertionhandler.h
1345
1346// start catch_assertioninfo.h
1347
1348// start catch_result_type.h
1349
1350namespace Catch {
1351
1352 // ResultWas::OfType enum
1353 struct ResultWas { enum OfType {
1355 Ok = 0,
1356 Info = 1,
1358
1360
1363
1365
1368
1370
1371 }; };
1372
1373 bool isOk( ResultWas::OfType resultType );
1374 bool isJustInfo( int flags );
1375
1376 // ResultDisposition::Flags enum
1377 struct ResultDisposition { enum Flags {
1378 Normal = 0x01,
1379
1380 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
1381 FalseTest = 0x04, // Prefix expression with !
1382 SuppressFail = 0x08 // Failures are reported but do not fail the test
1383 }; };
1384
1386
1387 bool shouldContinueOnFailure( int flags );
1388 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
1389 bool shouldSuppressFailure( int flags );
1390
1391} // end namespace Catch
1392
1393// end catch_result_type.h
1394namespace Catch {
1395
1397 {
1402
1403 // We want to delete this constructor but a compiler bug in 4.8 means
1404 // the struct is then treated as non-aggregate
1405 //AssertionInfo() = delete;
1406 };
1407
1408} // end namespace Catch
1409
1410// end catch_assertioninfo.h
1411// start catch_decomposer.h
1412
1413// start catch_tostring.h
1414
1415#include <vector>
1416#include <cstddef>
1417#include <type_traits>
1418#include <string>
1419// start catch_stream.h
1420
1421#include <iosfwd>
1422#include <cstddef>
1423#include <ostream>
1424
1425namespace Catch {
1426
1427 std::ostream& cout();
1428 std::ostream& cerr();
1429 std::ostream& clog();
1430
1431 class StringRef;
1432
1433 struct IStream {
1434 virtual ~IStream();
1435 virtual std::ostream& stream() const = 0;
1436 };
1437
1438 auto makeStream( StringRef const &filename ) -> IStream const*;
1439
1441 std::size_t m_index;
1442 std::ostream* m_oss;
1443 public:
1446
1447 auto str() const -> std::string;
1448
1449 template<typename T>
1450 auto operator << ( T const& value ) -> ReusableStringStream& {
1451 *m_oss << value;
1452 return *this;
1453 }
1454 auto get() -> std::ostream& { return *m_oss; }
1455 };
1456}
1457
1458// end catch_stream.h
1459// start catch_interfaces_enum_values_registry.h
1460
1461#include <vector>
1462
1463namespace Catch {
1464
1465 namespace Detail {
1466 struct EnumInfo {
1468 std::vector<std::pair<int, StringRef>> m_values;
1469
1471
1472 StringRef lookup( int value ) const;
1473 };
1474 } // namespace Detail
1475
1478
1479 virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
1480
1481 template<typename E>
1482 Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
1483 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
1484 std::vector<int> intValues;
1485 intValues.reserve( values.size() );
1486 for( auto enumValue : values )
1487 intValues.push_back( static_cast<int>( enumValue ) );
1488 return registerEnum( enumName, allEnums, intValues );
1489 }
1490 };
1491
1492} // Catch
1493
1494// end catch_interfaces_enum_values_registry.h
1495
1496#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1497#include <string_view>
1498#endif
1499
1500#ifdef __OBJC__
1501// start catch_objc_arc.hpp
1502
1503#import <Foundation/Foundation.h>
1504
1505#ifdef __has_feature
1506#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1507#else
1508#define CATCH_ARC_ENABLED 0
1509#endif
1510
1511void arcSafeRelease( NSObject* obj );
1512id performOptionalSelector( id obj, SEL sel );
1513
1514#if !CATCH_ARC_ENABLED
1515inline void arcSafeRelease( NSObject* obj ) {
1516 [obj release];
1517}
1518inline id performOptionalSelector( id obj, SEL sel ) {
1519 if( [obj respondsToSelector: sel] )
1520 return [obj performSelector: sel];
1521 return nil;
1522}
1523#define CATCH_UNSAFE_UNRETAINED
1524#define CATCH_ARC_STRONG
1525#else
1526inline void arcSafeRelease( NSObject* ){}
1527inline id performOptionalSelector( id obj, SEL sel ) {
1528#ifdef __clang__
1529#pragma clang diagnostic push
1530#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1531#endif
1532 if( [obj respondsToSelector: sel] )
1533 return [obj performSelector: sel];
1534#ifdef __clang__
1535#pragma clang diagnostic pop
1536#endif
1537 return nil;
1538}
1539#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1540#define CATCH_ARC_STRONG __strong
1541#endif
1542
1543// end catch_objc_arc.hpp
1544#endif
1545
1546#ifdef _MSC_VER
1547#pragma warning(push)
1548#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
1549#endif
1550
1551namespace Catch {
1552 namespace Detail {
1553
1554 extern const std::string unprintableString;
1555
1556 std::string rawMemoryToString( const void *object, std::size_t size );
1557
1558 template<typename T>
1559 std::string rawMemoryToString( const T& object ) {
1560 return rawMemoryToString( &object, sizeof(object) );
1561 }
1562
1563 template<typename T>
1565 template<typename Stream, typename U>
1566 static auto test(int)
1567 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
1568
1569 template<typename, typename>
1570 static auto test(...)->std::false_type;
1571
1572 public:
1573 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
1574 };
1575
1576 template<typename E>
1577 std::string convertUnknownEnumToString( E e );
1578
1579 template<typename T>
1580 typename std::enable_if<
1582 std::string>::type convertUnstreamable( T const& ) {
1584 }
1585 template<typename T>
1586 typename std::enable_if<
1588 std::string>::type convertUnstreamable(T const& ex) {
1589 return ex.what();
1590 }
1591
1592 template<typename T>
1593 typename std::enable_if<
1595 , std::string>::type convertUnstreamable( T const& value ) {
1597 }
1598
1599#if defined(_MANAGED)
1601 template<typename T>
1602 std::string clrReferenceToString( T^ ref ) {
1603 if (ref == nullptr)
1604 return std::string("null");
1605 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
1606 cli::pin_ptr<System::Byte> p = &bytes[0];
1607 return std::string(reinterpret_cast<char const *>(p), bytes->Length);
1608 }
1609#endif
1610
1611 } // namespace Detail
1612
1613 // If we decide for C++14, change these to enable_if_ts
1614 template <typename T, typename = void>
1616 template <typename Fake = T>
1617 static
1619 convert(const Fake& value) {
1621 // NB: call using the function-like syntax to avoid ambiguity with
1622 // user-defined templated operator<< under clang.
1623 rss.operator<<(value);
1624 return rss.str();
1625 }
1626
1627 template <typename Fake = T>
1628 static
1630 convert( const Fake& value ) {
1631#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
1633#else
1634 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
1635#endif
1636 }
1637 };
1638
1639 namespace Detail {
1640
1641 // This function dispatches all stringification requests inside of Catch.
1642 // Should be preferably called fully qualified, like ::Catch::Detail::stringify
1643 template <typename T>
1644 std::string stringify(const T& e) {
1645 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
1646 }
1647
1648 template<typename E>
1650 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
1651 }
1652
1653#if defined(_MANAGED)
1654 template <typename T>
1655 std::string stringify( T^ e ) {
1656 return ::Catch::StringMaker<T^>::convert(e);
1657 }
1658#endif
1659
1660 } // namespace Detail
1661
1662 // Some predefined specializations
1663
1664 template<>
1665 struct StringMaker<std::string> {
1666 static std::string convert(const std::string& str);
1667 };
1668
1669#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1670 template<>
1671 struct StringMaker<std::string_view> {
1672 static std::string convert(std::string_view str);
1673 };
1674#endif
1675
1676 template<>
1677 struct StringMaker<char const *> {
1678 static std::string convert(char const * str);
1679 };
1680 template<>
1681 struct StringMaker<char *> {
1682 static std::string convert(char * str);
1683 };
1684
1685#ifdef CATCH_CONFIG_WCHAR
1686 template<>
1687 struct StringMaker<std::wstring> {
1688 static std::string convert(const std::wstring& wstr);
1689 };
1690
1691# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1692 template<>
1693 struct StringMaker<std::wstring_view> {
1694 static std::string convert(std::wstring_view str);
1695 };
1696# endif
1697
1698 template<>
1699 struct StringMaker<wchar_t const *> {
1700 static std::string convert(wchar_t const * str);
1701 };
1702 template<>
1703 struct StringMaker<wchar_t *> {
1704 static std::string convert(wchar_t * str);
1705 };
1706#endif
1707
1708 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
1709 // while keeping string semantics?
1710 template<int SZ>
1711 struct StringMaker<char[SZ]> {
1712 static std::string convert(char const* str) {
1713 return ::Catch::Detail::stringify(std::string{ str });
1714 }
1715 };
1716 template<int SZ>
1717 struct StringMaker<signed char[SZ]> {
1718 static std::string convert(signed char const* str) {
1719 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
1720 }
1721 };
1722 template<int SZ>
1723 struct StringMaker<unsigned char[SZ]> {
1724 static std::string convert(unsigned char const* str) {
1725 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
1726 }
1727 };
1728
1729#if defined(CATCH_CONFIG_CPP17_BYTE)
1730 template<>
1731 struct StringMaker<std::byte> {
1732 static std::string convert(std::byte value);
1733 };
1734#endif // defined(CATCH_CONFIG_CPP17_BYTE)
1735 template<>
1736 struct StringMaker<int> {
1737 static std::string convert(int value);
1738 };
1739 template<>
1740 struct StringMaker<long> {
1741 static std::string convert(long value);
1742 };
1743 template<>
1744 struct StringMaker<long long> {
1745 static std::string convert(long long value);
1746 };
1747 template<>
1748 struct StringMaker<unsigned int> {
1749 static std::string convert(unsigned int value);
1750 };
1751 template<>
1752 struct StringMaker<unsigned long> {
1753 static std::string convert(unsigned long value);
1754 };
1755 template<>
1756 struct StringMaker<unsigned long long> {
1757 static std::string convert(unsigned long long value);
1758 };
1759
1760 template<>
1761 struct StringMaker<bool> {
1762 static std::string convert(bool b);
1763 };
1764
1765 template<>
1766 struct StringMaker<char> {
1767 static std::string convert(char c);
1768 };
1769 template<>
1770 struct StringMaker<signed char> {
1771 static std::string convert(signed char c);
1772 };
1773 template<>
1774 struct StringMaker<unsigned char> {
1775 static std::string convert(unsigned char c);
1776 };
1777
1778 template<>
1779 struct StringMaker<std::nullptr_t> {
1780 static std::string convert(std::nullptr_t);
1781 };
1782
1783 template<>
1784 struct StringMaker<float> {
1785 static std::string convert(float value);
1786 static int precision;
1787 };
1788
1789 template<>
1790 struct StringMaker<double> {
1791 static std::string convert(double value);
1792 static int precision;
1793 };
1794
1795 template <typename T>
1796 struct StringMaker<T*> {
1797 template <typename U>
1798 static std::string convert(U* p) {
1799 if (p) {
1801 } else {
1802 return "nullptr";
1803 }
1804 }
1805 };
1806
1807 template <typename R, typename C>
1808 struct StringMaker<R C::*> {
1809 static std::string convert(R C::* p) {
1810 if (p) {
1812 } else {
1813 return "nullptr";
1814 }
1815 }
1816 };
1817
1818#if defined(_MANAGED)
1819 template <typename T>
1820 struct StringMaker<T^> {
1821 static std::string convert( T^ ref ) {
1822 return ::Catch::Detail::clrReferenceToString(ref);
1823 }
1824 };
1825#endif
1826
1827 namespace Detail {
1828 template<typename InputIterator, typename Sentinel = InputIterator>
1829 std::string rangeToString(InputIterator first, Sentinel last) {
1831 rss << "{ ";
1832 if (first != last) {
1833 rss << ::Catch::Detail::stringify(*first);
1834 for (++first; first != last; ++first)
1835 rss << ", " << ::Catch::Detail::stringify(*first);
1836 }
1837 rss << " }";
1838 return rss.str();
1839 }
1840 }
1841
1842#ifdef __OBJC__
1843 template<>
1844 struct StringMaker<NSString*> {
1845 static std::string convert(NSString * nsstring) {
1846 if (!nsstring)
1847 return "nil";
1848 return std::string("@") + [nsstring UTF8String];
1849 }
1850 };
1851 template<>
1852 struct StringMaker<NSObject*> {
1853 static std::string convert(NSObject* nsObject) {
1854 return ::Catch::Detail::stringify([nsObject description]);
1855 }
1856
1857 };
1858 namespace Detail {
1859 inline std::string stringify( NSString* nsstring ) {
1860 return StringMaker<NSString*>::convert( nsstring );
1861 }
1862
1863 } // namespace Detail
1864#endif // __OBJC__
1865
1866} // namespace Catch
1867
1869// Separate std-lib types stringification, so it can be selectively enabled
1870// This means that we do not bring in
1871
1872#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
1873# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1874# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1875# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
1876# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1877# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
1878#endif
1879
1880// Separate std::pair specialization
1881#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
1882#include <utility>
1883namespace Catch {
1884 template<typename T1, typename T2>
1885 struct StringMaker<std::pair<T1, T2> > {
1886 static std::string convert(const std::pair<T1, T2>& pair) {
1887 ReusableStringStream rss;
1888 rss << "{ "
1889 << ::Catch::Detail::stringify(pair.first)
1890 << ", "
1891 << ::Catch::Detail::stringify(pair.second)
1892 << " }";
1893 return rss.str();
1894 }
1895 };
1896}
1897#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1898
1899#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
1900#include <optional>
1901namespace Catch {
1902 template<typename T>
1903 struct StringMaker<std::optional<T> > {
1904 static std::string convert(const std::optional<T>& optional) {
1905 ReusableStringStream rss;
1906 if (optional.has_value()) {
1907 rss << ::Catch::Detail::stringify(*optional);
1908 } else {
1909 rss << "{ }";
1910 }
1911 return rss.str();
1912 }
1913 };
1914}
1915#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
1916
1917// Separate std::tuple specialization
1918#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
1919#include <tuple>
1920namespace Catch {
1921 namespace Detail {
1922 template<
1923 typename Tuple,
1924 std::size_t N = 0,
1926 >
1927 struct TupleElementPrinter {
1928 static void print(const Tuple& tuple, std::ostream& os) {
1929 os << (N ? ", " : " ")
1930 << ::Catch::Detail::stringify(std::get<N>(tuple));
1931 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1932 }
1933 };
1934
1935 template<
1936 typename Tuple,
1937 std::size_t N
1938 >
1939 struct TupleElementPrinter<Tuple, N, false> {
1940 static void print(const Tuple&, std::ostream&) {}
1941 };
1942
1943 }
1944
1945 template<typename ...Types>
1946 struct StringMaker<std::tuple<Types...>> {
1947 static std::string convert(const std::tuple<Types...>& tuple) {
1948 ReusableStringStream rss;
1949 rss << '{';
1950 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
1951 rss << " }";
1952 return rss.str();
1953 }
1954 };
1955}
1956#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1957
1958#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
1959#include <variant>
1960namespace Catch {
1961 template<>
1962 struct StringMaker<std::monostate> {
1963 static std::string convert(const std::monostate&) {
1964 return "{ }";
1965 }
1966 };
1967
1968 template<typename... Elements>
1969 struct StringMaker<std::variant<Elements...>> {
1970 static std::string convert(const std::variant<Elements...>& variant) {
1971 if (variant.valueless_by_exception()) {
1972 return "{valueless variant}";
1973 } else {
1974 return std::visit(
1975 [](const auto& value) {
1977 },
1978 variant
1979 );
1980 }
1981 }
1982 };
1983}
1984#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
1985
1986namespace Catch {
1987 // Import begin/ end from std here
1988 using std::begin;
1989 using std::end;
1990
1991 namespace detail {
1992 template <typename...>
1993 struct void_type {
1994 using type = void;
1995 };
1996
1997 template <typename T, typename = void>
1998 struct is_range_impl : std::false_type {
1999 };
2000
2001 template <typename T>
2003 };
2004 } // namespace detail
2005
2006 template <typename T>
2008 };
2009
2010#if defined(_MANAGED) // Managed types are never ranges
2011 template <typename T>
2012 struct is_range<T^> {
2013 static const bool value = false;
2014 };
2015#endif
2016
2017 template<typename Range>
2018 std::string rangeToString( Range const& range ) {
2020 }
2021
2022 // Handle vector<bool> specially
2023 template<typename Allocator>
2024 std::string rangeToString( std::vector<bool, Allocator> const& v ) {
2026 rss << "{ ";
2027 bool first = true;
2028 for( bool b : v ) {
2029 if( first )
2030 first = false;
2031 else
2032 rss << ", ";
2033 rss << ::Catch::Detail::stringify( b );
2034 }
2035 rss << " }";
2036 return rss.str();
2037 }
2038
2039 template<typename R>
2040 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
2041 static std::string convert( R const& range ) {
2042 return rangeToString( range );
2043 }
2044 };
2045
2046 template <typename T, int SZ>
2047 struct StringMaker<T[SZ]> {
2048 static std::string convert(T const(&arr)[SZ]) {
2049 return rangeToString(arr);
2050 }
2051 };
2052
2053} // namespace Catch
2054
2055// Separate std::chrono::duration specialization
2056#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
2057#include <ctime>
2058#include <ratio>
2059#include <chrono>
2060
2061namespace Catch {
2062
2063template <class Ratio>
2064struct ratio_string {
2065 static std::string symbol();
2066};
2067
2068template <class Ratio>
2069std::string ratio_string<Ratio>::symbol() {
2071 rss << '[' << Ratio::num << '/'
2072 << Ratio::den << ']';
2073 return rss.str();
2074}
2075template <>
2076struct ratio_string<std::atto> {
2077 static std::string symbol();
2078};
2079template <>
2080struct ratio_string<std::femto> {
2081 static std::string symbol();
2082};
2083template <>
2084struct ratio_string<std::pico> {
2085 static std::string symbol();
2086};
2087template <>
2088struct ratio_string<std::nano> {
2089 static std::string symbol();
2090};
2091template <>
2092struct ratio_string<std::micro> {
2093 static std::string symbol();
2094};
2095template <>
2096struct ratio_string<std::milli> {
2097 static std::string symbol();
2098};
2099
2101 // std::chrono::duration specializations
2102 template<typename Value, typename Ratio>
2103 struct StringMaker<std::chrono::duration<Value, Ratio>> {
2104 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
2105 ReusableStringStream rss;
2106 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
2107 return rss.str();
2108 }
2109 };
2110 template<typename Value>
2111 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
2112 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
2113 ReusableStringStream rss;
2114 rss << duration.count() << " s";
2115 return rss.str();
2116 }
2117 };
2118 template<typename Value>
2119 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
2120 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
2121 ReusableStringStream rss;
2122 rss << duration.count() << " m";
2123 return rss.str();
2124 }
2125 };
2126 template<typename Value>
2127 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
2128 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
2129 ReusableStringStream rss;
2130 rss << duration.count() << " h";
2131 return rss.str();
2132 }
2133 };
2134
2136 // std::chrono::time_point specialization
2137 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
2138 template<typename Clock, typename Duration>
2139 struct StringMaker<std::chrono::time_point<Clock, Duration>> {
2140 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
2141 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
2142 }
2143 };
2144 // std::chrono::time_point<system_clock> specialization
2145 template<typename Duration>
2146 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
2147 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
2148 auto converted = std::chrono::system_clock::to_time_t(time_point);
2149
2150#ifdef _MSC_VER
2151 std::tm timeInfo = {};
2152 gmtime_s(&timeInfo, &converted);
2153#else
2154 std::tm* timeInfo = std::gmtime(&converted);
2155#endif
2156
2157 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
2158 char timeStamp[timeStampSize];
2159 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
2160
2161#ifdef _MSC_VER
2162 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
2163#else
2164 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
2165#endif
2166 return std::string(timeStamp);
2167 }
2168 };
2169}
2170#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
2171
2172#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
2173namespace Catch { \
2174 template<> struct StringMaker<enumName> { \
2175 static std::string convert( enumName value ) { \
2176 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
2177 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
2178 } \
2179 }; \
2180}
2181
2182#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
2183
2184#ifdef _MSC_VER
2185#pragma warning(pop)
2186#endif
2187
2188// end catch_tostring.h
2189#include <iosfwd>
2190
2191#ifdef _MSC_VER
2192#pragma warning(push)
2193#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
2194#pragma warning(disable:4018) // more "signed/unsigned mismatch"
2195#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
2196#pragma warning(disable:4180) // qualifier applied to function type has no meaning
2197#pragma warning(disable:4800) // Forcing result to true or false
2198#endif
2199
2200namespace Catch {
2201
2203 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
2204 auto getResult() const -> bool { return m_result; }
2205 virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
2206
2209 m_result( result )
2210 {}
2211
2212 // We don't actually need a virtual destructor, but many static analysers
2213 // complain if it's not here :-(
2215
2218
2219 };
2220
2221 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
2222
2223 template<typename LhsT, typename RhsT>
2225 LhsT m_lhs;
2226 StringRef m_op;
2227 RhsT m_rhs;
2228
2229 void streamReconstructedExpression( std::ostream &os ) const override {
2231 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
2232 }
2233
2234 public:
2235 BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
2236 : ITransientExpression{ true, comparisonResult },
2237 m_lhs( lhs ),
2238 m_op( op ),
2239 m_rhs( rhs )
2240 {}
2241
2242 template<typename T>
2244 static_assert(always_false<T>::value,
2245 "chained comparisons are not supported inside assertions, "
2246 "wrap the expression inside parentheses, or decompose it");
2247 }
2248
2249 template<typename T>
2251 static_assert(always_false<T>::value,
2252 "chained comparisons are not supported inside assertions, "
2253 "wrap the expression inside parentheses, or decompose it");
2254 }
2255
2256 template<typename T>
2258 static_assert(always_false<T>::value,
2259 "chained comparisons are not supported inside assertions, "
2260 "wrap the expression inside parentheses, or decompose it");
2261 }
2262
2263 template<typename T>
2265 static_assert(always_false<T>::value,
2266 "chained comparisons are not supported inside assertions, "
2267 "wrap the expression inside parentheses, or decompose it");
2268 }
2269
2270 template<typename T>
2272 static_assert(always_false<T>::value,
2273 "chained comparisons are not supported inside assertions, "
2274 "wrap the expression inside parentheses, or decompose it");
2275 }
2276
2277 template<typename T>
2279 static_assert(always_false<T>::value,
2280 "chained comparisons are not supported inside assertions, "
2281 "wrap the expression inside parentheses, or decompose it");
2282 }
2283
2284 template<typename T>
2286 static_assert(always_false<T>::value,
2287 "chained comparisons are not supported inside assertions, "
2288 "wrap the expression inside parentheses, or decompose it");
2289 }
2290
2291 template<typename T>
2293 static_assert(always_false<T>::value,
2294 "chained comparisons are not supported inside assertions, "
2295 "wrap the expression inside parentheses, or decompose it");
2296 }
2297 };
2298
2299 template<typename LhsT>
2301 LhsT m_lhs;
2302
2303 void streamReconstructedExpression( std::ostream &os ) const override {
2304 os << Catch::Detail::stringify( m_lhs );
2305 }
2306
2307 public:
2308 explicit UnaryExpr( LhsT lhs )
2309 : ITransientExpression{ false, static_cast<bool>(lhs) },
2310 m_lhs( lhs )
2311 {}
2312 };
2313
2314 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
2315 template<typename LhsT, typename RhsT>
2316 auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
2317 template<typename T>
2318 auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
2319 template<typename T>
2320 auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
2321 template<typename T>
2322 auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
2323 template<typename T>
2324 auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
2325
2326 template<typename LhsT, typename RhsT>
2327 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
2328 template<typename T>
2329 auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
2330 template<typename T>
2331 auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
2332 template<typename T>
2333 auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
2334 template<typename T>
2335 auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
2336
2337 template<typename LhsT>
2338 class ExprLhs {
2339 LhsT m_lhs;
2340 public:
2341 explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
2342
2343 template<typename RhsT>
2344 auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2345 return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
2346 }
2347 auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
2348 return { m_lhs == rhs, m_lhs, "==", rhs };
2349 }
2350
2351 template<typename RhsT>
2352 auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2353 return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
2354 }
2355 auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
2356 return { m_lhs != rhs, m_lhs, "!=", rhs };
2357 }
2358
2359 template<typename RhsT>
2360 auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2361 return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
2362 }
2363 template<typename RhsT>
2364 auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2365 return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
2366 }
2367 template<typename RhsT>
2368 auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2369 return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
2370 }
2371 template<typename RhsT>
2372 auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2373 return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
2374 }
2375 template <typename RhsT>
2376 auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
2377 return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };
2378 }
2379 template <typename RhsT>
2380 auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
2381 return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };
2382 }
2383 template <typename RhsT>
2384 auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {
2385 return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs };
2386 }
2387
2388 template<typename RhsT>
2389 auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
2390 static_assert(always_false<RhsT>::value,
2391 "operator&& is not supported inside assertions, "
2392 "wrap the expression inside parentheses, or decompose it");
2393 }
2394
2395 template<typename RhsT>
2396 auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
2397 static_assert(always_false<RhsT>::value,
2398 "operator|| is not supported inside assertions, "
2399 "wrap the expression inside parentheses, or decompose it");
2400 }
2401
2402 auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
2403 return UnaryExpr<LhsT>{ m_lhs };
2404 }
2405 };
2406
2408
2409 template<typename T>
2410 void handleExpression( ExprLhs<T> const& expr ) {
2412 }
2413
2414 struct Decomposer {
2415 template<typename T>
2416 auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
2417 return ExprLhs<T const&>{ lhs };
2418 }
2419
2421 return ExprLhs<bool>{ value };
2422 }
2423 };
2424
2425} // end namespace Catch
2426
2427#ifdef _MSC_VER
2428#pragma warning(pop)
2429#endif
2430
2431// end catch_decomposer.h
2432// start catch_interfaces_capture.h
2433
2434#include <string>
2435#include <chrono>
2436
2437namespace Catch {
2438
2439 class AssertionResult;
2440 struct AssertionInfo;
2441 struct SectionInfo;
2442 struct SectionEndInfo;
2443 struct MessageInfo;
2444 struct MessageBuilder;
2445 struct Counts;
2446 struct AssertionReaction;
2447 struct SourceLineInfo;
2448
2449 struct ITransientExpression;
2450 struct IGeneratorTracker;
2451
2452#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2453 struct BenchmarkInfo;
2454 template <typename Duration = std::chrono::duration<double, std::nano>>
2455 struct BenchmarkStats;
2456#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
2457
2459
2461
2462 virtual bool sectionStarted( SectionInfo const& sectionInfo,
2463 Counts& assertions ) = 0;
2464 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2465 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
2466
2467 virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
2468
2469#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2470 virtual void benchmarkPreparing( std::string const& name ) = 0;
2471 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
2472 virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
2473 virtual void benchmarkFailed( std::string const& error ) = 0;
2474#endif // CATCH_CONFIG_ENABLE_BENCHMARKING
2475
2476 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2477 virtual void popScopedMessage( MessageInfo const& message ) = 0;
2478
2479 virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
2480
2481 virtual void handleFatalErrorCondition( StringRef message ) = 0;
2482
2483 virtual void handleExpr
2484 ( AssertionInfo const& info,
2485 ITransientExpression const& expr,
2486 AssertionReaction& reaction ) = 0;
2487 virtual void handleMessage
2488 ( AssertionInfo const& info,
2489 ResultWas::OfType resultType,
2490 StringRef const& message,
2491 AssertionReaction& reaction ) = 0;
2493 ( AssertionInfo const& info,
2494 AssertionReaction& reaction ) = 0;
2496 ( AssertionInfo const& info,
2497 std::string const& message,
2498 AssertionReaction& reaction ) = 0;
2499 virtual void handleIncomplete
2500 ( AssertionInfo const& info ) = 0;
2501 virtual void handleNonExpr
2502 ( AssertionInfo const &info,
2503 ResultWas::OfType resultType,
2504 AssertionReaction &reaction ) = 0;
2505
2506 virtual bool lastAssertionPassed() = 0;
2507 virtual void assertionPassed() = 0;
2508
2509 // Deprecated, do not use:
2510 virtual std::string getCurrentTestName() const = 0;
2511 virtual const AssertionResult* getLastResult() const = 0;
2512 virtual void exceptionEarlyReported() = 0;
2513 };
2514
2516}
2517
2518// end catch_interfaces_capture.h
2519namespace Catch {
2520
2522 struct AssertionResultData;
2523 struct IResultCapture;
2524 class RunContext;
2525
2527 friend class AssertionHandler;
2528 friend struct AssertionStats;
2529 friend class RunContext;
2530
2531 ITransientExpression const* m_transientExpression = nullptr;
2532 bool m_isNegated;
2533 public:
2534 LazyExpression( bool isNegated );
2537
2538 explicit operator bool() const;
2539
2540 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
2541 };
2542
2544 bool shouldDebugBreak = false;
2545 bool shouldThrow = false;
2546 };
2547
2549 AssertionInfo m_assertionInfo;
2550 AssertionReaction m_reaction;
2551 bool m_completed = false;
2552 IResultCapture& m_resultCapture;
2553
2554 public:
2556 ( StringRef const& macroName,
2557 SourceLineInfo const& lineInfo,
2558 StringRef capturedExpression,
2559 ResultDisposition::Flags resultDisposition );
2561 if ( !m_completed ) {
2562 m_resultCapture.handleIncomplete( m_assertionInfo );
2563 }
2564 }
2565
2566 template<typename T>
2567 void handleExpr( ExprLhs<T> const& expr ) {
2568 handleExpr( expr.makeUnaryExpr() );
2569 }
2571
2572 void handleMessage(ResultWas::OfType resultType, StringRef const& message);
2573
2579
2580 void complete();
2582
2583 // query
2584 auto allowThrows() const -> bool;
2585 };
2586
2587 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
2588
2589} // namespace Catch
2590
2591// end catch_assertionhandler.h
2592// start catch_message.h
2593
2594#include <string>
2595#include <vector>
2596
2597namespace Catch {
2598
2600 MessageInfo( StringRef const& _macroName,
2601 SourceLineInfo const& _lineInfo,
2602 ResultWas::OfType _type );
2603
2605 std::string message;
2608 unsigned int sequence;
2609
2610 bool operator == ( MessageInfo const& other ) const;
2611 bool operator < ( MessageInfo const& other ) const;
2612 private:
2613 static unsigned int globalCount;
2614 };
2615
2617
2618 template<typename T>
2620 m_stream << value;
2621 return *this;
2622 }
2623
2625 };
2626
2628 MessageBuilder( StringRef const& macroName,
2629 SourceLineInfo const& lineInfo,
2630 ResultWas::OfType type );
2631
2632 template<typename T>
2634 m_stream << value;
2635 return *this;
2636 }
2637
2639 };
2640
2642 public:
2643 explicit ScopedMessage( MessageBuilder const& builder );
2644 ScopedMessage( ScopedMessage& duplicate ) = delete;
2647
2650 };
2651
2652 class Capturer {
2653 std::vector<MessageInfo> m_messages;
2654 IResultCapture& m_resultCapture = getResultCapture();
2655 size_t m_captured = 0;
2656 public:
2657 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
2659
2660 void captureValue( size_t index, std::string const& value );
2661
2662 template<typename T>
2663 void captureValues( size_t index, T const& value ) {
2664 captureValue( index, Catch::Detail::stringify( value ) );
2665 }
2666
2667 template<typename T, typename... Ts>
2668 void captureValues( size_t index, T const& value, Ts const&... values ) {
2669 captureValue( index, Catch::Detail::stringify(value) );
2670 captureValues( index+1, values... );
2671 }
2672 };
2673
2674} // end namespace Catch
2675
2676// end catch_message.h
2677#if !defined(CATCH_CONFIG_DISABLE)
2678
2679#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
2680 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
2681#else
2682 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
2683#endif
2684
2685#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
2686
2688// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2689// macros.
2690#define INTERNAL_CATCH_TRY
2691#define INTERNAL_CATCH_CATCH( capturer )
2692
2693#else // CATCH_CONFIG_FAST_COMPILE
2694
2695#define INTERNAL_CATCH_TRY try
2696#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
2697
2698#endif
2699
2700#define INTERNAL_CATCH_REACT( handler ) handler.complete();
2701
2703#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
2704 do { \
2705 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
2706 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2707 INTERNAL_CATCH_TRY { \
2708 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2709 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2710 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
2711 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
2712 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
2713 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2714 } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )
2715
2717#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
2718 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2719 if( Catch::getResultCapture().lastAssertionPassed() )
2720
2722#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
2723 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2724 if( !Catch::getResultCapture().lastAssertionPassed() )
2725
2727#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
2728 do { \
2729 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2730 try { \
2731 static_cast<void>(__VA_ARGS__); \
2732 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
2733 } \
2734 catch( ... ) { \
2735 catchAssertionHandler.handleUnexpectedInflightException(); \
2736 } \
2737 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2738 } while( false )
2739
2741#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
2742 do { \
2743 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
2744 if( catchAssertionHandler.allowThrows() ) \
2745 try { \
2746 static_cast<void>(__VA_ARGS__); \
2747 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2748 } \
2749 catch( ... ) { \
2750 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2751 } \
2752 else \
2753 catchAssertionHandler.handleThrowingCallSkipped(); \
2754 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2755 } while( false )
2756
2758#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
2759 do { \
2760 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
2761 if( catchAssertionHandler.allowThrows() ) \
2762 try { \
2763 static_cast<void>(expr); \
2764 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2765 } \
2766 catch( exceptionType const& ) { \
2767 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2768 } \
2769 catch( ... ) { \
2770 catchAssertionHandler.handleUnexpectedInflightException(); \
2771 } \
2772 else \
2773 catchAssertionHandler.handleThrowingCallSkipped(); \
2774 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2775 } while( false )
2776
2778#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
2779 do { \
2780 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
2781 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
2782 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2783 } while( false )
2784
2786#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
2787 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
2788 varName.captureValues( 0, __VA_ARGS__ )
2789
2791#define INTERNAL_CATCH_INFO( macroName, log ) \
2792 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
2793
2795#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
2796 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
2797
2799// Although this is matcher-based, it can be used with just a string
2800#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
2801 do { \
2802 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2803 if( catchAssertionHandler.allowThrows() ) \
2804 try { \
2805 static_cast<void>(__VA_ARGS__); \
2806 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2807 } \
2808 catch( ... ) { \
2809 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
2810 } \
2811 else \
2812 catchAssertionHandler.handleThrowingCallSkipped(); \
2813 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2814 } while( false )
2815
2816#endif // CATCH_CONFIG_DISABLE
2817
2818// end catch_capture.hpp
2819// start catch_section.h
2820
2821// start catch_section_info.h
2822
2823// start catch_totals.h
2824
2825#include <cstddef>
2826
2827namespace Catch {
2828
2829 struct Counts {
2830 Counts operator - ( Counts const& other ) const;
2831 Counts& operator += ( Counts const& other );
2832
2833 std::size_t total() const;
2834 bool allPassed() const;
2835 bool allOk() const;
2836
2837 std::size_t passed = 0;
2838 std::size_t failed = 0;
2839 std::size_t failedButOk = 0;
2840 };
2841
2842 struct Totals {
2843
2844 Totals operator - ( Totals const& other ) const;
2845 Totals& operator += ( Totals const& other );
2846
2847 Totals delta( Totals const& prevTotals ) const;
2848
2849 int error = 0;
2852 };
2853}
2854
2855// end catch_totals.h
2856#include <string>
2857
2858namespace Catch {
2859
2862 ( SourceLineInfo const& _lineInfo,
2863 std::string const& _name );
2864
2865 // Deprecated
2867 ( SourceLineInfo const& _lineInfo,
2868 std::string const& _name,
2869 std::string const& ) : SectionInfo( _lineInfo, _name ) {}
2870
2871 std::string name;
2872 std::string description; // !Deprecated: this will always be empty
2874 };
2875
2880 };
2881
2882} // end namespace Catch
2883
2884// end catch_section_info.h
2885// start catch_timer.h
2886
2887#include <cstdint>
2888
2889namespace Catch {
2890
2893
2894 class Timer {
2895 uint64_t m_nanoseconds = 0;
2896 public:
2897 void start();
2898 auto getElapsedNanoseconds() const -> uint64_t;
2899 auto getElapsedMicroseconds() const -> uint64_t;
2900 auto getElapsedMilliseconds() const -> unsigned int;
2901 auto getElapsedSeconds() const -> double;
2902 };
2903
2904} // namespace Catch
2905
2906// end catch_timer.h
2907#include <string>
2908
2909namespace Catch {
2910
2912 public:
2913 Section( SectionInfo const& info );
2915
2916 // This indicates whether the section should be executed or not
2917 explicit operator bool() const;
2918
2919 private:
2920 SectionInfo m_info;
2921
2922 std::string m_name;
2923 Counts m_assertions;
2924 bool m_sectionIncluded;
2925 Timer m_timer;
2926 };
2927
2928} // end namespace Catch
2929
2930#define INTERNAL_CATCH_SECTION( ... ) \
2931 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2932 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2933 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
2934 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
2935
2936#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
2937 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2938 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2939 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
2940 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
2941
2942// end catch_section.h
2943// start catch_interfaces_exception.h
2944
2945// start catch_interfaces_registry_hub.h
2946
2947#include <string>
2948#include <memory>
2949
2950namespace Catch {
2951
2952 class TestCase;
2953 struct ITestCaseRegistry;
2954 struct IExceptionTranslatorRegistry;
2955 struct IExceptionTranslator;
2956 struct IReporterRegistry;
2957 struct IReporterFactory;
2958 struct ITagAliasRegistry;
2959 struct IMutableEnumValuesRegistry;
2960
2961 class StartupExceptionRegistry;
2962
2963 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
2964
2966 virtual ~IRegistryHub();
2967
2968 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2969 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2970 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
2972
2973 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
2974 };
2975
2978 virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
2979 virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
2980 virtual void registerTest( TestCase const& testInfo ) = 0;
2981 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2982 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
2983 virtual void registerStartupException() noexcept = 0;
2984 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
2985 };
2986
2989 void cleanUp();
2991
2992}
2993
2994// end catch_interfaces_registry_hub.h
2995#if defined(CATCH_CONFIG_DISABLE)
2996 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
2997 static std::string translatorName( signature )
2998#endif
2999
3000#include <exception>
3001#include <string>
3002#include <vector>
3003
3004namespace Catch {
3005 using exceptionTranslateFunction = std::string(*)();
3006
3007 struct IExceptionTranslator;
3008 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
3009
3012 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
3013 };
3014
3017
3018 virtual std::string translateActiveException() const = 0;
3019 };
3020
3022 template<typename T>
3023 class ExceptionTranslator : public IExceptionTranslator {
3024 public:
3025
3026 ExceptionTranslator( std::string(*translateFunction)( T& ) )
3027 : m_translateFunction( translateFunction )
3028 {}
3029
3030 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
3031#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3032 return "";
3033#else
3034 try {
3035 if( it == itEnd )
3036 std::rethrow_exception(std::current_exception());
3037 else
3038 return (*it)->translate( it+1, itEnd );
3039 }
3040 catch( T& ex ) {
3041 return m_translateFunction( ex );
3042 }
3043#endif
3044 }
3045
3046 protected:
3047 std::string(*m_translateFunction)( T& );
3048 };
3049
3050 public:
3051 template<typename T>
3052 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
3054 ( new ExceptionTranslator<T>( translateFunction ) );
3055 }
3056 };
3057}
3058
3060#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
3061 static std::string translatorName( signature ); \
3062 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
3063 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
3064 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
3065 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
3066 static std::string translatorName( signature )
3067
3068#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
3069
3070// end catch_interfaces_exception.h
3071// start catch_approx.h
3072
3073#include <type_traits>
3074
3075namespace Catch {
3076namespace Detail {
3077
3078 class Approx {
3079 private:
3080 bool equalityComparisonImpl(double other) const;
3081 // Validates the new margin (margin >= 0)
3082 // out-of-line to avoid including stdexcept in the header
3083 void setMargin(double margin);
3084 // Validates the new epsilon (0 < epsilon < 1)
3085 // out-of-line to avoid including stdexcept in the header
3086 void setEpsilon(double epsilon);
3087
3088 public:
3089 explicit Approx ( double value );
3090
3091 static Approx custom();
3092
3094
3096 Approx operator()( T const& value ) const {
3097 Approx approx( static_cast<double>(value) );
3098 approx.m_epsilon = m_epsilon;
3099 approx.m_margin = m_margin;
3100 approx.m_scale = m_scale;
3101 return approx;
3102 }
3103
3105 explicit Approx( T const& value ): Approx(static_cast<double>(value))
3106 {}
3107
3109 friend bool operator == ( const T& lhs, Approx const& rhs ) {
3110 auto lhs_v = static_cast<double>(lhs);
3111 return rhs.equalityComparisonImpl(lhs_v);
3112 }
3113
3115 friend bool operator == ( Approx const& lhs, const T& rhs ) {
3116 return operator==( rhs, lhs );
3117 }
3118
3120 friend bool operator != ( T const& lhs, Approx const& rhs ) {
3121 return !operator==( lhs, rhs );
3122 }
3123
3125 friend bool operator != ( Approx const& lhs, T const& rhs ) {
3126 return !operator==( rhs, lhs );
3127 }
3128
3130 friend bool operator <= ( T const& lhs, Approx const& rhs ) {
3131 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
3132 }
3133
3135 friend bool operator <= ( Approx const& lhs, T const& rhs ) {
3136 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
3137 }
3138
3140 friend bool operator >= ( T const& lhs, Approx const& rhs ) {
3141 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
3142 }
3143
3145 friend bool operator >= ( Approx const& lhs, T const& rhs ) {
3146 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
3147 }
3148
3150 Approx& epsilon( T const& newEpsilon ) {
3151 double epsilonAsDouble = static_cast<double>(newEpsilon);
3152 setEpsilon(epsilonAsDouble);
3153 return *this;
3154 }
3155
3157 Approx& margin( T const& newMargin ) {
3158 double marginAsDouble = static_cast<double>(newMargin);
3159 setMargin(marginAsDouble);
3160 return *this;
3161 }
3162
3164 Approx& scale( T const& newScale ) {
3165 m_scale = static_cast<double>(newScale);
3166 return *this;
3167 }
3168
3169 std::string toString() const;
3170
3171 private:
3172 double m_epsilon;
3173 double m_margin;
3174 double m_scale;
3175 double m_value;
3176 };
3177} // end namespace Detail
3178
3179namespace literals {
3180 Detail::Approx operator "" _a(long double val);
3181 Detail::Approx operator "" _a(unsigned long long val);
3182} // end namespace literals
3183
3184template<>
3186 static std::string convert(Catch::Detail::Approx const& value);
3187};
3188
3189} // end namespace Catch
3190
3191// end catch_approx.h
3192// start catch_string_manip.h
3193
3194#include <string>
3195#include <iosfwd>
3196#include <vector>
3197
3198namespace Catch {
3199
3200 bool startsWith( std::string const& s, std::string const& prefix );
3201 bool startsWith( std::string const& s, char prefix );
3202 bool endsWith( std::string const& s, std::string const& suffix );
3203 bool endsWith( std::string const& s, char suffix );
3204 bool contains( std::string const& s, std::string const& infix );
3205 void toLowerInPlace( std::string& s );
3206 std::string toLower( std::string const& s );
3208 std::string trim( std::string const& str );
3211
3212 // !!! Be aware, returns refs into original string - make sure original string outlives them
3213 std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
3214 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
3215
3216 struct pluralise {
3217 pluralise( std::size_t count, std::string const& label );
3218
3219 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
3220
3221 std::size_t m_count;
3222 std::string m_label;
3223 };
3224}
3225
3226// end catch_string_manip.h
3227#ifndef CATCH_CONFIG_DISABLE_MATCHERS
3228// start catch_capture_matchers.h
3229
3230// start catch_matchers.h
3231
3232#include <string>
3233#include <vector>
3234
3235namespace Catch {
3236namespace Matchers {
3237 namespace Impl {
3238
3239 template<typename ArgT> struct MatchAllOf;
3240 template<typename ArgT> struct MatchAnyOf;
3241 template<typename ArgT> struct MatchNotOf;
3242
3244 public:
3247 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
3248 std::string toString() const;
3249
3250 protected:
3252 virtual std::string describe() const = 0;
3253 mutable std::string m_cachedToString;
3254 };
3255
3256#ifdef __clang__
3257# pragma clang diagnostic push
3258# pragma clang diagnostic ignored "-Wnon-virtual-dtor"
3259#endif
3260
3261 template<typename ObjectT>
3263 virtual bool match( ObjectT const& arg ) const = 0;
3264 };
3265
3266#if defined(__OBJC__)
3267 // Hack to fix Catch GH issue #1661. Could use id for generic Object support.
3268 // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation
3269 template<>
3270 struct MatcherMethod<NSString*> {
3271 virtual bool match( NSString* arg ) const = 0;
3272 };
3273#endif
3274
3275#ifdef __clang__
3276# pragma clang diagnostic pop
3277#endif
3278
3279 template<typename T>
3281
3282 MatchAllOf<T> operator && ( MatcherBase const& other ) const;
3283 MatchAnyOf<T> operator || ( MatcherBase const& other ) const;
3284 MatchNotOf<T> operator ! () const;
3285 };
3286
3287 template<typename ArgT>
3288 struct MatchAllOf : MatcherBase<ArgT> {
3289 bool match( ArgT const& arg ) const override {
3290 for( auto matcher : m_matchers ) {
3291 if (!matcher->match(arg))
3292 return false;
3293 }
3294 return true;
3295 }
3296 std::string describe() const override {
3297 std::string description;
3298 description.reserve( 4 + m_matchers.size()*32 );
3299 description += "( ";
3300 bool first = true;
3301 for( auto matcher : m_matchers ) {
3302 if( first )
3303 first = false;
3304 else
3305 description += " and ";
3306 description += matcher->toString();
3307 }
3308 description += " )";
3309 return description;
3310 }
3311
3312 MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) {
3313 auto copy(*this);
3314 copy.m_matchers.push_back( &other );
3315 return copy;
3316 }
3317
3318 std::vector<MatcherBase<ArgT> const*> m_matchers;
3319 };
3320 template<typename ArgT>
3321 struct MatchAnyOf : MatcherBase<ArgT> {
3322
3323 bool match( ArgT const& arg ) const override {
3324 for( auto matcher : m_matchers ) {
3325 if (matcher->match(arg))
3326 return true;
3327 }
3328 return false;
3329 }
3330 std::string describe() const override {
3331 std::string description;
3332 description.reserve( 4 + m_matchers.size()*32 );
3333 description += "( ";
3334 bool first = true;
3335 for( auto matcher : m_matchers ) {
3336 if( first )
3337 first = false;
3338 else
3339 description += " or ";
3340 description += matcher->toString();
3341 }
3342 description += " )";
3343 return description;
3344 }
3345
3346 MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) {
3347 auto copy(*this);
3348 copy.m_matchers.push_back( &other );
3349 return copy;
3350 }
3351
3352 std::vector<MatcherBase<ArgT> const*> m_matchers;
3353 };
3354
3355 template<typename ArgT>
3356 struct MatchNotOf : MatcherBase<ArgT> {
3357
3358 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
3359
3360 bool match( ArgT const& arg ) const override {
3361 return !m_underlyingMatcher.match( arg );
3362 }
3363
3364 std::string describe() const override {
3365 return "not " + m_underlyingMatcher.toString();
3366 }
3368 };
3369
3370 template<typename T>
3372 return MatchAllOf<T>() && *this && other;
3373 }
3374 template<typename T>
3376 return MatchAnyOf<T>() || *this || other;
3377 }
3378 template<typename T>
3380 return MatchNotOf<T>( *this );
3381 }
3382
3383 } // namespace Impl
3384
3385} // namespace Matchers
3386
3387using namespace Matchers;
3389
3390} // namespace Catch
3391
3392// end catch_matchers.h
3393// start catch_matchers_exception.hpp
3394
3395namespace Catch {
3396namespace Matchers {
3397namespace Exception {
3398
3399class ExceptionMessageMatcher : public MatcherBase<std::exception> {
3400 std::string m_message;
3401public:
3402
3403 ExceptionMessageMatcher(std::string const& message):
3404 m_message(message)
3405 {}
3406
3407 bool match(std::exception const& ex) const override;
3408
3409 std::string describe() const override;
3410};
3411
3412} // namespace Exception
3413
3415
3416} // namespace Matchers
3417} // namespace Catch
3418
3419// end catch_matchers_exception.hpp
3420// start catch_matchers_floating.h
3421
3422namespace Catch {
3423namespace Matchers {
3424
3425 namespace Floating {
3426
3427 enum class FloatingPointKind : uint8_t;
3428
3430 WithinAbsMatcher(double target, double margin);
3431 bool match(double const& matchee) const override;
3432 std::string describe() const override;
3433 private:
3434 double m_target;
3435 double m_margin;
3436 };
3437
3439 WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);
3440 bool match(double const& matchee) const override;
3441 std::string describe() const override;
3442 private:
3443 double m_target;
3444 uint64_t m_ulps;
3445 FloatingPointKind m_type;
3446 };
3447
3448 // Given IEEE-754 format for floats and doubles, we can assume
3449 // that float -> double promotion is lossless. Given this, we can
3450 // assume that if we do the standard relative comparison of
3451 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
3452 // the same result if we do this for floats, as if we do this for
3453 // doubles that were promoted from floats.
3455 WithinRelMatcher(double target, double epsilon);
3456 bool match(double const& matchee) const override;
3457 std::string describe() const override;
3458 private:
3459 double m_target;
3460 double m_epsilon;
3461 };
3462
3463 } // namespace Floating
3464
3465 // The following functions create the actual matcher objects.
3466 // This allows the types to be inferred
3467 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
3468 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
3469 Floating::WithinAbsMatcher WithinAbs(double target, double margin);
3470 Floating::WithinRelMatcher WithinRel(double target, double eps);
3471 // defaults epsilon to 100*numeric_limits<double>::epsilon()
3473 Floating::WithinRelMatcher WithinRel(float target, float eps);
3474 // defaults epsilon to 100*numeric_limits<float>::epsilon()
3476
3477} // namespace Matchers
3478} // namespace Catch
3479
3480// end catch_matchers_floating.h
3481// start catch_matchers_generic.hpp
3482
3483#include <functional>
3484#include <string>
3485
3486namespace Catch {
3487namespace Matchers {
3488namespace Generic {
3489
3490namespace Detail {
3491 std::string finalizeDescription(const std::string& desc);
3492}
3493
3494template <typename T>
3496 std::function<bool(T const&)> m_predicate;
3497 std::string m_description;
3498public:
3499
3500 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
3501 :m_predicate(std::move(elem)),
3502 m_description(Detail::finalizeDescription(descr))
3503 {}
3504
3505 bool match( T const& item ) const override {
3506 return m_predicate(item);
3507 }
3508
3509 std::string describe() const override {
3510 return m_description;
3511 }
3512};
3513
3514} // namespace Generic
3515
3516 // The following functions create the actual matcher objects.
3517 // The user has to explicitly specify type to the function, because
3518 // inferring std::function<bool(T const&)> is hard (but possible) and
3519 // requires a lot of TMP.
3520 template<typename T>
3521 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
3522 return Generic::PredicateMatcher<T>(predicate, description);
3523 }
3524
3525} // namespace Matchers
3526} // namespace Catch
3527
3528// end catch_matchers_generic.hpp
3529// start catch_matchers_string.h
3530
3531#include <string>
3532
3533namespace Catch {
3534namespace Matchers {
3535
3536 namespace StdString {
3537
3539 {
3540 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
3541 std::string adjustString( std::string const& str ) const;
3542 std::string caseSensitivitySuffix() const;
3543
3545 std::string m_str;
3546 };
3547
3548 struct StringMatcherBase : MatcherBase<std::string> {
3549 StringMatcherBase( std::string const& operation, CasedString const& comparator );
3550 std::string describe() const override;
3551
3553 std::string m_operation;
3554 };
3555
3557 EqualsMatcher( CasedString const& comparator );
3558 bool match( std::string const& source ) const override;
3559 };
3561 ContainsMatcher( CasedString const& comparator );
3562 bool match( std::string const& source ) const override;
3563 };
3565 StartsWithMatcher( CasedString const& comparator );
3566 bool match( std::string const& source ) const override;
3567 };
3569 EndsWithMatcher( CasedString const& comparator );
3570 bool match( std::string const& source ) const override;
3571 };
3572
3573 struct RegexMatcher : MatcherBase<std::string> {
3574 RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );
3575 bool match( std::string const& matchee ) const override;
3576 std::string describe() const override;
3577
3578 private:
3579 std::string m_regex;
3580 CaseSensitive::Choice m_caseSensitivity;
3581 };
3582
3583 } // namespace StdString
3584
3585 // The following functions create the actual matcher objects.
3586 // This allows the types to be inferred
3587
3588 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3592 StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3593
3594} // namespace Matchers
3595} // namespace Catch
3596
3597// end catch_matchers_string.h
3598// start catch_matchers_vector.h
3599
3600#include <algorithm>
3601
3602namespace Catch {
3603namespace Matchers {
3604
3605 namespace Vector {
3606 template<typename T, typename Alloc>
3607 struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
3608
3609 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
3610
3611 bool match(std::vector<T, Alloc> const &v) const override {
3612 for (auto const& el : v) {
3613 if (el == m_comparator) {
3614 return true;
3615 }
3616 }
3617 return false;
3618 }
3619
3620 std::string describe() const override {
3621 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
3622 }
3623
3625 };
3626
3627 template<typename T, typename AllocComp, typename AllocMatch>
3628 struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3629
3630 ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
3631
3632 bool match(std::vector<T, AllocMatch> const &v) const override {
3633 // !TBD: see note in EqualsMatcher
3634 if (m_comparator.size() > v.size())
3635 return false;
3636 for (auto const& comparator : m_comparator) {
3637 auto present = false;
3638 for (const auto& el : v) {
3639 if (el == comparator) {
3640 present = true;
3641 break;
3642 }
3643 }
3644 if (!present) {
3645 return false;
3646 }
3647 }
3648 return true;
3649 }
3650 std::string describe() const override {
3651 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
3652 }
3653
3654 std::vector<T, AllocComp> const& m_comparator;
3655 };
3656
3657 template<typename T, typename AllocComp, typename AllocMatch>
3658 struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3659
3660 EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}
3661
3662 bool match(std::vector<T, AllocMatch> const &v) const override {
3663 // !TBD: This currently works if all elements can be compared using !=
3664 // - a more general approach would be via a compare template that defaults
3665 // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
3666 // - then just call that directly
3667 if (m_comparator.size() != v.size())
3668 return false;
3669 for (std::size_t i = 0; i < v.size(); ++i)
3670 if (m_comparator[i] != v[i])
3671 return false;
3672 return true;
3673 }
3674 std::string describe() const override {
3675 return "Equals: " + ::Catch::Detail::stringify( m_comparator );
3676 }
3677 std::vector<T, AllocComp> const& m_comparator;
3678 };
3679
3680 template<typename T, typename AllocComp, typename AllocMatch>
3681 struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3682
3683 ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}
3684
3685 bool match(std::vector<T, AllocMatch> const &v) const override {
3686 if (m_comparator.size() != v.size())
3687 return false;
3688 for (std::size_t i = 0; i < v.size(); ++i)
3689 if (m_comparator[i] != approx(v[i]))
3690 return false;
3691 return true;
3692 }
3693 std::string describe() const override {
3694 return "is approx: " + ::Catch::Detail::stringify( m_comparator );
3695 }
3697 ApproxMatcher& epsilon( T const& newEpsilon ) {
3698 approx.epsilon(newEpsilon);
3699 return *this;
3700 }
3702 ApproxMatcher& margin( T const& newMargin ) {
3703 approx.margin(newMargin);
3704 return *this;
3705 }
3707 ApproxMatcher& scale( T const& newScale ) {
3708 approx.scale(newScale);
3709 return *this;
3710 }
3711
3712 std::vector<T, AllocComp> const& m_comparator;
3714 };
3715
3716 template<typename T, typename AllocComp, typename AllocMatch>
3717 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3718 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
3719 bool match(std::vector<T, AllocMatch> const& vec) const override {
3720 if (m_target.size() != vec.size()) {
3721 return false;
3722 }
3723 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
3724 }
3725
3726 std::string describe() const override {
3727 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
3728 }
3729 private:
3730 std::vector<T, AllocComp> const& m_target;
3731 };
3732
3733 } // namespace Vector
3734
3735 // The following functions create the actual matcher objects.
3736 // This allows the types to be inferred
3737
3738 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3739 Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {
3741 }
3742
3743 template<typename T, typename Alloc = std::allocator<T>>
3745 return Vector::ContainsElementMatcher<T, Alloc>( comparator );
3746 }
3747
3748 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3749 Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {
3751 }
3752
3753 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3754 Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {
3756 }
3757
3758 template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3761 }
3762
3763} // namespace Matchers
3764} // namespace Catch
3765
3766// end catch_matchers_vector.h
3767namespace Catch {
3768
3769 template<typename ArgT, typename MatcherT>
3771 ArgT const& m_arg;
3772 MatcherT m_matcher;
3773 StringRef m_matcherString;
3774 public:
3775 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
3776 : ITransientExpression{ true, matcher.match( arg ) },
3777 m_arg( arg ),
3778 m_matcher( matcher ),
3779 m_matcherString( matcherString )
3780 {}
3781
3782 void streamReconstructedExpression( std::ostream &os ) const override {
3783 auto matcherAsString = m_matcher.toString();
3784 os << Catch::Detail::stringify( m_arg ) << ' ';
3785 if( matcherAsString == Detail::unprintableString )
3786 os << m_matcherString;
3787 else
3788 os << matcherAsString;
3789 }
3790 };
3791
3793
3794 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString );
3795
3796 template<typename ArgT, typename MatcherT>
3797 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> {
3798 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
3799 }
3800
3801} // namespace Catch
3802
3804#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
3805 do { \
3806 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3807 INTERNAL_CATCH_TRY { \
3808 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
3809 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
3810 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3811 } while( false )
3812
3814#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
3815 do { \
3816 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3817 if( catchAssertionHandler.allowThrows() ) \
3818 try { \
3819 static_cast<void>(__VA_ARGS__ ); \
3820 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
3821 } \
3822 catch( exceptionType const& ex ) { \
3823 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
3824 } \
3825 catch( ... ) { \
3826 catchAssertionHandler.handleUnexpectedInflightException(); \
3827 } \
3828 else \
3829 catchAssertionHandler.handleThrowingCallSkipped(); \
3830 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3831 } while( false )
3832
3833// end catch_capture_matchers.h
3834#endif
3835// start catch_generators.hpp
3836
3837// start catch_interfaces_generatortracker.h
3838
3839
3840#include <memory>
3841
3842namespace Catch {
3843
3844 namespace Generators {
3846 public:
3849 // Attempts to move the generator to the next element
3850 //
3851 // Returns true iff the move succeeded (and a valid element
3852 // can be retrieved).
3853 virtual bool next() = 0;
3854 };
3855 using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
3856
3857 } // namespace Generators
3858
3861 virtual auto hasGenerator() const -> bool = 0;
3862 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
3863 virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
3864 };
3865
3866} // namespace Catch
3867
3868// end catch_interfaces_generatortracker.h
3869// start catch_enforce.h
3870
3871#include <exception>
3872
3873namespace Catch {
3874#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3875 template <typename Ex>
3876 [[noreturn]]
3877 void throw_exception(Ex const& e) {
3878 throw e;
3879 }
3880#else // ^^ Exceptions are enabled // Exceptions are disabled vv
3881 [[noreturn]]
3882 void throw_exception(std::exception const& e);
3883#endif
3884
3885 [[noreturn]]
3886 void throw_logic_error(std::string const& msg);
3887 [[noreturn]]
3888 void throw_domain_error(std::string const& msg);
3889 [[noreturn]]
3890 void throw_runtime_error(std::string const& msg);
3891
3892} // namespace Catch;
3893
3894#define CATCH_MAKE_MSG(...) \
3895 (Catch::ReusableStringStream() << __VA_ARGS__).str()
3896
3897#define CATCH_INTERNAL_ERROR(...) \
3898 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
3899
3900#define CATCH_ERROR(...) \
3901 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
3902
3903#define CATCH_RUNTIME_ERROR(...) \
3904 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
3905
3906#define CATCH_ENFORCE( condition, ... ) \
3907 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
3908
3909// end catch_enforce.h
3910#include <memory>
3911#include <vector>
3912#include <cassert>
3913
3914#include <utility>
3915#include <exception>
3916
3917namespace Catch {
3918
3919class GeneratorException : public std::exception {
3920 const char* const m_msg = "";
3921
3922public:
3923 GeneratorException(const char* msg):
3924 m_msg(msg)
3925 {}
3926
3927 const char* what() const noexcept override final;
3928};
3929
3930namespace Generators {
3931
3932 // !TBD move this into its own location?
3933 namespace pf{
3934 template<typename T, typename... Args>
3935 std::unique_ptr<T> make_unique( Args&&... args ) {
3936 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
3937 }
3938 }
3939
3940 template<typename T>
3942 virtual ~IGenerator() = default;
3943
3944 // Returns the current element of the generator
3945 //
3946 // \Precondition The generator is either freshly constructed,
3947 // or the last call to `next()` returned true
3948 virtual T const& get() const = 0;
3949 using type = T;
3950 };
3951
3952 template<typename T>
3953 class SingleValueGenerator final : public IGenerator<T> {
3954 T m_value;
3955 public:
3956 SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
3957
3958 T const& get() const override {
3959 return m_value;
3960 }
3961 bool next() override {
3962 return false;
3963 }
3964 };
3965
3966 template<typename T>
3967 class FixedValuesGenerator final : public IGenerator<T> {
3968 static_assert(!std::is_same<T, bool>::value,
3969 "FixedValuesGenerator does not support bools because of std::vector<bool>"
3970 "specialization, use SingleValue Generator instead.");
3971 std::vector<T> m_values;
3972 size_t m_idx = 0;
3973 public:
3974 FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
3975
3976 T const& get() const override {
3977 return m_values[m_idx];
3978 }
3979 bool next() override {
3980 ++m_idx;
3981 return m_idx < m_values.size();
3982 }
3983 };
3984
3985 template <typename T>
3986 class GeneratorWrapper final {
3987 std::unique_ptr<IGenerator<T>> m_generator;
3988 public:
3989 GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
3990 m_generator(std::move(generator))
3991 {}
3992 T const& get() const {
3993 return m_generator->get();
3994 }
3995 bool next() {
3996 return m_generator->next();
3997 }
3998 };
3999
4000 template <typename T>
4003 }
4004 template <typename T>
4005 GeneratorWrapper<T> values(std::initializer_list<T> values) {
4007 }
4008
4009 template<typename T>
4010 class Generators : public IGenerator<T> {
4011 std::vector<GeneratorWrapper<T>> m_generators;
4012 size_t m_current = 0;
4013
4014 void populate(GeneratorWrapper<T>&& generator) {
4015 m_generators.emplace_back(std::move(generator));
4016 }
4017 void populate(T&& val) {
4018 m_generators.emplace_back(value(std::forward<T>(val)));
4019 }
4020 template<typename U>
4021 void populate(U&& val) {
4022 populate(T(std::forward<U>(val)));
4023 }
4024 template<typename U, typename... Gs>
4025 void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
4026 populate(std::forward<U>(valueOrGenerator));
4027 populate(std::forward<Gs>(moreGenerators)...);
4028 }
4029
4030 public:
4031 template <typename... Gs>
4032 Generators(Gs &&... moreGenerators) {
4033 m_generators.reserve(sizeof...(Gs));
4034 populate(std::forward<Gs>(moreGenerators)...);
4035 }
4036
4037 T const& get() const override {
4038 return m_generators[m_current].get();
4039 }
4040
4041 bool next() override {
4042 if (m_current >= m_generators.size()) {
4043 return false;
4044 }
4045 const bool current_status = m_generators[m_current].next();
4046 if (!current_status) {
4047 ++m_current;
4048 }
4049 return m_current < m_generators.size();
4050 }
4051 };
4052
4053 template<typename... Ts>
4054 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
4055 return values<std::tuple<Ts...>>( tuples );
4056 }
4057
4058 // Tag type to signal that a generator sequence should convert arguments to a specific type
4059 template <typename T>
4060 struct as {};
4061
4062 template<typename T, typename... Gs>
4063 auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
4064 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
4065 }
4066 template<typename T>
4068 return Generators<T>(std::move(generator));
4069 }
4070 template<typename T, typename... Gs>
4071 auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
4072 return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
4073 }
4074 template<typename T, typename U, typename... Gs>
4075 auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
4076 return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
4077 }
4078
4079 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
4080
4081 template<typename L>
4082 // Note: The type after -> is weird, because VS2015 cannot parse
4083 // the expression used in the typedef inside, when it is in
4084 // return type. Yeah.
4085 auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
4086 using UnderlyingType = typename decltype(generatorExpression())::type;
4087
4088 IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo );
4089 if (!tracker.hasGenerator()) {
4090 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
4091 }
4092
4093 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
4094 return generator.get();
4095 }
4096
4097} // namespace Generators
4098} // namespace Catch
4099
4100#define GENERATE( ... ) \
4101 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4102 CATCH_INTERNAL_LINEINFO, \
4103 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
4104#define GENERATE_COPY( ... ) \
4105 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4106 CATCH_INTERNAL_LINEINFO, \
4107 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
4108#define GENERATE_REF( ... ) \
4109 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4110 CATCH_INTERNAL_LINEINFO, \
4111 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
4112
4113// end catch_generators.hpp
4114// start catch_generators_generic.hpp
4115
4116namespace Catch {
4117namespace Generators {
4118
4119 template <typename T>
4120 class TakeGenerator : public IGenerator<T> {
4121 GeneratorWrapper<T> m_generator;
4122 size_t m_returned = 0;
4123 size_t m_target;
4124 public:
4125 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
4126 m_generator(std::move(generator)),
4127 m_target(target)
4128 {
4129 assert(target != 0 && "Empty generators are not allowed");
4130 }
4131 T const& get() const override {
4132 return m_generator.get();
4133 }
4134 bool next() override {
4135 ++m_returned;
4136 if (m_returned >= m_target) {
4137 return false;
4138 }
4139
4140 const auto success = m_generator.next();
4141 // If the underlying generator does not contain enough values
4142 // then we cut short as well
4143 if (!success) {
4144 m_returned = m_target;
4145 }
4146 return success;
4147 }
4148 };
4149
4150 template <typename T>
4151 GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
4152 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
4153 }
4154
4155 template <typename T, typename Predicate>
4156 class FilterGenerator : public IGenerator<T> {
4157 GeneratorWrapper<T> m_generator;
4158 Predicate m_predicate;
4159 public:
4160 template <typename P = Predicate>
4161 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
4162 m_generator(std::move(generator)),
4163 m_predicate(std::forward<P>(pred))
4164 {
4165 if (!m_predicate(m_generator.get())) {
4166 // It might happen that there are no values that pass the
4167 // filter. In that case we throw an exception.
4168 auto has_initial_value = nextImpl();
4169 if (!has_initial_value) {
4170 Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
4171 }
4172 }
4173 }
4174
4175 T const& get() const override {
4176 return m_generator.get();
4177 }
4178
4179 bool next() override {
4180 return nextImpl();
4181 }
4182
4183 private:
4184 bool nextImpl() {
4185 bool success = m_generator.next();
4186 if (!success) {
4187 return false;
4188 }
4189 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
4190 return success;
4191 }
4192 };
4193
4194 template <typename T, typename Predicate>
4196 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
4197 }
4198
4199 template <typename T>
4200 class RepeatGenerator : public IGenerator<T> {
4201 static_assert(!std::is_same<T, bool>::value,
4202 "RepeatGenerator currently does not support bools"
4203 "because of std::vector<bool> specialization");
4204 GeneratorWrapper<T> m_generator;
4205 mutable std::vector<T> m_returned;
4206 size_t m_target_repeats;
4207 size_t m_current_repeat = 0;
4208 size_t m_repeat_index = 0;
4209 public:
4210 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
4211 m_generator(std::move(generator)),
4212 m_target_repeats(repeats)
4213 {
4214 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
4215 }
4216
4217 T const& get() const override {
4218 if (m_current_repeat == 0) {
4219 m_returned.push_back(m_generator.get());
4220 return m_returned.back();
4221 }
4222 return m_returned[m_repeat_index];
4223 }
4224
4225 bool next() override {
4226 // There are 2 basic cases:
4227 // 1) We are still reading the generator
4228 // 2) We are reading our own cache
4229
4230 // In the first case, we need to poke the underlying generator.
4231 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
4232 if (m_current_repeat == 0) {
4233 const auto success = m_generator.next();
4234 if (!success) {
4235 ++m_current_repeat;
4236 }
4237 return m_current_repeat < m_target_repeats;
4238 }
4239
4240 // In the second case, we need to move indices forward and check that we haven't run up against the end
4241 ++m_repeat_index;
4242 if (m_repeat_index == m_returned.size()) {
4243 m_repeat_index = 0;
4244 ++m_current_repeat;
4245 }
4246 return m_current_repeat < m_target_repeats;
4247 }
4248 };
4249
4250 template <typename T>
4251 GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
4252 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
4253 }
4254
4255 template <typename T, typename U, typename Func>
4256 class MapGenerator : public IGenerator<T> {
4257 // TBD: provide static assert for mapping function, for friendly error message
4258 GeneratorWrapper<U> m_generator;
4259 Func m_function;
4260 // To avoid returning dangling reference, we have to save the values
4261 T m_cache;
4262 public:
4263 template <typename F2 = Func>
4264 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
4265 m_generator(std::move(generator)),
4266 m_function(std::forward<F2>(function)),
4267 m_cache(m_function(m_generator.get()))
4268 {}
4269
4270 T const& get() const override {
4271 return m_cache;
4272 }
4273 bool next() override {
4274 const auto success = m_generator.next();
4275 if (success) {
4276 m_cache = m_function(m_generator.get());
4277 }
4278 return success;
4279 }
4280 };
4281
4282 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
4283 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
4284 return GeneratorWrapper<T>(
4285 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
4286 );
4287 }
4288
4289 template <typename T, typename U, typename Func>
4290 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
4291 return GeneratorWrapper<T>(
4292 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
4293 );
4294 }
4295
4296 template <typename T>
4297 class ChunkGenerator final : public IGenerator<std::vector<T>> {
4298 std::vector<T> m_chunk;
4299 size_t m_chunk_size;
4300 GeneratorWrapper<T> m_generator;
4301 bool m_used_up = false;
4302 public:
4304 m_chunk_size(size), m_generator(std::move(generator))
4305 {
4306 m_chunk.reserve(m_chunk_size);
4307 if (m_chunk_size != 0) {
4308 m_chunk.push_back(m_generator.get());
4309 for (size_t i = 1; i < m_chunk_size; ++i) {
4310 if (!m_generator.next()) {
4311 Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
4312 }
4313 m_chunk.push_back(m_generator.get());
4314 }
4315 }
4316 }
4317 std::vector<T> const& get() const override {
4318 return m_chunk;
4319 }
4320 bool next() override {
4321 m_chunk.clear();
4322 for (size_t idx = 0; idx < m_chunk_size; ++idx) {
4323 if (!m_generator.next()) {
4324 return false;
4325 }
4326 m_chunk.push_back(m_generator.get());
4327 }
4328 return true;
4329 }
4330 };
4331
4332 template <typename T>
4335 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
4336 );
4337 }
4338
4339} // namespace Generators
4340} // namespace Catch
4341
4342// end catch_generators_generic.hpp
4343// start catch_generators_specific.hpp
4344
4345// start catch_context.h
4346
4347#include <memory>
4348
4349namespace Catch {
4350
4351 struct IResultCapture;
4352 struct IRunner;
4353 struct IConfig;
4354 struct IMutableContext;
4355
4356 using IConfigPtr = std::shared_ptr<IConfig const>;
4357
4359 {
4360 virtual ~IContext();
4361
4363 virtual IRunner* getRunner() = 0;
4364 virtual IConfigPtr const& getConfig() const = 0;
4365 };
4366
4368 {
4370 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
4371 virtual void setRunner( IRunner* runner ) = 0;
4372 virtual void setConfig( IConfigPtr const& config ) = 0;
4373
4374 private:
4375 static IMutableContext *currentContext;
4377 friend void cleanUpContext();
4378 static void createContext();
4379 };
4380
4382 {
4383 if( !IMutableContext::currentContext )
4384 IMutableContext::createContext();
4385 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
4386 return *IMutableContext::currentContext;
4387 }
4388
4390 {
4391 return getCurrentMutableContext();
4392 }
4393
4395
4396 class SimplePcg32;
4398}
4399
4400// end catch_context.h
4401// start catch_interfaces_config.h
4402
4403// start catch_option.hpp
4404
4405namespace Catch {
4406
4407 // An optional type
4408 template<typename T>
4409 class Option {
4410 public:
4411 Option() : nullableValue( nullptr ) {}
4412 Option( T const& _value )
4413 : nullableValue( new( storage ) T( _value ) )
4414 {}
4415 Option( Option const& _other )
4416 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
4417 {}
4418
4420 reset();
4421 }
4422
4423 Option& operator= ( Option const& _other ) {
4424 if( &_other != this ) {
4425 reset();
4426 if( _other )
4427 nullableValue = new( storage ) T( *_other );
4428 }
4429 return *this;
4430 }
4431 Option& operator = ( T const& _value ) {
4432 reset();
4433 nullableValue = new( storage ) T( _value );
4434 return *this;
4435 }
4436
4437 void reset() {
4438 if( nullableValue )
4439 nullableValue->~T();
4440 nullableValue = nullptr;
4441 }
4442
4443 T& operator*() { return *nullableValue; }
4444 T const& operator*() const { return *nullableValue; }
4445 T* operator->() { return nullableValue; }
4446 const T* operator->() const { return nullableValue; }
4447
4448 T valueOr( T const& defaultValue ) const {
4449 return nullableValue ? *nullableValue : defaultValue;
4450 }
4451
4452 bool some() const { return nullableValue != nullptr; }
4453 bool none() const { return nullableValue == nullptr; }
4454
4455 bool operator !() const { return nullableValue == nullptr; }
4456 explicit operator bool() const {
4457 return some();
4458 }
4459
4460 private:
4461 T *nullableValue;
4462 alignas(alignof(T)) char storage[sizeof(T)];
4463 };
4464
4465} // end namespace Catch
4466
4467// end catch_option.hpp
4468#include <chrono>
4469#include <iosfwd>
4470#include <string>
4471#include <vector>
4472#include <memory>
4473
4474namespace Catch {
4475
4476 enum class Verbosity {
4477 Quiet = 0,
4478 Normal,
4479 High
4480 };
4481
4482 struct WarnAbout { enum What {
4483 Nothing = 0x00,
4484 NoAssertions = 0x01,
4485 NoTests = 0x02
4486 }; };
4487
4488 struct ShowDurations { enum OrNot {
4491 Never
4492 }; };
4493 struct RunTests { enum InWhatOrder {
4496 InRandomOrder
4497 }; };
4498 struct UseColour { enum YesOrNo {
4501 No
4502 }; };
4503 struct WaitForKeypress { enum When {
4505 BeforeStart = 1,
4506 BeforeExit = 2,
4507 BeforeStartAndExit = BeforeStart | BeforeExit
4508 }; };
4509
4510 class TestSpec;
4511
4513
4514 virtual ~IConfig();
4515
4516 virtual bool allowThrows() const = 0;
4517 virtual std::ostream& stream() const = 0;
4518 virtual std::string name() const = 0;
4519 virtual bool includeSuccessfulResults() const = 0;
4520 virtual bool shouldDebugBreak() const = 0;
4521 virtual bool warnAboutMissingAssertions() const = 0;
4522 virtual bool warnAboutNoTests() const = 0;
4523 virtual int abortAfter() const = 0;
4524 virtual bool showInvisibles() const = 0;
4526 virtual double minDuration() const = 0;
4527 virtual TestSpec const& testSpec() const = 0;
4528 virtual bool hasTestFilters() const = 0;
4529 virtual std::vector<std::string> const& getTestsOrTags() const = 0;
4530 virtual RunTests::InWhatOrder runOrder() const = 0;
4531 virtual unsigned int rngSeed() const = 0;
4532 virtual UseColour::YesOrNo useColour() const = 0;
4533 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
4534 virtual Verbosity verbosity() const = 0;
4535
4536 virtual bool benchmarkNoAnalysis() const = 0;
4537 virtual int benchmarkSamples() const = 0;
4538 virtual double benchmarkConfidenceInterval() const = 0;
4539 virtual unsigned int benchmarkResamples() const = 0;
4540 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
4541 };
4542
4543 using IConfigPtr = std::shared_ptr<IConfig const>;
4544}
4545
4546// end catch_interfaces_config.h
4547// start catch_random_number_generator.h
4548
4549#include <cstdint>
4550
4551namespace Catch {
4552
4553 // This is a simple implementation of C++11 Uniform Random Number
4554 // Generator. It does not provide all operators, because Catch2
4555 // does not use it, but it should behave as expected inside stdlib's
4556 // distributions.
4557 // The implementation is based on the PCG family (http://pcg-random.org)
4559 using state_type = std::uint64_t;
4560 public:
4561 using result_type = std::uint32_t;
4562 static constexpr result_type (min)() {
4563 return 0;
4564 }
4565 static constexpr result_type (max)() {
4566 return static_cast<result_type>(-1);
4567 }
4568
4569 // Provide some default initial state for the default constructor
4570 SimplePcg32():SimplePcg32(0xed743cc4U) {}
4571
4572 explicit SimplePcg32(result_type seed_);
4573
4574 void seed(result_type seed_);
4575 void discard(uint64_t skip);
4576
4578
4579 private:
4580 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
4581 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
4582
4583 // In theory we also need operator<< and operator>>
4584 // In practice we do not use them, so we will skip them for now
4585
4586 std::uint64_t m_state;
4587 // This part of the state determines which "stream" of the numbers
4588 // is chosen -- we take it as a constant for Catch2, so we only
4589 // need to deal with seeding the main state.
4590 // Picked by reading 8 bytes from `/dev/random` :-)
4591 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
4592 };
4593
4594} // end namespace Catch
4595
4596// end catch_random_number_generator.h
4597#include <random>
4598
4599namespace Catch {
4600namespace Generators {
4601
4602template <typename Float>
4603class RandomFloatingGenerator final : public IGenerator<Float> {
4604 Catch::SimplePcg32& m_rng;
4605 std::uniform_real_distribution<Float> m_dist;
4606 Float m_current_number;
4607public:
4608
4610 m_rng(rng()),
4611 m_dist(a, b) {
4612 static_cast<void>(next());
4613 }
4614
4615 Float const& get() const override {
4616 return m_current_number;
4617 }
4618 bool next() override {
4619 m_current_number = m_dist(m_rng);
4620 return true;
4621 }
4622};
4623
4624template <typename Integer>
4625class RandomIntegerGenerator final : public IGenerator<Integer> {
4626 Catch::SimplePcg32& m_rng;
4627 std::uniform_int_distribution<Integer> m_dist;
4628 Integer m_current_number;
4629public:
4630
4631 RandomIntegerGenerator(Integer a, Integer b):
4632 m_rng(rng()),
4633 m_dist(a, b) {
4634 static_cast<void>(next());
4635 }
4636
4637 Integer const& get() const override {
4638 return m_current_number;
4639 }
4640 bool next() override {
4641 m_current_number = m_dist(m_rng);
4642 return true;
4643 }
4644};
4645
4646// TODO: Ideally this would be also constrained against the various char types,
4647// but I don't expect users to run into that in practice.
4648template <typename T>
4650GeneratorWrapper<T>>::type
4651random(T a, T b) {
4652 return GeneratorWrapper<T>(
4654 );
4655}
4656
4657template <typename T>
4659GeneratorWrapper<T>>::type
4660random(T a, T b) {
4661 return GeneratorWrapper<T>(
4663 );
4664}
4665
4666template <typename T>
4667class RangeGenerator final : public IGenerator<T> {
4668 T m_current;
4669 T m_end;
4670 T m_step;
4671 bool m_positive;
4672
4673public:
4674 RangeGenerator(T const& start, T const& end, T const& step):
4675 m_current(start),
4676 m_end(end),
4677 m_step(step),
4678 m_positive(m_step > T(0))
4679 {
4680 assert(m_current != m_end && "Range start and end cannot be equal");
4681 assert(m_step != T(0) && "Step size cannot be zero");
4682 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
4683 }
4684
4685 RangeGenerator(T const& start, T const& end):
4686 RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
4687 {}
4688
4689 T const& get() const override {
4690 return m_current;
4691 }
4692
4693 bool next() override {
4694 m_current += m_step;
4695 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4696 }
4697};
4698
4699template <typename T>
4700GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
4701 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
4702 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
4703}
4704
4705template <typename T>
4706GeneratorWrapper<T> range(T const& start, T const& end) {
4707 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
4709}
4710
4711template <typename T>
4712class IteratorGenerator final : public IGenerator<T> {
4713 static_assert(!std::is_same<T, bool>::value,
4714 "IteratorGenerator currently does not support bools"
4715 "because of std::vector<bool> specialization");
4716
4717 std::vector<T> m_elems;
4718 size_t m_current = 0;
4719public:
4720 template <typename InputIterator, typename InputSentinel>
4721 IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
4722 if (m_elems.empty()) {
4723 Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values"));
4724 }
4725 }
4726
4727 T const& get() const override {
4728 return m_elems[m_current];
4729 }
4730
4731 bool next() override {
4732 ++m_current;
4733 return m_current != m_elems.size();
4734 }
4735};
4736
4737template <typename InputIterator,
4738 typename InputSentinel,
4739 typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
4740GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
4742}
4743
4744template <typename Container,
4745 typename ResultType = typename Container::value_type>
4748}
4749
4750} // namespace Generators
4751} // namespace Catch
4752
4753// end catch_generators_specific.hpp
4754
4755// These files are included here so the single_include script doesn't put them
4756// in the conditionally compiled sections
4757// start catch_test_case_info.h
4758
4759#include <string>
4760#include <vector>
4761#include <memory>
4762
4763#ifdef __clang__
4764#pragma clang diagnostic push
4765#pragma clang diagnostic ignored "-Wpadded"
4766#endif
4767
4768namespace Catch {
4769
4770 struct ITestInvoker;
4771
4774 None = 0,
4775 IsHidden = 1 << 1,
4776 ShouldFail = 1 << 2,
4777 MayFail = 1 << 3,
4778 Throws = 1 << 4,
4779 NonPortable = 1 << 5,
4780 Benchmark = 1 << 6
4782
4783 TestCaseInfo( std::string const& _name,
4784 std::string const& _className,
4785 std::string const& _description,
4786 std::vector<std::string> const& _tags,
4787 SourceLineInfo const& _lineInfo );
4788
4789 friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
4790
4791 bool isHidden() const;
4792 bool throws() const;
4793 bool okToFail() const;
4794 bool expectedToFail() const;
4795
4796 std::string tagsAsString() const;
4797
4798 std::string name;
4799 std::string className;
4800 std::string description;
4801 std::vector<std::string> tags;
4802 std::vector<std::string> lcaseTags;
4805 };
4806
4807 class TestCase : public TestCaseInfo {
4808 public:
4809
4810 TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
4811
4812 TestCase withName( std::string const& _newName ) const;
4813
4814 void invoke() const;
4815
4817
4818 bool operator == ( TestCase const& other ) const;
4819 bool operator < ( TestCase const& other ) const;
4820
4821 private:
4822 std::shared_ptr<ITestInvoker> test;
4823 };
4824
4826 std::string const& className,
4827 NameAndTags const& nameAndTags,
4828 SourceLineInfo const& lineInfo );
4829}
4830
4831#ifdef __clang__
4832#pragma clang diagnostic pop
4833#endif
4834
4835// end catch_test_case_info.h
4836// start catch_interfaces_runner.h
4837
4838namespace Catch {
4839
4840 struct IRunner {
4841 virtual ~IRunner();
4842 virtual bool aborting() const = 0;
4843 };
4844}
4845
4846// end catch_interfaces_runner.h
4847
4848#ifdef __OBJC__
4849// start catch_objc.hpp
4850
4851#import <objc/runtime.h>
4852
4853#include <string>
4854
4855// NB. Any general catch headers included here must be included
4856// in catch.hpp first to make sure they are included by the single
4857// header for non obj-usage
4858
4860// This protocol is really only here for (self) documenting purposes, since
4861// all its methods are optional.
4862@protocol OcFixture
4863
4864@optional
4865
4866-(void) setUp;
4867-(void) tearDown;
4868
4869@end
4870
4871namespace Catch {
4872
4873 class OcMethod : public ITestInvoker {
4874
4875 public:
4876 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
4877
4878 virtual void invoke() const {
4879 id obj = [[m_cls alloc] init];
4880
4881 performOptionalSelector( obj, @selector(setUp) );
4882 performOptionalSelector( obj, m_sel );
4883 performOptionalSelector( obj, @selector(tearDown) );
4884
4885 arcSafeRelease( obj );
4886 }
4887 private:
4888 virtual ~OcMethod() {}
4889
4890 Class m_cls;
4891 SEL m_sel;
4892 };
4893
4894 namespace Detail{
4895
4896 inline std::string getAnnotation( Class cls,
4897 std::string const& annotationName,
4898 std::string const& testCaseName ) {
4899 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
4900 SEL sel = NSSelectorFromString( selStr );
4901 arcSafeRelease( selStr );
4902 id value = performOptionalSelector( cls, sel );
4903 if( value )
4904 return [(NSString*)value UTF8String];
4905 return "";
4906 }
4907 }
4908
4909 inline std::size_t registerTestMethods() {
4910 std::size_t noTestMethods = 0;
4911 int noClasses = objc_getClassList( nullptr, 0 );
4912
4913 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
4914 objc_getClassList( classes, noClasses );
4915
4916 for( int c = 0; c < noClasses; c++ ) {
4917 Class cls = classes[c];
4918 {
4919 u_int count;
4920 Method* methods = class_copyMethodList( cls, &count );
4921 for( u_int m = 0; m < count ; m++ ) {
4922 SEL selector = method_getName(methods[m]);
4923 std::string methodName = sel_getName(selector);
4924 if( startsWith( methodName, "Catch_TestCase_" ) ) {
4925 std::string testCaseName = methodName.substr( 15 );
4926 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
4927 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
4928 const char* className = class_getName( cls );
4929
4930 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
4931 noTestMethods++;
4932 }
4933 }
4934 free(methods);
4935 }
4936 }
4937 return noTestMethods;
4938 }
4939
4940#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
4941
4942 namespace Matchers {
4943 namespace Impl {
4944 namespace NSStringMatchers {
4945
4946 struct StringHolder : MatcherBase<NSString*>{
4947 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
4948 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
4949 StringHolder() {
4950 arcSafeRelease( m_substr );
4951 }
4952
4953 bool match( NSString* str ) const override {
4954 return false;
4955 }
4956
4957 NSString* CATCH_ARC_STRONG m_substr;
4958 };
4959
4960 struct Equals : StringHolder {
4961 Equals( NSString* substr ) : StringHolder( substr ){}
4962
4963 bool match( NSString* str ) const override {
4964 return (str != nil || m_substr == nil ) &&
4965 [str isEqualToString:m_substr];
4966 }
4967
4968 std::string describe() const override {
4969 return "equals string: " + Catch::Detail::stringify( m_substr );
4970 }
4971 };
4972
4973 struct Contains : StringHolder {
4974 Contains( NSString* substr ) : StringHolder( substr ){}
4975
4976 bool match( NSString* str ) const override {
4977 return (str != nil || m_substr == nil ) &&
4978 [str rangeOfString:m_substr].location != NSNotFound;
4979 }
4980
4981 std::string describe() const override {
4982 return "contains string: " + Catch::Detail::stringify( m_substr );
4983 }
4984 };
4985
4986 struct StartsWith : StringHolder {
4987 StartsWith( NSString* substr ) : StringHolder( substr ){}
4988
4989 bool match( NSString* str ) const override {
4990 return (str != nil || m_substr == nil ) &&
4991 [str rangeOfString:m_substr].location == 0;
4992 }
4993
4994 std::string describe() const override {
4995 return "starts with: " + Catch::Detail::stringify( m_substr );
4996 }
4997 };
4998 struct EndsWith : StringHolder {
4999 EndsWith( NSString* substr ) : StringHolder( substr ){}
5000
5001 bool match( NSString