diff --git a/.gitignore b/.gitignore
index 8423e54..ca53a10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-.idea*
+*.idea*
cmake-build-debug/*
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index fd229ea..fc60e84 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -12,7 +12,11 @@
+
+
+
+
@@ -29,7 +33,7 @@
-
+
@@ -38,6 +42,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -105,13 +127,14 @@
+
-
-
-
-
+
+
+
+
@@ -290,12 +313,12 @@
-
+
-
+
@@ -307,7 +330,7 @@
-
+
@@ -358,16 +381,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -629,13 +642,6 @@
-
-
-
-
-
-
-
@@ -727,5 +733,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FlippR-Driver/CMakeLists.txt b/FlippR-Driver/CMakeLists.txt
index b1c92ce..1ae897c 100644
--- a/FlippR-Driver/CMakeLists.txt
+++ b/FlippR-Driver/CMakeLists.txt
@@ -132,6 +132,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC Easylogging)
######################## CATCH ############################
set(CATCH_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/tests)
+
add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
diff --git a/FlippR-Driver/tests/catch.hpp b/FlippR-Driver/tests/catch.hpp
index 5a791f8..bf5e0e7 100644
--- a/FlippR-Driver/tests/catch.hpp
+++ b/FlippR-Driver/tests/catch.hpp
@@ -1,9 +1,9 @@
/*
- * Catch v2.0.1
- * Generated: 2017-11-03 11:53:39.642003
+ * Catch v2.7.2
+ * Generated: 2019-04-22 23:13:14.687465
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
- * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved.
+ * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -13,6 +13,10 @@
// start catch.hpp
+#define CATCH_VERSION_MAJOR 2
+#define CATCH_VERSION_MINOR 7
+#define CATCH_VERSION_PATCH 2
+
#ifdef __clang__
# pragma clang system_header
#elif defined __GNUC__
@@ -26,37 +30,45 @@
# pragma warning(push)
# pragma warning(disable: 161 1682)
# else // __ICC
-# pragma clang diagnostic ignored "-Wglobal-constructors"
-# pragma clang diagnostic ignored "-Wvariadic-macros"
-# pragma clang diagnostic ignored "-Wc99-extensions"
-# pragma clang diagnostic ignored "-Wunused-variable"
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wswitch-enum"
# pragma clang diagnostic ignored "-Wcovered-switch-default"
# endif
#elif defined __GNUC__
-# pragma GCC diagnostic ignored "-Wvariadic-macros"
-# pragma GCC diagnostic ignored "-Wunused-variable"
-# pragma GCC diagnostic ignored "-Wparentheses"
+// Because REQUIREs trigger GCC's -Wparentheses, and because still
+// supported version of g++ have only buggy support for _Pragmas,
+// Wparentheses have to be suppressed globally.
+# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-variable"
# pragma GCC diagnostic ignored "-Wpadded"
#endif
// end catch_suppress_warnings.h
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_IMPL
+# define CATCH_CONFIG_ALL_PARTS
+#endif
+
+// In the impl file, we want to have access to all parts of the headers
+// Can also be used to sanely support PCHs
+#if defined(CATCH_CONFIG_ALL_PARTS)
# define CATCH_CONFIG_EXTERNAL_INTERFACES
# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
# undef CATCH_CONFIG_DISABLE_MATCHERS
# endif
+# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
+# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+# endif
#endif
+#if !defined(CATCH_CONFIG_IMPL_ONLY)
// start catch_platform.h
#ifdef __APPLE__
# include
-# if TARGET_OS_MAC == 1
+# if TARGET_OS_OSX == 1
# define CATCH_PLATFORM_MAC
# elif TARGET_OS_IPHONE == 1
# define CATCH_PLATFORM_IPHONE
@@ -65,11 +77,12 @@
#elif defined(linux) || defined(__linux) || defined(__linux__)
# define CATCH_PLATFORM_LINUX
-#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
+#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
# define CATCH_PLATFORM_WINDOWS
#endif
// end catch_platform.h
+
#ifdef CATCH_IMPL
# ifndef CLARA_CONFIG_MAIN
# define CLARA_CONFIG_MAIN_NOT_DEFINED
@@ -77,6 +90,13 @@
# endif
#endif
+// start catch_user_interfaces.h
+
+namespace Catch {
+unsigned int rngSeed();
+}
+
+// end catch_user_interfaces.h
// start catch_tag_alias_autoregistrar.h
// start catch_common.h
@@ -89,6 +109,7 @@
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
+// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
// ****************
// Note to maintainers: if new toggles are added please document them
// in configuration.md, too
@@ -101,10 +122,18 @@
#ifdef __cplusplus
-# if __cplusplus >= 201402L
+# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
# define CATCH_CPP14_OR_GREATER
# endif
+# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
+# define CATCH_CPP17_OR_GREATER
+# endif
+
+#endif
+
+#if defined(CATCH_CPP17_OR_GREATER)
+# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#ifdef __clang__
@@ -122,16 +151,24 @@
# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
_Pragma( "clang diagnostic pop" )
+# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
+ _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
+# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
+ _Pragma( "clang diagnostic pop" )
+
#endif // __clang__
+////////////////////////////////////////////////////////////////////////////////
+// Assume that non-Windows platforms support posix signals by default
+#if !defined(CATCH_PLATFORM_WINDOWS)
+#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// We know some environments not to support full POSIX signals
-#if defined(__CYGWIN__) || defined(__QNX__)
-
-# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
-# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
-# endif
-
+#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
+#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
#endif
#ifdef __OS400__
@@ -139,6 +176,24 @@
# define CATCH_CONFIG_COLOUR_NONE
#endif
+////////////////////////////////////////////////////////////////////////////////
+// Android somehow still does not support std::to_string
+#if defined(__ANDROID__)
+# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Not all Windows environments support SEH properly
+#if defined(__MINGW32__)
+# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// PS4
+#if defined(__ORBIS__)
+# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// Cygwin
#ifdef __CYGWIN__
@@ -146,13 +201,24 @@
// Required for some versions of Cygwin to declare gettimeofday
// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
# define _BSD_SOURCE
+// some versions of cygwin (most) do not support std::to_string. Use the libstd check.
+// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
+# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
+ && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
+# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
+
+# endif
#endif // __CYGWIN__
////////////////////////////////////////////////////////////////////////////////
// Visual C++
#ifdef _MSC_VER
+# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
+# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+# endif
+
// Universal Windows platform does not support SEH
// Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
@@ -161,8 +227,33 @@
# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
# endif
+// MSVC traditional preprocessor needs some workaround for __VA_ARGS__
+// _MSVC_TRADITIONAL == 0 means new conformant preprocessor
+// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
+# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
+# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+# endif
+
#endif // _MSC_VER
+////////////////////////////////////////////////////////////////////////////////
+// Check if we are compiled with -fno-exceptions or equivalent
+#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
+# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// DJGPP
+#ifdef __DJGPP__
+# define CATCH_INTERNAL_CONFIG_NO_WCHAR
+#endif // __DJGPP__
+
+////////////////////////////////////////////////////////////////////////////////
+// Embarcadero C++Build
+#if defined(__BORLANDC__)
+#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// Use of __COUNTER__ is suppressed during code analysis in
@@ -171,19 +262,95 @@
// Otherwise all supported compilers support COUNTER macro,
// but user still might want to turn it off
#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
- #define CATCH_INTERNAL_CONFIG_COUNTER
+#define CATCH_INTERNAL_CONFIG_COUNTER
#endif
+////////////////////////////////////////////////////////////////////////////////
+// Check if string_view is available and usable
+// The check is split apart to work around v140 (VS2015) preprocessor issue...
+#if defined(__has_include)
+#if __has_include() && defined(CATCH_CPP17_OR_GREATER)
+# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
+#endif
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Check if optional is available and usable
+#if defined(__has_include)
+# if __has_include() && defined(CATCH_CPP17_OR_GREATER)
+# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
+# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER)
+#endif // __has_include
+
+////////////////////////////////////////////////////////////////////////////////
+// Check if variant is available and usable
+#if defined(__has_include)
+# if __has_include() && defined(CATCH_CPP17_OR_GREATER)
+# if defined(__clang__) && (__clang_major__ < 8)
+// work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
+// fix should be in clang 8, workaround in libstdc++ 8.2
+# include
+# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
+# define CATCH_CONFIG_NO_CPP17_VARIANT
+# else
+# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
+# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
+# else
+# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
+# endif // defined(__clang__) && (__clang_major__ < 8)
+# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER)
+#endif // __has_include
+
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
# define CATCH_CONFIG_COUNTER
#endif
-#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
+#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)
# define CATCH_CONFIG_WINDOWS_SEH
#endif
// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
-#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
+#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)
# define CATCH_CONFIG_POSIX_SIGNALS
#endif
+// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
+#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
+# define CATCH_CONFIG_WCHAR
+#endif
+
+#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
+# define CATCH_CONFIG_CPP11_TO_STRING
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
+# define CATCH_CONFIG_CPP17_OPTIONAL
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
+# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
+# define CATCH_CONFIG_CPP17_STRING_VIEW
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
+# define CATCH_CONFIG_CPP17_VARIANT
+#endif
+
+#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
+# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
+#endif
+
+#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)
+# define CATCH_CONFIG_NEW_CAPTURE
+#endif
+
+#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+# define CATCH_CONFIG_DISABLE_EXCEPTIONS
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
+# define CATCH_CONFIG_POLYFILL_ISNAN
+#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
@@ -193,6 +360,24 @@
# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
#endif
+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
+# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
+# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
+#endif
+
+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
+#define CATCH_TRY if ((true))
+#define CATCH_CATCH_ALL if ((false))
+#define CATCH_CATCH_ANON(type) if ((false))
+#else
+#define CATCH_TRY try
+#define CATCH_CATCH_ALL catch (...)
+#define CATCH_CATCH_ANON(type) catch (type)
+#endif
+
+#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
+#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#endif
// end catch_compiler_capabilities.h
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
@@ -207,60 +392,67 @@
#include
#include
+// We need a dummy global operator<< so we can bring it into Catch namespace later
+struct Catch_global_namespace_dummy {};
+std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
+
namespace Catch {
- struct CaseSensitive { enum Choice {
- Yes,
- No
- }; };
+struct CaseSensitive { enum Choice {
+Yes,
+No
+}; };
- class NonCopyable {
- NonCopyable( NonCopyable const& ) = delete;
- NonCopyable( NonCopyable && ) = delete;
- NonCopyable& operator = ( NonCopyable const& ) = delete;
- NonCopyable& operator = ( NonCopyable && ) = delete;
+class NonCopyable {
+NonCopyable( NonCopyable const& ) = delete;
+NonCopyable( NonCopyable && ) = delete;
+NonCopyable& operator = ( NonCopyable const& ) = delete;
+NonCopyable& operator = ( NonCopyable && ) = delete;
- protected:
- NonCopyable();
- virtual ~NonCopyable();
- };
+protected:
+NonCopyable();
+virtual ~NonCopyable();
+};
- struct SourceLineInfo {
+struct SourceLineInfo {
- SourceLineInfo() = delete;
- SourceLineInfo( char const* _file, std::size_t _line ) noexcept;
+SourceLineInfo() = delete;
+SourceLineInfo( char const* _file, std::size_t _line ) noexcept
+: file( _file ),
+line( _line )
+{}
- SourceLineInfo( SourceLineInfo const& other ) = default;
- SourceLineInfo( SourceLineInfo && ) = default;
- SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
- SourceLineInfo& operator = ( SourceLineInfo && ) = default;
+SourceLineInfo( SourceLineInfo const& other ) = default;
+SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
+SourceLineInfo( SourceLineInfo&& ) noexcept = default;
+SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
- bool empty() const noexcept;
- bool operator == ( SourceLineInfo const& other ) const noexcept;
- bool operator < ( SourceLineInfo const& other ) const noexcept;
+bool empty() const noexcept;
+bool operator == ( SourceLineInfo const& other ) const noexcept;
+bool operator < ( SourceLineInfo const& other ) const noexcept;
- char const* file;
- std::size_t line;
- };
+char const* file;
+std::size_t line;
+};
- std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
+std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
- // This is just here to avoid compiler warnings with macro constants and boolean literals
- bool isTrue( bool value );
- bool alwaysTrue();
- bool alwaysFalse();
+// Bring in operator<< from global namespace into Catch namespace
+// This is necessary because the overload of operator<< above makes
+// lookup stop at namespace Catch
+using ::operator<<;
- // Use this in variadic streaming macros to allow
- // >> +StreamEndStop
- // as well as
- // >> stuff +StreamEndStop
- struct StreamEndStop {
- std::string operator+() const;
- };
- template
- T const& operator + ( T const& value, StreamEndStop ) {
- return value;
- }
+// Use this in variadic streaming macros to allow
+// >> +StreamEndStop
+// as well as
+// >> stuff +StreamEndStop
+struct StreamEndStop {
+std::string operator+() const;
+};
+template
+T const& operator + ( T const& value, StreamEndStop ) {
+return value;
+}
}
#define CATCH_INTERNAL_LINEINFO \
@@ -269,13 +461,16 @@ namespace Catch {
// end catch_common.h
namespace Catch {
- struct RegistrarForTagAliases {
- RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
- };
+struct RegistrarForTagAliases {
+RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
+};
} // end namespace Catch
-#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
+#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
// end catch_tag_alias_autoregistrar.h
// start catch_test_registry.h
@@ -283,31 +478,28 @@ namespace Catch {
// start catch_interfaces_testcase.h
#include
-#include
namespace Catch {
- class TestSpec;
+class TestSpec;
- struct ITestInvoker {
- virtual void invoke () const = 0;
- virtual ~ITestInvoker();
- };
+struct ITestInvoker {
+virtual void invoke () const = 0;
+virtual ~ITestInvoker();
+};
- using ITestCasePtr = std::shared_ptr;
+class TestCase;
+struct IConfig;
- class TestCase;
- struct IConfig;
+struct ITestCaseRegistry {
+virtual ~ITestCaseRegistry();
+virtual std::vector const& getAllTests() const = 0;
+virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0;
+};
- struct ITestCaseRegistry {
- virtual ~ITestCaseRegistry();
- virtual std::vector const& getAllTests() const = 0;
- virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0;
- };
-
- bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
- std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config );
- std::vector const& getAllTestCasesSorted( IConfig const& config );
+bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
+std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config );
+std::vector const& getAllTestCasesSorted( IConfig const& config );
}
@@ -320,168 +512,664 @@ namespace Catch {
namespace Catch {
- class StringData;
+/// A non-owning string class (similar to the forthcoming std::string_view)
+/// Note that, because a StringRef may be a substring of another string,
+/// it may not be null terminated. c_str() must return a null terminated
+/// string, however, and so the StringRef will internally take ownership
+/// (taking a copy), if necessary. In theory this ownership is not externally
+/// visible - but it does mean (substring) StringRefs should not be shared between
+/// threads.
+class StringRef {
+public:
+using size_type = std::size_t;
- /// A non-owning string class (similar to the forthcoming std::string_view)
- /// Note that, because a StringRef may be a substring of another string,
- /// it may not be null terminated. c_str() must return a null terminated
- /// string, however, and so the StringRef will internally take ownership
- /// (taking a copy), if necessary. In theory this ownership is not externally
- /// visible - but it does mean (substring) StringRefs should not be shared between
- /// threads.
- class StringRef {
- friend struct StringRefTestAccess;
+private:
+friend struct StringRefTestAccess;
- using size_type = std::size_t;
+char const* m_start;
+size_type m_size;
- char const* m_start;
- size_type m_size;
+char* m_data = nullptr;
- char* m_data = nullptr;
+void takeOwnership();
- void takeOwnership();
+static constexpr char const* const s_empty = "";
- public: // construction/ assignment
- StringRef() noexcept;
- StringRef( StringRef const& other ) noexcept;
- StringRef( StringRef&& other ) noexcept;
- StringRef( char const* rawChars ) noexcept;
- StringRef( char const* rawChars, size_type size ) noexcept;
- StringRef( std::string const& stdString ) noexcept;
- ~StringRef() noexcept;
+public: // construction/ assignment
+StringRef() noexcept
+: StringRef( s_empty, 0 )
+{}
- auto operator = ( StringRef other ) noexcept -> StringRef&;
- operator std::string() const;
+StringRef( StringRef const& other ) noexcept
+: m_start( other.m_start ),
+m_size( other.m_size )
+{}
- void swap( StringRef& other ) noexcept;
+StringRef( StringRef&& other ) noexcept
+: m_start( other.m_start ),
+m_size( other.m_size ),
+m_data( other.m_data )
+{
+other.m_data = nullptr;
+}
- public: // operators
- auto operator == ( StringRef const& other ) const noexcept -> bool;
- auto operator != ( StringRef const& other ) const noexcept -> bool;
+StringRef( char const* rawChars ) noexcept;
- auto operator[] ( size_type index ) const noexcept -> char;
+StringRef( char const* rawChars, size_type size ) noexcept
+: m_start( rawChars ),
+m_size( size )
+{}
- public: // named queries
- auto empty() const noexcept -> bool;
- auto size() const noexcept -> size_type;
- auto numberOfCharacters() const noexcept -> size_type;
- auto c_str() const -> char const*;
+StringRef( std::string const& stdString ) noexcept
+: m_start( stdString.c_str() ),
+m_size( stdString.size() )
+{}
- public: // substrings and searches
- auto substr( size_type start, size_type size ) const noexcept -> StringRef;
+~StringRef() noexcept {
+delete[] m_data;
+}
- private: // ownership queries - may not be consistent between calls
- auto isOwned() const noexcept -> bool;
- auto isSubstring() const noexcept -> bool;
- auto data() const noexcept -> char const*;
- };
+auto operator = ( StringRef const &other ) noexcept -> StringRef& {
+delete[] m_data;
+m_data = nullptr;
+m_start = other.m_start;
+m_size = other.m_size;
+return *this;
+}
- auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
- auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
- auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
+operator std::string() const;
- auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
+void swap( StringRef& other ) noexcept;
+
+public: // operators
+auto operator == ( StringRef const& other ) const noexcept -> bool;
+auto operator != ( StringRef const& other ) const noexcept -> bool;
+
+auto operator[] ( size_type index ) const noexcept -> char;
+
+public: // named queries
+auto empty() const noexcept -> bool {
+return m_size == 0;
+}
+auto size() const noexcept -> size_type {
+return m_size;
+}
+
+auto numberOfCharacters() const noexcept -> size_type;
+auto c_str() const -> char const*;
+
+public: // substrings and searches
+auto substr( size_type start, size_type size ) const noexcept -> StringRef;
+
+// Returns the current start pointer.
+// Note that the pointer can change when if the StringRef is a substring
+auto currentData() const noexcept -> char const*;
+
+private: // ownership queries - may not be consistent between calls
+auto isOwned() const noexcept -> bool;
+auto isSubstring() const noexcept -> bool;
+};
+
+auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
+auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
+auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
+
+auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
+auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
+
+inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
+return StringRef( rawChars, size );
+}
} // namespace Catch
+inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
+return Catch::StringRef( rawChars, size );
+}
+
// end catch_stringref.h
+// start catch_type_traits.hpp
+
+
+#include
+
+namespace Catch{
+
+#ifdef CATCH_CPP17_OR_GREATER
+template
+inline constexpr auto is_unique = std::true_type{};
+
+template
+inline constexpr auto is_unique = std::bool_constant<
+(!std::is_same_v && ...) && is_unique
+>{};
+#else
+
+template
+struct is_unique : std::true_type{};
+
+template
+struct is_unique : std::integral_constant
+::value
+&& is_unique::value
+&& is_unique::value
+>{};
+
+#endif
+}
+
+// end catch_type_traits.hpp
+// start catch_preprocessor.hpp
+
+
+#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
+#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
+#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
+
+#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
+// MSVC needs more evaluations
+#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
+#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
+#else
+#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
+#endif
+
+#define CATCH_REC_END(...)
+#define CATCH_REC_OUT
+
+#define CATCH_EMPTY()
+#define CATCH_DEFER(id) id CATCH_EMPTY()
+
+#define CATCH_REC_GET_END2() 0, CATCH_REC_END
+#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
+#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
+#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
+#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
+#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
+
+#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
+#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
+
+#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__ )
+#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__ )
+#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__ )
+
+// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
+// and passes userdata as the first parameter to each invocation,
+// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
+#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
+
+#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
+
+#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
+#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
+#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
+#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
+#else
+// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
+#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
+#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
+#endif
+
+#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
+
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__)
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
+#else
+// MSVC is adding extra space and needs more calls to properly remove ()
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__)
+#define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
+#endif
+
+#define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList
+
+#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
+ CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))
+
+// end catch_preprocessor.hpp
+// start catch_meta.hpp
+
+
+#include
+
+namespace Catch {
+template< typename... >
+struct TypeList {};
+
+template< typename... >
+struct append;
+
+template< template class L1
+, typename...E1
+, template class L2
+, typename...E2
+>
+struct append< L1, L2 > {
+using type = L1;
+};
+
+template< template class L1
+, typename...E1
+, template class L2
+, typename...E2
+, typename...Rest
+>
+struct append< L1, L2, Rest...> {
+using type = typename append< L1, Rest... >::type;
+};
+
+template< template class
+, typename...
+>
+struct rewrap;
+
+template< template class Container
+, template class List
+, typename...elems
+>
+struct rewrap> {
+using type = TypeList< Container< elems... > >;
+};
+
+template< template class Container
+, template class List
+, class...Elems
+, typename...Elements>
+struct rewrap, Elements...> {
+using type = typename append>, typename rewrap::type>::type;
+};
+
+template< template class...Containers >
+struct combine {
+template< typename...Types >
+struct with_types {
+template< template class Final >
+struct into {
+using type = typename append, typename rewrap::type...>::type;
+};
+};
+};
+
+template
+struct always_false : std::false_type {};
+
+} // namespace Catch
+
+// end catch_meta.hpp
namespace Catch {
template
class TestInvokerAsMethod : public ITestInvoker {
- void (C::*m_testAsMethod)();
+void (C::*m_testAsMethod)();
public:
- TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
+TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
- void invoke() const override {
- C obj;
- (obj.*m_testAsMethod)();
- }
+void invoke() const override {
+C obj;
+(obj.*m_testAsMethod)();
+}
};
auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
template
auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
- return new(std::nothrow) TestInvokerAsMethod( testAsMethod );
+return new(std::nothrow) TestInvokerAsMethod( testAsMethod );
}
struct NameAndTags {
- NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept;
- StringRef name;
- StringRef tags;
+NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
+StringRef name;
+StringRef tags;
};
struct AutoReg : NonCopyable {
- AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept;
- ~AutoReg();
+AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
+~AutoReg();
};
} // end namespace Catch
#if defined(CATCH_CONFIG_DISABLE)
- #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
+#define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
static void TestName()
- #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
+#define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
namespace{ \
- struct TestName : ClassName { \
+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
void test(); \
}; \
} \
void TestName::test()
-
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... ) \
+ template \
+ static void TestName()
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
+ namespace{ \
+ template \
+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \
+ void test(); \
+ }; \
+ } \
+ template \
+ void TestName::test()
#endif
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
static void TestName(); \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
+ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
static void TestName()
- #define INTERNAL_CATCH_TESTCASE( ... ) \
+#define INTERNAL_CATCH_TESTCASE( ... ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
namespace{ \
- struct TestName : ClassName{ \
+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
void test(); \
}; \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
} \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
void TestName::test()
- #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
+#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
- ///////////////////////////////////////////////////////////////////////////////
- #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
- Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
+ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
+///////////////////////////////////////////////////////////////////////////////
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ template \
+ static void TestFunc();\
+ namespace {\
+ template \
+ struct TestName{\
+ template \
+ TestName(Ts...names){\
+ CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
+ using expander = int[];\
+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
+ }\
+ };\
+ INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \
+ }\
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ template \
+ static void TestFunc()
+
+#if defined(CATCH_CPP17_OR_GREATER)
+#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case");
+#else
+#define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case");
+#endif
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
+ 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, __VA_ARGS__ )
+#else
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
+ 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, __VA_ARGS__ ) )
+#endif
+
+#define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\
+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+ TestName(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\
+ return 0;\
+ }();
+
+#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ template static void TestFuncName(); \
+ namespace { \
+ template \
+ struct TestName { \
+ TestName() { \
+ CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \
+ int index = 0; \
+ using expander = int[]; \
+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
+ } \
+ }; \
+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
+ using TestInit = Catch::combine \
+ ::with_types::into::type; \
+ TestInit(); \
+ return 0; \
+ }(); \
+ } \
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ template \
+ static void TestFuncName()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
+ 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,__VA_ARGS__)
+#else
+#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
+ 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, __VA_ARGS__ ) )
+#endif
+
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ namespace{ \
+ template \
+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \
+ void test();\
+ };\
+ template \
+ struct TestNameClass{\
+ template \
+ TestNameClass(Ts...names){\
+ CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
+ using expander = int[];\
+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
+ }\
+ };\
+ INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\
+ }\
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
+ template \
+ void TestName::test()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
+ 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, __VA_ARGS__ )
+#else
+#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
+ 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, __VA_ARGS__ ) )
+#endif
+
+#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\
+ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ template \
+ struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \
+ void test();\
+ };\
+ namespace {\
+ template\
+ struct TestNameClass{\
+ TestNameClass(){\
+ CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
+ int index = 0;\
+ using expander = int[];\
+ constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
+ constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
+ constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
+ (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
+ }\
+ };\
+ static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
+ using TestInit = Catch::combine\
+ ::with_types::into::type;\
+ TestInit();\
+ return 0;\
+ }(); \
+ }\
+ CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ template \
+ void TestName::test()
+
+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
+#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
+ 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, __VA_ARGS__ )
+#else
+#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
+ 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, __VA_ARGS__ ) )
+#endif
+
// end catch_test_registry.h
// start catch_capture.hpp
// start catch_assertionhandler.h
+// start catch_assertioninfo.h
+
+// start catch_result_type.h
+
+namespace Catch {
+
+// ResultWas::OfType enum
+struct ResultWas { enum OfType {
+Unknown = -1,
+Ok = 0,
+Info = 1,
+Warning = 2,
+
+FailureBit = 0x10,
+
+ExpressionFailed = FailureBit | 1,
+ExplicitFailure = FailureBit | 2,
+
+Exception = 0x100 | FailureBit,
+
+ThrewException = Exception | 1,
+DidntThrowException = Exception | 2,
+
+FatalErrorCondition = 0x200 | FailureBit
+
+}; };
+
+bool isOk( ResultWas::OfType resultType );
+bool isJustInfo( int flags );
+
+// ResultDisposition::Flags enum
+struct ResultDisposition { enum Flags {
+Normal = 0x01,
+
+ContinueOnFailure = 0x02, // Failures fail test, but execution continues
+FalseTest = 0x04, // Prefix expression with !
+SuppressFail = 0x08 // Failures are reported but do not fail the test
+}; };
+
+ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
+
+bool shouldContinueOnFailure( int flags );
+inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
+bool shouldSuppressFailure( int flags );
+
+} // end namespace Catch
+
+// end catch_result_type.h
+namespace Catch {
+
+struct AssertionInfo
+{
+StringRef macroName;
+SourceLineInfo lineInfo;
+StringRef capturedExpression;
+ResultDisposition::Flags resultDisposition;
+
+// We want to delete this constructor but a compiler bug in 4.8 means
+// the struct is then treated as non-aggregate
+//AssertionInfo() = delete;
+};
+
+} // end namespace Catch
+
+// end catch_assertioninfo.h
// start catch_decomposer.h
// start catch_tostring.h
-#include
#include
#include
#include
#include
+// start catch_stream.h
+
+#include
+#include
+#include
+
+namespace Catch {
+
+std::ostream& cout();
+std::ostream& cerr();
+std::ostream& clog();
+
+class StringRef;
+
+struct IStream {
+virtual ~IStream();
+virtual std::ostream& stream() const = 0;
+};
+
+auto makeStream( StringRef const &filename ) -> IStream const*;
+
+class ReusableStringStream {
+std::size_t m_index;
+std::ostream* m_oss;
+public:
+ReusableStringStream();
+~ReusableStringStream();
+
+auto str() const -> std::string;
+
+template
+auto operator << ( T const& value ) -> ReusableStringStream& {
+*m_oss << value;
+return *this;
+}
+auto get() -> std::ostream& { return *m_oss; }
+};
+}
+
+// end catch_stream.h
+
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+#include
+#endif
#ifdef __OBJC__
// start catch_objc_arc.hpp
@@ -499,12 +1187,12 @@ id performOptionalSelector( id obj, SEL sel );
#if !CATCH_ARC_ENABLED
inline void arcSafeRelease( NSObject* obj ) {
- [obj release];
+[obj release];
}
inline id performOptionalSelector( id obj, SEL sel ) {
- if( [obj respondsToSelector: sel] )
- return [obj performSelector: sel];
- return nil;
+if( [obj respondsToSelector: sel] )
+return [obj performSelector: sel];
+return nil;
}
#define CATCH_UNSAFE_UNRETAINED
#define CATCH_ARC_STRONG
@@ -515,12 +1203,12 @@ inline id performOptionalSelector( id obj, SEL sel ) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
#endif
- if( [obj respondsToSelector: sel] )
- return [obj performSelector: sel];
+if( [obj respondsToSelector: sel] )
+return [obj performSelector: sel];
#ifdef __clang__
#pragma clang diagnostic pop
#endif
- return nil;
+return nil;
}
#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
#define CATCH_ARC_STRONG __strong
@@ -534,249 +1222,310 @@ inline id performOptionalSelector( id obj, SEL sel ) {
#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
#endif
-// We need a dummy global operator<< so we can bring it into Catch namespace later
-struct Catch_global_namespace_dummy;
-std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
-
namespace Catch {
- // Bring in operator<< from global namespace into Catch namespace
- using ::operator<<;
+namespace Detail {
- namespace Detail {
+extern const std::string unprintableString;
- extern const std::string unprintableString;
+std::string rawMemoryToString( const void *object, std::size_t size );
- std::string rawMemoryToString( const void *object, std::size_t size );
+template
+std::string rawMemoryToString( const T& object ) {
+return rawMemoryToString( &object, sizeof(object) );
+}
- template
- std::string rawMemoryToString( const T& object ) {
- return rawMemoryToString( &object, sizeof(object) );
- }
+template
+class IsStreamInsertable {
+template
+static auto test(int)
+-> decltype(std::declval() << std::declval(), std::true_type());
- template
- class IsStreamInsertable {
- template
- static auto test(int)
- -> decltype(std::declval() << std::declval(), std::true_type());
+template
+static auto test(...)->std::false_type;
- template
- static auto test(...)->std::false_type;
+public:
+static const bool value = decltype(test(0))::value;
+};
- public:
- static const bool value = decltype(test(0))::value;
- };
+template
+std::string convertUnknownEnumToString( E e );
- } // namespace Detail
+template
+typename std::enable_if<
+!std::is_enum::value && !std::is_base_of::value,
+std::string>::type convertUnstreamable( T const& ) {
+return Detail::unprintableString;
+}
+template
+typename std::enable_if<
+!std::is_enum::value && std::is_base_of::value,
+std::string>::type convertUnstreamable(T const& ex) {
+return ex.what();
+}
- // If we decide for C++14, change these to enable_if_ts
- template
- struct StringMaker {
- template
- static
- typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type
- convert(const Fake& t) {
- std::ostringstream sstr;
- sstr << t;
- return sstr.str();
- }
+template
+typename std::enable_if<
+std::is_enum::value
+, std::string>::type convertUnstreamable( T const& value ) {
+return convertUnknownEnumToString( value );
+}
- template
- static
- typename std::enable_if::value, std::string>::type
- convert(const Fake&) {
- return Detail::unprintableString;
- }
- };
+#if defined(_MANAGED)
+//! Convert a CLR string to a utf8 std::string
+template
+std::string clrReferenceToString( T^ ref ) {
+if (ref == nullptr)
+return std::string("null");
+auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
+cli::pin_ptr p = &bytes[0];
+return std::string(reinterpret_cast(p), bytes->Length);
+}
+#endif
- namespace Detail {
+} // namespace Detail
- // This function dispatches all stringification requests inside of Catch.
- // Should be preferably called fully qualified, like ::Catch::Detail::stringify
- template
- std::string stringify(const T& e) {
- return ::Catch::StringMaker::type>::type>::convert(e);
- }
+// If we decide for C++14, change these to enable_if_ts
+template
+struct StringMaker {
+template
+static
+typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type
+convert(const Fake& value) {
+ReusableStringStream rss;
+// NB: call using the function-like syntax to avoid ambiguity with
+// user-defined templated operator<< under clang.
+rss.operator<<(value);
+return rss.str();
+}
- } // namespace Detail
+template
+static
+typename std::enable_if::value, std::string>::type
+convert( const Fake& value ) {
+#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
+return Detail::convertUnstreamable(value);
+#else
+return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
+#endif
+}
+};
- // Some predefined specializations
+namespace Detail {
- template<>
- struct StringMaker {
- static std::string convert(const std::string& str);
- };
- template<>
- struct StringMaker {
- static std::string convert(const std::wstring& wstr);
- };
+// This function dispatches all stringification requests inside of Catch.
+// Should be preferably called fully qualified, like ::Catch::Detail::stringify
+template
+std::string stringify(const T& e) {
+return ::Catch::StringMaker::type>::type>::convert(e);
+}
- template<>
- struct StringMaker {
- static std::string convert(char const * str);
- };
- template<>
- struct StringMaker {
- static std::string convert(char * str);
- };
- template<>
- struct StringMaker {
- static std::string convert(wchar_t const * str);
- };
- template<>
- struct StringMaker {
- static std::string convert(wchar_t * str);
- };
+template
+std::string convertUnknownEnumToString( E e ) {
+return ::Catch::Detail::stringify(static_cast::type>(e));
+}
- template
- struct StringMaker {
- static std::string convert(const char* str) {
- return ::Catch::Detail::stringify(std::string{ str });
- }
- };
- template
- struct StringMaker {
- static std::string convert(const char* str) {
- return ::Catch::Detail::stringify(std::string{ str });
- }
- };
- template
- struct StringMaker {
- static std::string convert(const char* str) {
- return ::Catch::Detail::stringify(std::string{ str });
- }
- };
+#if defined(_MANAGED)
+template
+std::string stringify( T^ e ) {
+return ::Catch::StringMaker::convert(e);
+}
+#endif
- template<>
- struct StringMaker {
- static std::string convert(int value);
- };
- template<>
- struct StringMaker {
- static std::string convert(long value);
- };
- template<>
- struct StringMaker {
- static std::string convert(long long value);
- };
- template<>
- struct StringMaker {
- static std::string convert(unsigned int value);
- };
- template<>
- struct StringMaker {
- static std::string convert(unsigned long value);
- };
- template<>
- struct StringMaker {
- static std::string convert(unsigned long long value);
- };
+} // namespace Detail
- template<>
- struct StringMaker {
- static std::string convert(bool b);
- };
+// Some predefined specializations
- template<>
- struct StringMaker {
- static std::string convert(char c);
- };
- template<>
- struct StringMaker {
- static std::string convert(signed char c);
- };
- template<>
- struct StringMaker {
- static std::string convert(unsigned char c);
- };
+template<>
+struct StringMaker {
+static std::string convert(const std::string& str);
+};
- template<>
- struct StringMaker {
- static std::string convert(std::nullptr_t);
- };
+#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+template<>
+struct StringMaker {
+static std::string convert(std::string_view str);
+};
+#endif
- template<>
- struct StringMaker {
- static std::string convert(float value);
- };
- template<>
- struct StringMaker {
- static std::string convert(double value);
- };
+template<>
+struct StringMaker {
+static std::string convert(char const * str);
+};
+template<>
+struct StringMaker {
+static std::string convert(char * str);
+};
- template
- struct StringMaker {
- template
- static std::string convert(U* p) {
- if (p) {
- return ::Catch::Detail::rawMemoryToString(p);
- } else {
- return "nullptr";
- }
- }
- };
+#ifdef CATCH_CONFIG_WCHAR
+template<>
+struct StringMaker {
+static std::string convert(const std::wstring& wstr);
+};
- template
- struct StringMaker {
- static std::string convert(R C::* p) {
- if (p) {
- return ::Catch::Detail::rawMemoryToString(p);
- } else {
- return "nullptr";
- }
- }
- };
+# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
+template<>
+struct StringMaker {
+static std::string convert(std::wstring_view str);
+};
+# endif
- namespace Detail {
- template
- std::string rangeToString(InputIterator first, InputIterator last) {
- std::ostringstream oss;
- oss << "{ ";
- if (first != last) {
- oss << ::Catch::Detail::stringify(*first);
- for (++first; first != last; ++first)
- oss << ", " << ::Catch::Detail::stringify(*first);
- }
- oss << " }";
- return oss.str();
- }
- }
+template<>
+struct StringMaker {
+static std::string convert(wchar_t const * str);
+};
+template<>
+struct StringMaker {
+static std::string convert(wchar_t * str);
+};
+#endif
- template
- struct StringMaker > {
- static std::string convert( std::vector const& v ) {
- return ::Catch::Detail::rangeToString( v.begin(), v.end() );
- }
- };
+// TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
+// while keeping string semantics?
+template
+struct StringMaker {
+static std::string convert(char const* str) {
+return ::Catch::Detail::stringify(std::string{ str });
+}
+};
+template
+struct StringMaker {
+static std::string convert(signed char const* str) {
+return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) });
+}
+};
+template
+struct StringMaker {
+static std::string convert(unsigned char const* str) {
+return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) });
+}
+};
- template
- struct EnumStringMaker {
- static std::string convert(const T& t) {
- return ::Catch::Detail::stringify(static_cast::type>(t));
- }
- };
+template<>
+struct StringMaker {
+static std::string convert(int value);
+};
+template<>
+struct StringMaker {
+static std::string convert(long value);
+};
+template<>
+struct StringMaker {
+static std::string convert(long long value);
+};
+template<>
+struct StringMaker {
+static std::string convert(unsigned int value);
+};
+template<>
+struct StringMaker {
+static std::string convert(unsigned long value);
+};
+template<>
+struct StringMaker {
+static std::string convert(unsigned long long value);
+};
+
+template<>
+struct StringMaker {
+static std::string convert(bool b);
+};
+
+template<>
+struct StringMaker {
+static std::string convert(char c);
+};
+template<>
+struct StringMaker {
+static std::string convert(signed char c);
+};
+template<>
+struct StringMaker {
+static std::string convert(unsigned char c);
+};
+
+template<>
+struct StringMaker {
+static std::string convert(std::nullptr_t);
+};
+
+template<>
+struct StringMaker {
+static std::string convert(float value);
+};
+template<>
+struct StringMaker {
+static std::string convert(double value);
+};
+
+template
+struct StringMaker {
+template
+static std::string convert(U* p) {
+if (p) {
+return ::Catch::Detail::rawMemoryToString(p);
+} else {
+return "nullptr";
+}
+}
+};
+
+template
+struct StringMaker {
+static std::string convert(R C::* p) {
+if (p) {
+return ::Catch::Detail::rawMemoryToString(p);
+} else {
+return "nullptr";
+}
+}
+};
+
+#if defined(_MANAGED)
+template
+struct StringMaker {
+static std::string convert( T^ ref ) {
+return ::Catch::Detail::clrReferenceToString(ref);
+}
+};
+#endif
+
+namespace Detail {
+template
+std::string rangeToString(InputIterator first, InputIterator last) {
+ReusableStringStream rss;
+rss << "{ ";
+if (first != last) {
+rss << ::Catch::Detail::stringify(*first);
+for (++first; first != last; ++first)
+rss << ", " << ::Catch::Detail::stringify(*first);
+}
+rss << " }";
+return rss.str();
+}
+}
#ifdef __OBJC__
- template<>
- struct StringMaker {
- static std::string convert(NSString * nsstring) {
- if (!nsstring)
- return "nil";
- return std::string("@") + [nsstring UTF8String];
- }
- };
- template<>
- struct StringMaker {
- static std::string convert(NSObject* nsObject) {
- return ::Catch::Detail::stringify([nsObject description]);
- }
+template<>
+struct StringMaker {
+static std::string convert(NSString * nsstring) {
+if (!nsstring)
+return "nil";
+return std::string("@") + [nsstring UTF8String];
+}
+};
+template<>
+struct StringMaker {
+static std::string convert(NSObject* nsObject) {
+return ::Catch::Detail::stringify([nsObject description]);
+}
- };
- namespace Detail {
- inline std::string stringify( NSString* nsstring ) {
- return StringMaker::convert( nsstring );
- }
+};
+namespace Detail {
+inline std::string stringify( NSString* nsstring ) {
+return StringMaker::convert( nsstring );
+}
- } // namespace Detail
+} // namespace Detail
#endif // __OBJC__
} // namespace Catch
@@ -788,182 +1537,293 @@ namespace Catch {
#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
+# define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
+# define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
#endif
// Separate std::pair specialization
#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
#include
namespace Catch {
- template
- struct StringMaker > {
- static std::string convert(const std::pair& pair) {
- std::ostringstream oss;
- oss << "{ "
- << ::Catch::Detail::stringify(pair.first)
- << ", "
- << ::Catch::Detail::stringify(pair.second)
- << " }";
- return oss.str();
- }
- };
+template
+struct StringMaker > {
+static std::string convert(const std::pair& pair) {
+ReusableStringStream rss;
+rss << "{ "
+<< ::Catch::Detail::stringify(pair.first)
+<< ", "
+<< ::Catch::Detail::stringify(pair.second)
+<< " }";
+return rss.str();
+}
+};
}
#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
+#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
+#include
+namespace Catch {
+template
+struct StringMaker > {
+static std::string convert(const std::optional& optional) {
+ReusableStringStream rss;
+if (optional.has_value()) {
+rss << ::Catch::Detail::stringify(*optional);
+} else {
+rss << "{ }";
+}
+return rss.str();
+}
+};
+}
+#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
+
// Separate std::tuple specialization
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
#include
namespace Catch {
- namespace Detail {
- template<
- typename Tuple,
- std::size_t N = 0,
- bool = (N < std::tuple_size::value)
- >
- struct TupleElementPrinter {
- static void print(const Tuple& tuple, std::ostream& os) {
- os << (N ? ", " : " ")
- << ::Catch::Detail::stringify(std::get(tuple));
- TupleElementPrinter::print(tuple, os);
- }
- };
+namespace Detail {
+template<
+typename Tuple,
+std::size_t N = 0,
+bool = (N < std::tuple_size::value)
+>
+struct TupleElementPrinter {
+static void print(const Tuple& tuple, std::ostream& os) {
+os << (N ? ", " : " ")
+<< ::Catch::Detail::stringify(std::get(tuple));
+TupleElementPrinter::print(tuple, os);
+}
+};
- template<
- typename Tuple,
- std::size_t N
- >
- struct TupleElementPrinter {
- static void print(const Tuple&, std::ostream&) {}
- };
+template<
+typename Tuple,
+std::size_t N
+>
+struct TupleElementPrinter {
+static void print(const Tuple&, std::ostream&) {}
+};
- }
+}
- template
- struct StringMaker> {
- static std::string convert(const std::tuple& tuple) {
- std::ostringstream os;
- os << '{';
- Detail::TupleElementPrinter