diff options
| author | Martin Hořeňovský | 2018-09-04 11:59:15 +0200 |
|---|---|---|
| committer | Martin Hořeňovský | 2018-09-04 11:59:15 +0200 |
| commit | 60b05b20413afe4ad9980e627862474a9b8ba4cd (patch) | |
| tree | 89612c7d982d903a68bf7a85458ebe5f0c9a7496 /single_include | |
| parent | 232ea3c456ee6fe70a9a8971c4e0e45bb27d1293 (diff) | |
| download | catch3-2.4.0.tar.gz | |
v2.4.0v2.4.0
Diffstat (limited to 'single_include')
| -rw-r--r-- | single_include/catch2/catch.hpp | 957 | ||||
| -rw-r--r-- | single_include/catch2/catch_reporter_teamcity.hpp | 4 |
2 files changed, 762 insertions, 199 deletions
diff --git a/single_include/catch2/catch.hpp b/single_include/catch2/catch.hpp index bdc2f74a..b0fa6416 100644 --- a/single_include/catch2/catch.hpp +++ b/single_include/catch2/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.3.0 - * Generated: 2018-07-23 10:09:14.936841 + * Catch v2.4.0 + * Generated: 2018-09-04 11:55:01.682061 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. @@ -14,7 +14,7 @@ #define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 3 +#define CATCH_VERSION_MINOR 4 #define CATCH_VERSION_PATCH 0 #ifdef __clang__ @@ -108,6 +108,7 @@ namespace Catch { // 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 @@ -221,7 +222,12 @@ namespace Catch { #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 @@ -269,6 +275,10 @@ namespace Catch { # 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_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS @@ -282,6 +292,16 @@ namespace Catch { # 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 + // end catch_compiler_capabilities.h #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) @@ -522,6 +542,10 @@ namespace Catch { } // 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 namespace Catch { @@ -725,8 +749,6 @@ namespace Catch { return *this; } auto get() -> std::ostream& { return *m_oss; } - - static void cleanup(); }; } @@ -1514,8 +1536,10 @@ namespace Catch { struct BenchmarkInfo; struct BenchmarkStats; struct AssertionReaction; + struct SourceLineInfo; struct ITransientExpression; + struct IGeneratorTracker; struct IResultCapture { @@ -1526,6 +1550,8 @@ namespace Catch { virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; + virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; @@ -1607,7 +1633,7 @@ namespace Catch { public: AssertionHandler - ( StringRef macroName, + ( StringRef const& macroName, SourceLineInfo const& lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition ); @@ -1638,7 +1664,7 @@ namespace Catch { auto allowThrows() const -> bool; }; - void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ); } // namespace Catch @@ -1646,15 +1672,16 @@ namespace Catch { // start catch_message.h #include <string> +#include <vector> namespace Catch { struct MessageInfo { - MessageInfo( std::string const& _macroName, + MessageInfo( StringRef const& _macroName, SourceLineInfo const& _lineInfo, ResultWas::OfType _type ); - std::string macroName; + StringRef macroName; std::string message; SourceLineInfo lineInfo; ResultWas::OfType type; @@ -1678,7 +1705,7 @@ namespace Catch { }; struct MessageBuilder : MessageStream { - MessageBuilder( std::string const& macroName, + MessageBuilder( StringRef const& macroName, SourceLineInfo const& lineInfo, ResultWas::OfType type ); @@ -1699,6 +1726,28 @@ namespace Catch { MessageInfo m_info; }; + class Capturer { + std::vector<MessageInfo> m_messages; + IResultCapture& m_resultCapture = getResultCapture(); + size_t m_captured = 0; + public: + Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); + ~Capturer(); + + void captureValue( size_t index, StringRef value ); + + template<typename T> + void captureValues( size_t index, T&& value ) { + captureValue( index, Catch::Detail::stringify( value ) ); + } + + template<typename T, typename... Ts> + void captureValues( size_t index, T&& value, Ts&&... values ) { + captureValues( index, value ); + captureValues( index+1, values... ); + } + }; + } // end namespace Catch // end catch_message.h @@ -1710,7 +1759,7 @@ namespace Catch { #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" #endif -#if defined(CATCH_CONFIG_FAST_COMPILE) +#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) /////////////////////////////////////////////////////////////////////////////// // Another way to speed-up compilation is to omit local try-catch for REQUIRE* @@ -1730,7 +1779,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ INTERNAL_CATCH_TRY { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ @@ -1753,7 +1802,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ try { \ static_cast<void>(__VA_ARGS__); \ catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ @@ -1767,7 +1816,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast<void>(__VA_ARGS__); \ @@ -1784,7 +1833,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast<void>(expr); \ @@ -1804,27 +1853,32 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( false ) /////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ + auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ + varName.captureValues( 0, __VA_ARGS__ ) + +/////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); /////////////////////////////////////////////////////////////////////////////// // Although this is matcher-based, it can be used with just a string #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast<void>(__VA_ARGS__); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ } \ catch( ... ) { \ - Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ + Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ } \ else \ catchAssertionHandler.handleThrowingCallSkipped(); \ @@ -2029,7 +2083,7 @@ namespace Catch { virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0; virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; }; @@ -2044,7 +2098,7 @@ namespace Catch { virtual void registerStartupException() noexcept = 0; }; - IRegistryHub& getRegistryHub(); + IRegistryHub const& getRegistryHub(); IMutableRegistryHub& getMutableRegistryHub(); void cleanUp(); std::string translateActiveException(); @@ -2126,7 +2180,6 @@ namespace Catch { // start catch_approx.h #include <type_traits> -#include <stdexcept> namespace Catch { namespace Detail { @@ -2134,6 +2187,12 @@ namespace Detail { class Approx { private: bool equalityComparisonImpl(double other) const; + // Validates the new margin (margin >= 0) + // out-of-line to avoid including stdexcept in the header + void setMargin(double margin); + // Validates the new epsilon (0 < epsilon < 1) + // out-of-line to avoid including stdexcept in the header + void setEpsilon(double epsilon); public: explicit Approx ( double value ); @@ -2145,9 +2204,9 @@ namespace Detail { template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> Approx operator()( T const& value ) { Approx approx( static_cast<double>(value) ); - approx.epsilon( m_epsilon ); - approx.margin( m_margin ); - approx.scale( m_scale ); + approx.m_epsilon = m_epsilon; + approx.m_margin = m_margin; + approx.m_scale = m_scale; return approx; } @@ -2199,27 +2258,14 @@ namespace Detail { template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> Approx& epsilon( T const& newEpsilon ) { double epsilonAsDouble = static_cast<double>(newEpsilon); - if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) { - throw std::domain_error - ( "Invalid Approx::epsilon: " + - Catch::Detail::stringify( epsilonAsDouble ) + - ", Approx::epsilon has to be between 0 and 1" ); - } - m_epsilon = epsilonAsDouble; + setEpsilon(epsilonAsDouble); return *this; } template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> Approx& margin( T const& newMargin ) { double marginAsDouble = static_cast<double>(newMargin); - if( marginAsDouble < 0 ) { - throw std::domain_error - ( "Invalid Approx::margin: " + - Catch::Detail::stringify( marginAsDouble ) + - ", Approx::Margin has to be non-negative." ); - - } - m_margin = marginAsDouble; + setMargin(marginAsDouble); return *this; } @@ -2309,6 +2355,11 @@ namespace Matchers { mutable std::string m_cachedToString; }; +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wnon-virtual-dtor" +#endif + template<typename ObjectT> struct MatcherMethod { virtual bool match( ObjectT const& arg ) const = 0; @@ -2318,6 +2369,10 @@ namespace Matchers { virtual bool match( PtrT* arg ) const = 0; }; +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + template<typename T> struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { @@ -2771,7 +2826,7 @@ namespace Catch { MatcherT m_matcher; StringRef m_matcherString; public: - MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) + MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) : ITransientExpression{ true, matcher.match( arg ) }, m_arg( arg ), m_matcher( matcher ), @@ -2790,10 +2845,10 @@ namespace Catch { using StringMatcher = Matchers::Impl::MatcherBase<std::string>; - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); template<typename ArgT, typename MatcherT> - auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr<ArgT, MatcherT> { + auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); } @@ -2802,9 +2857,9 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ INTERNAL_CATCH_TRY { \ - catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ + catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( false ) @@ -2812,14 +2867,14 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast<void>(__VA_ARGS__ ); \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ } \ catch( exceptionType const& ex ) { \ - catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ + catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ } \ catch( ... ) { \ catchAssertionHandler.handleUnexpectedInflightException(); \ @@ -2831,6 +2886,304 @@ namespace Catch { // end catch_capture_matchers.h #endif +// start catch_generators.hpp + +// start catch_interfaces_generatortracker.h + + +#include <memory> + +namespace Catch { + + namespace Generators { + class GeneratorBase { + protected: + size_t m_size = 0; + + public: + GeneratorBase( size_t size ) : m_size( size ) {} + virtual ~GeneratorBase(); + auto size() const -> size_t { return m_size; } + }; + using GeneratorBasePtr = std::unique_ptr<GeneratorBase>; + + } // namespace Generators + + struct IGeneratorTracker { + virtual ~IGeneratorTracker(); + virtual auto hasGenerator() const -> bool = 0; + virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0; + virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0; + virtual auto getIndex() const -> std::size_t = 0; + }; + +} // namespace Catch + +// end catch_interfaces_generatortracker.h +// start catch_enforce.h + +#include <stdexcept> + +namespace Catch { +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) + template <typename Ex> + [[noreturn]] + void throw_exception(Ex const& e) { + throw e; + } +#else // ^^ Exceptions are enabled // Exceptions are disabled vv + [[noreturn]] + void throw_exception(std::exception const& e); +#endif +} // namespace Catch; + +#define CATCH_PREPARE_EXCEPTION( type, msg ) \ + type( ( Catch::ReusableStringStream() << msg ).str() ) +#define CATCH_INTERNAL_ERROR( msg ) \ + Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg)) +#define CATCH_ERROR( msg ) \ + Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg )) +#define CATCH_RUNTIME_ERROR( msg ) \ + Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg )) +#define CATCH_ENFORCE( condition, msg ) \ + do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) + +// end catch_enforce.h +#include <memory> +#include <vector> +#include <cassert> + +#include <utility> + +namespace Catch { +namespace Generators { + + // !TBD move this into its own location? + namespace pf{ + template<typename T, typename... Args> + std::unique_ptr<T> make_unique( Args&&... args ) { + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); + } + } + + template<typename T> + struct IGenerator { + virtual ~IGenerator() {} + virtual auto get( size_t index ) const -> T = 0; + }; + + template<typename T> + class SingleValueGenerator : public IGenerator<T> { + T m_value; + public: + SingleValueGenerator( T const& value ) : m_value( value ) {} + + auto get( size_t ) const -> T override { + return m_value; + } + }; + + template<typename T> + class FixedValuesGenerator : public IGenerator<T> { + std::vector<T> m_values; + + public: + FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {} + + auto get( size_t index ) const -> T override { + return m_values[index]; + } + }; + + template<typename T> + class RangeGenerator : public IGenerator<T> { + T const m_first; + T const m_last; + + public: + RangeGenerator( T const& first, T const& last ) : m_first( first ), m_last( last ) { + assert( m_last > m_first ); + } + + auto get( size_t index ) const -> T override { + // ToDo:: introduce a safe cast to catch potential overflows + return static_cast<T>(m_first+index); + } + }; + + template<typename T> + struct NullGenerator : IGenerator<T> { + auto get( size_t ) const -> T override { + CATCH_INTERNAL_ERROR("A Null Generator is always empty"); + } + }; + + template<typename T> + class Generator { + std::unique_ptr<IGenerator<T>> m_generator; + size_t m_size; + + public: + Generator( size_t size, std::unique_ptr<IGenerator<T>> generator ) + : m_generator( std::move( generator ) ), + m_size( size ) + {} + + auto size() const -> size_t { return m_size; } + auto operator[]( size_t index ) const -> T { + assert( index < m_size ); + return m_generator->get( index ); + } + }; + + std::vector<size_t> randomiseIndices( size_t selectionSize, size_t sourceSize ); + + template<typename T> + class GeneratorRandomiser : public IGenerator<T> { + Generator<T> m_baseGenerator; + + std::vector<size_t> m_indices; + public: + GeneratorRandomiser( Generator<T>&& baseGenerator, size_t numberOfItems ) + : m_baseGenerator( std::move( baseGenerator ) ), + m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) ) + {} + + auto get( size_t index ) const -> T override { + return m_baseGenerator[m_indices[index]]; + } + }; + + template<typename T> + struct RequiresASpecialisationFor; + + template<typename T> + auto all() -> Generator<T> { return RequiresASpecialisationFor<T>(); } + + template<> + auto all<int>() -> Generator<int>; + + template<typename T> + auto range( T const& first, T const& last ) -> Generator<T> { + return Generator<T>( (last-first), pf::make_unique<RangeGenerator<T>>( first, last ) ); + } + + template<typename T> + auto random( T const& first, T const& last ) -> Generator<T> { + auto gen = range( first, last ); + auto size = gen.size(); + + return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) ); + } + template<typename T> + auto random( size_t size ) -> Generator<T> { + return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) ); + } + + template<typename T> + auto values( std::initializer_list<T> values ) -> Generator<T> { + return Generator<T>( values.size(), pf::make_unique<FixedValuesGenerator<T>>( values ) ); + } + template<typename T> + auto value( T const& val ) -> Generator<T> { + return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) ); + } + + template<typename T> + auto as() -> Generator<T> { + return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() ); + } + + template<typename... Ts> + auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) -> Generator<std::tuple<Ts...>> { + return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) ); + } + + template<typename T> + struct Generators : GeneratorBase { + std::vector<Generator<T>> m_generators; + + using type = T; + + Generators() : GeneratorBase( 0 ) {} + + void populate( T&& val ) { + m_size += 1; + m_generators.emplace_back( value( std::move( val ) ) ); + } + template<typename U> + void populate( U&& val ) { + populate( T( std::move( val ) ) ); + } + void populate( Generator<T>&& generator ) { + m_size += generator.size(); + m_generators.emplace_back( std::move( generator ) ); + } + + template<typename U, typename... Gs> + void populate( U&& valueOrGenerator, Gs... moreGenerators ) { + populate( std::forward<U>( valueOrGenerator ) ); + populate( std::forward<Gs>( moreGenerators )... ); + } + + auto operator[]( size_t index ) const -> T { + size_t sizes = 0; + for( auto const& gen : m_generators ) { + auto localIndex = index-sizes; + sizes += gen.size(); + if( index < sizes ) + return gen[localIndex]; + } + CATCH_INTERNAL_ERROR("Index '" << index << "' is out of range (" << sizes << ')'); + } + }; + + template<typename T, typename... Gs> + auto makeGenerators( Generator<T>&& generator, Gs... moreGenerators ) -> Generators<T> { + Generators<T> generators; + generators.m_generators.reserve( 1+sizeof...(Gs) ); + generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... ); + return generators; + } + template<typename T> + auto makeGenerators( Generator<T>&& generator ) -> Generators<T> { + Generators<T> generators; + generators.populate( std::move( generator ) ); + return generators; + } + template<typename T, typename... Gs> + auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> { + return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... ); + } + template<typename T, typename U, typename... Gs> + auto makeGenerators( U&& val, Gs... moreGenerators ) -> Generators<T> { + return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); + } + + auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; + + template<typename L> + // Note: The type after -> is weird, because VS2015 cannot parse + // the expression used in the typedef inside, when it is in + // return type. Yeah, ¯\_(ツ)_/¯ + auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>()[0]) { + using UnderlyingType = typename decltype(generatorExpression())::type; + + IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); + if( !tracker.hasGenerator() ) + tracker.setGenerator( pf::make_unique<Generators<UnderlyingType>>( generatorExpression() ) ); + + auto const& generator = static_cast<Generators<UnderlyingType> const&>( *tracker.getGenerator() ); + return generator[tracker.getIndex()]; + } + +} // namespace Generators +} // namespace Catch + +#define GENERATE( ... ) \ + Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + +// end catch_generators.hpp // These files are included here so the single_include script doesn't put them // in the conditionally compiled sections @@ -3842,7 +4195,7 @@ namespace Catch { { m_reporterPrefs.shouldRedirectStdOut = false; if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) - throw std::domain_error( "Verbosity level not supported by this reporter" ); + CATCH_ERROR( "Verbosity level not supported by this reporter" ); } ReporterPreferences getPreferences() const override { @@ -3956,7 +4309,7 @@ namespace Catch { { m_reporterPrefs.shouldRedirectStdOut = false; if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) - throw std::domain_error( "Verbosity level not supported by this reporter" ); + CATCH_ERROR( "Verbosity level not supported by this reporter" ); } ~CumulativeReporterBase() override = default; @@ -4596,13 +4949,6 @@ namespace TestCaseTracking { Failed }; - class TrackerHasName { - NameAndLocation m_nameAndLocation; - public: - TrackerHasName( NameAndLocation const& nameAndLocation ); - bool operator ()( ITrackerPtr const& tracker ) const; - }; - using Children = std::vector<ITrackerPtr>; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; @@ -4740,6 +5086,20 @@ namespace Detail { return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); } + void Approx::setMargin(double margin) { + CATCH_ENFORCE(margin >= 0, + "Invalid Approx::margin: " << margin << '.' + << " Approx::Margin has to be non-negative."); + m_margin = margin; + } + + void Approx::setEpsilon(double epsilon) { + CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0, + "Invalid Approx::epsilon: " << epsilon << '.' + << " Approx::epsilon has to be in [0, 1]"); + m_epsilon = epsilon; + } + } // end namespace Detail namespace literals { @@ -4992,6 +5352,8 @@ namespace Catch { void sectionEnded( SectionEndInfo const& endInfo ) override; void sectionEndedEarly( SectionEndInfo const& endInfo ) override; + auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; + void benchmarkStarting( BenchmarkInfo const& info ) override; void benchmarkEnded( BenchmarkStats const& stats ) override; @@ -5093,7 +5455,7 @@ namespace Catch { } AssertionHandler::AssertionHandler - ( StringRef macroName, + ( StringRef const& macroName, SourceLineInfo const& lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition ) @@ -5122,8 +5484,13 @@ namespace Catch { // (To go back to the test and change execution, jump over the throw, next) CATCH_BREAK_INTO_DEBUGGER(); } - if( m_reaction.shouldThrow ) + if (m_reaction.shouldThrow) { +#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) throw Catch::TestFailureException(); +#else + CATCH_ERROR( "Test failure requires aborting test!" ); +#endif + } } void AssertionHandler::setCompleted() { m_completed = true; @@ -5150,7 +5517,7 @@ namespace Catch { // This is the overload that takes a string and infers the Equals matcher from it // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp - void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) { + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString ) { handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); } @@ -5282,7 +5649,7 @@ namespace Catch { // This is the general overload that takes a any string matcher // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers // the Equals matcher (so the header does not mention matchers) - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) { std::string exceptionMessage = Catch::translateActiveException(); MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString ); handler.handleExpr( expr ); @@ -6767,7 +7134,9 @@ namespace Catch { return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); } bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { - return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); + // We can assume that the same file will usually have the same pointer. + // Thus, if the pointers are the same, there is no point in calling the strcmp + return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0)); } std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { @@ -6790,20 +7159,6 @@ namespace Catch { // end catch_common.cpp // start catch_config.cpp -// start catch_enforce.h |