From 2fdd81a33f36685b0708680a2ea15e670d5db730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 11:11:26 +0200 Subject: [PATCH 001/398] Removed C++98 backcompat from Approx Now it always uses type traits to work with all types convertible to double --- include/internal/catch_approx.hpp | 67 ------------------------------- 1 file changed, 67 deletions(-) diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index fc681436..406c7ef1 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -13,9 +13,7 @@ #include #include -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) #include -#endif namespace Catch { namespace Detail { @@ -40,8 +38,6 @@ namespace Detail { return Approx( 0 ); } -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) - template ::value>::type> Approx operator()( T value ) { Approx approx( static_cast(value) ); @@ -120,69 +116,6 @@ namespace Detail { return *this; } -#else - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.margin( m_margin ); - approx.scale( m_scale ); - return approx; - } - - - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); - if (relativeOK) { - return true; - } - return std::fabs(lhs - rhs.m_value) < rhs.m_margin; - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - friend bool operator <= ( double lhs, Approx const& rhs ) { - return lhs < rhs.m_value || lhs == rhs; - } - - friend bool operator <= ( Approx const& lhs, double rhs ) { - return lhs.m_value < rhs || lhs == rhs; - } - - friend bool operator >= ( double lhs, Approx const& rhs ) { - return lhs > rhs.m_value || lhs == rhs; - } - - friend bool operator >= ( Approx const& lhs, double rhs ) { - return lhs.m_value > rhs || lhs == rhs; - } - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& margin( double newMargin ) { - m_margin = newMargin; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } -#endif std::string toString() const { std::ostringstream oss; From 7c900660ef4cad84b61380b817e3b5e0561fd9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 11:19:01 +0200 Subject: [PATCH 002/398] Removed superfluous reimplementation of type traits --- include/internal/catch_type_traits.hpp | 47 -------------------------- 1 file changed, 47 deletions(-) delete mode 100644 include/internal/catch_type_traits.hpp diff --git a/include/internal/catch_type_traits.hpp b/include/internal/catch_type_traits.hpp deleted file mode 100644 index 9be89162..00000000 --- a/include/internal/catch_type_traits.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Created by Martin on 08/02/2017. - * - * 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) - */ -#ifndef TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) -#include -#endif - - -namespace Catch { - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) - - template - using add_lvalue_reference = std::add_lvalue_reference; - - template - using add_const = std::add_const; - -#else - - template - struct add_const { - typedef const T type; - }; - - template - struct add_lvalue_reference { - typedef T& type; - }; - template - struct add_lvalue_reference { - typedef T& type; - }; - // No && overload, because that is C++11, in which case we have - // proper type_traits implementation from the standard library - -#endif - -} - -#endif // TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED From c6980ec2d852e3a5163b2bcb1a5a6b24c87b69ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 11:21:22 +0200 Subject: [PATCH 003/398] Remove C++98 backcompat from toString --- include/internal/catch_tostring.h | 41 +++-------------------------- include/internal/catch_tostring.hpp | 4 --- 2 files changed, 3 insertions(+), 42 deletions(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 21ab99a0..f72eeca3 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -20,13 +20,9 @@ #include "catch_objc_arc.hpp" #endif -#ifdef CATCH_CONFIG_CPP11_TUPLE #include -#endif -#ifdef CATCH_CONFIG_CPP11_IS_ENUM #include -#endif namespace Catch { @@ -52,14 +48,10 @@ std::string toString( char value ); std::string toString( signed char value ); std::string toString( unsigned char value ); -#ifdef CATCH_CONFIG_CPP11_LONG_LONG std::string toString( long long value ); std::string toString( unsigned long long value ); -#endif -#ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ); -#endif #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ); @@ -72,26 +64,6 @@ namespace Detail { extern const std::string unprintableString; - #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) - struct BorgType { - template BorgType( T const& ); - }; - - struct TrueType { char sizer[1]; }; - struct FalseType { char sizer[2]; }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; -#else template class IsStreamInsertable { template @@ -104,9 +76,8 @@ namespace Detail { public: static const bool value = decltype(test(0))::value; }; -#endif -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) + template::value > @@ -125,19 +96,14 @@ namespace Detail { ); } }; -#endif + template struct StringMakerBase { -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) template static std::string convert( T const& v ) { return EnumStringMaker::convert( v ); } -#else - template - static std::string convert( T const& ) { return unprintableString; } -#endif }; template<> @@ -202,7 +168,6 @@ std::string toString( std::vector const& v ) { } -#ifdef CATCH_CONFIG_CPP11_TUPLE // toString for tuples namespace TupleDetail { @@ -242,7 +207,7 @@ struct StringMaker> { return os.str(); } }; -#endif // CATCH_CONFIG_CPP11_TUPLE + namespace Detail { template diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index e61191b9..f20c41a2 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -169,7 +169,6 @@ std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } -#ifdef CATCH_CONFIG_CPP11_LONG_LONG std::string toString( long long value ) { std::ostringstream oss; oss << value; @@ -184,13 +183,10 @@ std::string toString( unsigned long long value ) { oss << " (0x" << std::hex << value << ')'; return oss.str(); } -#endif -#ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; } -#endif #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ) { From c6e5738d54f400b8dc02d6b43cc1beb6edfe5e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 11:25:49 +0200 Subject: [PATCH 004/398] Remove c++98 backcompat from timer --- include/internal/catch_timer.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 607aa6bb..1d690160 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -10,17 +10,7 @@ #include "catch_platform.h" -#ifdef _MSC_VER - -namespace Catch { - typedef unsigned long long UInt64; -} -#else #include -namespace Catch { - typedef uint64_t UInt64; -} -#endif namespace Catch { @@ -33,7 +23,7 @@ namespace Catch { double getElapsedSeconds() const; private: - UInt64 m_ticks; + uint64_t m_ticks; }; } // namespace Catch From 6a09425de176ac2b03df496d01f5c0925aae3339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 11:28:40 +0200 Subject: [PATCH 005/398] Remove C++98 backcompat from evaluate --- include/internal/catch_evaluate.hpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 87fcc17f..e1d2505f 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -39,10 +39,8 @@ namespace Internal { template inline T& opCast(T const& t) { return const_cast(t); } -// nullptr_t support based on pull request #154 from Konstantin Baumann -#ifdef CATCH_CONFIG_CPP11_NULLPTR + // nullptr_t support based on pull request #154 from Konstantin Baumann inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } -#endif // CATCH_CONFIG_CPP11_NULLPTR // So the compare overloads can be operator agnostic we convey the operator as a template @@ -161,7 +159,6 @@ namespace Internal { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } -#ifdef CATCH_CONFIG_CPP11_LONG_LONG // long long to unsigned X template bool compare( long long lhs, unsigned int rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); @@ -197,9 +194,7 @@ namespace Internal { template bool compare( T* lhs, long long rhs ) { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } -#endif // CATCH_CONFIG_CPP11_LONG_LONG -#ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { return Evaluator::evaluate( nullptr, rhs ); @@ -207,7 +202,6 @@ namespace Internal { template bool compare( T* lhs, std::nullptr_t ) { return Evaluator::evaluate( lhs, nullptr ); } -#endif // CATCH_CONFIG_CPP11_NULLPTR } // end of namespace Internal } // end of namespace Catch From 073377a4e47e190e6631b64ecd5441f747de0e1a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 11:06:28 +0100 Subject: [PATCH 006/398] CMake defaults to C++11 --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95bdf68e..758293ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,13 +10,13 @@ set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark) set(HEADER_DIR ${CATCH_DIR}/include) -if(USE_CPP11) - ## We can't turn this on by default, since it breaks on travis - message(STATUS "Enabling C++11") - set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") -elseif(USE_CPP14) +if(USE_CPP14) message(STATUS "Enabling C++14") set(CMAKE_CXX_FLAGS "-std=c++14 ${CMAKE_CXX_FLAGS}") +else() + message(STATUS "Enabling C++11") + set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") + endif() #checks that the given hard-coded list contains all headers + sources in the given folder From 1f3ba8a0b670362ad7adc1dc161bef69e0a86c92 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 11:06:52 +0100 Subject: [PATCH 007/398] Converted (almost) all for-loops with iterators or indices to range-based --- include/catch_session.hpp | 33 ++++----- include/internal/catch_common.h | 12 ++-- include/internal/catch_config.hpp | 4 +- include/internal/catch_generators.hpp | 6 +- include/internal/catch_generators_impl.hpp | 6 +- .../catch_legacy_reporter_adapter.hpp | 10 ++- include/internal/catch_list.hpp | 49 +++++-------- include/internal/catch_matchers.hpp | 26 ++++--- include/internal/catch_matchers_vector.h | 4 +- include/internal/catch_section_info.hpp | 12 ++-- include/internal/catch_tag_alias_registry.hpp | 10 ++- include/internal/catch_test_case_info.hpp | 6 +- .../catch_test_case_registry_impl.hpp | 18 ++--- include/internal/catch_test_spec.hpp | 8 +-- include/reporters/catch_reporter_console.hpp | 26 ++++--- include/reporters/catch_reporter_junit.hpp | 34 +++------ include/reporters/catch_reporter_multi.hpp | 72 +++++++------------ include/reporters/catch_reporter_teamcity.hpp | 8 +-- include/reporters/catch_reporter_xml.hpp | 12 ++-- 19 files changed, 136 insertions(+), 220 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index be51bef8..8d200aa6 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -37,18 +37,14 @@ namespace Catch { reporters.push_back( "console" ); Ptr reporter; - for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); - it != itEnd; - ++it ) - reporter = addReporter( reporter, createReporter( *it, config ) ); + for( auto const& name : reporters ) + reporter = addReporter( reporter, createReporter( name, config ) ); return reporter; } Ptr addListeners( Ptr const& config, Ptr reporters ) { IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); - for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); - it != itEnd; - ++it ) - reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + for( auto const& listener : listeners ) + reporters = addReporter(reporters, listener->create( ReporterConfig( config ) ) ); return reporters; } @@ -71,13 +67,11 @@ namespace Catch { testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); - for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); - it != itEnd; - ++it ) { - if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) - totals += context.runTest( *it ); + for( auto const& testCase : allTestCases ) { + if( !context.aborting() && matchTest( testCase, testSpec, *iconfig ) ) + totals += context.runTest( testCase ); else - reporter->skipTest( *it ); + reporter->skipTest( testCase ); } context.testGroupEnded( iconfig->name(), totals, 1, 1 ); @@ -85,12 +79,11 @@ namespace Catch { } void applyFilenamesAsTags( IConfig const& config ) { - std::vector const& tests = getAllTestCasesSorted( config ); - for(std::size_t i = 0; i < tests.size(); ++i ) { - TestCase& test = const_cast( tests[i] ); - std::set tags = test.tags; + auto& tests = const_cast&>( getAllTestCasesSorted( config ) ); + for( auto& testCase : tests ) { + std::set tags = testCase.tags; - std::string filename = test.lineInfo.file; + std::string filename = testCase.lineInfo.file; std::string::size_type lastSlash = filename.find_last_of( "\\/" ); if( lastSlash != std::string::npos ) filename = filename.substr( lastSlash+1 ); @@ -100,7 +93,7 @@ namespace Catch { filename = filename.substr( 0, lastDot ); tags.insert( "#" + filename ); - setTags( test, tags ); + setTags( testCase, tags ); } } diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index d325a089..bdf0f318 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -62,17 +62,13 @@ namespace Catch { template inline void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; + for( auto p : container ) + delete p; } template inline void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; + for( auto const& kvp : container ) + delete kvp.second; } bool startsWith( std::string const& s, std::string const& prefix ); diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 174850bf..5431cb9a 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -93,8 +93,8 @@ namespace Catch { { if( !data.testsOrTags.empty() ) { TestSpecParser parser( ITagAliasRegistry::get() ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - parser.parse( data.testsOrTags[i] ); + for( auto const& testOrTags : data.testsOrTags ) + parser.parse( testOrTags ); m_testSpec = parser.testSpec(); } } diff --git a/include/internal/catch_generators.hpp b/include/internal/catch_generators.hpp index a9ba7eb8..e02691cf 100644 --- a/include/internal/catch_generators.hpp +++ b/include/internal/catch_generators.hpp @@ -88,11 +88,9 @@ public: operator T () const { size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - typename std::vector*>::const_iterator it = m_composed.begin(); - typename std::vector*>::const_iterator itEnd = m_composed.end(); - for( size_t index = 0; it != itEnd; ++it ) + size_t index = 0; + for( auto generator : m_composed ) { - const IGenerator* generator = *it; if( overallIndex >= index && overallIndex < index + generator->size() ) { return generator->getValue( overallIndex-index ); diff --git a/include/internal/catch_generators_impl.hpp b/include/internal/catch_generators_impl.hpp index fea699ae..51eb80c4 100644 --- a/include/internal/catch_generators_impl.hpp +++ b/include/internal/catch_generators_impl.hpp @@ -62,10 +62,8 @@ namespace Catch { } bool moveNext() { - std::vector::const_iterator it = m_generatorsInOrder.begin(); - std::vector::const_iterator itEnd = m_generatorsInOrder.end(); - for(; it != itEnd; ++it ) { - if( (*it)->moveNext() ) + for( auto generator : m_generatorsInOrder ) { + if( generator->moveNext() ) return true; } return false; diff --git a/include/internal/catch_legacy_reporter_adapter.hpp b/include/internal/catch_legacy_reporter_adapter.hpp index 6034581e..17a59181 100644 --- a/include/internal/catch_legacy_reporter_adapter.hpp +++ b/include/internal/catch_legacy_reporter_adapter.hpp @@ -42,12 +42,10 @@ namespace Catch bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); - rb << it->message; + for( auto const& messageInfo : assertionStats.infoMessages ) { + if( messageInfo.type == ResultWas::Info ) { + ResultBuilder rb( messageInfo.macroName.c_str(), messageInfo.lineInfo, "", ResultDisposition::Normal ); + rb << messageInfo.message; rb.setResultType( ResultWas::Info ); AssertionResult result = rb.build(); m_legacyReporter->Result( result ); diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index e09898e9..fc1cc91a 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -35,11 +35,8 @@ namespace Catch { tagsAttr.setIndent( 6 ); std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { + for( auto const& testCaseInfo : matchedTestCases ) { matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); Colour::Code colour = testCaseInfo.isHidden() ? Colour::SecondaryText : Colour::None; @@ -63,11 +60,8 @@ namespace Catch { testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); std::size_t matchedTests = 0; std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { + for( auto const& testCaseInfo : matchedTestCases ) { matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); if( startsWith( testCaseInfo.name, '#' ) ) Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl; else @@ -84,10 +78,8 @@ namespace Catch { } std::string all() const { std::string out; - for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); - it != itEnd; - ++it ) - out += "[" + *it + "]"; + for( auto const& spelling : spellings ) + out += "[" + spelling + "]"; return out; } std::set spellings; @@ -106,29 +98,20 @@ namespace Catch { std::map tagCounts; std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), - tagItEnd = it->getTestCaseInfo().tags.end(); - tagIt != tagItEnd; - ++tagIt ) { - std::string tagName = *tagIt; + for( auto const& testCase : matchedTestCases ) { + for( auto const& tagName : testCase.getTestCaseInfo().tags ) { std::string lcaseTagName = toLower( tagName ); - std::map::iterator countIt = tagCounts.find( lcaseTagName ); + auto countIt = tagCounts.find( lcaseTagName ); if( countIt == tagCounts.end() ) countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; countIt->second.add( tagName ); } } - for( std::map::const_iterator countIt = tagCounts.begin(), - countItEnd = tagCounts.end(); - countIt != countItEnd; - ++countIt ) { + for( auto const& tagCount : tagCounts ) { std::ostringstream oss; - oss << " " << std::setw(2) << countIt->second.count << " "; - Text wrapper( countIt->second.all(), TextAttributes() + oss << " " << std::setw(2) << tagCount.second.count << " "; + Text wrapper( tagCount.second.all(), TextAttributes() .setInitialIndent( 0 ) .setIndent( oss.str().size() ) .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); @@ -143,18 +126,18 @@ namespace Catch { IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); + for( auto const factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) + maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() + for( auto const factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) { + Text wrapper( factoryKvp.second->getDescription(), TextAttributes() .setInitialIndent( 0 ) .setIndent( 7+maxNameLen ) .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); Catch::cout() << " " - << it->first + << factoryKvp.first << ':' - << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << std::string( maxNameLen - factoryKvp.first.size() + 2, ' ' ) << wrapper << '\n'; } Catch::cout() << std::endl; diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 2193c540..12f2333e 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -55,8 +55,8 @@ namespace Matchers { template struct MatchAllOf : MatcherBase { virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (!m_matchers[i]->match(arg)) + for( auto matcher : m_matchers ) { + if (!matcher->match(arg)) return false; } return true; @@ -65,10 +65,13 @@ namespace Matchers { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else description += " and "; - description += m_matchers[i]->toString(); + description += matcher->toString(); } description += " )"; return description; @@ -85,8 +88,8 @@ namespace Matchers { struct MatchAnyOf : MatcherBase { virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (m_matchers[i]->match(arg)) + for( auto matcher : m_matchers ) { + if (matcher->match(arg)) return true; } return false; @@ -95,10 +98,13 @@ namespace Matchers { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else description += " or "; - description += m_matchers[i]->toString(); + description += matcher->toString(); } description += " )"; return description; diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 6a48a4e0..2889013d 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -40,8 +40,8 @@ namespace Matchers { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; - for (size_t i = 0; i < m_comparator.size(); ++i) - if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) + for ( auto const& comparator : m_comparator ) + if (std::find(v.begin(), v.end(), comparator) == v.end()) return false; return true; } diff --git a/include/internal/catch_section_info.hpp b/include/internal/catch_section_info.hpp index aebbf6a5..74fe4c6b 100644 --- a/include/internal/catch_section_info.hpp +++ b/include/internal/catch_section_info.hpp @@ -60,10 +60,8 @@ namespace Catch { bool hasUntestedSections() const { if( m_state == Unknown ) return true; - for( SubSections::const_iterator it = m_subSections.begin(); - it != m_subSections.end(); - ++it) - if( (*it)->hasUntestedSections() ) + for( auto subSection : m_subSections ) + if( subSection->hasUntestedSections() ) return true; return false; } @@ -75,10 +73,8 @@ namespace Catch { } RunningSection* findOrAddSubSection( std::string const& name, bool& changed ) { - for( SubSections::const_iterator it = m_subSections.begin(); - it != m_subSections.end(); - ++it) - if( (*it)->getName() == name ) + for( auto subSection : m_subSections ) + if( subSection->getName() == name ) return *it; RunningSection* subSection = new RunningSection( this, name ); m_subSections.push_back( subSection ); diff --git a/include/internal/catch_tag_alias_registry.hpp b/include/internal/catch_tag_alias_registry.hpp index 11d9e65a..f7928a64 100644 --- a/include/internal/catch_tag_alias_registry.hpp +++ b/include/internal/catch_tag_alias_registry.hpp @@ -27,14 +27,12 @@ namespace Catch { std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { std::string expandedTestSpec = unexpandedTestSpec; - for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); - it != itEnd; - ++it ) { - std::size_t pos = expandedTestSpec.find( it->first ); + for( auto const& registryKvp : m_registry ) { + std::size_t pos = expandedTestSpec.find( registryKvp.first ); if( pos != std::string::npos ) { expandedTestSpec = expandedTestSpec.substr( 0, pos ) + - it->second.tag + - expandedTestSpec.substr( pos + it->first.size() ); + registryKvp.second.tag + + expandedTestSpec.substr( pos + registryKvp.first.size() ); } } return expandedTestSpec; diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 4aa70441..1c73699b 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -99,9 +99,9 @@ namespace Catch { testCaseInfo.lcaseTags.clear(); std::ostringstream oss; - for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { - oss << '[' << *it << ']'; - std::string lcaseTag = toLower( *it ); + for( auto const& tag : tags ) { + oss << '[' << tag << ']'; + std::string lcaseTag = toLower( tag ); testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); testCaseInfo.lcaseTags.insert( lcaseTag ); } diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 316c6c2c..ca5c9504 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -68,17 +68,15 @@ namespace Catch { void enforceNoDuplicateTestCases( std::vector const& functions ) { std::set seenFunctions; - for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); - it != itEnd; - ++it ) { - std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + for( auto const function : functions ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( function ); if( !prev.second ) { std::ostringstream ss; ss << Colour( Colour::Red ) - << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' - << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + << "\tRedefined at " << function.getTestCaseInfo().lineInfo << std::endl; throw std::runtime_error(ss.str()); } @@ -88,11 +86,9 @@ namespace Catch { std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; filtered.reserve( testCases.size() ); - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) - if( matchTest( *it, testSpec, config ) ) - filtered.push_back( *it ); + for( auto const& testCase : testCases ) + if( matchTest( testCase, testSpec, config ) ) + filtered.push_back( testCase ); return filtered; } std::vector const& getAllTestCasesSorted( IConfig const& config ) { diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index 3ec59b55..8565661a 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -64,8 +64,8 @@ namespace Catch { bool matches( TestCaseInfo const& testCase ) const { // All patterns in a filter must match for the filter to be a match - for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { - if( !(*it)->matches( testCase ) ) + for( auto const& pattern : m_patterns ) { + if( !pattern->matches( testCase ) ) return false; } return true; @@ -78,8 +78,8 @@ namespace Catch { } bool matches( TestCaseInfo const& testCase ) const { // A TestSpec matches if any filter matches - for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) - if( it->matches( testCase ) ) + for( auto const& filter : m_filters ) + if( filter.matches( testCase ) ) return true; return false; } diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.hpp index 5f181241..6d64b132 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.hpp @@ -218,12 +218,10 @@ namespace Catch { void printMessage() const { if( !messageLabel.empty() ) stream << messageLabel << ':' << '\n'; - for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); - it != itEnd; - ++it ) { + for( auto const& message : messages ) { // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; + if( printInfoMessages || message.type != ResultWas::Info ) + stream << Text( message.message, TextAttributes().setIndent(2) ) << '\n'; } } void printSourceInfo() const { @@ -331,10 +329,10 @@ namespace Catch { std::ostringstream oss; oss << count; std::string row = oss.str(); - for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { - while( it->size() < row.size() ) - *it = ' ' + *it; - while( it->size() > row.size() ) + for( auto& oldRow : rows ) { + while( oldRow.size() < row.size() ) + oldRow = ' ' + oldRow; + while( oldRow.size() > row.size() ) row = ' ' + row; } rows.push_back( row ); @@ -379,9 +377,9 @@ namespace Catch { } } void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { - for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { - std::string value = it->rows[row]; - if( it->label.empty() ) { + for( auto col : cols ) { + std::string value = col.rows[row]; + if( col.label.empty() ) { stream << label << ": "; if( value != "0" ) stream << value; @@ -390,8 +388,8 @@ namespace Catch { } else if( value != "0" ) { stream << Colour( Colour::LightGrey ) << " | "; - stream << Colour( it->colour ) - << value << ' ' << it->label; + stream << Colour( col.colour ) + << value << ' ' << col.label; } } stream << '\n'; diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index a671c68f..18e501ee 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -118,11 +118,8 @@ namespace Catch { xml.writeAttribute( "timestamp", getCurrentTimestamp() ); // Write test cases - for( TestGroupNode::ChildNodes::const_iterator - it = groupNode.children.begin(), itEnd = groupNode.children.end(); - it != itEnd; - ++it ) - writeTestCase( **it ); + for( auto const& child : groupNode.children ) + writeTestCase( *child ); xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); @@ -173,23 +170,16 @@ namespace Catch { if( !sectionNode.stdErr.empty() ) xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); } - for( SectionNode::ChildSections::const_iterator - it = sectionNode.childSections.begin(), - itEnd = sectionNode.childSections.end(); - it != itEnd; - ++it ) + for( auto const& childNode : sectionNode.childSections ) if( className.empty() ) - writeSection( name, "", **it ); + writeSection( name, "", *childNode ); else - writeSection( className, name, **it ); + writeSection( className, name, *childNode ); } void writeAssertions( SectionNode const& sectionNode ) { - for( SectionNode::Assertions::const_iterator - it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); - it != itEnd; - ++it ) - writeAssertion( *it ); + for( auto const& assertion : sectionNode.assertions ) + writeAssertion( assertion ); } void writeAssertion( AssertionStats const& stats ) { AssertionResult const& result = stats.assertionResult; @@ -229,13 +219,9 @@ namespace Catch { std::ostringstream oss; if( !result.getMessage().empty() ) oss << result.getMessage() << '\n'; - for( std::vector::const_iterator - it = stats.infoMessages.begin(), - itEnd = stats.infoMessages.end(); - it != itEnd; - ++it ) - if( it->type == ResultWas::Info ) - oss << it->message << '\n'; + for( auto const& msg : stats.infoMessages ) + if( msg.type == ResultWas::Info ) + oss << msg.message << '\n'; oss << "at " << result.getSourceInfo(); xml.writeText( oss.str(), false ); diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 0e06892f..4dcd6ec0 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -28,95 +28,71 @@ public: // IStreamingReporter } virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->noMatchingTestCases( spec ); + for( auto const& reporter : m_reporters ) + reporter->noMatchingTestCases( spec ); } virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunStarting( testRunInfo ); + for( auto const& reporter : m_reporters ) + reporter->testRunStarting( testRunInfo ); } virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupStarting( groupInfo ); + for( auto const& reporter : m_reporters ) + reporter->testGroupStarting( groupInfo ); } virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseStarting( testInfo ); + for( auto const& reporter : m_reporters ) + reporter->testCaseStarting( testInfo ); } virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionStarting( sectionInfo ); + for( auto const& reporter : m_reporters ) + reporter->sectionStarting( sectionInfo ); } virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->assertionStarting( assertionInfo ); + for( auto const& reporter : m_reporters ) + reporter->assertionStarting( assertionInfo ); } // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { bool clearBuffer = false; - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - clearBuffer |= (*it)->assertionEnded( assertionStats ); + for( auto const& reporter : m_reporters ) + clearBuffer |= reporter->assertionEnded( assertionStats ); return clearBuffer; } virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionEnded( sectionStats ); + for( auto const& reporter : m_reporters ) + reporter->sectionEnded( sectionStats ); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseEnded( testCaseStats ); + for( auto const& reporter : m_reporters ) + reporter->testCaseEnded( testCaseStats ); } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupEnded( testGroupStats ); + for( auto const& reporter : m_reporters ) + reporter->testGroupEnded( testGroupStats ); } virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunEnded( testRunStats ); + for( auto const& reporter : m_reporters ) + reporter->testRunEnded( testRunStats ); } virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->skipTest( testInfo ); + for( auto const& reporter : m_reporters ) + reporter->skipTest( testInfo ); } virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index e685a6ad..248ea3fb 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -112,12 +112,8 @@ namespace Catch { msg << " with message:"; if( assertionStats.infoMessages.size() > 1 ) msg << " with messages:"; - for( std::vector::const_iterator - it = assertionStats.infoMessages.begin(), - itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) - msg << "\n \"" << it->message << "\""; + for( auto const& messageInfo : assertionStats.infoMessages ) + msg << "\n \"" << messageInfo.message << "\""; if( result.hasExpression() ) { diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.hpp index 55c19564..546c1095 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.hpp @@ -99,15 +99,13 @@ namespace Catch { if( includeResults ) { // Print any info messages in tags. - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { + for( auto const& msg : assertionStats.infoMessages ) { + if( msg.type == ResultWas::Info ) { m_xml.scopedElement( "Info" ) - .writeText( it->message ); - } else if ( it->type == ResultWas::Warning ) { + .writeText( msg.message ); + } else if ( msg.type == ResultWas::Warning ) { m_xml.scopedElement( "Warning" ) - .writeText( it->message ); + .writeText( msg.message ); } } } From 97707afae1e51487e9062cf14826a374d6e1c4ea Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 11:09:06 +0100 Subject: [PATCH 008/398] Removed catch_type_traits from CMakeLists.txt --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 758293ca..61cdc09c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_tostring.h ${HEADER_DIR}/internal/catch_tostring.hpp ${HEADER_DIR}/internal/catch_totals.hpp - ${HEADER_DIR}/internal/catch_type_traits.hpp ${HEADER_DIR}/internal/catch_version.h ${HEADER_DIR}/internal/catch_version.hpp ${HEADER_DIR}/internal/catch_wildcard_pattern.hpp From 71df66365ead5740bef8a316d8de1b3672cb9962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 12:41:30 +0200 Subject: [PATCH 009/398] Gutted catch_compiler_capabilities All C++11 toggles are now removed. What is left is either platform specific (POSIX_SIGNALS, WINDOWS_SEH), or possibly still needed (USE_COUNTER). If current CLion is compatible with `__COUNTER__`, then we should also force `__COUNTER__` usage. Changed * CATCH_AUTO_PTR -> std::unique_ptr * CATCH_OVERRIDE -> override * CATCH_NULL -> nullptr * CATCH_NOEXCEPT -> noexcept * CATCH_NOEXCEPT_IS -> noexcept Removed * CATCH_CONFIG_CPP11_UNIQUE_PTR * CATCH_CONFIG_CPP11_SHUFFLE * CATCH_CONFIG_CPP11_TYPE_TRAITS * CATCH_CONFIG_CPP11_OVERRIDE * CATCH_CONFIG_CPP11_LONG_LONG * CATCH_CONFIG_CPP11_TUPLE * CATCH_CONFIG_CPP11_IS_ENUM * CATCH_CONFIG_CPP11_GENERATED_METHODS * CATCH_CONFIG_CPP11_NOEXCEPT * CATCH_CONFIG_CPP11_NULLPTR * CATCH_CONFIG_VARIADIC_MACROS --- include/catch.hpp | 50 +---- include/internal/catch_assertionresult.h | 17 +- include/internal/catch_assertionresult.hpp | 2 +- include/internal/catch_capture.hpp | 10 - include/internal/catch_common.h | 9 +- .../internal/catch_compiler_capabilities.h | 173 +----------------- include/internal/catch_config.hpp | 30 +-- include/internal/catch_context_impl.hpp | 8 +- include/internal/catch_debugger.hpp | 2 +- include/internal/catch_expression_lhs.hpp | 10 +- include/internal/catch_fatal_condition.hpp | 10 +- include/internal/catch_impl.hpp | 10 +- include/internal/catch_interfaces_exception.h | 2 +- include/internal/catch_interfaces_reporter.h | 18 +- include/internal/catch_matchers.hpp | 12 +- include/internal/catch_matchers_string.h | 10 +- include/internal/catch_matchers_vector.h | 12 +- .../internal/catch_notimplemented_exception.h | 4 +- .../catch_notimplemented_exception.hpp | 2 +- include/internal/catch_objc.hpp | 14 +- include/internal/catch_option.hpp | 14 +- include/internal/catch_ptr.hpp | 8 +- include/internal/catch_registry_hub.hpp | 22 +-- include/internal/catch_reporter_registry.hpp | 10 +- include/internal/catch_result_builder.h | 2 +- include/internal/catch_run_context.hpp | 6 +- include/internal/catch_section.h | 5 - include/internal/catch_section_info.hpp | 2 +- include/internal/catch_stream.h | 16 +- include/internal/catch_stream.hpp | 2 +- include/internal/catch_streambuf.h | 2 +- .../catch_test_case_registry_impl.hpp | 6 - include/internal/catch_test_case_tracker.hpp | 48 ++--- include/internal/catch_test_registry.hpp | 39 ---- include/internal/catch_timer.hpp | 2 +- include/internal/catch_xmlwriter.hpp | 2 +- include/reporters/catch_reporter_automake.hpp | 8 +- include/reporters/catch_reporter_bases.hpp | 52 +++--- include/reporters/catch_reporter_compact.hpp | 2 +- include/reporters/catch_reporter_console.hpp | 24 +-- include/reporters/catch_reporter_junit.hpp | 18 +- include/reporters/catch_reporter_multi.hpp | 28 +-- include/reporters/catch_reporter_teamcity.hpp | 20 +- include/reporters/catch_reporter_xml.hpp | 24 +-- projects/SelfTest/ApproxTests.cpp | 2 - projects/SelfTest/CmdLineTests.cpp | 2 +- projects/SelfTest/ConditionTests.cpp | 22 +-- projects/SelfTest/ExceptionTests.cpp | 2 +- projects/SelfTest/MessageTests.cpp | 2 - projects/SelfTest/MiscTests.cpp | 8 +- projects/SelfTest/TestMain.cpp | 2 +- projects/SelfTest/TrickyTests.cpp | 2 +- projects/SelfTest/VariadicMacrosTests.cpp | 2 - 53 files changed, 261 insertions(+), 550 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index bf0d72d6..2182ba8c 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -130,25 +130,15 @@ LeakDetector leakDetector; #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) - #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) +#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) +#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) @@ -157,13 +147,8 @@ LeakDetector leakDetector; #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) // "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) @@ -213,7 +198,6 @@ LeakDetector leakDetector; #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) @@ -222,16 +206,6 @@ LeakDetector leakDetector; #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else -#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) @@ -244,13 +218,9 @@ LeakDetector leakDetector; #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) // "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif + #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index a193c556..c729e8d0 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -53,7 +53,7 @@ namespace Catch { struct AssertionResultData { - AssertionResultData() : decomposedExpression( CATCH_NULL ) + AssertionResultData() : decomposedExpression( nullptr ) , resultType( ResultWas::Unknown ) , negated( false ) , parenthesized( false ) {} @@ -68,7 +68,7 @@ namespace Catch { } std::string const& reconstructExpression() const { - if( decomposedExpression != CATCH_NULL ) { + if( decomposedExpression != nullptr ) { decomposedExpression->reconstructExpression( reconstructedExpression ); if( parenthesized ) { reconstructedExpression.insert( 0, 1, '(' ); @@ -77,7 +77,7 @@ namespace Catch { if( negated ) { reconstructedExpression.insert( 0, 1, '!' ); } - decomposedExpression = CATCH_NULL; + decomposedExpression = nullptr; } return reconstructedExpression; } @@ -95,12 +95,11 @@ namespace Catch { AssertionResult(); AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); ~AssertionResult(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionResult( AssertionResult const& ) = default; - AssertionResult( AssertionResult && ) = default; - AssertionResult& operator = ( AssertionResult const& ) = default; - AssertionResult& operator = ( AssertionResult && ) = default; -# endif + + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; bool isOk() const; bool succeeded() const; diff --git a/include/internal/catch_assertionresult.hpp b/include/internal/catch_assertionresult.hpp index 9b637028..bbabaf1f 100644 --- a/include/internal/catch_assertionresult.hpp +++ b/include/internal/catch_assertionresult.hpp @@ -87,7 +87,7 @@ namespace Catch { } void AssertionResult::discardDecomposedExpression() const { - m_resultData.decomposedExpression = CATCH_NULL; + m_resultData.decomposedExpression = nullptr; } void AssertionResult::expandDecomposedExpression() const { diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 58993718..ee3dd598 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -143,7 +143,6 @@ /////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ @@ -151,15 +150,6 @@ __catchResult.captureResult( messageType ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) -#else - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << log + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#endif /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index bdf0f318..c207d8e8 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -34,15 +34,10 @@ namespace Catch { }; }; class NonCopyable { -#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete; -#else - NonCopyable( NonCopyable const& info ); - NonCopyable& operator = ( NonCopyable const& ); -#endif protected: NonCopyable() {} @@ -94,12 +89,12 @@ namespace Catch { SourceLineInfo(); SourceLineInfo( char const* _file, std::size_t _line ); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS + SourceLineInfo(SourceLineInfo const& other) = default; SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; -# endif + bool empty() const; bool operator == ( SourceLineInfo const& other ) const; bool operator < ( SourceLineInfo const& other ) const; diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index ac6f259d..9684cf8f 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -8,23 +8,9 @@ #ifndef TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler +// Detect a number of compiler features - by compiler // The following features are defined: // -// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? -// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported -// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? -// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? -// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) -// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? -// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? - -// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? @@ -34,18 +20,13 @@ // **************** // In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. -// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 #ifdef __cplusplus -# if __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER -# endif - # if __cplusplus >= 201402L # define CATCH_CPP14_OR_GREATER # endif @@ -54,15 +35,7 @@ #ifdef __clang__ -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# if defined(CATCH_CPP11_OR_GREATER) # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) @@ -74,7 +47,6 @@ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic pop" ) -# endif #endif // __clang__ @@ -125,14 +97,6 @@ // GCC #ifdef __GNUC__ -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - #endif // __GNUC__ @@ -142,32 +106,10 @@ #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -#endif - #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS - -#endif - // Use __COUNTER__ if the compiler supports it #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ @@ -177,95 +119,15 @@ #endif -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(CATCH_CPP11_OR_GREATER) - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# endif - -# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) -# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) -# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) -# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) -# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -# endif - -#endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NULLPTR -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_IS_ENUM -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TUPLE -#endif -#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -# define CATCH_CONFIG_VARIADIC_MACROS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_LONG_LONG -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_UNIQUE_PTR -#endif + // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for // analytics) because, at time of writing, __COUNTER__ is not properly handled by it. // This does not affect compilation #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) # define CATCH_CONFIG_COUNTER #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_SHUFFLE -#endif -# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TYPE_TRAITS -# endif #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif @@ -283,35 +145,6 @@ # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #endif -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL -#endif - -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override -#else -# define CATCH_OVERRIDE -#endif - -// unique_ptr support -#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR -# define CATCH_AUTO_PTR( T ) std::unique_ptr -#else -# define CATCH_AUTO_PTR( T ) std::auto_ptr -#endif #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 5431cb9a..64141e7f 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -113,25 +113,25 @@ namespace Catch { std::string getProcessName() const { return m_data.processName; } std::vector const& getReporterNames() const { return m_data.reporterNames; } - std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } + std::vector const& getSectionsToRun() const override { return m_data.sectionsToRun; } - virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } + virtual TestSpec const& testSpec() const override { return m_testSpec; } bool showHelp() const { return m_data.showHelp; } // IConfig interface - virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } - virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } - virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } - virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } - virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } - virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } - virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } + virtual bool allowThrows() const override { return !m_data.noThrow; } + virtual std::ostream& stream() const override { return m_stream->stream(); } + virtual std::string name() const override { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const override { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const override { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const override { return m_data.showDurations; } + virtual RunTests::InWhatOrder runOrder() const override { return m_data.runOrder; } + virtual unsigned int rngSeed() const override { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const override { return m_data.useColour; } + virtual bool shouldDebugBreak() const override { return m_data.shouldDebugBreak; } + virtual int abortAfter() const override { return m_data.abortAfter; } + virtual bool showInvisibles() const override { return m_data.showInvisibles; } private: @@ -149,7 +149,7 @@ namespace Catch { } ConfigData m_data; - CATCH_AUTO_PTR( IStream const ) m_stream; + std::unique_ptr m_stream; TestSpec m_testSpec; }; diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index 8516ad93..84f1ca1c 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -18,7 +18,7 @@ namespace Catch { class Context : public IMutableContext { - Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} + Context() : m_config( nullptr ), m_runner( nullptr ), m_resultCapture( nullptr ) {} Context( Context const& ); void operator=( Context const& ); @@ -69,7 +69,7 @@ namespace Catch { m_generatorsByTestName.find( testName ); return it != m_generatorsByTestName.end() ? it->second - : CATCH_NULL; + : nullptr; } IGeneratorsForTest& getGeneratorsForCurrentTest() { @@ -90,7 +90,7 @@ namespace Catch { }; namespace { - Context* currentContext = CATCH_NULL; + Context* currentContext = nullptr; } IMutableContext& getCurrentMutableContext() { if( !currentContext ) @@ -103,7 +103,7 @@ namespace Catch { void cleanUpContext() { delete currentContext; - currentContext = CATCH_NULL; + currentContext = nullptr; } } diff --git a/include/internal/catch_debugger.hpp b/include/internal/catch_debugger.hpp index 00017d16..2048904a 100644 --- a/include/internal/catch_debugger.hpp +++ b/include/internal/catch_debugger.hpp @@ -49,7 +49,7 @@ // Call sysctl. size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 106a6b0a..8cf41409 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -80,7 +80,7 @@ public: .endExpression( *this ); } - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { + virtual void reconstructExpression( std::string& dest ) const override { dest = Catch::toString( m_truthy ); } @@ -115,11 +115,11 @@ public: .endExpression( *this ); } - virtual bool isBinaryExpression() const CATCH_OVERRIDE { + virtual bool isBinaryExpression() const override { return true; } - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { + virtual void reconstructExpression( std::string& dest ) const override { std::string lhs = Catch::toString( m_lhs ); std::string rhs = Catch::toString( m_rhs ); char delim = lhs.size() + rhs.size() < 40 && @@ -149,11 +149,11 @@ public: MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} - virtual bool isBinaryExpression() const CATCH_OVERRIDE { + virtual bool isBinaryExpression() const override { return true; } - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { + virtual void reconstructExpression( std::string& dest ) const override { std::string matcherAsString = m_matcher.toString(); dest = Catch::toString( m_arg ); dest += ' '; diff --git a/include/internal/catch_fatal_condition.hpp b/include/internal/catch_fatal_condition.hpp index 1d6674fc..810d9e0f 100644 --- a/include/internal/catch_fatal_condition.hpp +++ b/include/internal/catch_fatal_condition.hpp @@ -66,7 +66,7 @@ namespace Catch { // 32k seems enough for Catch to handle stack overflow, // but the value was found experimentally, so there is no strong guarantee guaranteeSize = 32 * 1024; - exceptionHandlerHandle = CATCH_NULL; + exceptionHandlerHandle = nullptr; // Register as first handler in current chain exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); // Pass in guarantee size to be filled @@ -78,7 +78,7 @@ namespace Catch { // Unregister handler and restore the old guarantee RemoveVectoredExceptionHandler(exceptionHandlerHandle); SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = CATCH_NULL; + exceptionHandlerHandle = nullptr; isSet = false; } } @@ -94,7 +94,7 @@ namespace Catch { bool FatalConditionHandler::isSet = false; ULONG FatalConditionHandler::guaranteeSize = 0; - PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; + PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; } // namespace Catch @@ -176,10 +176,10 @@ namespace Catch { if( isSet ) { // Set signals back to previous values -- hopefully nobody overwrote them in the meantime for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); } // Return the old stack - sigaltstack(&oldSigStack, CATCH_NULL); + sigaltstack(&oldSigStack, nullptr); isSet = false; } } diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 85cf266f..e28a8902 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -49,11 +49,11 @@ namespace Catch { // virtual methods NonCopyable::~NonCopyable() {} IShared::~IShared() {} - IStream::~IStream() CATCH_NOEXCEPT {} - FileStream::~FileStream() CATCH_NOEXCEPT {} - CoutStream::~CoutStream() CATCH_NOEXCEPT {} - DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} - StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IStream::~IStream() noexcept {} + FileStream::~FileStream() noexcept {} + CoutStream::~CoutStream() noexcept {} + DebugOutStream::~DebugOutStream() noexcept {} + StreamBufBase::~StreamBufBase() noexcept {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} ITestCase::~ITestCase() {} diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index bf29b715..6387ba9d 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -40,7 +40,7 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { try { if( it == itEnd ) throw; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 6c47d8e4..a1c5aa57 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -100,12 +100,10 @@ namespace Catch } virtual ~AssertionStats(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats && ) = default; -# endif AssertionResult assertionResult; std::vector infoMessages; @@ -123,12 +121,10 @@ namespace Catch missingAssertions( _missingAssertions ) {} virtual ~SectionStats(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SectionStats( SectionStats const& ) = default; SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats && ) = default; -# endif SectionInfo sectionInfo; Counts assertions; @@ -150,12 +146,10 @@ namespace Catch {} virtual ~TestCaseStats(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats && ) = default; -# endif TestCaseInfo testInfo; Totals totals; @@ -178,12 +172,10 @@ namespace Catch {} virtual ~TestGroupStats(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats && ) = default; -# endif GroupInfo groupInfo; Totals totals; @@ -200,18 +192,10 @@ namespace Catch {} virtual ~TestRunStats(); -# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestRunStats( TestRunStats const& _other ) - : runInfo( _other.runInfo ), - totals( _other.totals ), - aborting( _other.aborting ) - {} -# else TestRunStats( TestRunStats const& ) = default; TestRunStats( TestRunStats && ) = default; TestRunStats& operator = ( TestRunStats const& ) = default; TestRunStats& operator = ( TestRunStats && ) = default; -# endif TestRunInfo runInfo; Totals totals; @@ -248,7 +232,7 @@ namespace Catch virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } + virtual MultipleReporters* tryAsMulti() { return nullptr; } }; diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 12f2333e..21445347 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -54,14 +54,14 @@ namespace Matchers { template struct MatchAllOf : MatcherBase { - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { + virtual bool match( ArgT const& arg ) const override { for( auto matcher : m_matchers ) { if (!matcher->match(arg)) return false; } return true; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; @@ -87,14 +87,14 @@ namespace Matchers { template struct MatchAnyOf : MatcherBase { - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { + virtual bool match( ArgT const& arg ) const override { for( auto matcher : m_matchers ) { if (matcher->match(arg)) return true; } return false; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; @@ -123,11 +123,11 @@ namespace Matchers { MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { + virtual bool match( ArgT const& arg ) const override { return !m_underlyingMatcher.match( arg ); } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "not " + m_underlyingMatcher.toString(); } MatcherBase const& m_underlyingMatcher; diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index 69dabcb5..e3772cbf 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -27,7 +27,7 @@ namespace Matchers { struct StringMatcherBase : MatcherBase { StringMatcherBase( std::string const& operation, CasedString const& comparator ); - virtual std::string describe() const CATCH_OVERRIDE; + virtual std::string describe() const override; CasedString m_comparator; std::string m_operation; @@ -35,19 +35,19 @@ namespace Matchers { struct EqualsMatcher : StringMatcherBase { EqualsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + virtual bool match( std::string const& source ) const override; }; struct ContainsMatcher : StringMatcherBase { ContainsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + virtual bool match( std::string const& source ) const override; }; struct StartsWithMatcher : StringMatcherBase { StartsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + virtual bool match( std::string const& source ) const override; }; struct EndsWithMatcher : StringMatcherBase { EndsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; + virtual bool match( std::string const& source ) const override; }; } // namespace StdString diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 2889013d..11aee020 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -20,11 +20,11 @@ namespace Matchers { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} - bool match(std::vector const &v) const CATCH_OVERRIDE { + bool match(std::vector const &v) const override { return std::find(v.begin(), v.end(), m_comparator) != v.end(); } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "Contains: " + Catch::toString( m_comparator ); } @@ -36,7 +36,7 @@ namespace Matchers { ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const CATCH_OVERRIDE { + bool match(std::vector const &v) const override { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; @@ -45,7 +45,7 @@ namespace Matchers { return false; return true; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "Contains: " + Catch::toString( m_comparator ); } @@ -57,7 +57,7 @@ namespace Matchers { EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const CATCH_OVERRIDE { + bool match(std::vector const &v) const override { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector etc @@ -69,7 +69,7 @@ namespace Matchers { return false; return true; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "Equals: " + Catch::toString( m_comparator ); } std::vector const& m_comparator; diff --git a/include/internal/catch_notimplemented_exception.h b/include/internal/catch_notimplemented_exception.h index 128fff28..30a60cad 100644 --- a/include/internal/catch_notimplemented_exception.h +++ b/include/internal/catch_notimplemented_exception.h @@ -18,9 +18,9 @@ namespace Catch { NotImplementedException( SourceLineInfo const& lineInfo ); NotImplementedException( NotImplementedException const& ) {} - virtual ~NotImplementedException() CATCH_NOEXCEPT {} + virtual ~NotImplementedException() noexcept {} - virtual const char* what() const CATCH_NOEXCEPT; + virtual const char* what() const noexcept; private: std::string m_what; diff --git a/include/internal/catch_notimplemented_exception.hpp b/include/internal/catch_notimplemented_exception.hpp index e4afdc67..f5b1ea66 100644 --- a/include/internal/catch_notimplemented_exception.hpp +++ b/include/internal/catch_notimplemented_exception.hpp @@ -21,7 +21,7 @@ namespace Catch { m_what = oss.str(); } - const char* NotImplementedException::what() const CATCH_NOEXCEPT { + const char* NotImplementedException::what() const noexcept { return m_what.c_str(); } diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 616383b1..baded73e 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -72,7 +72,7 @@ namespace Catch { inline size_t registerTestMethods() { size_t noTestMethods = 0; - int noClasses = objc_getClassList( CATCH_NULL, 0 ); + int noClasses = objc_getClassList( nullptr, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); @@ -112,7 +112,7 @@ namespace Catch { arcSafeRelease( m_substr ); } - virtual bool match( NSString* arg ) const CATCH_OVERRIDE { + virtual bool match( NSString* arg ) const override { return false; } @@ -122,12 +122,12 @@ namespace Catch { struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const CATCH_OVERRIDE { + virtual bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "equals string: " + Catch::toString( m_substr ); } }; @@ -140,7 +140,7 @@ namespace Catch { [str rangeOfString:m_substr].location != NSNotFound; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "contains string: " + Catch::toString( m_substr ); } }; @@ -153,7 +153,7 @@ namespace Catch { [str rangeOfString:m_substr].location == 0; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "starts with: " + Catch::toString( m_substr ); } }; @@ -165,7 +165,7 @@ namespace Catch { [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } - virtual std::string describe() const CATCH_OVERRIDE { + virtual std::string describe() const override { return "ends with: " + Catch::toString( m_substr ); } }; diff --git a/include/internal/catch_option.hpp b/include/internal/catch_option.hpp index 909e5cec..c9c3c165 100644 --- a/include/internal/catch_option.hpp +++ b/include/internal/catch_option.hpp @@ -16,12 +16,12 @@ namespace Catch { template class Option { public: - Option() : nullableValue( CATCH_NULL ) {} + Option() : nullableValue( nullptr ) {} Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) {} Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) + : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) {} ~Option() { @@ -45,7 +45,7 @@ namespace Catch { void reset() { if( nullableValue ) nullableValue->~T(); - nullableValue = CATCH_NULL; + nullableValue = nullptr; } T& operator*() { return *nullableValue; } @@ -57,10 +57,10 @@ namespace Catch { return nullableValue ? *nullableValue : defaultValue; } - bool some() const { return nullableValue != CATCH_NULL; } - bool none() const { return nullableValue == CATCH_NULL; } + bool some() const { return nullableValue != nullptr; } + bool none() const { return nullableValue == nullptr; } - bool operator !() const { return nullableValue == CATCH_NULL; } + bool operator !() const { return nullableValue == nullptr; } operator SafeBool::type() const { return SafeBool::makeSafe( some() ); } @@ -74,9 +74,7 @@ namespace Catch { long double dummy1; void (*dummy2)(); long double dummy3; -#ifdef CATCH_CONFIG_CPP11_LONG_LONG long long dummy4; -#endif }; }; diff --git a/include/internal/catch_ptr.hpp b/include/internal/catch_ptr.hpp index 940e5d19..5da73aa1 100644 --- a/include/internal/catch_ptr.hpp +++ b/include/internal/catch_ptr.hpp @@ -23,7 +23,7 @@ namespace Catch { template class Ptr { public: - Ptr() : m_p( CATCH_NULL ){} + Ptr() : m_p( nullptr ){} Ptr( T* p ) : m_p( p ){ if( m_p ) m_p->addRef(); @@ -39,7 +39,7 @@ namespace Catch { void reset() { if( m_p ) m_p->release(); - m_p = CATCH_NULL; + m_p = nullptr; } Ptr& operator = ( T* p ){ Ptr temp( p ); @@ -55,8 +55,8 @@ namespace Catch { T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } - bool operator !() const { return m_p == CATCH_NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } + bool operator !() const { return m_p == nullptr; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != nullptr ); } private: T* m_p; diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index 2523cd9d..b9e42b72 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -27,34 +27,34 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { + virtual IReporterRegistry const& getReporterRegistry() const override { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { + virtual ITestCaseRegistry const& getTestCaseRegistry() const override { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { return m_exceptionTranslatorRegistry; } - virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { + virtual ITagAliasRegistry const& getTagAliasRegistry() const override { return m_tagAliasRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { + virtual void registerReporter( std::string const& name, Ptr const& factory ) override { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { + virtual void registerListener( Ptr const& factory ) override { m_reporterRegistry.registerListener( factory ); } - virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { + virtual void registerTest( TestCase const& testInfo ) override { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { + virtual void registerTranslator( const IExceptionTranslator* translator ) override { m_exceptionTranslatorRegistry.registerTranslator( translator ); } - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { + virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { m_tagAliasRegistry.add( alias, tag, lineInfo ); } @@ -67,7 +67,7 @@ namespace Catch { // Single, global, instance inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = CATCH_NULL; + static RegistryHub* theRegistryHub = nullptr; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); return theRegistryHub; @@ -82,7 +82,7 @@ namespace Catch { } void cleanUp() { delete getTheRegistryHub(); - getTheRegistryHub() = CATCH_NULL; + getTheRegistryHub() = nullptr; cleanUpContext(); } std::string translateActiveException() { diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index 71f23ff7..7a0c783a 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -18,12 +18,12 @@ namespace Catch { public: - virtual ~ReporterRegistry() CATCH_OVERRIDE {} + virtual ~ReporterRegistry() override {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const override { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) - return CATCH_NULL; + return nullptr; return it->second->create( ReporterConfig( config ) ); } @@ -34,10 +34,10 @@ namespace Catch { m_listeners.push_back( factory ); } - virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { + virtual FactoryMap const& getFactories() const override { return m_factories; } - virtual Listeners const& getListeners() const CATCH_OVERRIDE { + virtual Listeners const& getListeners() const override { return m_listeners; } diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 82494566..a2cf596d 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -56,7 +56,7 @@ namespace Catch { void endExpression( DecomposedExpression const& expr ); - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; + virtual void reconstructExpression( std::string& dest ) const override; AssertionResult build() const; AssertionResult build( DecomposedExpression const& expr ) const; diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index e6dbd38c..12435cdc 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -62,7 +62,7 @@ namespace Catch { explicit RunContext( Ptr const& _config, Ptr const& reporter ) : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), - m_activeTestCase( CATCH_NULL ), + m_activeTestCase( nullptr ), m_config( _config ), m_reporter( reporter ), m_shouldReportUnexpected ( true ) @@ -124,8 +124,8 @@ namespace Catch { redirectedCerr, aborting() ) ); - m_activeTestCase = CATCH_NULL; - m_testCaseTracker = CATCH_NULL; + m_activeTestCase = nullptr; + m_testCaseTracker = nullptr; return deltaTotals; } diff --git a/include/internal/catch_section.h b/include/internal/catch_section.h index d8b3ae42..2667b74e 100644 --- a/include/internal/catch_section.h +++ b/include/internal/catch_section.h @@ -35,12 +35,7 @@ namespace Catch { } // end namespace Catch -#ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_SECTION( ... ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif #endif // TWOBLUECUBES_CATCH_SECTION_H_INCLUDED diff --git a/include/internal/catch_section_info.hpp b/include/internal/catch_section_info.hpp index 74fe4c6b..b1ce0ba8 100644 --- a/include/internal/catch_section_info.hpp +++ b/include/internal/catch_section_info.hpp @@ -33,7 +33,7 @@ namespace Catch { RunningSection( std::string const& name ) : m_state( Root ), - m_parent( CATCH_NULL ), + m_parent( nullptr ), m_name( name ) {} diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index d8deebab..73aa9ace 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -24,7 +24,7 @@ namespace Catch { struct IStream { - virtual ~IStream() CATCH_NOEXCEPT; + virtual ~IStream() noexcept; virtual std::ostream& stream() const = 0; }; @@ -32,9 +32,9 @@ namespace Catch { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); - virtual ~FileStream() CATCH_NOEXCEPT; + virtual ~FileStream() noexcept; public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; + virtual std::ostream& stream() const override; }; @@ -42,22 +42,22 @@ namespace Catch { mutable std::ostream m_os; public: CoutStream(); - virtual ~CoutStream() CATCH_NOEXCEPT; + virtual ~CoutStream() noexcept; public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; + virtual std::ostream& stream() const override; }; class DebugOutStream : public IStream { - CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; + std::unique_ptr m_streamBuf; mutable std::ostream m_os; public: DebugOutStream(); - virtual ~DebugOutStream() CATCH_NOEXCEPT; + virtual ~DebugOutStream() noexcept; public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; + virtual std::ostream& stream() const override; }; } diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index 42f51e82..cc6c38a1 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -28,7 +28,7 @@ namespace Catch { setp( data, data + sizeof(data) ); } - ~StreamBufImpl() CATCH_NOEXCEPT { + ~StreamBufImpl() noexcept { sync(); } diff --git a/include/internal/catch_streambuf.h b/include/internal/catch_streambuf.h index 4f5e238c..dba84357 100644 --- a/include/internal/catch_streambuf.h +++ b/include/internal/catch_streambuf.h @@ -16,7 +16,7 @@ namespace Catch { class StreamBufBase : public std::streambuf { public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; + virtual ~StreamBufBase() noexcept; }; } diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index ca5c9504..5900d6f0 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -26,19 +26,13 @@ namespace Catch { result_type operator()( result_type n ) const { return std::rand() % n; } -#ifdef CATCH_CONFIG_CPP11_SHUFFLE static constexpr result_type min() { return 0; } static constexpr result_type max() { return 1000000; } result_type operator()() const { return std::rand() % max(); } -#endif template static void shuffle( V& vector ) { RandomNumberGenerator rng; -#ifdef CATCH_CONFIG_CPP11_SHUFFLE std::shuffle( vector.begin(), vector.end(), rng ); -#else - std::random_shuffle( vector.begin(), vector.end(), rng ); -#endif } }; diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 705f92ab..6654734f 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -80,7 +80,7 @@ namespace TestCaseTracking { } TrackerContext() - : m_currentTracker( CATCH_NULL ), + : m_currentTracker( nullptr ), m_runState( NotStarted ) {} @@ -89,7 +89,7 @@ namespace TestCaseTracking { void endRun() { m_rootTracker.reset(); - m_currentTracker = CATCH_NULL; + m_currentTracker = nullptr; m_runState = NotStarted; } @@ -147,39 +147,39 @@ namespace TestCaseTracking { {} virtual ~TrackerBase(); - virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { + virtual NameAndLocation const& nameAndLocation() const override { return m_nameAndLocation; } - virtual bool isComplete() const CATCH_OVERRIDE { + virtual bool isComplete() const override { return m_runState == CompletedSuccessfully || m_runState == Failed; } - virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + virtual bool isSuccessfullyCompleted() const override { return m_runState == CompletedSuccessfully; } - virtual bool isOpen() const CATCH_OVERRIDE { + virtual bool isOpen() const override { return m_runState != NotStarted && !isComplete(); } - virtual bool hasChildren() const CATCH_OVERRIDE { + virtual bool hasChildren() const override { return !m_children.empty(); } - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + virtual void addChild( Ptr const& child ) override { m_children.push_back( child ); } - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { + virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) override { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); return( it != m_children.end() ) ? it->get() - : CATCH_NULL; + : nullptr; } - virtual ITracker& parent() CATCH_OVERRIDE { + virtual ITracker& parent() override { assert( m_parent ); // Should always be non-null except for root return *m_parent; } - virtual void openChild() CATCH_OVERRIDE { + virtual void openChild() override { if( m_runState != ExecutingChildren ) { m_runState = ExecutingChildren; if( m_parent ) @@ -187,8 +187,8 @@ namespace TestCaseTracking { } } - virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } - virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + virtual bool isSectionTracker() const override { return false; } + virtual bool isIndexTracker() const override { return false; } void open() { m_runState = Executing; @@ -197,7 +197,7 @@ namespace TestCaseTracking { m_parent->openChild(); } - virtual void close() CATCH_OVERRIDE { + virtual void close() override { // Close any still open children (e.g. generators) while( &m_ctx.currentTracker() != this ) @@ -226,14 +226,14 @@ namespace TestCaseTracking { moveToParent(); m_ctx.completeCycle(); } - virtual void fail() CATCH_OVERRIDE { + virtual void fail() override { m_runState = Failed; if( m_parent ) m_parent->markAsNeedingAnotherRun(); moveToParent(); m_ctx.completeCycle(); } - virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + virtual void markAsNeedingAnotherRun() override { m_runState = NeedsAnotherRun; } private: @@ -262,10 +262,10 @@ namespace TestCaseTracking { } virtual ~SectionTracker(); - virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + virtual bool isSectionTracker() const override { return true; } static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - SectionTracker* section = CATCH_NULL; + SectionTracker* section = nullptr; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { @@ -311,10 +311,10 @@ namespace TestCaseTracking { {} virtual ~IndexTracker(); - virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + virtual bool isIndexTracker() const override { return true; } static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - IndexTracker* tracker = CATCH_NULL; + IndexTracker* tracker = nullptr; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { @@ -343,7 +343,7 @@ namespace TestCaseTracking { m_children.clear(); } - virtual void close() CATCH_OVERRIDE { + virtual void close() override { TrackerBase::close(); if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) m_runState = Executing; @@ -351,8 +351,8 @@ namespace TestCaseTracking { }; inline ITracker& TrackerContext::startRun() { - m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); - m_currentTracker = CATCH_NULL; + m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); + m_currentTracker = nullptr; m_runState = Executing; return *m_rootTracker; } diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index 075ad1c6..b6d423c8 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -83,7 +83,6 @@ void registerTestCaseFunction } // end namespace Catch -#ifdef CATCH_CONFIG_VARIADIC_MACROS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ @@ -120,43 +119,5 @@ void registerTestCaseFunction Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ - static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ \ - struct TestCaseName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ - } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - void TestCaseName::test() - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -#endif #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_timer.hpp b/include/internal/catch_timer.hpp index dfb7811f..d8bcfce9 100644 --- a/include/internal/catch_timer.hpp +++ b/include/internal/catch_timer.hpp @@ -41,7 +41,7 @@ namespace Catch { #else uint64_t getCurrentTicks() { timeval t; - gettimeofday(&t,CATCH_NULL); + gettimeofday(&t,nullptr); return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); } #endif diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index ae59627c..b39a2fd7 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -89,7 +89,7 @@ namespace Catch { ScopedElement( ScopedElement const& other ) : m_writer( other.m_writer ){ - other.m_writer = CATCH_NULL; + other.m_writer = nullptr; } ~ScopedElement() { diff --git a/include/reporters/catch_reporter_automake.hpp b/include/reporters/catch_reporter_automake.hpp index c267d8a9..00478e1f 100644 --- a/include/reporters/catch_reporter_automake.hpp +++ b/include/reporters/catch_reporter_automake.hpp @@ -27,11 +27,11 @@ namespace Catch { return "Reports test results in the format of Automake .trs files"; } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& /*_assertionStats*/ ) CATCH_OVERRIDE { return true; } + virtual bool assertionEnded( AssertionStats const& /*_assertionStats*/ ) override { return true; } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) override { // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR. stream << ":test-result: "; if (_testCaseStats.totals.assertions.allPassed()) { @@ -45,7 +45,7 @@ namespace Catch { StreamingReporterBase::testCaseEnded( _testCaseStats ); } - virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + virtual void skipTest( TestCaseInfo const& testInfo ) override { stream << ":test-result: SKIP " << testInfo.name << '\n'; } diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index aca5f355..d94c15b4 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -50,44 +50,44 @@ namespace Catch { m_reporterPrefs.shouldRedirectStdOut = false; } - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + virtual ReporterPreferences getPreferences() const override { return m_reporterPrefs; } - virtual ~StreamingReporterBase() CATCH_OVERRIDE; + virtual ~StreamingReporterBase() override; - virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + virtual void noMatchingTestCases( std::string const& ) override {} - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) override { currentTestRunInfo = _testRunInfo; } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { + virtual void testGroupStarting( GroupInfo const& _groupInfo ) override { currentGroupInfo = _groupInfo; } - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) override { currentTestCaseInfo = _testInfo; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) override { m_sectionStack.push_back( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) override { m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) override { currentTestCaseInfo.reset(); } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) override { currentGroupInfo.reset(); } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) override { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { + virtual void skipTest( TestCaseInfo const& ) override { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } @@ -157,16 +157,16 @@ namespace Catch { } ~CumulativeReporterBase(); - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + virtual ReporterPreferences getPreferences() const override { return m_reporterPrefs; } - virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} - virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} + virtual void testRunStarting( TestRunInfo const& ) override {} + virtual void testGroupStarting( GroupInfo const& ) override {} - virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + virtual void testCaseStarting( TestCaseInfo const& ) override {} - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + virtual void sectionStarting( SectionInfo const& sectionInfo ) override { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); Ptr node; if( m_sectionStack.empty() ) { @@ -191,9 +191,9 @@ namespace Catch { m_deepestSection = node; } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& assertionStats ) override { assert( !m_sectionStack.empty() ); SectionNode& sectionNode = *m_sectionStack.back(); sectionNode.assertions.push_back( assertionStats ); @@ -205,13 +205,13 @@ namespace Catch { prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + virtual void sectionEnded( SectionStats const& sectionStats ) override { assert( !m_sectionStack.empty() ); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { Ptr node = new TestCaseNode( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); @@ -222,12 +222,12 @@ namespace Catch { m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { Ptr node = new TestGroupNode( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + virtual void testRunEnded( TestRunStats const& testRunStats ) override { Ptr node = new TestRunNode( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); @@ -235,7 +235,7 @@ namespace Catch { } virtual void testRunEndedCumulative() = 0; - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} + virtual void skipTest( TestCaseInfo const& ) override {} virtual void prepareExpandedExpression( AssertionResult& result ) const { if( result.isOk() ) @@ -276,8 +276,8 @@ namespace Catch { : StreamingReporterBase( _config ) {} - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { + virtual void assertionStarting( AssertionInfo const& ) override {} + virtual bool assertionEnded( AssertionStats const& ) override { return false; } }; diff --git a/include/reporters/catch_reporter_compact.hpp b/include/reporters/catch_reporter_compact.hpp index 8d6f9085..3987d37c 100644 --- a/include/reporters/catch_reporter_compact.hpp +++ b/include/reporters/catch_reporter_compact.hpp @@ -58,7 +58,7 @@ namespace Catch { return true; } - virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { + virtual void sectionEnded(SectionStats const& _sectionStats) override { if (m_config->showDurations() == ShowDurations::Always) { stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.hpp index 6d64b132..29951fcf 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.hpp @@ -25,19 +25,19 @@ namespace Catch { m_headerPrinted( false ) {} - virtual ~ConsoleReporter() CATCH_OVERRIDE; + virtual ~ConsoleReporter() override; static std::string getDescription() { return "Reports test results as plain lines of text"; } - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + virtual void noMatchingTestCases( std::string const& spec ) override { stream << "No test cases matched '" << spec << '\'' << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + virtual void assertionStarting( AssertionInfo const& ) override { } - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& _assertionStats ) override { AssertionResult const& result = _assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); @@ -54,11 +54,11 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) override { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { + virtual void sectionEnded( SectionStats const& _sectionStats ) override { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -77,11 +77,11 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) override { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) override { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -90,7 +90,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { + virtual void testRunEnded( TestRunStats const& _testRunStats ) override { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; @@ -218,10 +218,10 @@ namespace Catch { void printMessage() const { if( !messageLabel.empty() ) stream << messageLabel << ':' << '\n'; - for( auto const& message : messages ) { + for( auto const& msg : messages ) { // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || message.type != ResultWas::Info ) - stream << Text( message.message, TextAttributes().setIndent(2) ) << '\n'; + if( printInfoMessages || msg.type != ResultWas::Info ) + stream << Text( msg.message, TextAttributes().setIndent(2) ) << '\n'; } } void printSourceInfo() const { diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index 18e501ee..acc5664c 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -57,20 +57,20 @@ namespace Catch { m_reporterPrefs.shouldRedirectStdOut = true; } - virtual ~JunitReporter() CATCH_OVERRIDE; + virtual ~JunitReporter() override; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } - virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} + virtual void noMatchingTestCases( std::string const& /*spec*/ ) override {} - virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { + virtual void testRunStarting( TestRunInfo const& runInfo ) override { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + virtual void testGroupStarting( GroupInfo const& groupInfo ) override { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); @@ -78,28 +78,28 @@ namespace Catch { CumulativeReporterBase::testGroupStarting( groupInfo ); } - virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { + virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) override { m_okToFail = testCaseInfo.okToFail(); } - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& assertionStats ) override { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } - virtual void testRunEndedCumulative() CATCH_OVERRIDE { + virtual void testRunEndedCumulative() override { xml.endElement(); } diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 4dcd6ec0..6b460bf0 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -23,79 +23,79 @@ public: public: // IStreamingReporter - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + virtual ReporterPreferences getPreferences() const override { return m_reporters[0]->getPreferences(); } - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + virtual void noMatchingTestCases( std::string const& spec ) override { for( auto const& reporter : m_reporters ) reporter->noMatchingTestCases( spec ); } - virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + virtual void testRunStarting( TestRunInfo const& testRunInfo ) override { for( auto const& reporter : m_reporters ) reporter->testRunStarting( testRunInfo ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + virtual void testGroupStarting( GroupInfo const& groupInfo ) override { for( auto const& reporter : m_reporters ) reporter->testGroupStarting( groupInfo ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) override { for( auto const& reporter : m_reporters ) reporter->testCaseStarting( testInfo ); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + virtual void sectionStarting( SectionInfo const& sectionInfo ) override { for( auto const& reporter : m_reporters ) reporter->sectionStarting( sectionInfo ); } - virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + virtual void assertionStarting( AssertionInfo const& assertionInfo ) override { for( auto const& reporter : m_reporters ) reporter->assertionStarting( assertionInfo ); } // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& assertionStats ) override { bool clearBuffer = false; for( auto const& reporter : m_reporters ) clearBuffer |= reporter->assertionEnded( assertionStats ); return clearBuffer; } - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + virtual void sectionEnded( SectionStats const& sectionStats ) override { for( auto const& reporter : m_reporters ) reporter->sectionEnded( sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { for( auto const& reporter : m_reporters ) reporter->testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { for( auto const& reporter : m_reporters ) reporter->testGroupEnded( testGroupStats ); } - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + virtual void testRunEnded( TestRunStats const& testRunStats ) override { for( auto const& reporter : m_reporters ) reporter->testRunEnded( testRunStats ); } - virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + virtual void skipTest( TestCaseInfo const& testInfo ) override { for( auto const& reporter : m_reporters ) reporter->skipTest( testInfo ); } - virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { + virtual MultipleReporters* tryAsMulti() override { return this; } diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 248ea3fb..6f52615a 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -43,33 +43,33 @@ namespace Catch { replaceInPlace( escaped, "]", "|]" ); return escaped; } - virtual ~TeamCityReporter() CATCH_OVERRIDE; + virtual ~TeamCityReporter() override; static std::string getDescription() { return "Reports test results as TeamCity service messages"; } - virtual void skipTest( TestCaseInfo const& /* testInfo */ ) CATCH_OVERRIDE { + virtual void skipTest( TestCaseInfo const& /* testInfo */ ) override { } - virtual void noMatchingTestCases( std::string const& /* spec */ ) CATCH_OVERRIDE {} + virtual void noMatchingTestCases( std::string const& /* spec */ ) override {} - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + virtual void testGroupStarting( GroupInfo const& groupInfo ) override { StreamingReporterBase::testGroupStarting( groupInfo ); stream << "##teamcity[testSuiteStarted name='" << escape( groupInfo.name ) << "']\n"; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { StreamingReporterBase::testGroupEnded( testGroupStats ); stream << "##teamcity[testSuiteFinished name='" << escape( testGroupStats.groupInfo.name ) << "']\n"; } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { + virtual void assertionStarting( AssertionInfo const& ) override { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& assertionStats ) override { AssertionResult const& result = assertionStats.assertionResult; if( !result.isOk() ) { @@ -140,18 +140,18 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + virtual void sectionStarting( SectionInfo const& sectionInfo ) override { m_headerPrintedForThisSection = false; StreamingReporterBase::sectionStarting( sectionInfo ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) override { StreamingReporterBase::testCaseStarting( testInfo ); stream << "##teamcity[testStarted name='" << escape( testInfo.name ) << "']\n"; } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { StreamingReporterBase::testCaseEnded( testCaseStats ); if( !testCaseStats.stdOut.empty() ) stream << "##teamcity[testStdOut name='" diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.hpp index 546c1095..cf26834f 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.hpp @@ -26,7 +26,7 @@ namespace Catch { m_reporterPrefs.shouldRedirectStdOut = true; } - virtual ~XmlReporter() CATCH_OVERRIDE; + virtual ~XmlReporter() override; static std::string getDescription() { return "Reports test results as an XML document"; @@ -44,11 +44,11 @@ namespace Catch { public: // StreamingReporterBase - virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { + virtual void noMatchingTestCases( std::string const& s ) override { StreamingReporterBase::noMatchingTestCases( s ); } - virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { + virtual void testRunStarting( TestRunInfo const& testInfo ) override { StreamingReporterBase::testRunStarting( testInfo ); std::string stylesheetRef = getStylesheetRef(); if( !stylesheetRef.empty() ) @@ -58,13 +58,13 @@ namespace Catch { m_xml.writeAttribute( "name", m_config->name() ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + virtual void testGroupStarting( GroupInfo const& groupInfo ) override { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) override { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ) .writeAttribute( "name", trim( testInfo.name ) ) @@ -78,7 +78,7 @@ namespace Catch { m_xml.ensureTagClosed(); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + virtual void sectionStarting( SectionInfo const& sectionInfo ) override { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) @@ -89,9 +89,9 @@ namespace Catch { } } - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } + virtual void assertionStarting( AssertionInfo const& ) override { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& assertionStats ) override { AssertionResult const& result = assertionStats.assertionResult; @@ -166,7 +166,7 @@ namespace Catch { return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + virtual void sectionEnded( SectionStats const& sectionStats ) override { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); @@ -181,7 +181,7 @@ namespace Catch { } } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); @@ -197,7 +197,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) @@ -207,7 +207,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + virtual void testRunEnded( TestRunStats const& testRunStats ) override { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) diff --git a/projects/SelfTest/ApproxTests.cpp b/projects/SelfTest/ApproxTests.cpp index 14a8234e..e4bc6ecd 100644 --- a/projects/SelfTest/ApproxTests.cpp +++ b/projects/SelfTest/ApproxTests.cpp @@ -153,7 +153,6 @@ TEST_CASE( "Absolute margin", "[Approx]" ) { //////////////////////////////////////////////////////////////////////////////// -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) class StrongDoubleTypedef { double d_ = 0.0; @@ -192,6 +191,5 @@ TEST_CASE REQUIRE(Approx(11.0) >= td); } -#endif //////////////////////////////////////////////////////////////////////////////// diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp index 83b79fde..ec14cb8b 100644 --- a/projects/SelfTest/CmdLineTests.cpp +++ b/projects/SelfTest/CmdLineTests.cpp @@ -13,7 +13,7 @@ # pragma clang diagnostic ignored "-Wc++98-compat" #endif -inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( nullptr, "", name, desc, CATCH_INTERNAL_LINEINFO ); } TEST_CASE( "Parse test names and tags", "" ) { diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index 2eb99ba3..ec56b799 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -257,32 +257,32 @@ TEST_CASE( "Comparisons between ints where one side is computed", "" ) #pragma GCC diagnostic pop #endif -inline const char* returnsConstNull(){ return CATCH_NULL; } -inline char* returnsNull(){ return CATCH_NULL; } +inline const char* returnsConstNull(){ return nullptr; } +inline char* returnsNull(){ return nullptr; } TEST_CASE( "Pointers can be compared to null", "" ) { - TestData* p = CATCH_NULL; - TestData* pNULL = CATCH_NULL; + TestData* p = nullptr; + TestData* pNULL = nullptr; - REQUIRE( p == CATCH_NULL ); + REQUIRE( p == nullptr ); REQUIRE( p == pNULL ); TestData data; p = &data; - REQUIRE( p != CATCH_NULL ); + REQUIRE( p != nullptr ); const TestData* cp = p; - REQUIRE( cp != CATCH_NULL ); + REQUIRE( cp != nullptr ); const TestData* const cpc = p; - REQUIRE( cpc != CATCH_NULL ); + REQUIRE( cpc != nullptr ); - REQUIRE( returnsNull() == CATCH_NULL ); - REQUIRE( returnsConstNull() == CATCH_NULL ); + REQUIRE( returnsNull() == nullptr ); + REQUIRE( returnsConstNull() == nullptr ); - REQUIRE( CATCH_NULL != p ); + REQUIRE( nullptr != p ); } // Not (!) tests diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 8ba5cb54..c9754d4a 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -120,7 +120,7 @@ public: CustomStdException( const std::string& msg ) : m_msg( msg ) {} - ~CustomStdException() CATCH_NOEXCEPT {} + ~CustomStdException() noexcept {} std::string getMessage() const { diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp index bed9c137..1c944a3d 100644 --- a/projects/SelfTest/MessageTests.cpp +++ b/projects/SelfTest/MessageTests.cpp @@ -62,7 +62,6 @@ TEST_CASE( "FAIL_CHECK does not abort the test", "[failing][messages][.]" ) WARN( "This message appears in the output"); } -#ifdef CATCH_CONFIG_VARIADIC_MACROS TEST_CASE( "FAIL does not require an argument", "[failing][messages][.]" ) { FAIL(); @@ -71,7 +70,6 @@ TEST_CASE( "SUCCESS does not require an argument", "[messages][.]" ) { SUCCEED(); } -#endif TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) { diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 02099a71..aab0295f 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -131,13 +131,13 @@ TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) inline const char* makeString( bool makeNull ) { - return makeNull ? CATCH_NULL : "valid string"; + return makeNull ? nullptr : "valid string"; } TEST_CASE( "null strings", "" ) { - REQUIRE( makeString( false ) != static_cast(CATCH_NULL)); - REQUIRE( makeString( true ) == static_cast(CATCH_NULL)); + REQUIRE( makeString( false ) != static_cast(nullptr)); + REQUIRE( makeString( true ) == static_cast(nullptr)); } @@ -372,13 +372,11 @@ TEST_CASE( "XmlEncode" ) { } } -#ifdef CATCH_CONFIG_CPP11_LONG_LONG TEST_CASE( "long long", "[c++11][.]" ) { long long l = std::numeric_limits::max(); REQUIRE( l == std::numeric_limits::max() ); } -#endif //TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) { // int i = 0; diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index e03a9e44..8005a2eb 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -43,7 +43,7 @@ std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::Co return ""; } -inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( nullptr, "", name, desc, CATCH_INTERNAL_LINEINFO ); } TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 26625b03..ae1e5844 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -236,7 +236,7 @@ struct Obj TEST_CASE("boolean member", "[Tricky]") { Obj obj; - REQUIRE( obj.prop != CATCH_NULL ); + REQUIRE( obj.prop != nullptr ); } // Tests for a problem submitted by Ralph McArdell diff --git a/projects/SelfTest/VariadicMacrosTests.cpp b/projects/SelfTest/VariadicMacrosTests.cpp index b784076d..fd651c5e 100644 --- a/projects/SelfTest/VariadicMacrosTests.cpp +++ b/projects/SelfTest/VariadicMacrosTests.cpp @@ -8,7 +8,6 @@ #include "catch.hpp" -#ifdef CATCH_CONFIG_VARIADIC_MACROS TEST_CASE() { @@ -28,4 +27,3 @@ TEST_CASE( "Variadic macros", "[variadic][sections]" ) } } -#endif From f57f96f1901431c1d8db9cfa47198fce2326d8ef Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 12:10:04 +0100 Subject: [PATCH 010/398] Removed pre-C++11 versions of Clang (3.4) and GCC (4.4) --- .travis.yml | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/.travis.yml b/.travis.yml index 278ea40b..277431a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,19 +5,6 @@ matrix: include: # 1/ Linux Clang Builds - - os: linux - compiler: clang - addons: &clang34 - apt: - sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test'] - packages: ['clang'] - env: COMPILER='clang++' BUILD_TYPE='Release' - - - os: linux - compiler: clang - addons: *clang34 - env: COMPILER='clang++' BUILD_TYPE='Debug' - - os: linux compiler: clang addons: &clang35 @@ -75,20 +62,6 @@ matrix: # 2/ Linux GCC Builds - - os: linux - compiler: gcc - addons: &gcc44 - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.4'] - env: COMPILER='g++-4.4' BUILD_TYPE='Release' - - - os: linux - compiler: gcc - addons: *gcc44 - env: COMPILER='g++-4.4' BUILD_TYPE='Debug' - - - os: linux compiler: gcc addons: &gcc47 From 67005d290cac91ddbbf53dbe7fc9f803fbec9629 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 12:13:16 +0100 Subject: [PATCH 011/398] Removed more redundant compatibility stuff from timer --- include/internal/catch_timer.h | 3 --- include/internal/catch_timer.hpp | 9 --------- 2 files changed, 12 deletions(-) diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 1d690160..6e8cf089 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -8,11 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_TIMER_H_INCLUDED #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED -#include "catch_platform.h" - #include - namespace Catch { class Timer { public: diff --git a/include/internal/catch_timer.hpp b/include/internal/catch_timer.hpp index d8bcfce9..52de3e83 100644 --- a/include/internal/catch_timer.hpp +++ b/include/internal/catch_timer.hpp @@ -9,11 +9,6 @@ #include "catch_timer.h" #include "catch_platform.h" -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++11-long-long" -#endif - #ifdef CATCH_PLATFORM_WINDOWS # include "catch_windows_h_proxy.h" @@ -61,7 +56,3 @@ namespace Catch { } } // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif From 242022460d5b466358fcab5e9ca884f2f7d99c6a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 12:24:34 +0100 Subject: [PATCH 012/398] Use std::chrono for Timer to eliminate platform dependency --- include/internal/catch_timer.h | 4 ++-- include/internal/catch_timer.hpp | 34 +++++--------------------------- 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 6e8cf089..81b9fdb7 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -13,14 +13,14 @@ namespace Catch { class Timer { public: - Timer() : m_ticks( 0 ) {} + Timer() : m_microSeconds( 0 ) {} void start(); unsigned int getElapsedMicroseconds() const; unsigned int getElapsedMilliseconds() const; double getElapsedSeconds() const; private: - uint64_t m_ticks; + uint64_t m_microSeconds; }; } // namespace Catch diff --git a/include/internal/catch_timer.hpp b/include/internal/catch_timer.hpp index 52de3e83..d4066fa9 100644 --- a/include/internal/catch_timer.hpp +++ b/include/internal/catch_timer.hpp @@ -7,46 +7,22 @@ */ #include "catch_timer.h" -#include "catch_platform.h" -#ifdef CATCH_PLATFORM_WINDOWS - -# include "catch_windows_h_proxy.h" - -#else - -#include - -#endif +#include namespace Catch { namespace { -#ifdef CATCH_PLATFORM_WINDOWS - uint64_t getCurrentTicks() { - static uint64_t hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency( reinterpret_cast( &hz ) ); - QueryPerformanceCounter( reinterpret_cast( &hzo ) ); - } - uint64_t t; - QueryPerformanceCounter( reinterpret_cast( &t ) ); - return ((t-hzo)*1000000)/hz; + uint64_t getCurrentMicrosecondsSinceEpoch() { + return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); } -#else - uint64_t getCurrentTicks() { - timeval t; - gettimeofday(&t,nullptr); - return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); - } -#endif } void Timer::start() { - m_ticks = getCurrentTicks(); + m_microSeconds = getCurrentMicrosecondsSinceEpoch(); } unsigned int Timer::getElapsedMicroseconds() const { - return static_cast(getCurrentTicks() - m_ticks); + return static_cast(getCurrentMicrosecondsSinceEpoch() - m_microSeconds); } unsigned int Timer::getElapsedMilliseconds() const { return static_cast(getElapsedMicroseconds()/1000); From 5c8ea03cc85a750d4d8fdd9da1ef02f645a17cac Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 12:27:26 +0100 Subject: [PATCH 013/398] Removed debug break support for PowerPC Macs --- include/internal/catch_debugger.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/include/internal/catch_debugger.h b/include/internal/catch_debugger.h index 15a4c64b..ddb37097 100644 --- a/include/internal/catch_debugger.h +++ b/include/internal/catch_debugger.h @@ -21,15 +21,7 @@ namespace Catch{ #ifdef CATCH_PLATFORM_MAC - // The following code snippet based on: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #if defined(__ppc64__) || defined(__ppc__) - #define CATCH_TRAP() \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ) - #else - #define CATCH_TRAP() __asm__("int $3\n" : : ) - #endif + #define CATCH_TRAP() __asm__("int $3\n" : : ) #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break From 79650e44f47f39e9fa3a70d1c713f95069a0ba8f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 12:40:52 +0100 Subject: [PATCH 014/398] Removed more C++98/03 compatibility --- include/reporters/catch_reporter_teamcity.hpp | 2 -- projects/SelfTest/ConditionTests.cpp | 1 - projects/SelfTest/EnumToString.cpp | 11 ----------- projects/SelfTest/ToStringTuple.cpp | 15 +-------------- projects/SelfTest/ToStringVector.cpp | 15 --------------- projects/SelfTest/TrickyTests.cpp | 9 --------- 6 files changed, 1 insertion(+), 52 deletions(-) diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 6f52615a..ae2efd88 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -19,8 +19,6 @@ #ifdef __clang__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #endif namespace Catch { diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index ec56b799..ff66854d 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -7,7 +7,6 @@ */ #ifdef __clang__ # pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" #endif #include "catch.hpp" diff --git a/projects/SelfTest/EnumToString.cpp b/projects/SelfTest/EnumToString.cpp index f591520f..52a39812 100644 --- a/projects/SelfTest/EnumToString.cpp +++ b/projects/SelfTest/EnumToString.cpp @@ -29,12 +29,6 @@ TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) { CHECK( Catch::toString(e1) == "E2{1}" ); } -#if defined(CATCH_CPP11_OR_GREATER) -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat" -#endif - // Enum class without user-provided stream operator enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 }; @@ -69,8 +63,3 @@ TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass][c++ CHECK( Catch::toString(e3) == "Unknown enum value 10" ); } -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -#endif // CATCH_CPP11_OR_GREATER - diff --git a/projects/SelfTest/ToStringTuple.cpp b/projects/SelfTest/ToStringTuple.cpp index fa61f631..86f68d37 100644 --- a/projects/SelfTest/ToStringTuple.cpp +++ b/projects/SelfTest/ToStringTuple.cpp @@ -1,11 +1,6 @@ #include "catch.hpp" -#ifdef CATCH_CPP11_OR_GREATER - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat" -#endif +#include TEST_CASE( "tuple<>", "[toString][tuple][c++11][.]" ) { @@ -42,18 +37,10 @@ TEST_CASE( "tuple,tuple<>,float>", "[toString][tuple][c++11][.]" ) CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) ); } -#ifdef CATCH_CONFIG_CPP11_NULLPTR TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) { typedef std::tuple type; type value { nullptr, 42, "Catch me" }; CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) ); } -#endif - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif /* #ifdef CATCH_CPP11_OR_GREATER */ diff --git a/projects/SelfTest/ToStringVector.cpp b/projects/SelfTest/ToStringVector.cpp index cd071a9d..002d8ef4 100644 --- a/projects/SelfTest/ToStringVector.cpp +++ b/projects/SelfTest/ToStringVector.cpp @@ -23,16 +23,6 @@ TEST_CASE( "vector -> toString", "[toString][vector]" ) REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" ); } -#if defined(CATCH_CPP11_OR_GREATER) -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++98-compat" -#endif - -/* - Note: These tests *can* be made to work with C++ < 11, but the - allocator is a lot more work... -*/ namespace { /* Minimal Allocator */ template @@ -70,8 +60,3 @@ TEST_CASE( "vec> -> toString", "[toString][vector,allocator][c v.push_back( inner { "world" } ); REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" ); } - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -#endif // CATCH_CPP11_OR_GREATER diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index ae1e5844..70c56965 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -14,11 +14,6 @@ #include "catch.hpp" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wc++98-compat" -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - namespace Catch { template<> @@ -385,8 +380,6 @@ TEST_CASE( "pointer to class", "[Tricky]" ) REQUIRE( p == 0 ); } -#ifdef CATCH_CONFIG_CPP11_NULLPTR - #include TEST_CASE( "null_ptr", "[Tricky][c++11][.]" ) @@ -395,8 +388,6 @@ TEST_CASE( "null_ptr", "[Tricky][c++11][.]" ) REQUIRE(ptr.get() == nullptr); } -#endif - TEST_CASE( "X/level/0/a", "[Tricky]" ) { SUCCEED(""); } TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); } TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); } From 569d355b3676da90fb742e1f83f0fba1a5214fb3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 14:57:47 +0100 Subject: [PATCH 015/398] Removed C++11 config macro docs --- docs/configuration.md | 43 +------------------------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index daa79931..48250b62 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -50,48 +50,7 @@ Catch does not use ```std::cout``` and ```std::cerr``` directly but gets them fr This can be useful on certain platforms that do not provide ```std::cout``` and ```std::cerr```, such as certain embedded systems. -# C++ conformance toggles - CATCH_CONFIG_CPP11_NULLPTR // nullptr is supported? - CATCH_CONFIG_CPP11_NOEXCEPT // noexcept is supported? - CATCH_CONFIG_CPP11_GENERATED_METHODS // delete and default keywords for methods - CATCH_CONFIG_CPP11_IS_ENUM // std::is_enum is supported? - CATCH_CONFIG_CPP11_TUPLE // std::tuple is supported - CATCH_CONFIG_VARIADIC_MACROS // Usually pre-C++11 compiler extensions are sufficient - CATCH_CONFIG_CPP11_LONG_LONG // generates overloads for the long long type - CATCH_CONFIG_CPP11_OVERRIDE // CATCH_OVERRIDE expands to override (for virtual function implementations) - CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr - CATCH_CONFIG_CPP11_SHUFFLE // Use std::shuffle instead of std::random_shuffle - CATCH_CONFIG_CPP11_TYPE_TRAITS // Use std::enable_if and - CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK // Use C++11 expression SFINAE to check if class can be inserted to std::ostream - -Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative. -So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support. -You may also suppress any of these features by using the `_NO_` form, e.g. `CATCH_CONFIG_CPP11_NO_NULLPTR`. - -All C++11 support can be disabled with `CATCH_CONFIG_NO_CPP11` - -## `CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK` - -This flag is off by default, but allows you to resolve problems caused by types with private base class that are streamable, but the classes themselves are not. Without it, the following code will cause a compilation error: -```cpp -#define CATCH_CONFIG_MAIN -#include -struct A {}; -std::ostream &operator<< (std::ostream &o, const A &v) { return o << 0; } - -struct B : private A { - bool operator==(int){ return true;} -}; - -B f (); -std::ostream g (); - -TEST_CASE ("Error in streamable check") { - B x; - REQUIRE (x == 4); -} -``` # Other toggles @@ -107,7 +66,7 @@ Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, `CATCH_CONFIG_WINDOWS_CRTDBG` is off by default. If enabled, Windows's CRT is used to check for memory leaks, and displays them after the tests finish running. -Just as with the C++11 conformance toggles, these toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`. +These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`. ## `CATCH_CONFIG_FAST_COMPILE` Defining this flag speeds up compilation of test files by ~20%, by making 2 changes: From 61ac34045c07705b13d14d84ca416cc5c28ebb79 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 14:57:58 +0100 Subject: [PATCH 016/398] Enabled SFINAE stream test --- .../Baselines/console.std.approved.txt | 4 ++-- .../SelfTest/Baselines/console.sw.approved.txt | 18 ++++++++++++++++-- .../Baselines/console.swa4.approved.txt | 18 ++++++++++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 3 ++- .../SelfTest/Baselines/xml.sw.approved.txt | 18 ++++++++++++++++-- projects/SelfTest/CompilationTests.cpp | 12 ++++++++++-- 6 files changed, 62 insertions(+), 11 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index e6bcf41e..2e76ce75 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -940,6 +940,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 167 | 119 passed | 44 failed | 4 failed as expected -assertions: 967 | 859 passed | 87 failed | 21 failed as expected +test cases: 168 | 120 passed | 44 failed | 4 failed as expected +assertions: 968 | 860 passed | 87 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index ac178f80..41693f3a 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -123,6 +123,20 @@ PASSED: with expansion: 1 == 1 +------------------------------------------------------------------------------- +#872 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( x == 4 ) +with expansion: + {?} == 4 +with message: + dummy := 0 + ------------------------------------------------------------------------------- 'Not' checks that should fail ------------------------------------------------------------------------------- @@ -9466,6 +9480,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 167 | 118 passed | 45 failed | 4 failed as expected -assertions: 969 | 859 passed | 89 failed | 21 failed as expected +test cases: 168 | 119 passed | 45 failed | 4 failed as expected +assertions: 970 | 860 passed | 89 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index dcabf4e0..6ce6850a 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -123,6 +123,20 @@ PASSED: with expansion: 1 == 1 +------------------------------------------------------------------------------- +#872 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( x == 4 ) +with expansion: + {?} == 4 +with message: + dummy := 0 + ------------------------------------------------------------------------------- 'Not' checks that should fail ------------------------------------------------------------------------------- @@ -144,6 +158,6 @@ ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) =============================================================================== -test cases: 6 | 3 passed | 1 failed | 2 failed as expected -assertions: 18 | 11 passed | 4 failed | 3 failed as expected +test cases: 7 | 4 passed | 1 failed | 2 failed as expected +assertions: 19 | 12 passed | 4 failed | 3 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 49df947e..ee691ce0 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -24,6 +24,7 @@ ExceptionTests.cpp: MiscTests.cpp: + ConditionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index fed55cd0..1373c6d3 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -136,6 +136,20 @@ + + + dummy := 0 + + + + x == 4 + + + {?} == 4 + + + + @@ -10114,7 +10128,7 @@ spanner - + - + diff --git a/projects/SelfTest/CompilationTests.cpp b/projects/SelfTest/CompilationTests.cpp index ed1978f3..06d361fb 100644 --- a/projects/SelfTest/CompilationTests.cpp +++ b/projects/SelfTest/CompilationTests.cpp @@ -51,8 +51,12 @@ TEST_CASE("#833") { REQUIRE(templated_tests(3)); } +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif + // Test containing example where original stream insertable check breaks compilation -#if defined (CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) namespace { struct A {}; std::ostream& operator<< (std::ostream &o, const A &) { return o << 0; } @@ -64,9 +68,13 @@ namespace { B f (); std::ostream g (); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif TEST_CASE( "#872" ) { + A dummy; + CAPTURE( dummy ); B x; REQUIRE (x == 4); } -#endif From be0fc60c0769ec1c1dcb3abb266332fe659d9a3a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 14:43:13 +0000 Subject: [PATCH 017/398] Updated version number for v2 development and removed single include (for now). --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 11475 --------------------------- 3 files changed, 2 insertions(+), 11477 deletions(-) delete mode 100644 single_include/catch.hpp diff --git a/README.md b/README.md index f4f30fd3..372e2279 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch) [![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master) -The latest, single header, version can be downloaded directly using this link +The latest, single header, version can be downloaded directly using this link ## What's the Catch? diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index fdf3be6e..8f515109 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -38,7 +38,7 @@ namespace Catch { } inline Version libraryVersion() { - static Version version( 1, 9, 2, "", 0 ); + static Version version( 2, 0, 0, "develop", 1 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp deleted file mode 100644 index f0d5e756..00000000 --- a/single_include/catch.hpp +++ /dev/null @@ -1,11475 +0,0 @@ -/* - * Catch v1.9.2 - * Generated: 2017-04-25 10:41:53.040184 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2012 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) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - -#define TWOBLUECUBES_CATCH_HPP_INCLUDED - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// #included from: internal/catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# 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 "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -# 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" - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wpadded" -#endif -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -#endif - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// #included from: internal/catch_notimplemented_exception.h -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -// #included from: catch_common.h -#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED - -// #included from: catch_compiler_capabilities.h -#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? -// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported -// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? -// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? -// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) -// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? -// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? - -// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 - -#ifdef __cplusplus - -# if __cplusplus >= 201103L -# define CATCH_CPP11_OR_GREATER -# endif - -# if __cplusplus >= 201402L -# define CATCH_CPP14_OR_GREATER -# endif - -#endif - -#ifdef __clang__ - -# if __has_feature(cxx_nullptr) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# if __has_feature(cxx_noexcept) -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# if defined(CATCH_CPP11_OR_GREATER) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - _Pragma( "clang diagnostic pop" ) - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic pop" ) -# endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// 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 - -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Cygwin -#ifdef __CYGWIN__ - -// 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 - -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH - -#if (_MSC_VER >= 1600) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -#endif - -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// - -// Use variadic macros if the compiler supports them -#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ - ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ - ( defined __GNUC__ && __GNUC__ >= 3 ) || \ - ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) - -#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS - -#endif - -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ - ( defined __clang__ && __clang_major__ >= 3 ) - -#define CATCH_INTERNAL_CONFIG_COUNTER - -#endif - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(CATCH_CPP11_OR_GREATER) - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM -# endif - -# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE -# endif - -# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) -# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG -# endif - -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) -# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) -# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE -# endif -# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) -# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS -# endif - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NULLPTR -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_IS_ENUM -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TUPLE -#endif -#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -# define CATCH_CONFIG_VARIADIC_MACROS -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_LONG_LONG -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_UNIQUE_PTR -#endif -// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for -// analytics) because, at time of writing, __COUNTER__ is not properly handled by it. -// This does not affect compilation -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) -# define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_SHUFFLE -#endif -# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) -# define CATCH_CONFIG_CPP11_TYPE_TRAITS -# endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_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) -# define CATCH_CONFIG_POSIX_SIGNALS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS -#endif - -// noexcept support: -#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) -# define CATCH_NOEXCEPT noexcept -# define CATCH_NOEXCEPT_IS(x) noexcept(x) -#else -# define CATCH_NOEXCEPT throw() -# define CATCH_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CATCH_CONFIG_CPP11_NULLPTR -# define CATCH_NULL nullptr -#else -# define CATCH_NULL NULL -#endif - -// override support -#ifdef CATCH_CONFIG_CPP11_OVERRIDE -# define CATCH_OVERRIDE override -#else -# define CATCH_OVERRIDE -#endif - -// unique_ptr support -#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR -# define CATCH_AUTO_PTR( T ) std::unique_ptr -#else -# define CATCH_AUTO_PTR( T ) std::auto_ptr -#endif - -#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 ) -#ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) -#endif - -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - -#include -#include - -namespace Catch { - - struct IConfig; - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { -#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; -#else - NonCopyable( NonCopyable const& info ); - NonCopyable& operator = ( NonCopyable const& ); -#endif - - protected: - NonCopyable() {} - virtual ~NonCopyable(); - }; - - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - - template - inline void deleteAll( ContainerT& container ) { - typename ContainerT::const_iterator it = container.begin(); - typename ContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete *it; - } - template - inline void deleteAllValues( AssociativeContainerT& container ) { - typename AssociativeContainerT::const_iterator it = container.begin(); - typename AssociativeContainerT::const_iterator itEnd = container.end(); - for(; it != itEnd; ++it ) - delete it->second; - } - - bool startsWith( std::string const& s, std::string const& prefix ); - bool startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - - struct SourceLineInfo { - - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SourceLineInfo(SourceLineInfo const& other) = default; - SourceLineInfo( SourceLineInfo && ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo& operator = ( SourceLineInfo && ) = default; -# endif - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - bool operator < ( SourceLineInfo const& other ) const; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - inline bool alwaysTrue() { return true; } - inline bool alwaysFalse() { return false; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - - void seedRng( IConfig const& config ); - unsigned int rngSeed(); - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() { - return std::string(); - } - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - NotImplementedException( NotImplementedException const& ) {} - - virtual ~NotImplementedException() CATCH_NOEXCEPT {} - - virtual const char* what() const CATCH_NOEXCEPT; - - private: - std::string m_what; - SourceLineInfo m_lineInfo; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// #included from: internal/catch_context.h -#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED - -// #included from: catch_interfaces_generators.h -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -// #included from: catch_ptr.hpp -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { - public: - Ptr() : m_p( CATCH_NULL ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( Ptr const& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - void reset() { - if( m_p ) - m_p->release(); - m_p = CATCH_NULL; - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( Ptr const& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() const{ return m_p; } - T& operator*() const { return *m_p; } - T* operator->() const { return m_p; } - bool operator !() const { return m_p == CATCH_NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; - - template - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef() const { - ++m_rc; - } - virtual void release() const { - if( --m_rc == 0 ) - delete this; - } - - mutable unsigned int m_rc; - }; - -} // end namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IGeneratorsForTest; - struct IConfig; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual Ptr getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); - Stream createStream( std::string const& streamName ); - -} - -// #included from: internal/catch_test_registry.hpp -#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED - -// #included from: catch_interfaces_testcase.h -#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED - -#include - -namespace Catch { - - class TestSpec; - - struct ITestCase : IShared { - virtual void invoke () const = 0; - protected: - virtual ~ITestCase(); - }; - - 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; - }; - - 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 ); - -} - -namespace Catch { - -template -class MethodTestCase : public SharedImpl { - -public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} - - virtual void invoke() const { - C obj; - (obj.*m_method)(); - } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); -}; - -typedef void(*TestFunction)(); - -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} - - const char* name; - const char* description; -}; - -void registerTestCase - ( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - -struct AutoReg { - - AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template - AutoReg - ( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - registerTestCase - ( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } - - ~AutoReg(); - -private: - AutoReg( AutoReg const& ); - void operator= ( AutoReg const& ); -}; - -void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ - static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - static void TestName() - #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, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ \ - struct TestName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ - } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - void TestName::test() - #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, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -#else - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ - static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - static void TestName() - #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ \ - struct TestCaseName : ClassName{ \ - void test(); \ - }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ - } \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ - void TestCaseName::test() - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ - INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) - - /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -#endif - -// #included from: internal/catch_capture.hpp -#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED - -// #included from: catch_result_builder.h -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED - -// #included from: catch_result_type.h -#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED - -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 - - }; }; - - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } - - // 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 - }; }; - - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } - - inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } - inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } - -} // end namespace Catch - -// #included from: catch_assertionresult.h -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED - -#include - -namespace Catch { - - struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - - struct DecomposedExpression - { - virtual ~DecomposedExpression() {} - virtual bool isBinaryExpression() const { - return false; - } - virtual void reconstructExpression( std::string& dest ) const = 0; - - // Only simple binary comparisons can be decomposed. - // If more complex check is required then wrap sub-expressions in parentheses. - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); - - private: - DecomposedExpression& operator = (DecomposedExpression const&); - }; - - struct AssertionInfo - { - AssertionInfo() {} - AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ); - - std::string macroName; - SourceLineInfo lineInfo; - std::string capturedExpression; - ResultDisposition::Flags resultDisposition; - }; - - struct AssertionResultData - { - AssertionResultData() : decomposedExpression( CATCH_NULL ) - , resultType( ResultWas::Unknown ) - , negated( false ) - , parenthesized( false ) {} - - void negate( bool parenthesize ) { - negated = !negated; - parenthesized = parenthesize; - if( resultType == ResultWas::Ok ) - resultType = ResultWas::ExpressionFailed; - else if( resultType == ResultWas::ExpressionFailed ) - resultType = ResultWas::Ok; - } - - std::string const& reconstructExpression() const { - if( decomposedExpression != CATCH_NULL ) { - decomposedExpression->reconstructExpression( reconstructedExpression ); - if( parenthesized ) { - reconstructedExpression.insert( 0, 1, '(' ); - reconstructedExpression.append( 1, ')' ); - } - if( negated ) { - reconstructedExpression.insert( 0, 1, '!' ); - } - decomposedExpression = CATCH_NULL; - } - return reconstructedExpression; - } - - mutable DecomposedExpression const* decomposedExpression; - mutable std::string reconstructedExpression; - std::string message; - ResultWas::OfType resultType; - bool negated; - bool parenthesized; - }; - - class AssertionResult { - public: - AssertionResult(); - AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionResult( AssertionResult const& ) = default; - AssertionResult( AssertionResult && ) = default; - AssertionResult& operator = ( AssertionResult const& ) = default; - AssertionResult& operator = ( AssertionResult && ) = default; -# endif - - bool isOk() const; - bool succeeded() const; - ResultWas::OfType getResultType() const; - bool hasExpression() const; - bool hasMessage() const; - std::string getExpression() const; - std::string getExpressionInMacro() const; - bool hasExpandedExpression() const; - std::string getExpandedExpression() const; - std::string getMessage() const; - SourceLineInfo getSourceInfo() const; - std::string getTestMacroName() const; - void discardDecomposedExpression() const; - void expandDecomposedExpression() const; - - protected: - AssertionInfo m_info; - AssertionResultData m_resultData; - }; - -} // end namespace Catch - -// #included from: catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template struct MatchAllOf; - template struct MatchAnyOf; - template struct MatchNotOf; - - class MatcherUntypedBase { - public: - std::string toString() const { - if( m_cachedToString.empty() ) - m_cachedToString = describe(); - return m_cachedToString; - } - - protected: - virtual ~MatcherUntypedBase(); - virtual std::string describe() const = 0; - mutable std::string m_cachedToString; - private: - MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); - }; - - template - struct MatcherMethod { - virtual bool match( ObjectT const& arg ) const = 0; - }; - template - struct MatcherMethod { - virtual bool match( PtrT* arg ) const = 0; - }; - - template - struct MatcherBase : MatcherUntypedBase, MatcherMethod { - - MatchAllOf operator && ( MatcherBase const& other ) const; - MatchAnyOf operator || ( MatcherBase const& other ) const; - MatchNotOf operator ! () const; - }; - - template - struct MatchAllOf : MatcherBase { - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (!m_matchers[i]->match(arg)) - return false; - } - return true; - } - virtual std::string describe() const CATCH_OVERRIDE { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - description += " and "; - description += m_matchers[i]->toString(); - } - description += " )"; - return description; - } - - MatchAllOf& operator && ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - template - struct MatchAnyOf : MatcherBase { - - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if (m_matchers[i]->match(arg)) - return true; - } - return false; - } - virtual std::string describe() const CATCH_OVERRIDE { - std::string description; - description.reserve( 4 + m_matchers.size()*32 ); - description += "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - description += " or "; - description += m_matchers[i]->toString(); - } - description += " )"; - return description; - } - - MatchAnyOf& operator || ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; - } - - std::vector const*> m_matchers; - }; - - template - struct MatchNotOf : MatcherBase { - - MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} - - virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { - return !m_underlyingMatcher.match( arg ); - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "not " + m_underlyingMatcher.toString(); - } - MatcherBase const& m_underlyingMatcher; - }; - - template - MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { - return MatchAllOf() && *this && other; - } - template - MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { - return MatchAnyOf() || *this || other; - } - template - MatchNotOf MatcherBase::operator ! () const { - return MatchNotOf( *this ); - } - - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - // - deprecated: prefer ||, && and ! - template - inline Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { - return Impl::MatchNotOf( underlyingMatcher ); - } - template - inline Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAllOf() && m1 && m2; - } - template - inline Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAllOf() && m1 && m2 && m3; - } - template - inline Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAnyOf() || m1 || m2; - } - template - inline Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAnyOf() || m1 || m2 || m3; - } - -} // namespace Matchers - -using namespace Matchers; -using Matchers::Impl::MatcherBase; - -} // namespace Catch - -namespace Catch { - - struct TestFailureException{}; - - template class ExpressionLhs; - - struct CopyableStream { - CopyableStream() {} - CopyableStream( CopyableStream const& other ) { - oss << other.oss.str(); - } - CopyableStream& operator=( CopyableStream const& other ) { - oss.str(std::string()); - oss << other.oss.str(); - return *this; - } - std::ostringstream oss; - }; - - class ResultBuilder : public DecomposedExpression { - public: - ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg = "" ); - ~ResultBuilder(); - - template - ExpressionLhs operator <= ( T const& operand ); - ExpressionLhs operator <= ( bool value ); - - template - ResultBuilder& operator << ( T const& value ) { - m_stream.oss << value; - return *this; - } - - ResultBuilder& setResultType( ResultWas::OfType result ); - ResultBuilder& setResultType( bool result ); - - void endExpression( DecomposedExpression const& expr ); - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; - - AssertionResult build() const; - AssertionResult build( DecomposedExpression const& expr ) const; - - void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); - void captureResult( ResultWas::OfType resultType ); - void captureExpression(); - void captureExpectedException( std::string const& expectedMessage ); - void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); - void handleResult( AssertionResult const& result ); - void react(); - bool shouldDebugBreak() const; - bool allowThrows() const; - - template - void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); - - void setExceptionGuard(); - void unsetExceptionGuard(); - - private: - AssertionInfo m_assertionInfo; - AssertionResultData m_data; - CopyableStream m_stream; - - bool m_shouldDebugBreak; - bool m_shouldThrow; - bool m_guardException; - }; - -} // namespace Catch - -// Include after due to circular dependency: -// #included from: catch_expression_lhs.hpp -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -// #included from: catch_evaluate.hpp -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) -#endif - -#include - -namespace Catch { -namespace Internal { - - enum Operator { - IsEqualTo, - IsNotEqualTo, - IsLessThan, - IsGreaterThan, - IsLessThanOrEqualTo, - IsGreaterThanOrEqualTo - }; - - template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; - template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; - template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; - - template - inline T& opCast(T const& t) { return const_cast(t); } - -// nullptr_t support based on pull request #154 from Konstantin Baumann -#ifdef CATCH_CONFIG_CPP11_NULLPTR - inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } -#endif // CATCH_CONFIG_CPP11_NULLPTR - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template - class Evaluator{}; - - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs) { - return bool( opCast( lhs ) == opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) != opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) < opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) > opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) >= opCast( rhs ) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) <= opCast( rhs ) ); - } - }; - - template - bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // This level of indirection allows us to specialise for integer types - // to avoid signed/ unsigned warnings - - // "base" overload - template - bool compare( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // unsigned X to int - template bool compare( unsigned int lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // unsigned X to long - template bool compare( unsigned int lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // int to unsigned X - template bool compare( int lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // long to unsigned X - template bool compare( long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long (when comparing against NULL) - template bool compare( long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - - // pointer to int (when comparing against NULL) - template bool compare( int lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, int rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG - // long long to unsigned X - template bool compare( long long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // unsigned long long to X - template bool compare( unsigned long long lhs, int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long long (when comparing against NULL) - template bool compare( long long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } -#endif // CATCH_CONFIG_CPP11_LONG_LONG - -#ifdef CATCH_CONFIG_CPP11_NULLPTR - // pointer to nullptr_t (when comparing against nullptr) - template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( nullptr, rhs ); - } - template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, nullptr ); - } -#endif // CATCH_CONFIG_CPP11_NULLPTR - -} // end of namespace Internal -} // end of namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// #included from: catch_tostring.h -#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED - -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -// #included from: catch_objc_arc.hpp -#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED - -#import - -#ifdef __has_feature -#define CATCH_ARC_ENABLED __has_feature(objc_arc) -#else -#define CATCH_ARC_ENABLED 0 -#endif - -void arcSafeRelease( NSObject* obj ); -id performOptionalSelector( id obj, SEL sel ); - -#if !CATCH_ARC_ENABLED -inline void arcSafeRelease( NSObject* obj ) { - [obj release]; -} -inline id performOptionalSelector( id obj, SEL sel ) { - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; - return nil; -} -#define CATCH_UNSAFE_UNRETAINED -#define CATCH_ARC_STRONG -#else -inline void arcSafeRelease( NSObject* ){} -inline id performOptionalSelector( id obj, SEL sel ) { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#endif - if( [obj respondsToSelector: sel] ) - return [obj performSelector: sel]; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - return nil; -} -#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained -#define CATCH_ARC_STRONG __strong -#endif - -#endif - -#ifdef CATCH_CONFIG_CPP11_TUPLE -#include -#endif - -#ifdef CATCH_CONFIG_CPP11_IS_ENUM -#include -#endif - -namespace Catch { - -// Why we're here. -template -std::string toString( T const& value ); - -// Built in overloads - -std::string toString( std::string const& value ); -std::string toString( std::wstring const& value ); -std::string toString( const char* const value ); -std::string toString( char* const value ); -std::string toString( const wchar_t* const value ); -std::string toString( wchar_t* const value ); -std::string toString( int value ); -std::string toString( unsigned long value ); -std::string toString( unsigned int value ); -std::string toString( const double value ); -std::string toString( const float value ); -std::string toString( bool value ); -std::string toString( char value ); -std::string toString( signed char value ); -std::string toString( unsigned char value ); - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ); -std::string toString( unsigned long long value ); -#endif - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ); -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); - std::string toString( NSObject* const& nsObject ); -#endif - -namespace Detail { - - extern const std::string unprintableString; - - #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) - struct BorgType { - template BorgType( T const& ); - }; - - struct TrueType { char sizer[1]; }; - struct FalseType { char sizer[2]; }; - - TrueType& testStreamable( std::ostream& ); - FalseType testStreamable( FalseType ); - - FalseType operator<<( std::ostream const&, BorgType const& ); - - template - struct IsStreamInsertable { - static std::ostream &s; - static T const&t; - enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; - }; -#else - template - class IsStreamInsertable { - template - static auto test(int) - -> decltype( std::declval() << std::declval(), std::true_type() ); - - template - static auto test(...) -> std::false_type; - - public: - static const bool value = decltype(test(0))::value; - }; -#endif - -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template::value - > - struct EnumStringMaker - { - static std::string convert( T const& ) { return unprintableString; } - }; - - template - struct EnumStringMaker - { - static std::string convert( T const& v ) - { - return ::Catch::toString( - static_cast::type>(v) - ); - } - }; -#endif - template - struct StringMakerBase { -#if defined(CATCH_CONFIG_CPP11_IS_ENUM) - template - static std::string convert( T const& v ) - { - return EnumStringMaker::convert( v ); - } -#else - template - static std::string convert( T const& ) { return unprintableString; } -#endif - }; - - template<> - struct StringMakerBase { - template - static std::string convert( T const& _value ) { - std::ostringstream oss; - oss << _value; - return oss.str(); - } - }; - - std::string rawMemoryToString( const void *object, std::size_t size ); - - template - inline std::string rawMemoryToString( const T& object ) { - return rawMemoryToString( &object, sizeof(object) ); - } - -} // end namespace Detail - -template -struct StringMaker : - Detail::StringMakerBase::value> {}; - -template -struct StringMaker { - template - static std::string convert( U* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -template -struct StringMaker { - static std::string convert( R C::* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ); -} - -//template -//struct StringMaker > { -// static std::string convert( std::vector const& v ) { -// return Detail::rangeToString( v.begin(), v.end() ); -// } -//}; - -template -std::string toString( std::vector const& v ) { - return Detail::rangeToString( v.begin(), v.end() ); -} - -#ifdef CATCH_CONFIG_CPP11_TUPLE - -// toString for tuples -namespace TupleDetail { - template< - typename Tuple, - std::size_t N = 0, - bool = (N < std::tuple_size::value) - > - struct ElementPrinter { - static void print( const Tuple& tuple, std::ostream& os ) - { - os << ( N ? ", " : " " ) - << Catch::toString(std::get(tuple)); - ElementPrinter::print(tuple,os); - } - }; - - template< - typename Tuple, - std::size_t N - > - struct ElementPrinter { - static void print( const Tuple&, std::ostream& ) {} - }; - -} - -template -struct StringMaker> { - - static std::string convert( const std::tuple& tuple ) - { - std::ostringstream os; - os << '{'; - TupleDetail::ElementPrinter>::print( tuple, os ); - os << " }"; - return os.str(); - } -}; -#endif // CATCH_CONFIG_CPP11_TUPLE - -namespace Detail { - template - std::string makeString( T const& value ) { - return StringMaker::convert( value ); - } -} // end namespace Detail - -/// \brief converts any type to a string -/// -/// The default template forwards on to ostringstream - except when an -/// ostringstream overload does not exist - in which case it attempts to detect -/// that and writes {?}. -/// Overload (not specialise) this template for custom typs that you don't want -/// to provide an ostream overload for. -template -std::string toString( T const& value ) { - return StringMaker::convert( value ); -} - - namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ) { - std::ostringstream oss; - oss << "{ "; - if( first != last ) { - oss << Catch::toString( *first ); - for( ++first ; first != last ; ++first ) - oss << ", " << Catch::toString( *first ); - } - oss << " }"; - return oss.str(); - } -} - -} // end namespace Catch - -namespace Catch { - -template -class BinaryExpression; - -template -class MatchExpression; - -// Wraps the LHS of an expression and overloads comparison operators -// for also capturing those and RHS (if any) -template -class ExpressionLhs : public DecomposedExpression { -public: - ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} - - ExpressionLhs& operator = ( const ExpressionLhs& ); - - template - BinaryExpression - operator == ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator != ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator < ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator > ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator <= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator >= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - BinaryExpression operator == ( bool rhs ) { - return captureExpression( rhs ); - } - - BinaryExpression operator != ( bool rhs ) { - return captureExpression( rhs ); - } - - void endExpression() { - m_truthy = m_lhs ? true : false; - m_rb - .setResultType( m_truthy ) - .endExpression( *this ); - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - dest = Catch::toString( m_truthy ); - } - -private: - template - BinaryExpression captureExpression( RhsT& rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } - - template - BinaryExpression captureExpression( bool rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } - -private: - ResultBuilder& m_rb; - T m_lhs; - bool m_truthy; -}; - -template -class BinaryExpression : public DecomposedExpression { -public: - BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) - : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} - - BinaryExpression& operator = ( BinaryExpression& ); - - void endExpression() const { - m_rb - .setResultType( Internal::compare( m_lhs, m_rhs ) ) - .endExpression( *this ); - } - - virtual bool isBinaryExpression() const CATCH_OVERRIDE { - return true; - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - std::string lhs = Catch::toString( m_lhs ); - std::string rhs = Catch::toString( m_rhs ); - char delim = lhs.size() + rhs.size() < 40 && - lhs.find('\n') == std::string::npos && - rhs.find('\n') == std::string::npos ? ' ' : '\n'; - dest.reserve( 7 + lhs.size() + rhs.size() ); - // 2 for spaces around operator - // 2 for operator - // 2 for parentheses (conditionally added later) - // 1 for negation (conditionally added later) - dest = lhs; - dest += delim; - dest += Internal::OperatorTraits::getName(); - dest += delim; - dest += rhs; - } - -private: - ResultBuilder& m_rb; - LhsT m_lhs; - RhsT m_rhs; -}; - -template -class MatchExpression : public DecomposedExpression { -public: - MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) - : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} - - virtual bool isBinaryExpression() const CATCH_OVERRIDE { - return true; - } - - virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { - std::string matcherAsString = m_matcher.toString(); - dest = Catch::toString( m_arg ); - dest += ' '; - if( matcherAsString == Detail::unprintableString ) - dest += m_matcherString; - else - dest += matcherAsString; - } - -private: - ArgT m_arg; - MatcherT m_matcher; - char const* m_matcherString; -}; - -} // end namespace Catch - - -namespace Catch { - - template - inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { - return ExpressionLhs( *this, operand ); - } - - inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { - return ExpressionLhs( *this, value ); - } - - template - inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, - char const* matcherString ) { - MatchExpression expr( arg, matcher, matcherString ); - setResultType( matcher.match( arg ) ); - endExpression( expr ); - } - -} // namespace Catch - -// #included from: catch_message.h -#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED - -#include - -namespace Catch { - - struct MessageInfo { - MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - std::string macroName; - SourceLineInfo lineInfo; - ResultWas::OfType type; - std::string message; - unsigned int sequence; - - bool operator == ( MessageInfo const& other ) const { - return sequence == other.sequence; - } - bool operator < ( MessageInfo const& other ) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; - - struct MessageBuilder { - MessageBuilder( std::string const& macroName, - SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} - - template - MessageBuilder& operator << ( T const& value ) { - m_stream << value; - return *this; - } - - MessageInfo m_info; - std::ostringstream m_stream; - }; - - class ScopedMessage { - public: - ScopedMessage( MessageBuilder const& builder ); - ScopedMessage( ScopedMessage const& other ); - ~ScopedMessage(); - - MessageInfo m_info; - }; - -} // end namespace Catch - -// #included from: catch_interfaces_capture.h -#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct SectionEndInfo; - struct MessageInfo; - class ScopedMessageBuilder; - struct Counts; - - struct IResultCapture { - - virtual ~IResultCapture(); - - virtual void assertionEnded( AssertionResult const& result ) = 0; - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - - virtual void exceptionEarlyReported() = 0; - - virtual void handleFatalErrorCondition( std::string const& message ) = 0; - }; - - IResultCapture& getResultCapture(); -} - -// #included from: catch_debugger.h -#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED - -// #included from: catch_platform.h -#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED - -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -# define CATCH_PLATFORM_IPHONE -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -# define CATCH_PLATFORM_WINDOWS -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINES_NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# endif -#endif - -#include - -namespace Catch{ - - bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); -} - -#ifdef CATCH_PLATFORM_MAC - - // The following code snippet based on: - // http://cocoawithlove.com/2008/03/break-into-debugger.html - #if defined(__ppc64__) || defined(__ppc__) - #define CATCH_TRAP() \ - __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ - : : : "memory","r0","r3","r4" ) - #else - #define CATCH_TRAP() __asm__("int $3\n" : : ) - #endif - -#elif defined(CATCH_PLATFORM_LINUX) - // If we can use inline assembler, do it because this allows us to break - // directly at the location of the failing check instead of breaking inside - // raise() called from it, i.e. one stack frame below. - #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) - #define CATCH_TRAP() asm volatile ("int $3") - #else // Fall back to the generic way. - #include - - #define CATCH_TRAP() raise(SIGTRAP) - #endif -#elif defined(_MSC_VER) - #define CATCH_TRAP() __debugbreak() -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) void __stdcall DebugBreak(); - #define CATCH_TRAP() DebugBreak() -#endif - -#ifdef CATCH_TRAP - #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } -#else - #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); -#endif - -// #included from: catch_interfaces_runner.h -#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED - -namespace Catch { - class TestCase; - - struct IRunner { - virtual ~IRunner(); - virtual bool aborting() const = 0; - }; -} - -#if defined(CATCH_CONFIG_FAST_COMPILE) -/////////////////////////////////////////////////////////////////////////////// -// We can speedup compilation significantly by breaking into debugger lower in -// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER -// macro in each assertion -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - resultBuilder.react(); - -/////////////////////////////////////////////////////////////////////////////// -// Another way to speed-up compilation is to omit local try-catch for REQUIRE* -// macros. -// This can potentially cause false negative, if the test code catches -// the exception before it propagates back up to the runner. -#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look -// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. - -#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -#else -/////////////////////////////////////////////////////////////////////////////// -// In the event of a failure works out if the debugger needs to be invoked -// and/or an exception thrown and takes appropriate action. -// This needs to be done as a macro so the debugger will stop in the user -// source code rather than in Catch library code -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - resultBuilder.react(); -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look - // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ - if( Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ - if( !Catch::getResultCapture().getLastResult()->succeeded() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ - if( __catchResult.allowThrows() ) \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( ... ) { \ - __catchResult.captureExpectedException( matcher ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ - if( __catchResult.allowThrows() ) \ - try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( exceptionType ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ - else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -/////////////////////////////////////////////////////////////////////////////// -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#else - #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << log + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#endif - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_INFO( macroName, log ) \ - Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - try { \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - } catch( ... ) { \ - __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ - } \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) - -// #included from: internal/catch_section.h -#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED - -// #included from: catch_section_info.h -#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED - -// #included from: catch_totals.hpp -#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED - -#include - -namespace Catch { - - struct Counts { - Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} - - Counts operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - diff.failedButOk = failedButOk - other.failedButOk; - return diff; - } - Counts& operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; - } - - std::size_t total() const { - return passed + failed + failedButOk; - } - bool allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool allOk() const { - return failed == 0; - } - - std::size_t passed; - std::size_t failed; - std::size_t failedButOk; - }; - - struct Totals { - - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } - - Totals delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else if( diff.assertions.failedButOk > 0 ) - ++diff.testCases.failedButOk; - else - ++diff.testCases.passed; - return diff; - } - - Totals& operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } - - Counts assertions; - Counts testCases; - }; -} - -#include - -namespace Catch { - - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - - struct SectionEndInfo { - SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) - : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo sectionInfo; - Counts prevAssertions; - double durationInSeconds; - }; - -} // end namespace Catch - -// #included from: catch_timer.h -#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED - -#ifdef _MSC_VER - -namespace Catch { - typedef unsigned long long UInt64; -} -#else -#include -namespace Catch { - typedef uint64_t UInt64; -} -#endif - -namespace Catch { - class Timer { - public: - Timer() : m_ticks( 0 ) {} - void start(); - unsigned int getElapsedMicroseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - - private: - UInt64 m_ticks; - }; - -} // namespace Catch - -#include - -namespace Catch { - - class Section : NonCopyable { - public: - Section( SectionInfo const& info ); - ~Section(); - - // This indicates whether the section should be executed or not - operator bool() const; - - private: - SectionInfo m_info; - - std::string m_name; - Counts m_assertions; - bool m_sectionIncluded; - Timer m_timer; - }; - -} // end namespace Catch - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define INTERNAL_CATCH_SECTION( ... ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) -#else - #define INTERNAL_CATCH_SECTION( name, desc ) \ - if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) -#endif - -// #included from: internal/catch_generators.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - -template -struct IGenerator { - virtual ~IGenerator() {} - virtual T getValue( std::size_t index ) const = 0; - virtual std::size_t size () const = 0; -}; - -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast( index ); - } - - virtual std::size_t size() const { - return static_cast( 1+m_to-m_from ); - } - -private: - - T m_from; - T m_to; -}; - -template -class ValuesGenerator : public IGenerator { -public: - ValuesGenerator(){} - - void add( T value ) { - m_values.push_back( value ); - } - - virtual T getValue( std::size_t index ) const { - return m_values[index]; - } - - virtual std::size_t size() const { - return m_values.size(); - } - -private: - std::vector m_values; -}; - -template -class CompositeGenerator { -public: - CompositeGenerator() : m_totalSize( 0 ) {} - - // *** Move semantics, similar to auto_ptr *** - CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) - { - move( other ); - } - - CompositeGenerator& setFileInfo( const char* fileInfo ) { - m_fileInfo = fileInfo; - return *this; - } - - ~CompositeGenerator() { - deleteAll( m_composed ); - } - - operator T () const { - size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - - typename std::vector*>::const_iterator it = m_composed.begin(); - typename std::vector*>::const_iterator itEnd = m_composed.end(); - for( size_t index = 0; it != itEnd; ++it ) - { - const IGenerator* generator = *it; - if( overallIndex >= index && overallIndex < index + generator->size() ) - { - return generator->getValue( overallIndex-index ); - } - index += generator->size(); - } - CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so - } - - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> m_composed; - std::string m_fileInfo; - size_t m_totalSize; -}; - -namespace Generators -{ - template - CompositeGenerator between( T from, T to ) { - CompositeGenerator generators; - generators.add( new BetweenGenerator( from, to ) ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3 ){ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3, T val4 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - valuesGen->add( val4 ); - generators.add( valuesGen ); - return generators; - } - -} // end namespace Generators - -using namespace Generators; - -} // end namespace Catch - -#define INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -// #included from: internal/catch_interfaces_exception.h -#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED - -#include -#include - -// #included from: catch_interfaces_registry_hub.h -#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED - -#include - -namespace Catch { - - class TestCase; - struct ITestCaseRegistry; - struct IExceptionTranslatorRegistry; - struct IExceptionTranslator; - struct IReporterRegistry; - struct IReporterFactory; - struct ITagAliasRegistry; - - struct IRegistryHub { - virtual ~IRegistryHub(); - - virtual IReporterRegistry const& getReporterRegistry() const = 0; - virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; - virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; - - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; - }; - - struct IMutableRegistryHub { - virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; - virtual void registerListener( Ptr const& factory ) = 0; - virtual void registerTest( TestCase const& testInfo ) = 0; - virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; - }; - - IRegistryHub& getRegistryHub(); - IMutableRegistryHub& getMutableRegistryHub(); - void cleanUp(); - std::string translateActiveException(); - -} - -namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); - - struct IExceptionTranslator; - typedef std::vector ExceptionTranslators; - - struct IExceptionTranslator { - virtual ~IExceptionTranslator(); - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; - }; - - struct IExceptionTranslatorRegistry { - virtual ~IExceptionTranslatorRegistry(); - - virtual std::string translateActiveException() const = 0; - }; - - class ExceptionTranslatorRegistrar { - template - class ExceptionTranslator : public IExceptionTranslator { - public: - - ExceptionTranslator( std::string(*translateFunction)( T& ) ) - : m_translateFunction( translateFunction ) - {} - - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { - try { - if( it == itEnd ) - throw; - else - return (*it)->translate( it+1, itEnd ); - } - catch( T& ex ) { - return m_translateFunction( ex ); - } - } - - protected: - std::string(*m_translateFunction)( T& ); - }; - - public: - template - ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { - getMutableRegistryHub().registerTranslator - ( new ExceptionTranslator( translateFunction ) ); - } - }; -} - -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ - static std::string translatorName( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ - static std::string translatorName( signature ) - -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) - -// #included from: internal/catch_approx.hpp -#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED - -#include -#include - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) -#include -#endif - -namespace Catch { -namespace Detail { - - class Approx { - public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_margin( 0.0 ), - m_scale( 1.0 ), - m_value( value ) - {} - - Approx( Approx const& other ) - : m_epsilon( other.m_epsilon ), - m_margin( other.m_margin ), - m_scale( other.m_scale ), - m_value( other.m_value ) - {} - - static Approx custom() { - return Approx( 0 ); - } - -#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) - - template ::value>::type> - Approx operator()( T value ) { - Approx approx( static_cast(value) ); - approx.epsilon( m_epsilon ); - approx.margin( m_margin ); - approx.scale( m_scale ); - return approx; - } - - template ::value>::type> - explicit Approx( T value ): Approx(static_cast(value)) - {} - - template ::value>::type> - friend bool operator == ( const T& lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - auto lhs_v = double(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); - if (relativeOK) { - return true; - } - return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; - } - - template ::value>::type> - friend bool operator == ( Approx const& lhs, const T& rhs ) { - return operator==( rhs, lhs ); - } - - template ::value>::type> - friend bool operator != ( T lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - template ::value>::type> - friend bool operator != ( Approx const& lhs, T rhs ) { - return !operator==( rhs, lhs ); - } - - template ::value>::type> - friend bool operator <= ( T lhs, Approx const& rhs ) { - return double(lhs) < rhs.m_value || lhs == rhs; - } - - template ::value>::type> - friend bool operator <= ( Approx const& lhs, T rhs ) { - return lhs.m_value < double(rhs) || lhs == rhs; - } - - template ::value>::type> - friend bool operator >= ( T lhs, Approx const& rhs ) { - return double(lhs) > rhs.m_value || lhs == rhs; - } - - template ::value>::type> - friend bool operator >= ( Approx const& lhs, T rhs ) { - return lhs.m_value > double(rhs) || lhs == rhs; - } - - template ::value>::type> - Approx& epsilon( T newEpsilon ) { - m_epsilon = double(newEpsilon); - return *this; - } - - template ::value>::type> - Approx& margin( T newMargin ) { - m_margin = double(newMargin); - return *this; - } - - template ::value>::type> - Approx& scale( T newScale ) { - m_scale = double(newScale); - return *this; - } - -#else - - Approx operator()( double value ) { - Approx approx( value ); - approx.epsilon( m_epsilon ); - approx.margin( m_margin ); - approx.scale( m_scale ); - return approx; - } - - friend bool operator == ( double lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula - bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); - if (relativeOK) { - return true; - } - return std::fabs(lhs - rhs.m_value) < rhs.m_margin; - } - - friend bool operator == ( Approx const& lhs, double rhs ) { - return operator==( rhs, lhs ); - } - - friend bool operator != ( double lhs, Approx const& rhs ) { - return !operator==( lhs, rhs ); - } - - friend bool operator != ( Approx const& lhs, double rhs ) { - return !operator==( rhs, lhs ); - } - - friend bool operator <= ( double lhs, Approx const& rhs ) { - return lhs < rhs.m_value || lhs == rhs; - } - - friend bool operator <= ( Approx const& lhs, double rhs ) { - return lhs.m_value < rhs || lhs == rhs; - } - - friend bool operator >= ( double lhs, Approx const& rhs ) { - return lhs > rhs.m_value || lhs == rhs; - } - - friend bool operator >= ( Approx const& lhs, double rhs ) { - return lhs.m_value > rhs || lhs == rhs; - } - - Approx& epsilon( double newEpsilon ) { - m_epsilon = newEpsilon; - return *this; - } - - Approx& margin( double newMargin ) { - m_margin = newMargin; - return *this; - } - - Approx& scale( double newScale ) { - m_scale = newScale; - return *this; - } -#endif - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; - return oss.str(); - } - - private: - double m_epsilon; - double m_margin; - double m_scale; - double m_value; - }; -} - -template<> -inline std::string toString( Detail::Approx const& value ) { - return value.toString(); -} - -} // end namespace Catch - -// #included from: internal/catch_matchers_string.h -#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED - -namespace Catch { -namespace Matchers { - - namespace StdString { - - struct CasedString - { - CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); - std::string adjustString( std::string const& str ) const; - std::string caseSensitivitySuffix() const; - - CaseSensitive::Choice m_caseSensitivity; - std::string m_str; - }; - - struct StringMatcherBase : MatcherBase { - StringMatcherBase( std::string const& operation, CasedString const& comparator ); - virtual std::string describe() const CATCH_OVERRIDE; - - CasedString m_comparator; - std::string m_operation; - }; - - struct EqualsMatcher : StringMatcherBase { - EqualsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - struct ContainsMatcher : StringMatcherBase { - ContainsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - struct StartsWithMatcher : StringMatcherBase { - StartsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - struct EndsWithMatcher : StringMatcherBase { - EndsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const CATCH_OVERRIDE; - }; - - } // namespace StdString - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - - StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); - -} // namespace Matchers -} // namespace Catch - -// #included from: internal/catch_matchers_vector.h -#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED - -namespace Catch { -namespace Matchers { - - namespace Vector { - - template - struct ContainsElementMatcher : MatcherBase, T> { - - ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} - - bool match(std::vector const &v) const CATCH_OVERRIDE { - return std::find(v.begin(), v.end(), m_comparator) != v.end(); - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "Contains: " + Catch::toString( m_comparator ); - } - - T const& m_comparator; - }; - - template - struct ContainsMatcher : MatcherBase, std::vector > { - - ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - - bool match(std::vector const &v) const CATCH_OVERRIDE { - // !TBD: see note in EqualsMatcher - if (m_comparator.size() > v.size()) - return false; - for (size_t i = 0; i < m_comparator.size(); ++i) - if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) - return false; - return true; - } - virtual std::string describe() const CATCH_OVERRIDE { - return "Contains: " + Catch::toString( m_comparator ); - } - - std::vector const& m_comparator; - }; - - template - struct EqualsMatcher : MatcherBase, std::vector > { - - EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - - bool match(std::vector const &v) const CATCH_OVERRIDE { - // !TBD: This currently works if all elements can be compared using != - // - a more general approach would be via a compare template that defaults - // to using !=. but could be specialised for, e.g. std::vector etc - // - then just call that directly - if (m_comparator.size() != v.size()) - return false; - for (size_t i = 0; i < v.size(); ++i) - if (m_comparator[i] != v[i]) - return false; - return true; - } - virtual std::string describe() const CATCH_OVERRIDE { - return "Equals: " + Catch::toString( m_comparator ); - } - std::vector const& m_comparator; - }; - - } // namespace Vector - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - - template - Vector::ContainsMatcher Contains( std::vector const& comparator ) { - return Vector::ContainsMatcher( comparator ); - } - - template - Vector::ContainsElementMatcher VectorContains( T const& comparator ) { - return Vector::ContainsElementMatcher( comparator ); - } - - template - Vector::EqualsMatcher Equals( std::vector const& comparator ) { - return Vector::EqualsMatcher( comparator ); - } - -} // namespace Matchers -} // namespace Catch - -// #included from: internal/catch_interfaces_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED - -// #included from: catch_tag_alias.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED - -#include - -namespace Catch { - - struct TagAlias { - TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} - - std::string tag; - SourceLineInfo 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 ); } -// #included from: catch_option.hpp -#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED - -namespace Catch { - - // An optional type - template - class Option { - public: - Option() : nullableValue( CATCH_NULL ) {} - Option( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) - {} - - ~Option() { - reset(); - } - - Option& operator= ( Option const& _other ) { - if( &_other != this ) { - reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); - } - return *this; - } - Option& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); - return *this; - } - - void reset() { - if( nullableValue ) - nullableValue->~T(); - nullableValue = CATCH_NULL; - } - - T& operator*() { return *nullableValue; } - T const& operator*() const { return *nullableValue; } - T* operator->() { return nullableValue; } - const T* operator->() const { return nullableValue; } - - T valueOr( T const& defaultValue ) const { - return nullableValue ? *nullableValue : defaultValue; - } - - bool some() const { return nullableValue != CATCH_NULL; } - bool none() const { return nullableValue == CATCH_NULL; } - - bool operator !() const { return nullableValue == CATCH_NULL; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); - } - - private: - T *nullableValue; - union { - char storage[sizeof(T)]; - - // These are here to force alignment for the storage - long double dummy1; - void (*dummy2)(); - long double dummy3; -#ifdef CATCH_CONFIG_CPP11_LONG_LONG - long long dummy4; -#endif - }; - }; - -} // end namespace Catch - -namespace Catch { - - struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - virtual Option find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; - - static ITagAliasRegistry const& get(); - }; - -} // end namespace Catch - -// These files are included here so the single_include script doesn't put them -// in the conditionally compiled sections -// #included from: internal/catch_test_case_info.h -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED - -#include -#include - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - struct ITestCase; - - struct TestCaseInfo { - enum SpecialProperties{ - None = 0, - IsHidden = 1 << 1, - ShouldFail = 1 << 2, - MayFail = 1 << 3, - Throws = 1 << 4, - NonPortable = 1 << 5 - }; - - TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ); - - TestCaseInfo( TestCaseInfo const& other ); - - friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); - - bool isHidden() const; - bool throws() const; - bool okToFail() const; - bool expectedToFail() const; - - std::string name; - std::string className; - std::string description; - std::set tags; - std::set lcaseTags; - std::string tagsAsString; - SourceLineInfo lineInfo; - SpecialProperties properties; - }; - - class TestCase : public TestCaseInfo { - public: - - TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); - - TestCase withName( std::string const& _newName ) const; - - void invoke() const; - - TestCaseInfo const& getTestCaseInfo() const; - - void swap( TestCase& other ); - bool operator == ( TestCase const& other ) const; - bool operator < ( TestCase const& other ) const; - TestCase& operator = ( TestCase const& other ); - - private: - Ptr test; - }; - - TestCase makeTestCase( ITestCase* testCase, - std::string const& className, - std::string const& name, - std::string const& description, - SourceLineInfo const& lineInfo ); -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - - -#ifdef __OBJC__ -// #included from: internal/catch_objc.hpp -#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED - -#import - -#include - -// NB. Any general catch headers included here must be included -// in catch.hpp first to make sure they are included by the single -// header for non obj-usage - -/////////////////////////////////////////////////////////////////////////////// -// This protocol is really only here for (self) documenting purposes, since -// all its methods are optional. -@protocol OcFixture - -@optional - --(void) setUp; --(void) tearDown; - -@end - -namespace Catch { - - class OcMethod : public SharedImpl { - - public: - OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} - - virtual void invoke() const { - id obj = [[m_cls alloc] init]; - - performOptionalSelector( obj, @selector(setUp) ); - performOptionalSelector( obj, m_sel ); - performOptionalSelector( obj, @selector(tearDown) ); - - arcSafeRelease( obj ); - } - private: - virtual ~OcMethod() {} - - Class m_cls; - SEL m_sel; - }; - - namespace Detail{ - - inline std::string getAnnotation( Class cls, - std::string const& annotationName, - std::string const& testCaseName ) { - NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; - SEL sel = NSSelectorFromString( selStr ); - arcSafeRelease( selStr ); - id value = performOptionalSelector( cls, sel ); - if( value ) - return [(NSString*)value UTF8String]; - return ""; - } - } - - inline size_t registerTestMethods() { - size_t noTestMethods = 0; - int noClasses = objc_getClassList( CATCH_NULL, 0 ); - - Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); - objc_getClassList( classes, noClasses ); - - for( int c = 0; c < noClasses; c++ ) { - Class cls = classes[c]; - { - u_int count; - Method* methods = class_copyMethodList( cls, &count ); - for( u_int m = 0; m < count ; m++ ) { - SEL selector = method_getName(methods[m]); - std::string methodName = sel_getName(selector); - if( startsWith( methodName, "Catch_TestCase_" ) ) { - std::string testCaseName = methodName.substr( 15 ); - std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); - std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); - const char* className = class_getName( cls ); - - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); - noTestMethods++; - } - } - free(methods); - } - } - return noTestMethods; - } - - namespace Matchers { - namespace Impl { - namespace NSStringMatchers { - - struct StringHolder : MatcherBase{ - StringHolder( NSString* substr ) : m_substr( [substr copy] ){} - StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} - StringHolder() { - arcSafeRelease( m_substr ); - } - - virtual bool match( NSString* arg ) const CATCH_OVERRIDE { - return false; - } - - NSString* m_substr; - }; - - struct Equals : StringHolder { - Equals( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const CATCH_OVERRIDE { - return (str != nil || m_substr == nil ) && - [str isEqualToString:m_substr]; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "equals string: " + Catch::toString( m_substr ); - } - }; - - struct Contains : StringHolder { - Contains( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location != NSNotFound; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "contains string: " + Catch::toString( m_substr ); - } - }; - - struct StartsWith : StringHolder { - StartsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == 0; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "starts with: " + Catch::toString( m_substr ); - } - }; - struct EndsWith : StringHolder { - EndsWith( NSString* substr ) : StringHolder( substr ){} - - virtual bool match( NSString* str ) const { - return (str != nil || m_substr == nil ) && - [str rangeOfString:m_substr].location == [str length] - [m_substr length]; - } - - virtual std::string describe() const CATCH_OVERRIDE { - return "ends with: " + Catch::toString( m_substr ); - } - }; - - } // namespace NSStringMatchers - } // namespace Impl - - inline Impl::NSStringMatchers::Equals - Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } - - inline Impl::NSStringMatchers::Contains - Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } - - inline Impl::NSStringMatchers::StartsWith - StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } - - inline Impl::NSStringMatchers::EndsWith - EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } - - } // namespace Matchers - - using namespace Matchers; - -} // namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ -return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ -{ \ -return @ desc; \ -} \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) - -#endif - -#ifdef CATCH_IMPL - -// !TBD: Move the leak detector code into a separate header -#ifdef CATCH_CONFIG_WINDOWS_CRTDBG -#include -class LeakDetector { -public: - LeakDetector() { - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); - } -}; -#else -class LeakDetector {}; -#endif - -LeakDetector leakDetector; - -// #included from: internal/catch_impl.hpp -#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED - -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// #included from: ../catch_session.hpp -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -// #included from: internal/catch_commandline.hpp -#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED - -// #included from: catch_config.hpp -#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED - -// #included from: catch_test_spec_parser.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_test_spec.hpp -#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -// #included from: catch_wildcard_pattern.hpp -#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED - -#include - -namespace Catch -{ - class WildcardPattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - - public: - - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_wildcard( NoWildcard ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - virtual ~WildcardPattern(); - virtual bool matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - } - private: - std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } - CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard; - std::string m_pattern; - }; -} - -#include -#include - -namespace Catch { - - class TestSpec { - struct Pattern : SharedImpl<> { - virtual ~Pattern(); - virtual bool matches( TestCaseInfo const& testCase ) const = 0; - }; - class NamePattern : public Pattern { - public: - NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } - private: - WildcardPattern m_wildcardPattern; - }; - - class TagPattern : public Pattern { - public: - TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); - } - private: - std::string m_tag; - }; - - class ExcludedPattern : public Pattern { - public: - ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } - private: - Ptr m_underlyingPattern; - }; - - struct Filter { - std::vector > m_patterns; - - bool matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { - if( !(*it)->matches( testCase ) ) - return false; - } - return true; - } - }; - - public: - bool hasFilters() const { - return !m_filters.empty(); - } - bool matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) - if( it->matches( testCase ) ) - return true; - return false; - } - - private: - std::vector m_filters; - - friend class TestSpecParser; - }; -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -namespace Catch { - - class TestSpecParser { - enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - Mode m_mode; - bool m_exclusion; - std::size_t m_start, m_pos; - std::string m_arg; - std::vector m_escapeChars; - TestSpec::Filter m_currentFilter; - TestSpec m_testSpec; - ITagAliasRegistry const* m_tagAliases; - - public: - TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} - - TestSpecParser& parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - m_escapeChars.clear(); - for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); - if( m_mode == Name ) - addPattern(); - return *this; - } - TestSpec testSpec() { - addFilter(); - return m_testSpec; - } - private: - void visitChar( char c ) { - if( m_mode == None ) { - switch( c ) { - case ' ': return; - case '~': m_exclusion = true; return; - case '[': return startNewMode( Tag, ++m_pos ); - case '"': return startNewMode( QuotedName, ++m_pos ); - case '\\': return escape(); - default: startNewMode( Name, m_pos ); break; - } - } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern(); - startNewMode( Tag, ++m_pos ); - } - else if( c == '\\' ) - escape(); - } - else if( m_mode == EscapedName ) - m_mode = Name; - else if( m_mode == QuotedName && c == '"' ) - addPattern(); - else if( m_mode == Tag && c == ']' ) - addPattern(); - } - void startNewMode( Mode mode, std::size_t start ) { - m_mode = mode; - m_start = start; - } - void escape() { - if( m_mode == None ) - m_start = m_pos; - m_mode = EscapedName; - m_escapeChars.push_back( m_pos ); - } - std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } - template - void addPattern() { - std::string token = subString(); - for( size_t i = 0; i < m_escapeChars.size(); ++i ) - token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); - m_escapeChars.clear(); - if( startsWith( token, "exclude:" ) ) { - m_exclusion = true; - token = token.substr( 8 ); - } - if( !token.empty() ) { - Ptr pattern = new T( token ); - if( m_exclusion ) - pattern = new TestSpec::ExcludedPattern( pattern ); - m_currentFilter.m_patterns.push_back( pattern ); - } - m_exclusion = false; - m_mode = None; - } - void addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } - }; - inline TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -// #included from: catch_interfaces_config.h -#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; - - struct WarnAbout { enum What { - Nothing = 0x00, - NoAssertions = 0x01 - }; }; - - struct ShowDurations { enum OrNot { - DefaultForReporter, - Always, - Never - }; }; - struct RunTests { enum InWhatOrder { - InDeclarationOrder, - InLexicographicalOrder, - InRandomOrder - }; }; - struct UseColour { enum YesOrNo { - Auto, - Yes, - No - }; }; - - class TestSpec; - - struct IConfig : IShared { - - virtual ~IConfig(); - - virtual bool allowThrows() const = 0; - virtual std::ostream& stream() const = 0; - virtual std::string name() const = 0; - virtual bool includeSuccessfulResults() const = 0; - virtual bool shouldDebugBreak() const = 0; - virtual bool warnAboutMissingAssertions() const = 0; - virtual int abortAfter() const = 0; - virtual bool showInvisibles() const = 0; - virtual ShowDurations::OrNot showDurations() const = 0; - virtual TestSpec const& testSpec() const = 0; - virtual RunTests::InWhatOrder runOrder() const = 0; - virtual unsigned int rngSeed() const = 0; - virtual UseColour::YesOrNo useColour() const = 0; - virtual std::vector const& getSectionsToRun() const = 0; - - }; -} - -// #included from: catch_stream.h -#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED - -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - -#include -#include -#include -#include - -namespace Catch { - - std::ostream& cout(); - std::ostream& cerr(); - - struct IStream { - virtual ~IStream() CATCH_NOEXCEPT; - virtual std::ostream& stream() const = 0; - }; - - class FileStream : public IStream { - mutable std::ofstream m_ofs; - public: - FileStream( std::string const& filename ); - virtual ~FileStream() CATCH_NOEXCEPT; - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class CoutStream : public IStream { - mutable std::ostream m_os; - public: - CoutStream(); - virtual ~CoutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; - - class DebugOutStream : public IStream { - CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; - mutable std::ostream m_os; - public: - DebugOutStream(); - virtual ~DebugOutStream() CATCH_NOEXCEPT; - - public: // IStream - virtual std::ostream& stream() const CATCH_OVERRIDE; - }; -} - -#include -#include -#include -#include - -#ifndef CATCH_CONFIG_CONSOLE_WIDTH -#define CATCH_CONFIG_CONSOLE_WIDTH 80 -#endif - -namespace Catch { - - struct ConfigData { - - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - showInvisibles( false ), - filenamesAsTags( false ), - abortAfter( -1 ), - rngSeed( 0 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ), - useColour( UseColour::Auto ) - {} - - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; - - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; - bool filenamesAsTags; - - int abortAfter; - unsigned int rngSeed; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - RunTests::InWhatOrder runOrder; - UseColour::YesOrNo useColour; - - std::string outputFilename; - std::string name; - std::string processName; - - std::vector reporterNames; - std::vector testsOrTags; - std::vector sectionsToRun; - }; - - class Config : public SharedImpl { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); - virtual void dummy(); - public: - - Config() - {} - - Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) - parser.parse( data.testsOrTags[i] ); - m_testSpec = parser.testSpec(); - } - } - - virtual ~Config() {} - - std::string const& getFilename() const { - return m_data.outputFilename ; - } - - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } - - std::string getProcessName() const { return m_data.processName; } - - std::vector const& getReporterNames() const { return m_data.reporterNames; } - std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } - - virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } - - bool showHelp() const { return m_data.showHelp; } - - // IConfig interface - virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } - virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } - virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } - virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } - virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } - virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } - virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } - - private: - - IStream const* openStream() { - if( m_data.outputFilename.empty() ) - return new CoutStream(); - else if( m_data.outputFilename[0] == '%' ) { - if( m_data.outputFilename == "%debug" ) - return new DebugOutStream(); - else - throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); - } - else - return new FileStream( m_data.outputFilename ); - } - ConfigData m_data; - - CATCH_AUTO_PTR( IStream const ) m_stream; - TestSpec m_testSpec; - }; - -} // end namespace Catch - -// #included from: catch_clara.h -#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED - -// Use Catch's value for console width (store Clara's off to the side, if present) -#ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH -#undef CLARA_CONFIG_CONSOLE_WIDTH -#endif -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -// #included from: ../external/clara.h - -// Version 0.0.2.4 - -// Only use header guard if we are not using an outer namespace -#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) - -#ifndef STITCH_CLARA_OPEN_NAMESPACE -#define TWOBLUECUBES_CLARA_H_INCLUDED -#define STITCH_CLARA_OPEN_NAMESPACE -#define STITCH_CLARA_CLOSE_NAMESPACE -#else -#define STITCH_CLARA_CLOSE_NAMESPACE } -#endif - -#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE - -// ----------- #included from tbc_text_format.h ----------- - -// Only use header guard if we are not using an outer namespace -#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) -#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -#define TBC_TEXT_FORMAT_H_INCLUDED -#endif - -#include -#include -#include -#include -#include - -// Use optional outer namespace -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Tbc - -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TBC_TEXT_FORMAT_H_INCLUDED - -// ----------- end of #include from tbc_text_format.h ----------- -// ........... back in clara.h - -#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE - -// ----------- #included from clara_compilers.h ----------- - -#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED -#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? -// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) - -// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? - -// In general each macro has a _NO_ form -// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 - -#ifdef __clang__ - -#if __has_feature(cxx_nullptr) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#if __has_feature(cxx_noexcept) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1600) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(__cplusplus) && __cplusplus >= 201103L - -#define CLARA_CPP11_OR_GREATER - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) -#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE -#endif -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NULLPTR -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_UNIQUE_PTR -#endif - -// noexcept support: -#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) -#define CLARA_NOEXCEPT noexcept -# define CLARA_NOEXCEPT_IS(x) noexcept(x) -#else -#define CLARA_NOEXCEPT throw() -# define CLARA_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CLARA_CONFIG_CPP11_NULLPTR -#define CLARA_NULL nullptr -#else -#define CLARA_NULL NULL -#endif - -// override support -#ifdef CLARA_CONFIG_CPP11_OVERRIDE -#define CLARA_OVERRIDE override -#else -#define CLARA_OVERRIDE -#endif - -// unique_ptr support -#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR -# define CLARA_AUTO_PTR( T ) std::unique_ptr -#else -# define CLARA_AUTO_PTR( T ) std::auto_ptr -#endif - -#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - -// ----------- end of #include from clara_compilers.h ----------- -// ........... back in clara.h - -#include -#include -#include - -#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CLARA_PLATFORM_WINDOWS -#endif - -// Use optional outer namespace -#ifdef STITCH_CLARA_OPEN_NAMESPACE -STITCH_CLARA_OPEN_NAMESPACE -#endif - -namespace Clara { - - struct UnpositionalTag {}; - - extern UnpositionalTag _; - -#ifdef CLARA_CONFIG_MAIN - UnpositionalTag _; -#endif - - namespace Detail { - -#ifdef CLARA_CONSOLE_WIDTH - const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - using namespace Tbc; - - inline bool startsWith( std::string const& str, std::string const& prefix ) { - return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; - } - - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - - template struct IsBool { static const bool value = false; }; - template<> struct IsBool { static const bool value = true; }; - - template - void convertInto( std::string const& _source, T& _dest ) { - std::stringstream ss; - ss << _source; - ss >> _dest; - if( ss.fail() ) - throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); - } - inline void convertInto( std::string const& _source, std::string& _dest ) { - _dest = _source; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - inline void convertInto( std::string const& _source, bool& _dest ) { - std::string sourceLC = _source; - std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); - if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) - _dest = true; - else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) - _dest = false; - else - throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); - } - - template - struct IArgFunction { - virtual ~IArgFunction() {} -#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS - IArgFunction() = default; - IArgFunction( IArgFunction const& ) = default; -#endif - virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual bool takesArg() const = 0; - virtual IArgFunction* clone() const = 0; - }; - - template - class BoundArgFunction { - public: - BoundArgFunction() : functionObj( CLARA_NULL ) {} - BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} - BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; - delete functionObj; - functionObj = newFunctionObj; - return *this; - } - ~BoundArgFunction() { delete functionObj; } - - void set( ConfigT& config, std::string const& value ) const { - functionObj->set( config, value ); - } - bool takesArg() const { return functionObj->takesArg(); } - - bool isSet() const { - return functionObj != CLARA_NULL; - } - private: - IArgFunction* functionObj; - }; - - template - struct NullBinder : IArgFunction{ - virtual void set( C&, std::string const& ) const {} - virtual bool takesArg() const { return true; } - virtual IArgFunction* clone() const { return new NullBinder( *this ); } - }; - - template - struct BoundDataMember : IArgFunction{ - BoundDataMember( M C::* _member ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - convertInto( stringValue, p.*member ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } - M C::* member; - }; - template - struct BoundUnaryMethod : IArgFunction{ - BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - (p.*member)( value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } - void (C::*member)( M ); - }; - template - struct BoundNullaryMethod : IArgFunction{ - BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - (p.*member)(); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } - void (C::*member)(); - }; - - template - struct BoundUnaryFunction : IArgFunction{ - BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - function( obj ); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } - void (*function)( C& ); - }; - - template - struct BoundBinaryFunction : IArgFunction{ - BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - function( obj, value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } - void (*function)( C&, T ); - }; - - } // namespace Detail - - inline std::vector argsToVector( int argc, char const* const* const argv ) { - std::vector args( static_cast( argc ) ); - for( std::size_t i = 0; i < static_cast( argc ); ++i ) - args[i] = argv[i]; - - return args; - } - - class Parser { - enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; - Mode mode; - std::size_t from; - bool inQuotes; - public: - - struct Token { - enum Type { Positional, ShortOpt, LongOpt }; - Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} - Type type; - std::string data; - }; - - Parser() : mode( None ), from( 0 ), inQuotes( false ){} - - void parseIntoTokens( std::vector const& args, std::vector& tokens ) { - const std::string doubleDash = "--"; - for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) - parseIntoTokens( args[i], tokens); - } - - void parseIntoTokens( std::string const& arg, std::vector& tokens ) { - for( std::size_t i = 0; i < arg.size(); ++i ) { - char c = arg[i]; - if( c == '"' ) - inQuotes = !inQuotes; - mode = handleMode( i, c, arg, tokens ); - } - mode = handleMode( arg.size(), '\0', arg, tokens ); - } - Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - switch( mode ) { - case None: return handleNone( i, c ); - case MaybeShortOpt: return handleMaybeShortOpt( i, c ); - case ShortOpt: - case LongOpt: - case SlashOpt: return handleOpt( i, c, arg, tokens ); - case Positional: return handlePositional( i, c, arg, tokens ); - default: throw std::logic_error( "Unknown mode" ); - } - } - - Mode handleNone( std::size_t i, char c ) { - if( inQuotes ) { - from = i; - return Positional; - } - switch( c ) { - case '-': return MaybeShortOpt; -#ifdef CLARA_PLATFORM_WINDOWS - case '/': from = i+1; return SlashOpt; -#endif - default: from = i; return Positional; - } - } - Mode handleMaybeShortOpt( std::size_t i, char c ) { - switch( c ) { - case '-': from = i+1; return LongOpt; - default: from = i; return ShortOpt; - } - } - - Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) - return mode; - - std::string optName = arg.substr( from, i-from ); - if( mode == ShortOpt ) - for( std::size_t j = 0; j < optName.size(); ++j ) - tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); - else if( mode == SlashOpt && optName.size() == 1 ) - tokens.push_back( Token( Token::ShortOpt, optName ) ); - else - tokens.push_back( Token( Token::LongOpt, optName ) ); - return None; - } - Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) - return mode; - - std::string data = arg.substr( from, i-from ); - tokens.push_back( Token( Token::Positional, data ) ); - return None; - } - }; - - template - struct CommonArgProperties { - CommonArgProperties() {} - CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} - - Detail::BoundArgFunction boundField; - std::string description; - std::string detail; - std::string placeholder; // Only value if boundField takes an arg - - bool takesArg() const { - return !placeholder.empty(); - } - void validate() const { - if( !boundField.isSet() ) - throw std::logic_error( "option not bound" ); - } - }; - struct OptionArgProperties { - std::vector shortNames; - std::string longName; - - bool hasShortName( std::string const& shortName ) const { - return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); - } - bool hasLongName( std::string const& _longName ) const { - return _longName == longName; - } - }; - struct PositionalArgProperties { - PositionalArgProperties() : position( -1 ) {} - int position; // -1 means non-positional (floating) - - bool isFixedPositional() const { - return position != -1; - } - }; - - template - class CommandLine { - - struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { - Arg() {} - Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} - - using CommonArgProperties::placeholder; // !TBD - - std::string dbgName() const { - if( !longName.empty() ) - return "--" + longName; - if( !shortNames.empty() ) - return "-" + shortNames[0]; - return "positional args"; - } - std::string commands() const { - std::ostringstream oss; - bool first = true; - std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); - for(; it != itEnd; ++it ) { - if( first ) - first = false; - else - oss << ", "; - oss << "-" << *it; - } - if( !longName.empty() ) { - if( !first ) - oss << ", "; - oss << "--" << longName; - } - if( !placeholder.empty() ) - oss << " <" << placeholder << ">"; - return oss.str(); - } - }; - - typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; - - friend void addOptName( Arg& arg, std::string const& optName ) - { - if( optName.empty() ) - return; - if( Detail::startsWith( optName, "--" ) ) { - if( !arg.longName.empty() ) - throw std::logic_error( "Only one long opt may be specified. '" - + arg.longName - + "' already specified, now attempting to add '" - + optName + "'" ); - arg.longName = optName.substr( 2 ); - } - else if( Detail::startsWith( optName, "-" ) ) - arg.shortNames.push_back( optName.substr( 1 ) ); - else - throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); - } - friend void setPositionalArg( Arg& arg, int position ) - { - arg.position = position; - } - - class ArgBuilder { - public: - ArgBuilder( Arg* arg ) : m_arg( arg ) {} - - // Bind a non-boolean data member (requires placeholder string) - template - void bind( M C::* field, std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - m_arg->placeholder = placeholder; - } - // Bind a boolean data member (no placeholder required) - template - void bind( bool C::* field ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - } - - // Bind a method taking a single, non-boolean argument (requires a placeholder string) - template - void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - m_arg->placeholder = placeholder; - } - - // Bind a method taking a single, boolean argument (no placeholder string required) - template - void bind( void (C::* unaryMethod)( bool ) ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - } - - // Bind a method that takes no arguments (will be called if opt is present) - template - void bind( void (C::* nullaryMethod)() ) { - m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); - } - - // Bind a free function taking a single argument - the object to operate on (no placeholder string required) - template - void bind( void (* unaryFunction)( C& ) ) { - m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); - } - - // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) - template - void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); - m_arg->placeholder = placeholder; - } - - ArgBuilder& describe( std::string const& description ) { - m_arg->description = description; - return *this; - } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; - return *this; - } - - protected: - Arg* m_arg; - }; - - class OptBuilder : public ArgBuilder { - public: - OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} - OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} - - OptBuilder& operator[]( std::string const& optName ) { - addOptName( *ArgBuilder::m_arg, optName ); - return *this; - } - }; - - public: - - CommandLine() - : m_boundProcessName( new Detail::NullBinder() ), - m_highestSpecifiedArgPosition( 0 ), - m_throwOnUnrecognisedTokens( false ) - {} - CommandLine( CommandLine const& other ) - : m_boundProcessName( other.m_boundProcessName ), - m_options ( other.m_options ), - m_positionalArgs( other.m_positionalArgs ), - m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), - m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) - { - if( other.m_floatingArg.get() ) - m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); - } - - CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { - m_throwOnUnrecognisedTokens = shouldThrow; - return *this; - } - - OptBuilder operator[]( std::string const& optName ) { - m_options.push_back( Arg() ); - addOptName( m_options.back(), optName ); - OptBuilder builder( &m_options.back() ); - return builder; - } - - ArgBuilder operator[]( int position ) { - m_positionalArgs.insert( std::make_pair( position, Arg() ) ); - if( position > m_highestSpecifiedArgPosition ) - m_highestSpecifiedArgPosition = position; - setPositionalArg( m_positionalArgs[position], position ); - ArgBuilder builder( &m_positionalArgs[position] ); - return builder; - } - - // Invoke this with the _ instance - ArgBuilder operator[]( UnpositionalTag ) { - if( m_floatingArg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_floatingArg.reset( new Arg() ); - ArgBuilder builder( m_floatingArg.get() ); - return builder; - } - - template - void bindProcessName( M C::* field ) { - m_boundProcessName = new Detail::BoundDataMember( field ); - } - template - void bindProcessName( void (C::*_unaryMethod)( M ) ) { - m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); - } - - void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { - typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; - std::size_t maxWidth = 0; - for( it = itBegin; it != itEnd; ++it ) - maxWidth = (std::max)( maxWidth, it->commands().size() ); - - for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() - .setWidth( maxWidth+indent ) - .setIndent( indent ) ); - Detail::Text desc( it->description, Detail::TextAttributes() - .setWidth( width - maxWidth - 3 ) ); - - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; - os << usageCol; - - if( i < desc.size() && !desc[i].empty() ) - os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) - << desc[i]; - os << "\n"; - } - } - } - std::string optUsage() const { - std::ostringstream oss; - optUsage( oss ); - return oss.str(); - } - - void argSynopsis( std::ostream& os ) const { - for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { - if( i > 1 ) - os << " "; - typename std::map::const_iterator it = m_positionalArgs.find( i ); - if( it != m_positionalArgs.end() ) - os << "<" << it->second.placeholder << ">"; - else if( m_floatingArg.get() ) - os << "<" << m_floatingArg->placeholder << ">"; - else - throw std::logic_error( "non consecutive positional arguments with no floating args" ); - } - // !TBD No indication of mandatory args - if( m_floatingArg.get() ) { - if( m_highestSpecifiedArgPosition > 1 ) - os << " "; - os << "[<" << m_floatingArg->placeholder << "> ...]"; - } - } - std::string argSynopsis() const { - std::ostringstream oss; - argSynopsis( oss ); - return oss.str(); - } - - void usage( std::ostream& os, std::string const& procName ) const { - validate(); - os << "usage:\n " << procName << " "; - argSynopsis( os ); - if( !m_options.empty() ) { - os << " [options]\n\nwhere options are: \n"; - optUsage( os, 2 ); - } - os << "\n"; - } - std::string usage( std::string const& procName ) const { - std::ostringstream oss; - usage( oss, procName ); - return oss.str(); - } - - ConfigT parse( std::vector const& args ) const { - ConfigT config; - parseInto( args, config ); - return config; - } - - std::vector parseInto( std::vector const& args, ConfigT& config ) const { - std::string processName = args.empty() ? std::string() : args[0]; - std::size_t lastSlash = processName.find_last_of( "/\\" ); - if( lastSlash != std::string::npos ) - processName = processName.substr( lastSlash+1 ); - m_boundProcessName.set( config, processName ); - std::vector tokens; - Parser parser; - parser.parseIntoTokens( args, tokens ); - return populate( tokens, config ); - } - - std::vector populate( std::vector const& tokens, ConfigT& config ) const { - validate(); - std::vector unusedTokens = populateOptions( tokens, config ); - unusedTokens = populateFixedArgs( unusedTokens, config ); - unusedTokens = populateFloatingArgs( unusedTokens, config ); - return unusedTokens; - } - - std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - std::vector errors; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); - for(; it != itEnd; ++it ) { - Arg const& arg = *it; - - try { - if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || - ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { - if( arg.takesArg() ) { - if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) - errors.push_back( "Expected argument to option: " + token.data ); - else - arg.boundField.set( config, tokens[++i].data ); - } - else { - arg.boundField.set( config, "true" ); - } - break; - } - } - catch( std::exception& ex ) { - errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); - } - } - if( it == itEnd ) { - if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) - unusedTokens.push_back( token ); - else if( errors.empty() && m_throwOnUnrecognisedTokens ) - errors.push_back( "unrecognised option: " + token.data ); - } - } - if( !errors.empty() ) { - std::ostringstream oss; - for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); - it != itEnd; - ++it ) { - if( it != errors.begin() ) - oss << "\n"; - oss << *it; - } - throw std::runtime_error( oss.str() ); - } - return unusedTokens; - } - std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - int position = 1; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::map::const_iterator it = m_positionalArgs.find( position ); - if( it != m_positionalArgs.end() ) - it->second.boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - if( token.type == Parser::Token::Positional ) - position++; - } - return unusedTokens; - } - std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { - if( !m_floatingArg.get() ) - return tokens; - std::vector unusedTokens; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - if( token.type == Parser::Token::Positional ) - m_floatingArg->boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - } - return unusedTokens; - } - - void validate() const - { - if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) - throw std::logic_error( "No options or arguments specified" ); - - for( typename std::vector::const_iterator it = m_options.begin(), - itEnd = m_options.end(); - it != itEnd; ++it ) - it->validate(); - } - - private: - Detail::BoundArgFunction m_boundProcessName; - std::vector m_options; - std::map m_positionalArgs; - ArgAutoPtr m_floatingArg; - int m_highestSpecifiedArgPosition; - bool m_throwOnUnrecognisedTokens; - }; - -} // end namespace Clara - -STITCH_CLARA_CLOSE_NAMESPACE -#undef STITCH_CLARA_OPEN_NAMESPACE -#undef STITCH_CLARA_CLOSE_NAMESPACE - -#endif // TWOBLUECUBES_CLARA_H_INCLUDED -#undef STITCH_CLARA_OPEN_NAMESPACE - -// Restore Clara's value for console width, if present -#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#endif - -#include -#include - -namespace Catch { - - inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } - inline void abortAfterX( ConfigData& config, int x ) { - if( x < 1 ) - throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); - config.abortAfter = x; - } - inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } - inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } - inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } - - inline void addWarning( ConfigData& config, std::string const& _warning ) { - if( _warning == "NoAssertions" ) - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - else - throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' ); - } - inline void setOrder( ConfigData& config, std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); - } - inline void setRngSeed( ConfigData& config, std::string const& seed ) { - if( seed == "time" ) { - config.rngSeed = static_cast( std::time(0) ); - } - else { - std::stringstream ss; - ss << seed; - ss >> config.rngSeed; - if( ss.fail() ) - throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); - } - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = static_cast( level ); - } - inline void setShowDurations( ConfigData& config, bool _showDurations ) { - config.showDurations = _showDurations - ? ShowDurations::Always - : ShowDurations::Never; - } - inline void setUseColour( ConfigData& config, std::string const& value ) { - std::string mode = toLower( value ); - - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); - } - inline void forceColour( ConfigData& config ) { - config.useColour = UseColour::Yes; - } - inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { - std::ifstream f( _filename.c_str() ); - if( !f.is_open() ) - throw std::domain_error( "Unable to load input file: " + _filename ); - - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, '#' ) ) { - if( !startsWith( line, '"' ) ) - line = '"' + line + '"'; - addTestOrTags( config, line + ',' ); - } - } - } - - inline Clara::CommandLine makeCommandLineParser() { - - using namespace Clara; - CommandLine cli; - - cli.bindProcessName( &ConfigData::processName ); - - cli["-?"]["-h"]["--help"] - .describe( "display usage information" ) - .bind( &ConfigData::showHelp ); - - cli["-l"]["--list-tests"] - .describe( "list all/matching test cases" ) - .bind( &ConfigData::listTests ); - - cli["-t"]["--list-tags"] - .describe( "list all/matching tags" ) - .bind( &ConfigData::listTags ); - - cli["-s"]["--success"] - .describe( "include successful tests in output" ) - .bind( &ConfigData::showSuccessfulTests ); - - cli["-b"]["--break"] - .describe( "break into debugger on failure" ) - .bind( &ConfigData::shouldDebugBreak ); - - cli["-e"]["--nothrow"] - .describe( "skip exception tests" ) - .bind( &ConfigData::noThrow ); - - cli["-i"]["--invisibles"] - .describe( "show invisibles (tabs, newlines)" ) - .bind( &ConfigData::showInvisibles ); - - cli["-o"]["--out"] - .describe( "output filename" ) - .bind( &ConfigData::outputFilename, "filename" ); - - cli["-r"]["--reporter"] -// .placeholder( "name[:filename]" ) - .describe( "reporter to use (defaults to console)" ) - .bind( &addReporterName, "name" ); - - cli["-n"]["--name"] - .describe( "suite name" ) - .bind( &ConfigData::name, "name" ); - - cli["-a"]["--abort"] - .describe( "abort at first failure" ) - .bind( &abortAfterFirst ); - - cli["-x"]["--abortx"] - .describe( "abort after x failures" ) - .bind( &abortAfterX, "no. failures" ); - - cli["-w"]["--warn"] - .describe( "enable warnings" ) - .bind( &addWarning, "warning name" ); - -// - needs updating if reinstated -// cli.into( &setVerbosity ) -// .describe( "level of verbosity (0=no output)" ) -// .shortOpt( "v") -// .longOpt( "verbosity" ) -// .placeholder( "level" ); - - cli[_] - .describe( "which test or tests to use" ) - .bind( &addTestOrTags, "test name, pattern or tags" ); - - cli["-d"]["--durations"] - .describe( "show test durations" ) - .bind( &setShowDurations, "yes|no" ); - - cli["-f"]["--input-file"] - .describe( "load test names to run from a file" ) - .bind( &loadTestNamesFromFile, "filename" ); - - cli["-#"]["--filenames-as-tags"] - .describe( "adds a tag for the filename" ) - .bind( &ConfigData::filenamesAsTags ); - - cli["-c"]["--section"] - .describe( "specify section to run" ) - .bind( &addSectionToRun, "section name" ); - - // Less common commands which don't have a short form - cli["--list-test-names-only"] - .describe( "list all/matching test cases names only" ) - .bind( &ConfigData::listTestNamesOnly ); - - cli["--list-reporters"] - .describe( "list all reporters" ) - .bind( &ConfigData::listReporters ); - - cli["--order"] - .describe( "test case order (defaults to decl)" ) - .bind( &setOrder, "decl|lex|rand" ); - - cli["--rng-seed"] - .describe( "set a specific seed for random numbers" ) - .bind( &setRngSeed, "'time'|number" ); - - cli["--force-colour"] - .describe( "force colourised output (deprecated)" ) - .bind( &forceColour ); - - cli["--use-colour"] - .describe( "should output be colourised" ) - .bind( &setUseColour, "yes|no" ); - - return cli; - } - -} // end namespace Catch - -// #included from: internal/catch_list.hpp -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED - -// #included from: catch_text.h -#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED - -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: ../external/tbc_text_format.h -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include -#include -#include - -// Use optional outer namespace -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - const std::string wrappableBeforeChars = "[({<\t"; - const std::string wrappableAfterChars = "])}>-,./|\\"; - const std::string wrappableInsteadOfChars = " \n\r"; - std::string indent = _attr.initialIndent != std::string::npos - ? std::string( _attr.initialIndent, ' ' ) - : std::string( _attr.indent, ' ' ); - - typedef std::string::const_iterator iterator; - iterator it = _str.begin(); - const iterator strEnd = _str.end(); - - while( it != strEnd ) { - - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - - std::string suffix; - std::size_t width = (std::min)( static_cast( strEnd-it ), _attr.width-static_cast( indent.size() ) ); - iterator itEnd = it+width; - iterator itNext = _str.end(); - - iterator itNewLine = std::find( it, itEnd, '\n' ); - if( itNewLine != itEnd ) - itEnd = itNewLine; - - if( itEnd != strEnd ) { - bool foundWrapPoint = false; - iterator findIt = itEnd; - do { - if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { - itEnd = findIt+1; - itNext = findIt+1; - foundWrapPoint = true; - } - else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { - itEnd = findIt; - itNext = findIt; - foundWrapPoint = true; - } - else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { - itNext = findIt+1; - itEnd = findIt; - foundWrapPoint = true; - } - if( findIt == it ) - break; - else - --findIt; - } - while( !foundWrapPoint ); - - if( !foundWrapPoint ) { - // No good wrap char, so we'll break mid word and add a hyphen - --itEnd; - itNext = itEnd; - suffix = "-"; - } - else { - while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) - --itEnd; - } - } - lines.push_back( indent + std::string( it, itEnd ) + suffix ); - - if( indent.size() != _attr.indent ) - indent = std::string( _attr.indent, ' ' ); - it = itNext; - } - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Tbc - -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE - -namespace Catch { - using Tbc::Text; - using Tbc::TextAttributes; -} - -// #included from: catch_console_colour.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED - -namespace Catch { - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - - // By intention - FileName = LightGrey, - Warning = Yellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour( Code _colourCode ); - Colour( Colour const& other ); - ~Colour(); - - // Use static method for one-shot changes - static void use( Code _colourCode ); - - private: - bool m_moved; - }; - - inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } - -} // end namespace Catch - -// #included from: catch_interfaces_reporter.h -#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED - -#include -#include -#include - -namespace Catch -{ - struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) - : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} - - std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } - - private: - std::ostream* m_stream; - Ptr m_fullConfig; - }; - - struct ReporterPreferences { - ReporterPreferences() - : shouldRedirectStdOut( false ) - {} - - bool shouldRedirectStdOut; - }; - - template - struct LazyStat : Option { - LazyStat() : used( false ) {} - LazyStat& operator=( T const& _value ) { - Option::operator=( _value ); - used = false; - return *this; - } - void reset() { - Option::reset(); - used = false; - } - bool used; - }; - - struct TestRunInfo { - TestRunInfo( std::string const& _name ) : name( _name ) {} - std::string name; - }; - struct GroupInfo { - GroupInfo( std::string const& _name, - std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} - - std::string name; - std::size_t groupIndex; - std::size_t groupsCounts; - }; - - struct AssertionStats { - AssertionStats( AssertionResult const& _assertionResult, - std::vector const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) - { - if( assertionResult.hasMessage() ) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); - - infoMessages.push_back( builder.m_info ); - } - } - virtual ~AssertionStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - AssertionStats( AssertionStats const& ) = default; - AssertionStats( AssertionStats && ) = default; - AssertionStats& operator = ( AssertionStats const& ) = default; - AssertionStats& operator = ( AssertionStats && ) = default; -# endif - - AssertionResult assertionResult; - std::vector infoMessages; - Totals totals; - }; - - struct SectionStats { - SectionStats( SectionInfo const& _sectionInfo, - Counts const& _assertions, - double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} - virtual ~SectionStats(); -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - SectionStats( SectionStats const& ) = default; - SectionStats( SectionStats && ) = default; - SectionStats& operator = ( SectionStats const& ) = default; - SectionStats& operator = ( SectionStats && ) = default; -# endif - - SectionInfo sectionInfo; - Counts assertions; - double durationInSeconds; - bool missingAssertions; - }; - - struct TestCaseStats { - TestCaseStats( TestCaseInfo const& _testInfo, - Totals const& _totals, - std::string const& _stdOut, - std::string const& _stdErr, - bool _aborting ) - : testInfo( _testInfo ), - totals( _totals ), - stdOut( _stdOut ), - stdErr( _stdErr ), - aborting( _aborting ) - {} - virtual ~TestCaseStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestCaseStats( TestCaseStats const& ) = default; - TestCaseStats( TestCaseStats && ) = default; - TestCaseStats& operator = ( TestCaseStats const& ) = default; - TestCaseStats& operator = ( TestCaseStats && ) = default; -# endif - - TestCaseInfo testInfo; - Totals totals; - std::string stdOut; - std::string stdErr; - bool aborting; - }; - - struct TestGroupStats { - TestGroupStats( GroupInfo const& _groupInfo, - Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} - TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} - virtual ~TestGroupStats(); - -# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestGroupStats( TestGroupStats const& ) = default; - TestGroupStats( TestGroupStats && ) = default; - TestGroupStats& operator = ( TestGroupStats const& ) = default; - TestGroupStats& operator = ( TestGroupStats && ) = default; -# endif - - GroupInfo groupInfo; - Totals totals; - bool aborting; - }; - - struct TestRunStats { - TestRunStats( TestRunInfo const& _runInfo, - Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} - virtual ~TestRunStats(); - -# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS - TestRunStats( TestRunStats const& _other ) - : runInfo( _other.runInfo ), - totals( _other.totals ), - aborting( _other.aborting ) - {} -# else - TestRunStats( TestRunStats const& ) = default; - TestRunStats( TestRunStats && ) = default; - TestRunStats& operator = ( TestRunStats const& ) = default; - TestRunStats& operator = ( TestRunStats && ) = default; -# endif - - TestRunInfo runInfo; - Totals totals; - bool aborting; - }; - - class MultipleReporters; - - struct IStreamingReporter : IShared { - virtual ~IStreamingReporter(); - - // Implementing class must also provide the following static method: - // static std::string getDescription(); - - virtual ReporterPreferences getPreferences() const = 0; - - virtual void noMatchingTestCases( std::string const& spec ) = 0; - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; - virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; - virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; - - virtual void sectionEnded( SectionStats const& sectionStats ) = 0; - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; - virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - - virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - - virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } - }; - - struct IReporterFactory : IShared { - virtual ~IReporterFactory(); - virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; - virtual std::string getDescription() const = 0; - }; - - struct IReporterRegistry { - typedef std::map > FactoryMap; - typedef std::vector > Listeners; - - virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; - virtual FactoryMap const& getFactories() const = 0; - virtual Listeners const& getListeners() const = 0; - }; - - Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); - -} - -#include -#include - -namespace Catch { - - inline std::size_t listTests( Config const& config ) { - - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Matching test cases:\n"; - else { - Catch::cout() << "All available test cases:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } - - std::size_t matchedTests = 0; - TextAttributes nameAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - Colour::Code colour = testCaseInfo.isHidden() - ? Colour::SecondaryText - : Colour::None; - Colour colourGuard( colour ); - - Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; - if( !testCaseInfo.tags.empty() ) - Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; - } - - if( !config.testSpec().hasFilters() ) - Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; - else - Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; - return matchedTests; - } - - inline std::size_t listTestsNamesOnly( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( !config.testSpec().hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - std::size_t matchedTests = 0; - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - matchedTests++; - TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); - if( startsWith( testCaseInfo.name, '#' ) ) - Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl; - else - Catch::cout() << testCaseInfo.name << std::endl; - } - return matchedTests; - } - - struct TagInfo { - TagInfo() : count ( 0 ) {} - void add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); - } - std::string all() const { - std::string out; - for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); - it != itEnd; - ++it ) - out += "[" + *it + "]"; - return out; - } - std::set spellings; - std::size_t count; - }; - - inline std::size_t listTags( Config const& config ) { - TestSpec testSpec = config.testSpec(); - if( config.testSpec().hasFilters() ) - Catch::cout() << "Tags for matching test cases:\n"; - else { - Catch::cout() << "All available tags:\n"; - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); - } - - std::map tagCounts; - - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); - for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); - it != itEnd; - ++it ) { - for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), - tagItEnd = it->getTestCaseInfo().tags.end(); - tagIt != tagItEnd; - ++tagIt ) { - std::string tagName = *tagIt; - std::string lcaseTagName = toLower( tagName ); - std::map::iterator countIt = tagCounts.find( lcaseTagName ); - if( countIt == tagCounts.end() ) - countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; - countIt->second.add( tagName ); - } - } - - for( std::map::const_iterator countIt = tagCounts.begin(), - countItEnd = tagCounts.end(); - countIt != countItEnd; - ++countIt ) { - std::ostringstream oss; - oss << " " << std::setw(2) << countIt->second.count << " "; - Text wrapper( countIt->second.all(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( oss.str().size() ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); - Catch::cout() << oss.str() << wrapper << '\n'; - } - Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; - return tagCounts.size(); - } - - inline std::size_t listReporters( Config const& /*config*/ ) { - Catch::cout() << "Available reporters:\n"; - IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; - std::size_t maxNameLen = 0; - for(it = itBegin; it != itEnd; ++it ) - maxNameLen = (std::max)( maxNameLen, it->first.size() ); - - for(it = itBegin; it != itEnd; ++it ) { - Text wrapper( it->second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - Catch::cout() << " " - << it->first - << ':' - << std::string( maxNameLen - it->first.size() + 2, ' ' ) - << wrapper << '\n'; - } - Catch::cout() << std::endl; - return factories.size(); - } - - inline Option list( Config const& config ) { - Option listedCount; - if( config.listTests() ) - listedCount = listedCount.valueOr(0) + listTests( config ); - if( config.listTestNamesOnly() ) - listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); - if( config.listTags() ) - listedCount = listedCount.valueOr(0) + listTags( config ); - if( config.listReporters() ) - listedCount = listedCount.valueOr(0) + listReporters( config ); - return listedCount; - } - -} // end namespace Catch - -// #included from: internal/catch_run_context.hpp -#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED - -// #included from: catch_test_case_tracker.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED - -#include -#include -#include -#include -#include - -CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS - -namespace Catch { -namespace TestCaseTracking { - - struct NameAndLocation { - std::string name; - SourceLineInfo location; - - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) - : name( _name ), - location( _location ) - {} - }; - - struct ITracker : SharedImpl<> { - virtual ~ITracker(); - - // static queries - virtual NameAndLocation const& nameAndLocation() const = 0; - - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - virtual bool hasChildren() const = 0; - - virtual ITracker& parent() = 0; - - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; - - virtual void addChild( Ptr const& child ) = 0; - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; - virtual void openChild() = 0; - - // Debug/ checking - virtual bool isSectionTracker() const = 0; - virtual bool isIndexTracker() const = 0; - }; - - class TrackerContext { - - enum RunState { - NotStarted, - Executing, - CompletedCycle - }; - - Ptr m_rootTracker; - ITracker* m_currentTracker; - RunState m_runState; - - public: - - static TrackerContext& instance() { - static TrackerContext s_instance; - return s_instance; - } - - TrackerContext() - : m_currentTracker( CATCH_NULL ), - m_runState( NotStarted ) - {} - - ITracker& startRun(); - - void endRun() { - m_rootTracker.reset(); - m_currentTracker = CATCH_NULL; - m_runState = NotStarted; - } - - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void completeCycle() { - m_runState = CompletedCycle; - } - - bool completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& currentTracker() { - return *m_currentTracker; - } - void setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } - }; - - class TrackerBase : public ITracker { - protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; - class TrackerHasName { - NameAndLocation m_nameAndLocation; - public: - TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} - bool operator ()( Ptr const& tracker ) { - return - tracker->nameAndLocation().name == m_nameAndLocation.name && - tracker->nameAndLocation().location == m_nameAndLocation.location; - } - }; - typedef std::vector > Children; - NameAndLocation m_nameAndLocation; - TrackerContext& m_ctx; - ITracker* m_parent; - Children m_children; - CycleState m_runState; - public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), - m_ctx( ctx ), - m_parent( parent ), - m_runState( NotStarted ) - {} - virtual ~TrackerBase(); - - virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { - return m_nameAndLocation; - } - virtual bool isComplete() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully; - } - virtual bool isOpen() const CATCH_OVERRIDE { - return m_runState != NotStarted && !isComplete(); - } - virtual bool hasChildren() const CATCH_OVERRIDE { - return !m_children.empty(); - } - - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { - m_children.push_back( child ); - } - - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { - Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); - return( it != m_children.end() ) - ? it->get() - : CATCH_NULL; - } - virtual ITracker& parent() CATCH_OVERRIDE { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } - - virtual void openChild() CATCH_OVERRIDE { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } - virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } - - void open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } - - virtual void close() CATCH_OVERRIDE { - - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case NotStarted: - case CompletedSuccessfully: - case Failed: - throw std::logic_error( "Illogical state" ); - - case NeedsAnotherRun: - break;; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - default: - throw std::logic_error( "Unexpected state" ); - } - moveToParent(); - m_ctx.completeCycle(); - } - virtual void fail() CATCH_OVERRIDE { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { - m_runState = NeedsAnotherRun; - } - private: - void moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void moveToThis() { - m_ctx.setCurrentTracker( this ); - } - }; - - class SectionTracker : public TrackerBase { - std::vector m_filters; - public: - SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) - { - if( parent ) { - while( !parent->isSectionTracker() ) - parent = &parent->parent(); - - SectionTracker& parentSection = static_cast( *parent ); - addNextFilters( parentSection.m_filters ); - } - } - virtual ~SectionTracker(); - - virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } - - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - SectionTracker* section = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - section = static_cast( childTracker ); - } - else { - section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() ) - section->tryOpen(); - return *section; - } - - void tryOpen() { - if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) - open(); - } - - void addInitialFilters( std::vector const& filters ) { - if( !filters.empty() ) { - m_filters.push_back(""); // Root - should never be consulted - m_filters.push_back(""); // Test Case - not a section filter - m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); - } - } - void addNextFilters( std::vector const& filters ) { - if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); - } - }; - - class IndexTracker : public TrackerBase { - int m_size; - int m_index; - public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ), - m_index( -1 ) - {} - virtual ~IndexTracker(); - - virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } - - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - IndexTracker* tracker = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = static_cast( childTracker ); - } - else { - tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } - - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } - - return *tracker; - } - - int index() const { return m_index; } - - void moveNext() { - m_index++; - m_children.clear(); - } - - virtual void close() CATCH_OVERRIDE { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) - m_runState = Executing; - } - }; - - inline ITracker& TrackerContext::startRun() { - m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); - m_currentTracker = CATCH_NULL; - m_runState = Executing; - return *m_rootTracker; - } - -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::IndexTracker; - -} // namespace Catch - -CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -// #included from: catch_fatal_condition.hpp -#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED - -namespace Catch { - - // Report the error condition - inline void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); - } - -} // namespace Catch - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// -// #included from: catch_windows_h_proxy.h - -#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED - -#ifdef CATCH_DEFINES_NOMINMAX -# define NOMINMAX -#endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINES_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - - -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - -# else // CATCH_CONFIG_WINDOWS_SEH is defined - -namespace Catch { - - struct SignalDefs { DWORD id; const char* name; }; - extern SignalDefs signalDefs[]; - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { - { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, - { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, - { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, - }; - - struct FatalConditionHandler { - - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; - } - - FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = CATCH_NULL; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } - - static void reset() { - if (isSet) { - // Unregister handler and restore the old guarantee - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = CATCH_NULL; - isSet = false; - } - } - - ~FatalConditionHandler() { - reset(); - } - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; - - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; - -} // namespace Catch - -# endif // CATCH_CONFIG_WINDOWS_SEH - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - -# else // CATCH_CONFIG_POSIX_SIGNALS is defined - -#include - -namespace Catch { - - struct SignalDefs { - int id; - const char* name; - }; - extern SignalDefs signalDefs[]; - SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; - static stack_t oldSigStack; - static char altStackMem[SIGSTKSZ]; - - static void handleSignal( int sig ) { - std::string name = ""; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - SignalDefs &def = signalDefs[i]; - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise( sig ); - } - - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = SIGSTKSZ; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = { 0 }; - - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - ~FatalConditionHandler() { - reset(); - } - static void reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); - } - // Return the old stack - sigaltstack(&oldSigStack, CATCH_NULL); - isSet = false; - } - } - }; - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; - -} // namespace Catch - -# endif // CATCH_CONFIG_POSIX_SIGNALS - -#endif // not Windows - -#include -#include - -namespace Catch { - - class StreamRedirect { - - public: - StreamRedirect( std::ostream& stream, std::string& targetString ) - : m_stream( stream ), - m_prevBuf( stream.rdbuf() ), - m_targetString( targetString ) - { - stream.rdbuf( m_oss.rdbuf() ); - } - - ~StreamRedirect() { - m_targetString += m_oss.str(); - m_stream.rdbuf( m_prevBuf ); - } - - private: - std::ostream& m_stream; - std::streambuf* m_prevBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - /////////////////////////////////////////////////////////////////////////// - - class RunContext : public IResultCapture, public IRunner { - - RunContext( RunContext const& ); - void operator =( RunContext const& ); - - public: - - explicit RunContext( Ptr const& _config, Ptr const& reporter ) - : m_runInfo( _config->name() ), - m_context( getCurrentMutableContext() ), - m_activeTestCase( CATCH_NULL ), - m_config( _config ), - m_reporter( reporter ), - m_shouldReportUnexpected ( true ) - { - m_context.setRunner( this ); - m_context.setConfig( m_config ); - m_context.setResultCapture( this ); - m_reporter->testRunStarting( m_runInfo ); - } - - virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - } - - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); - } - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); - } - - Totals runTest( TestCase const& testCase ) { - Totals prevTotals = m_totals; - - std::string redirectedCout; - std::string redirectedCerr; - - TestCaseInfo testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting( testInfo ); - - m_activeTestCase = &testCase; - - do { - ITracker& rootTracker = m_trackerContext.startRun(); - assert( rootTracker.isSectionTracker() ); - static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); - } - // !TBD: deprecated - this will be replaced by indexed trackers - while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); - - Totals deltaTotals = m_totals.delta( prevTotals ); - if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { - deltaTotals.assertions.failed++; - deltaTotals.testCases.passed--; - deltaTotals.testCases.failed++; - } - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting() ) ); - - m_activeTestCase = CATCH_NULL; - m_testCaseTracker = CATCH_NULL; - - return deltaTotals; - } - - Ptr config() const { - return m_config; - } - - private: // IResultCapture - - virtual void assertionEnded( AssertionResult const& result ) { - if( result.getResultType() == ResultWas::Ok ) { - m_totals.assertions.passed++; - } - else if( !result.isOk() ) { - m_totals.assertions.failed++; - } - - if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) - m_messages.clear(); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - m_lastResult = result; - } - - virtual bool sectionStarted ( - SectionInfo const& sectionInfo, - Counts& assertions - ) - { - ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); - if( !sectionTracker.isOpen() ) - return false; - m_activeSections.push_back( §ionTracker ); - - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - - m_reporter->sectionStarting( sectionInfo ); - - assertions = m_totals.assertions; - - return true; - } - bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 ) - return false; - if( !m_config->warnAboutMissingAssertions() ) - return false; - if( m_trackerContext.currentTracker().hasChildren() ) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } - - virtual void sectionEnded( SectionEndInfo const& endInfo ) { - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( !m_activeSections.empty() ) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } - - m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } - - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { - if( m_unfinishedSections.empty() ) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back( endInfo ); - } - - virtual void pushScopedMessage( MessageInfo const& message ) { - m_messages.push_back( message ); - } - - virtual void popScopedMessage( MessageInfo const& message ) { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } - - virtual std::string getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : std::string(); - } - - virtual const AssertionResult* getLastResult() const { - return &m_lastResult; - } - - virtual void exceptionEarlyReported() { - m_shouldReportUnexpected = false; - } - - virtual void handleFatalErrorCondition( std::string const& message ) { - // Don't rebuild the result -- the stringification itself can cause more fatal errors - // Instead, fake a result data. - AssertionResultData tempResult; - tempResult.resultType = ResultWas::FatalErrorCondition; - tempResult.message = message; - AssertionResult result(m_lastAssertionInfo, tempResult); - - getResultCapture().assertionEnded(result); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); - m_reporter->sectionEnded( testCaseSectionStats ); - - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - std::string(), - std::string(), - false ) ); - m_totals.testCases.failed++; - testGroupEnded( std::string(), m_totals, 1, 1 ); - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); - } - - public: - // !TBD We need to do this another way! - bool aborting() const { - return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); - } - - private: - - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - m_reporter->sectionStarting( testCaseSection ); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - m_shouldReportUnexpected = true; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); - - seedRng( *m_config ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( Catch::cout(), redirectedCout ); - StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); - invokeActiveTestCase(); - } - else { - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions - // are reported without translation at the point of origin. - if (m_shouldReportUnexpected) { - makeUnexpectedResultBuilder().useActiveException(); - } - } - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( testCaseInfo.okToFail() ) { - std::swap( assertions.failedButOk, assertions.failed ); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - void invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } - - private: - - ResultBuilder makeUnexpectedResultBuilder() const { - return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression.c_str(), - m_lastAssertionInfo.resultDisposition ); - } - - void handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it ) - sectionEnded( *it ); - m_unfinishedSections.clear(); - } - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase; - ITracker* m_testCaseTracker; - ITracker* m_currentSectionTracker; - AssertionResult m_lastResult; - - Ptr m_config; - Totals m_totals; - Ptr m_reporter; - std::vector m_messages; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - bool m_shouldReportUnexpected; - }; - - IResultCapture& getResultCapture() { - if( IResultCapture* capture = getCurrentContext().getResultCapture() ) - return *capture; - else - throw std::logic_error( "No result capture instance" ); - } - -} // end namespace Catch - -// #included from: internal/catch_version.h -#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED - -namespace Catch { - - // Versioning information - struct Version { - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - char const * const branchName; - unsigned int const buildNumber; - - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - - private: - void operator=( Version const& ); - }; - - inline Version libraryVersion(); -} - -#include -#include -#include - -namespace Catch { - - Ptr createReporter( std::string const& reporterName, Ptr const& config ) { - Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); - if( !reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - return reporter; - } - - Ptr makeReporter( Ptr const& config ) { - std::vector reporters = config->getReporterNames(); - if( reporters.empty() ) - reporters.push_back( "console" ); - - Ptr reporter; - for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); - it != itEnd; - ++it ) - reporter = addReporter( reporter, createReporter( *it, config ) ); - return reporter; - } - Ptr addListeners( Ptr const& config, Ptr reporters ) { - IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); - for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); - it != itEnd; - ++it ) - reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); - return reporters; - } - - Totals runTests( Ptr const& config ) { - - Ptr iconfig = config.get(); - - Ptr reporter = makeReporter( config ); - reporter = addListeners( iconfig, reporter ); - - RunContext context( iconfig, reporter ); - - Totals totals; - - context.testGroupStarting( config->name(), 1, 1 ); - - TestSpec testSpec = config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); - for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); - it != itEnd; - ++it ) { - if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) - totals += context.runTest( *it ); - else - reporter->skipTest( *it ); - } - - context.testGroupEnded( iconfig->name(), totals, 1, 1 ); - return totals; - } - - void applyFilenamesAsTags( IConfig const& config ) { - std::vector const& tests = getAllTestCasesSorted( config ); - for(std::size_t i = 0; i < tests.size(); ++i ) { - TestCase& test = const_cast( tests[i] ); - std::set tags = test.tags; - - std::string filename = test.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\\/" ); - if( lastSlash != std::string::npos ) - filename = filename.substr( lastSlash+1 ); - - std::string::size_type lastDot = filename.find_last_of( "." ); - if( lastDot != std::string::npos ) - filename = filename.substr( 0, lastDot ); - - tags.insert( "#" + filename ); - setTags( test, tags ); - } - } - - class Session : NonCopyable { - static bool alreadyInstantiated; - - public: - - struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; - - Session() - : m_cli( makeCommandLineParser() ) { - if( alreadyInstantiated ) { - std::string msg = "Only one instance of Catch::Session can ever be used"; - Catch::cerr() << msg << std::endl; - throw std::logic_error( msg ); - } - alreadyInstantiated = true; - } - ~Session() { - Catch::cleanUp(); - } - - void showHelp( std::string const& processName ) { - Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; - - m_cli.usage( Catch::cout(), processName ); - Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; - } - - int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { - try { - m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); - if( m_configData.showHelp ) - showHelp( m_configData.processName ); - m_config.reset(); - } - catch( std::exception& ex ) { - { - Colour colourGuard( Colour::Red ); - Catch::cerr() - << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) - << "\n\n"; - } - m_cli.usage( Catch::cout(), m_configData.processName ); - return (std::numeric_limits::max)(); - } - return 0; - } - - void useConfigData( ConfigData const& _configData ) { - m_configData = _configData; - m_config.reset(); - } - - int run( int argc, char const* const* const argv ) { - - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - - int run() { - if( m_configData.showHelp ) - return 0; - - try - { - config(); // Force config to be constructed - - seedRng( *m_config ); - - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags( *m_config ); - - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); - - return static_cast( runTests( m_config ).assertions.failed ); - } - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return (std::numeric_limits::max)(); - } - } - - Clara::CommandLine const& cli() const { - return m_cli; - } - std::vector const& unusedTokens() const { - return m_unusedTokens; - } - ConfigData& configData() { - return m_configData; - } - Config& config() { - if( !m_config ) - m_config = new Config( m_configData ); - return *m_config; - } - private: - Clara::CommandLine m_cli; - std::vector m_unusedTokens; - ConfigData m_configData; - Ptr m_config; - }; - - bool Session::alreadyInstantiated = false; - -} // end namespace Catch - -// #included from: catch_registry_hub.hpp -#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED - -// #included from: catch_test_case_registry_impl.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - struct RandomNumberGenerator { - typedef std::ptrdiff_t result_type; - - result_type operator()( result_type n ) const { return std::rand() % n; } - -#ifdef CATCH_CONFIG_CPP11_SHUFFLE - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return 1000000; } - result_type operator()() const { return std::rand() % max(); } -#endif - template - static void shuffle( V& vector ) { - RandomNumberGenerator rng; -#ifdef CATCH_CONFIG_CPP11_SHUFFLE - std::shuffle( vector.begin(), vector.end(), rng ); -#else - std::random_shuffle( vector.begin(), vector.end(), rng ); -#endif - } - }; - - inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { - - std::vector sorted = unsortedTestCases; - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end() ); - break; - case RunTests::InRandomOrder: - { - seedRng( config ); - RandomNumberGenerator::shuffle( sorted ); - } - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - return sorted; - } - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); - } - - void enforceNoDuplicateTestCases( std::vector const& functions ) { - std::set seenFunctions; - for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); - it != itEnd; - ++it ) { - std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); - if( !prev.second ) { - std::ostringstream ss; - - ss << Colour( Colour::Red ) - << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' - << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; - - throw std::runtime_error(ss.str()); - } - } - } - - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { - std::vector filtered; - filtered.reserve( testCases.size() ); - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) - if( matchTest( *it, testSpec, config ) ) - filtered.push_back( *it ); - return filtered; - } - std::vector const& getAllTestCasesSorted( IConfig const& config ) { - return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); - } - - class TestRegistry : public ITestCaseRegistry { - public: - TestRegistry() - : m_currentSortOrder( RunTests::InDeclarationOrder ), - m_unnamedCount( 0 ) - {} - virtual ~TestRegistry(); - - virtual void registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name.empty() ) { - std::ostringstream oss; - oss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( oss.str() ) ); - } - m_functions.push_back( testCase ); - } - - virtual std::vector const& getAllTests() const { - return m_functions; - } - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { - if( m_sortedFunctions.empty() ) - enforceNoDuplicateTestCases( m_functions ); - - if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { - m_sortedFunctions = sortTests( config, m_functions ); - m_currentSortOrder = config.runOrder(); - } - return m_sortedFunctions; - } - - private: - std::vector m_functions; - mutable RunTests::InWhatOrder m_currentSortOrder; - mutable std::vector m_sortedFunctions; - size_t m_unnamedCount; - std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised - }; - - /////////////////////////////////////////////////////////////////////////// - - class FreeFunctionTestCase : public SharedImpl { - public: - - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} - - virtual void invoke() const { - m_fun(); - } - - private: - virtual ~FreeFunctionTestCase(); - - TestFunction m_fun; - }; - - inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; - if( startsWith( className, '&' ) ) - { - std::size_t lastColons = className.rfind( "::" ); - std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); - if( penultimateColons == std::string::npos ) - penultimateColons = 1; - className = className.substr( penultimateColons, lastColons-penultimateColons ); - } - return className; - } - - void registerTestCase - ( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase - ( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); - } - void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); - } - - /////////////////////////////////////////////////////////////////////////// - - AutoReg::AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCaseFunction( function, lineInfo, nameAndDesc ); - } - - AutoReg::~AutoReg() {} - -} // end namespace Catch - -// #included from: catch_reporter_registry.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED - -#include - -namespace Catch { - - class ReporterRegistry : public IReporterRegistry { - - public: - - virtual ~ReporterRegistry() CATCH_OVERRIDE {} - - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { - FactoryMap::const_iterator it = m_factories.find( name ); - if( it == m_factories.end() ) - return CATCH_NULL; - return it->second->create( ReporterConfig( config ) ); - } - - void registerReporter( std::string const& name, Ptr const& factory ) { - m_factories.insert( std::make_pair( name, factory ) ); - } - void registerListener( Ptr const& factory ) { - m_listeners.push_back( factory ); - } - - virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { - return m_factories; - } - virtual Listeners const& getListeners() const CATCH_OVERRIDE { - return m_listeners; - } - - private: - FactoryMap m_factories; - Listeners m_listeners; - }; -} - -// #included from: catch_exception_translator_registry.hpp -#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED - -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry() { - deleteAll( m_translators ); - } - - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( translator ); - } - - virtual std::string translateActiveException() const { - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - return tryTranslators(); - } - @catch (NSException *exception) { - return Catch::toString( [exception description] ); - } -#else - return tryTranslators(); -#endif - } - catch( TestFailureException& ) { - throw; - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return "Unknown exception"; - } - } - - std::string tryTranslators() const { - if( m_translators.empty() ) - throw; - else - return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); - } - - private: - std::vector m_translators; - }; -} - -// #included from: catch_tag_alias_registry.h -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED - -#include - -namespace Catch { - - class TagAliasRegistry : public ITagAliasRegistry { - public: - virtual ~TagAliasRegistry(); - virtual Option find( std::string const& alias ) const; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; - void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); - - private: - std::map m_registry; - }; - -} // end namespace Catch - -namespace Catch { - - namespace { - - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); - - public: // IRegistryHub - RegistryHub() { - } - virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { - return m_reporterRegistry; - } - virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { - return m_testCaseRegistry; - } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { - return m_exceptionTranslatorRegistry; - } - virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { - return m_tagAliasRegistry; - } - - public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { - m_reporterRegistry.registerReporter( name, factory ); - } - virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { - m_reporterRegistry.registerListener( factory ); - } - virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { - m_testCaseRegistry.registerTest( testInfo ); - } - virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { - m_exceptionTranslatorRegistry.registerTranslator( translator ); - } - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { - m_tagAliasRegistry.add( alias, tag, lineInfo ); - } - - private: - TestRegistry m_testCaseRegistry; - ReporterRegistry m_reporterRegistry; - ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; - TagAliasRegistry m_tagAliasRegistry; - }; - - // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = CATCH_NULL; - if( !theRegistryHub ) - theRegistryHub = new RegistryHub(); - return theRegistryHub; - } - } - - IRegistryHub& getRegistryHub() { - return *getTheRegistryHub(); - } - IMutableRegistryHub& getMutableRegistryHub() { - return *getTheRegistryHub(); - } - void cleanUp() { - delete getTheRegistryHub(); - getTheRegistryHub() = CATCH_NULL; - cleanUpContext(); - } - std::string translateActiveException() { - return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); - } - -} // end namespace Catch - -// #included from: catch_notimplemented_exception.hpp -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED - -#include - -namespace Catch { - - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) - : m_lineInfo( lineInfo ) { - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); - } - - const char* NotImplementedException::what() const CATCH_NOEXCEPT { - return m_what.c_str(); - } - -} // end namespace Catch - -// #included from: catch_context_impl.hpp -#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED - -// #included from: catch_stream.hpp -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - - template - class StreamBufImpl : public StreamBufBase { - char data[bufferSize]; - WriterF m_writer; - - public: - StreamBufImpl() { - setp( data, data + sizeof(data) ); - } - - ~StreamBufImpl() CATCH_NOEXCEPT { - sync(); - } - - private: - int overflow( int c ) { - sync(); - - if( c != EOF ) { - if( pbase() == epptr() ) - m_writer( std::string( 1, static_cast( c ) ) ); - else - sputc( static_cast( c ) ); - } - return 0; - } - - int sync() { - if( pbase() != pptr() ) { - m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); - setp( pbase(), epptr() ); - } - return 0; - } - }; - - /////////////////////////////////////////////////////////////////////////// - - FileStream::FileStream( std::string const& filename ) { - m_ofs.open( filename.c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << filename << '\''; - throw std::domain_error( oss.str() ); - } - } - - std::ostream& FileStream::stream() const { - return m_ofs; - } - - struct OutputDebugWriter { - - void operator()( std::string const&str ) { - writeToDebugConsole( str ); - } - }; - - DebugOutStream::DebugOutStream() - : m_streamBuf( new StreamBufImpl() ), - m_os( m_streamBuf.get() ) - {} - - std::ostream& DebugOutStream::stream() const { - return m_os; - } - - // Store the streambuf from cout up-front because - // cout may get redirected when running tests - CoutStream::CoutStream() - : m_os( Catch::cout().rdbuf() ) - {} - - std::ostream& CoutStream::stream() const { - return m_os; - } - -#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions - std::ostream& cout() { - return std::cout; - } - std::ostream& cerr() { - return std::cerr; - } -#endif -} - -namespace Catch { - - class Context : public IMutableContext { - - Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} - Context( Context const& ); - void operator=( Context const& ); - - public: - virtual ~Context() { - deleteAllValues( m_generatorsByTestName ); - } - - public: // IContext - virtual IResultCapture* getResultCapture() { - return m_resultCapture; - } - virtual IRunner* getRunner() { - return m_runner; - } - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { - return getGeneratorsForCurrentTest() - .getGeneratorInfo( fileInfo, totalSize ) - .getCurrentIndex(); - } - virtual bool advanceGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - return generators && generators->moveNext(); - } - - virtual Ptr getConfig() const { - return m_config; - } - - public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) { - m_resultCapture = resultCapture; - } - virtual void setRunner( IRunner* runner ) { - m_runner = runner; - } - virtual void setConfig( Ptr const& config ) { - m_config = config; - } - - friend IMutableContext& getCurrentMutableContext(); - - private: - IGeneratorsForTest* findGeneratorsForCurrentTest() { - std::string testName = getResultCapture()->getCurrentTestName(); - - std::map::const_iterator it = - m_generatorsByTestName.find( testName ); - return it != m_generatorsByTestName.end() - ? it->second - : CATCH_NULL; - } - - IGeneratorsForTest& getGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - if( !generators ) { - std::string testName = getResultCapture()->getCurrentTestName(); - generators = createGeneratorsForTest(); - m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); - } - return *generators; - } - - private: - Ptr m_config; - IRunner* m_runner; - IResultCapture* m_resultCapture; - std::map m_generatorsByTestName; - }; - - namespace { - Context* currentContext = CATCH_NULL; - } - IMutableContext& getCurrentMutableContext() { - if( !currentContext ) - currentContext = new Context(); - return *currentContext; - } - IContext& getCurrentContext() { - return getCurrentMutableContext(); - } - - void cleanUpContext() { - delete currentContext; - currentContext = CATCH_NULL; - } -} - -// #included from: catch_console_colour_impl.hpp -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED - -// #included from: catch_errno_guard.hpp -#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED - -#include - -namespace Catch { - - class ErrnoGuard { - public: - ErrnoGuard():m_oldErrno(errno){} - ~ErrnoGuard() { errno = m_oldErrno; } - private: - int m_oldErrno; - }; - -} - -namespace Catch { - namespace { - - struct IColourImpl { - virtual ~IColourImpl() {} - virtual void use( Colour::Code _colourCode ) = 0; - }; - - struct NoColourImpl : IColourImpl { - void use( Colour::Code ) {} - - static IColourImpl* instance() { - static NoColourImpl s_instance; - return &s_instance; - } - }; - - } // anon namespace -} // namespace Catch - -#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) -# ifdef CATCH_PLATFORM_WINDOWS -# define CATCH_CONFIG_COLOUR_WINDOWS -# else -# define CATCH_CONFIG_COLOUR_ANSI -# endif -#endif - -#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// - -namespace Catch { -namespace { - - class Win32ColourImpl : public IColourImpl { - public: - Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) - { - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); - originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); - } - - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalForegroundAttributes ); - case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Red: return setTextAttribute( FOREGROUND_RED ); - case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); - case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); - case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); - case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); - case Colour::Grey: return setTextAttribute( 0 ); - - case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); - case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); - case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); - case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - - private: - void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); - } - HANDLE stdoutHandle; - WORD originalForegroundAttributes; - WORD originalBackgroundAttributes; - }; - - IColourImpl* platformColourInstance() { - static Win32ColourImpl s_instance; - - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = !isDebuggerActive() - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? &s_instance - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// - -#include - -namespace Catch { -namespace { - - // use POSIX/ ANSI console terminal codes - // Thanks to Adam Strzelecki for original contribution - // (http://github.com/nanoant) - // https://github.com/philsquared/Catch/pull/131 - class PosixColourImpl : public IColourImpl { - public: - virtual void use( Colour::Code _colourCode ) { - switch( _colourCode ) { - case Colour::None: - case Colour::White: return setColour( "[0m" ); - case Colour::Red: return setColour( "[0;31m" ); - case Colour::Green: return setColour( "[0;32m" ); - case Colour::Blue: return setColour( "[0;34m" ); - case Colour::Cyan: return setColour( "[0;36m" ); - case Colour::Yellow: return setColour( "[0;33m" ); - case Colour::Grey: return setColour( "[1;30m" ); - - case Colour::LightGrey: return setColour( "[0;37m" ); - case Colour::BrightRed: return setColour( "[1;31m" ); - case Colour::BrightGreen: return setColour( "[1;32m" ); - case Colour::BrightWhite: return setColour( "[1;37m" ); - - case Colour::Bright: throw std::logic_error( "not a colour" ); - } - } - static IColourImpl* instance() { - static PosixColourImpl s_instance; - return &s_instance; - } - - private: - void setColour( const char* _escapeCode ) { - Catch::cout() << '\033' << _escapeCode; - } - }; - - IColourImpl* platformColourInstance() { - ErrnoGuard guard; - Ptr config = getCurrentContext().getConfig(); - UseColour::YesOrNo colourMode = config - ? config->useColour() - : UseColour::Auto; - if( colourMode == UseColour::Auto ) - colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) - ? UseColour::Yes - : UseColour::No; - return colourMode == UseColour::Yes - ? PosixColourImpl::instance() - : NoColourImpl::instance(); - } - -} // end anon namespace -} // end namespace Catch - -#else // not Windows or ANSI /////////////////////////////////////////////// - -namespace Catch { - - static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } - -} // end namespace Catch - -#endif // Windows/ ANSI/ None - -namespace Catch { - - Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } - Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } - Colour::~Colour(){ if( !m_moved ) use( None ); } - - void Colour::use( Code _colourCode ) { - static IColourImpl* impl = platformColourInstance(); - impl->use( _colourCode ); - } - -} // end namespace Catch - -// #included from: catch_generators_impl.hpp -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include -#include -#include - -namespace Catch { - - struct GeneratorInfo : IGeneratorInfo { - - GeneratorInfo( std::size_t size ) - : m_size( size ), - m_currentIndex( 0 ) - {} - - bool moveNext() { - if( ++m_currentIndex == m_size ) { - m_currentIndex = 0; - return false; - } - return true; - } - - std::size_t getCurrentIndex() const { - return m_currentIndex; - } - - std::size_t m_size; - std::size_t m_currentIndex; - }; - - /////////////////////////////////////////////////////////////////////////// - - class GeneratorsForTest : public IGeneratorsForTest { - - public: - ~GeneratorsForTest() { - deleteAll( m_generatorsInOrder ); - } - - IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { - std::map::const_iterator it = m_generatorsByName.find( fileInfo ); - if( it == m_generatorsByName.end() ) { - IGeneratorInfo* info = new GeneratorInfo( size ); - m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); - m_generatorsInOrder.push_back( info ); - return *info; - } - return *it->second; - } - - bool moveNext() { - std::vector::const_iterator it = m_generatorsInOrder.begin(); - std::vector::const_iterator itEnd = m_generatorsInOrder.end(); - for(; it != itEnd; ++it ) { - if( (*it)->moveNext() ) - return true; - } - return false; - } - - private: - std::map m_generatorsByName; - std::vector m_generatorsInOrder; - }; - - IGeneratorsForTest* createGeneratorsForTest() - { - return new GeneratorsForTest(); - } - -} // end namespace Catch - -// #included from: catch_assertionresult.hpp -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED - -namespace Catch { - - AssertionInfo::AssertionInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - std::string const& _capturedExpression, - ResultDisposition::Flags _resultDisposition ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ) - {} - - AssertionResult::AssertionResult() {} - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - AssertionResult::~AssertionResult() {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return !m_info.capturedExpression.empty(); - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return '!' + m_info.capturedExpression; - else - return m_info.capturedExpression; - } - std::string AssertionResult::getExpressionInMacro() const { - if( m_info.macroName.empty() ) - return m_info.capturedExpression; - else - return m_info.macroName + "( " + m_info.capturedExpression + " )"; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - return m_resultData.reconstructExpression(); - } - - std::string AssertionResult::getMessage() const { - return m_resultData.message; - } - SourceLineInfo AssertionResult::getSourceInfo() const { - return m_info.lineInfo; - } - - std::string AssertionResult::getTestMacroName() const { - return m_info.macroName; - } - - void AssertionResult::discardDecomposedExpression() const { - m_resultData.decomposedExpression = CATCH_NULL; - } - - void AssertionResult::expandDecomposedExpression() const { - m_resultData.reconstructExpression(); - } - -} // end namespace Catch - -// #included from: catch_test_case_info.hpp -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED - -#include - -namespace Catch { - - inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { - if( startsWith( tag, '.' ) || - tag == "hide" || - tag == "!hide" ) - return TestCaseInfo::IsHidden; - else if( tag == "!throws" ) - return TestCaseInfo::Throws; - else if( tag == "!shouldfail" ) - return TestCaseInfo::ShouldFail; - else if( tag == "!mayfail" ) - return TestCaseInfo::MayFail; - else if( tag == "!nonportable" ) - return TestCaseInfo::NonPortable; - else - return TestCaseInfo::None; - } - inline bool isReservedTag( std::string const& tag ) { - return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); - } - inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - if( isReservedTag( tag ) ) { - std::ostringstream ss; - ss << Colour(Colour::Red) - << "Tag name [" << tag << "] not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" - << Colour(Colour::FileName) - << _lineInfo << '\n'; - throw std::runtime_error(ss.str()); - } - } - - TestCase makeTestCase( ITestCase* _testCase, - std::string const& _className, - std::string const& _name, - std::string const& _descOrTags, - SourceLineInfo const& _lineInfo ) - { - bool isHidden( startsWith( _name, "./" ) ); // Legacy support - - // Parse out tags - std::set tags; - std::string desc, tag; - bool inTag = false; - for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { - char c = _descOrTags[i]; - if( !inTag ) { - if( c == '[' ) - inTag = true; - else - desc += c; - } - else { - if( c == ']' ) { - TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); - if( prop == TestCaseInfo::IsHidden ) - isHidden = true; - else if( prop == TestCaseInfo::None ) - enforceNotReservedTag( tag, _lineInfo ); - - tags.insert( tag ); - tag.clear(); - inTag = false; - } - else - tag += c; - } - } - if( isHidden ) { - tags.insert( "hide" ); - tags.insert( "." ); - } - - TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); - return TestCase( _testCase, info ); - } - - void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) - { - testCaseInfo.tags = tags; - testCaseInfo.lcaseTags.clear(); - - std::ostringstream oss; - for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { - oss << '[' << *it << ']'; - std::string lcaseTag = toLower( *it ); - testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); - testCaseInfo.lcaseTags.insert( lcaseTag ); - } - testCaseInfo.tagsAsString = oss.str(); - } - - TestCaseInfo::TestCaseInfo( std::string const& _name, - std::string const& _className, - std::string const& _description, - std::set const& _tags, - SourceLineInfo const& _lineInfo ) - : name( _name ), - className( _className ), - description( _description ), - lineInfo( _lineInfo ), - properties( None ) - { - setTags( *this, _tags ); - } - - TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) - : name( other.name ), - className( other.className ), - description( other.description ), - tags( other.tags ), - lcaseTags( other.lcaseTags ), - tagsAsString( other.tagsAsString ), - lineInfo( other.lineInfo ), - properties( other.properties ) - {} - - bool TestCaseInfo::isHidden() const { - return ( properties & IsHidden ) != 0; - } - bool TestCaseInfo::throws() const { - return ( properties & Throws ) != 0; - } - bool TestCaseInfo::okToFail() const { - return ( properties & (ShouldFail | MayFail ) ) != 0; - } - bool TestCaseInfo::expectedToFail() const { - return ( properties & (ShouldFail ) ) != 0; - } - - TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} - - TestCase::TestCase( TestCase const& other ) - : TestCaseInfo( other ), - test( other.test ) - {} - - TestCase TestCase::withName( std::string const& _newName ) const { - TestCase other( *this ); - other.name = _newName; - return other; - } - - void TestCase::swap( TestCase& other ) { - test.swap( other.test ); - name.swap( other.name ); - className.swap( other.className ); - description.swap( other.description ); - tags.swap( other.tags ); - lcaseTags.swap( other.lcaseTags ); - tagsAsString.swap( other.tagsAsString ); - std::swap( TestCaseInfo::properties, static_cast( other ).properties ); - std::swap( lineInfo, other.lineInfo ); - } - - void TestCase::invoke() const { - test->invoke(); - } - - bool TestCase::operator == ( TestCase const& other ) const { - return test.get() == other.test.get() && - name == other.name && - className == other.className; - } - - bool TestCase::operator < ( TestCase const& other ) const { - return name < other.name; - } - TestCase& TestCase::operator = ( TestCase const& other ) { - TestCase temp( other ); - swap( temp ); - return *this; - } - - TestCaseInfo const& TestCase::getTestCaseInfo() const - { - return *this; - } - -} // end namespace Catch - -// #included from: catch_version.hpp -#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED - -namespace Catch { - - Version::Version - ( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ) - : majorVersion( _majorVersion ), - minorVersion( _minorVersion ), - patchNumber( _patchNumber ), - branchName( _branchName ), - buildNumber( _buildNumber ) - {} - - std::ostream& operator << ( std::ostream& os, Version const& version ) { - os << version.majorVersion << '.' - << version.minorVersion << '.' - << version.patchNumber; - // branchName is never null -> 0th char is \0 if it is empty - if (version.branchName[0]) { - os << '-' << version.branchName - << '.' << version.buildNumber; - } - return os; - } - - inline Version libraryVersion() { - static Version version( 1, 9, 2, "", 0 ); - return version; - } - -} - -// #included from: catch_message.hpp -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED - -namespace Catch { - - MessageInfo::MessageInfo( std::string const& _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ) - : macroName( _macroName ), - lineInfo( _lineInfo ), - type( _type ), - sequence( ++globalCount ) - {} - - // This may need protecting if threading support is added - unsigned int MessageInfo::globalCount = 0; - - //////////////////////////////////////////////////////////////////////////// - - ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) - { - m_info.message = builder.m_stream.str(); - getResultCapture().pushScopedMessage( m_info ); - } - ScopedMessage::ScopedMessage( ScopedMessage const& other ) - : m_info( other.m_info ) - {} - - ScopedMessage::~ScopedMessage() { - if ( !std::uncaught_exception() ){ - getResultCapture().popScopedMessage(m_info); - } - } - -} // end namespace Catch - -// #included from: catch_legacy_reporter_adapter.hpp -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -// #included from: catch_legacy_reporter_adapter.h -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl - { - public: - LegacyReporterAdapter( Ptr const& legacyReporter ); - virtual ~LegacyReporterAdapter(); - - virtual ReporterPreferences getPreferences() const; - virtual void noMatchingTestCases( std::string const& ); - virtual void testRunStarting( TestRunInfo const& ); - virtual void testGroupStarting( GroupInfo const& groupInfo ); - virtual void testCaseStarting( TestCaseInfo const& testInfo ); - virtual void sectionStarting( SectionInfo const& sectionInfo ); - virtual void assertionStarting( AssertionInfo const& ); - virtual bool assertionEnded( AssertionStats const& assertionStats ); - virtual void sectionEnded( SectionStats const& sectionStats ); - virtual void testCaseEnded( TestCaseStats const& testCaseStats ); - virtual void testGroupEnded( TestGroupStats const& testGroupStats ); - virtual void testRunEnded( TestRunStats const& testRunStats ); - virtual void skipTest( TestCaseInfo const& ); - - private: - Ptr m_legacyReporter; - }; -} - -namespace Catch -{ - LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) - : m_legacyReporter( legacyReporter ) - {} - LegacyReporterAdapter::~LegacyReporterAdapter() {} - - ReporterPreferences LegacyReporterAdapter::getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); - return prefs; - } - - void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} - void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { - m_legacyReporter->StartTesting(); - } - void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { - m_legacyReporter->StartGroup( groupInfo.name ); - } - void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { - m_legacyReporter->StartTestCase( testInfo ); - } - void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { - m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); - } - void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { - // Not on legacy interface - } - - bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); - rb << it->message; - rb.setResultType( ResultWas::Info ); - AssertionResult result = rb.build(); - m_legacyReporter->Result( result ); - } - } - } - m_legacyReporter->Result( assertionStats.assertionResult ); - return true; - } - void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { - if( sectionStats.missingAssertions ) - m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); - m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); - } - void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { - m_legacyReporter->EndTestCase - ( testCaseStats.testInfo, - testCaseStats.totals, - testCaseStats.stdOut, - testCaseStats.stdErr ); - } - void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { - if( testGroupStats.aborting ) - m_legacyReporter->Aborted(); - m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); - } - void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { - m_legacyReporter->EndTesting( testRunStats.totals ); - } - void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { - } -} - -// #included from: catch_timer.hpp - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wc++11-long-long" -#endif - -#ifdef CATCH_PLATFORM_WINDOWS - -#else - -#include - -#endif - -namespace Catch { - - namespace { -#ifdef CATCH_PLATFORM_WINDOWS - uint64_t getCurrentTicks() { - static uint64_t hz=0, hzo=0; - if (!hz) { - QueryPerformanceFrequency( reinterpret_cast( &hz ) ); - QueryPerformanceCounter( reinterpret_cast( &hzo ) ); - } - uint64_t t; - QueryPerformanceCounter( reinterpret_cast( &t ) ); - return ((t-hzo)*1000000)/hz; - } -#else - uint64_t getCurrentTicks() { - timeval t; - gettimeofday(&t,CATCH_NULL); - return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); - } -#endif - } - - void Timer::start() { - m_ticks = getCurrentTicks(); - } - unsigned int Timer::getElapsedMicroseconds() const { - return static_cast(getCurrentTicks() - m_ticks); - } - unsigned int Timer::getElapsedMilliseconds() const { - return static_cast(getElapsedMicroseconds()/1000); - } - double Timer::getElapsedSeconds() const { - return getElapsedMicroseconds()/1000000.0; - } - -} // namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -// #included from: catch_common.hpp -#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED - -#include -#include - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } - - SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) - : file( _file ), - line( _line ) - {} - bool SourceLineInfo::empty() const { - return file[0] == '\0'; - } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { - return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); - } - bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { - return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); - } - - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) - std::srand( config.rngSeed() ); - } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { -#ifndef __GNUG__ - os << info.file << '(' << info.line << ')'; -#else - os << info.file << ':' << info.line; -#endif - return os; - } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { - std::ostringstream oss; - oss << locationInfo << ": Internal Catch error: '" << message << '\''; - if( alwaysTrue() ) - throw std::logic_error( oss.str() ); - } -} - -// #included from: catch_section.hpp -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED - -namespace Catch { - - SectionInfo::SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - - Section::Section( SectionInfo const& info ) - : m_info( info ), - m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) - { - m_timer.start(); - } - - Section::~Section() { - if( m_sectionIncluded ) { - SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); - if( std::uncaught_exception() ) - getResultCapture().sectionEndedEarly( endInfo ); - else - getResultCapture().sectionEnded( endInfo ); - } - } - - // This indicates whether the section should be executed or not - Section::operator bool() const { - return m_sectionIncluded; - } - -} // end namespace Catch - -// #included from: catch_debugger.hpp -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED - -#ifdef CATCH_PLATFORM_MAC - - #include - #include - #include - #include - #include - - namespace Catch{ - - // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html - - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive(){ - - int mib[4]; - struct kinfo_proc info; - size_t size; - - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - - info.kp_proc.p_flag = 0; - - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - - // Call sysctl. - - size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { - Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; - return false; - } - - // We're being debugged if the P_TRACED flag is set. - - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); - } - } // namespace Catch - -#elif defined(CATCH_PLATFORM_LINUX) - #include - #include - - namespace Catch{ - // The standard POSIX way of detecting a debugger is to attempt to - // ptrace() the process, but this needs to be done from a child and not - // this process itself to still allow attaching to this process later - // if wanted, so is rather heavy. Under Linux we have the PID of the - // "debugger" (which doesn't need to be gdb, of course, it could also - // be strace, for example) in /proc/$PID/status, so just get it from - // there instead. - bool isDebuggerActive(){ - // Libstdc++ has a bug, where std::ifstream sets errno to 0 - // This way our users can properly assert over errno values - ErrnoGuard guard; - std::ifstream in("/proc/self/status"); - for( std::string line; std::getline(in, line); ) { - static const int PREFIX_LEN = 11; - if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { - // We're traced if the PID is not 0 and no other PID starts - // with 0 digit, so it's enough to check for just a single - // character. - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - - return false; - } - } // namespace Catch -#elif defined(_MSC_VER) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#elif defined(__MINGW32__) - extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); - namespace Catch { - bool isDebuggerActive() { - return IsDebuggerPresent() != 0; - } - } -#else - namespace Catch { - inline bool isDebuggerActive() { return false; } - } -#endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } -#endif // Platform - -// #included from: catch_tostring.hpp -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED - -namespace Catch { - -namespace Detail { - - const std::string unprintableString = "{?}"; - - namespace { - const int hexThreshold = 255; - - struct Endianness { - enum Arch { Big, Little }; - - static Arch which() { - union _{ - int asInt; - char asChar[sizeof (int)]; - } u; - - u.asInt = 1; - return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; - } - }; - } - - std::string rawMemoryToString( const void *object, std::size_t size ) - { - // Reverse order for little endian architectures - int i = 0, end = static_cast( size ), inc = 1; - if( Endianness::which() == Endianness::Little ) { - i = end-1; - end = inc = -1; - } - - unsigned char const *bytes = static_cast(object); - std::ostringstream os; - os << "0x" << std::setfill('0') << std::hex; - for( ; i != end; i += inc ) - os << std::setw(2) << static_cast(bytes[i]); - return os.str(); - } -} - -std::string toString( std::string const& value ) { - std::string s = value; - if( getCurrentContext().getConfig()->showInvisibles() ) { - for(size_t i = 0; i < s.size(); ++i ) { - std::string subs; - switch( s[i] ) { - case '\n': subs = "\\n"; break; - case '\t': subs = "\\t"; break; - default: break; - } - if( !subs.empty() ) { - s = s.substr( 0, i ) + subs + s.substr( i+1 ); - ++i; - } - } - } - return '"' + s + '"'; -} -std::string toString( std::wstring const& value ) { - - std::string s; - s.reserve( value.size() ); - for(size_t i = 0; i < value.size(); ++i ) - s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; - return Catch::toString( s ); -} - -std::string toString( const char* const value ) { - return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -std::string toString( char* const value ) { - return Catch::toString( static_cast( value ) ); -} - -std::string toString( const wchar_t* const value ) -{ - return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); -} - -std::string toString( wchar_t* const value ) -{ - return Catch::toString( static_cast( value ) ); -} - -std::string toString( int value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned int value ) { - return Catch::toString( static_cast( value ) ); -} - -template -std::string fpToString( T value, int precision ) { - std::ostringstream oss; - oss << std::setprecision( precision ) - << std::fixed - << value; - std::string d = oss.str(); - std::size_t i = d.find_last_not_of( '0' ); - if( i != std::string::npos && i != d.size()-1 ) { - if( d[i] == '.' ) - i++; - d = d.substr( 0, i+1 ); - } - return d; -} - -std::string toString( const double value ) { - return fpToString( value, 10 ); -} -std::string toString( const float value ) { - return fpToString( value, 5 ) + 'f'; -} - -std::string toString( bool value ) { - return value ? "true" : "false"; -} - -std::string toString( char value ) { - if ( value == '\r' ) - return "'\\r'"; - if ( value == '\f' ) - return "'\\f'"; - if ( value == '\n' ) - return "'\\n'"; - if ( value == '\t' ) - return "'\\t'"; - if ( '\0' <= value && value < ' ' ) - return toString( static_cast( value ) ); - char chstr[] = "' '"; - chstr[1] = value; - return chstr; -} - -std::string toString( signed char value ) { - return toString( static_cast( value ) ); -} - -std::string toString( unsigned char value ) { - return toString( static_cast( value ) ); -} - -#ifdef CATCH_CONFIG_CPP11_LONG_LONG -std::string toString( long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} -std::string toString( unsigned long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} -#endif - -#ifdef CATCH_CONFIG_CPP11_NULLPTR -std::string toString( std::nullptr_t ) { - return "nullptr"; -} -#endif - -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } -#endif - -} // end namespace Catch - -// #included from: catch_result_builder.hpp -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED - -namespace Catch { - - std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { - return secondArg.empty() || secondArg == "\"\"" - ? capturedExpression - : capturedExpression + ", " + secondArg; - } - ResultBuilder::ResultBuilder( char const* macroName, - SourceLineInfo const& lineInfo, - char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), - m_shouldDebugBreak( false ), - m_shouldThrow( false ), - m_guardException( false ) - {} - - ResultBuilder::~ResultBuilder() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if ( m_guardException ) { - m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; - captureResult( ResultWas::ThrewException ); - getCurrentContext().getResultCapture()->exceptionEarlyReported(); - } -#endif - } - - ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { - m_data.resultType = result; - return *this; - } - ResultBuilder& ResultBuilder::setResultType( bool result ) { - m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; - return *this; - } - - void ResultBuilder::endExpression( DecomposedExpression const& expr ) { - AssertionResult result = build( expr ); - handleResult( result ); - } - - void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { - m_assertionInfo.resultDisposition = resultDisposition; - m_stream.oss << Catch::translateActiveException(); - captureResult( ResultWas::ThrewException ); - } - - void ResultBuilder::captureResult( ResultWas::OfType resultType ) { - setResultType( resultType ); - captureExpression(); - } - - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { - if( expectedMessage.empty() ) - captureExpectedException( Matchers::Impl::MatchAllOf() ); - else - captureExpectedException( Matchers::Equals( expectedMessage ) ); - } - - void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase const& matcher ) { - - assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); - AssertionResultData data = m_data; - data.resultType = ResultWas::Ok; - data.reconstructedExpression = m_assertionInfo.capturedExpression; - - std::string actualMessage = Catch::translateActiveException(); - if( !matcher.match( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; - } - AssertionResult result( m_assertionInfo, data ); - handleResult( result ); - } - - void ResultBuilder::captureExpression() { - AssertionResult result = build(); - handleResult( result ); - } - - void ResultBuilder::handleResult( AssertionResult const& result ) - { - getResultCapture().assertionEnded( result ); - - if( !result.isOk() ) { - if( getCurrentContext().getConfig()->shouldDebugBreak() ) - m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) - m_shouldThrow = true; - } - } - - void ResultBuilder::react() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if (m_shouldDebugBreak) { - /////////////////////////////////////////////////////////////////// - // To inspect the state during test, you need to go one level up the callstack - // To go back to the test and change execution, jump over the throw statement - /////////////////////////////////////////////////////////////////// - CATCH_BREAK_INTO_DEBUGGER(); - } -#endif - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - - bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } - bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } - - AssertionResult ResultBuilder::build() const - { - return build( *this ); - } - - // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, - // a temporary DecomposedExpression, which in turn holds references to - // operands, possibly temporary as well. - // It should immediately be passed to handleResult; if the expression - // needs to be reported, its string expansion must be composed before - // the temporaries are destroyed. - AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const - { - assert( m_data.resultType != ResultWas::Unknown ); - AssertionResultData data = m_data; - - // Flip bool results if FalseTest flag is set - if( isFalseTest( m_assertionInfo.resultDisposition ) ) { - data.negate( expr.isBinaryExpression() ); - } - - data.message = m_stream.oss.str(); - data.decomposedExpression = &expr; // for lazy reconstruction - return AssertionResult( m_assertionInfo, data ); - } - - void ResultBuilder::reconstructExpression( std::string& dest ) const { - dest = m_assertionInfo.capturedExpression; - } - - void ResultBuilder::setExceptionGuard() { - m_guardException = true; - } - void ResultBuilder::unsetExceptionGuard() { - m_guardException = false; - } - -} // end namespace Catch - -// #included from: catch_tag_alias_registry.hpp -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED - -namespace Catch { - - TagAliasRegistry::~TagAliasRegistry() {} - - Option TagAliasRegistry::find( std::string const& alias ) const { - std::map::const_iterator it = m_registry.find( alias ); - if( it != m_registry.end() ) - return it->second; - else - return Option(); - } - - std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { - std::string expandedTestSpec = unexpandedTestSpec; - for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); - it != itEnd; - ++it ) { - std::size_t pos = expandedTestSpec.find( it->first ); - if( pos != std::string::npos ) { - expandedTestSpec = expandedTestSpec.substr( 0, pos ) + - it->second.tag + - expandedTestSpec.substr( pos + it->first.size() ); - } - } - return expandedTestSpec; - } - - void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { - - if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" - << Colour( Colour::FileName ) - << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } - if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" already registered.\n" - << "\tFirst seen at " - << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' - << Colour( Colour::Red ) << "\tRedefined at " - << Colour( Colour::FileName) << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } - } - - ITagAliasRegistry::~ITagAliasRegistry() {} - - ITagAliasRegistry const& ITagAliasRegistry::get() { - return getRegistryHub().getTagAliasRegistry(); - } - - RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); - } - -} // end namespace Catch - -// #included from: catch_matchers_string.hpp - -namespace Catch { -namespace Matchers { - - namespace StdString { - - CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_str( adjustString( str ) ) - {} - std::string CasedString::adjustString( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No - ? toLower( str ) - : str; - } - std::string CasedString::caseSensitivitySuffix() const { - return m_caseSensitivity == CaseSensitive::No - ? " (case insensitive)" - : std::string(); - } - - StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) - : m_comparator( comparator ), - m_operation( operation ) { - } - - std::string StringMatcherBase::describe() const { - std::string description; - description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + - m_comparator.caseSensitivitySuffix().size()); - description += m_operation; - description += ": \""; - description += m_comparator.m_str; - description += "\""; - description += m_comparator.caseSensitivitySuffix(); - return description; - } - - EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} - - bool EqualsMatcher::match( std::string const& source ) const { - return m_comparator.adjustString( source ) == m_comparator.m_str; - } - - ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} - - bool ContainsMatcher::match( std::string const& source ) const { - return contains( m_comparator.adjustString( source ), m_comparator.m_str ); - } - - StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} - - bool StartsWithMatcher::match( std::string const& source ) const { - return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); - } - - EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} - - bool EndsWithMatcher::match( std::string const& source ) const { - return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); - } - - } // namespace StdString - - StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); - } - StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { - return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); - } - -} // namespace Matchers -} // namespace Catch -// #included from: ../reporters/catch_reporter_multi.hpp -#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED - -namespace Catch { - -class MultipleReporters : public SharedImpl { - typedef std::vector > Reporters; - Reporters m_reporters; - -public: - void add( Ptr const& reporter ) { - m_reporters.push_back( reporter ); - } - -public: // IStreamingReporter - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporters[0]->getPreferences(); - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->noMatchingTestCases( spec ); - } - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunStarting( testRunInfo ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseStarting( testInfo ); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionStarting( sectionInfo ); - } - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->assertionStarting( assertionInfo ); - } - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - bool clearBuffer = false; - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - clearBuffer |= (*it)->assertionEnded( assertionStats ); - return clearBuffer; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->sectionEnded( sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testGroupEnded( testGroupStats ); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->testRunEnded( testRunStats ); - } - - virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); - it != itEnd; - ++it ) - (*it)->skipTest( testInfo ); - } - - virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { - return this; - } - -}; - -Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { - Ptr resultingReporter; - - if( existingReporter ) { - MultipleReporters* multi = existingReporter->tryAsMulti(); - if( !multi ) { - multi = new MultipleReporters; - resultingReporter = Ptr( multi ); - if( existingReporter ) - multi->add( existingReporter ); - } - else - resultingReporter = existingReporter; - multi->add( additionalReporter ); - } - else - resultingReporter = additionalReporter; - - return resultingReporter; -} - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_xml.hpp -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED - -// #included from: catch_reporter_bases.hpp -#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - namespace { - // Because formatting using c++ streams is stateful, drop down to C is required - // Alternatively we could use stringstream, but its performance is... not good. - std::string getFormattedDuration( double duration ) { - // Max exponent + 1 is required to represent the whole part - // + 1 for decimal point - // + 3 for the 3 decimal places - // + 1 for null terminator - const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; - char buffer[maxDoubleSize]; - - // Save previous errno, to prevent sprintf from overwriting it - ErrnoGuard guard; -#ifdef _MSC_VER - sprintf_s(buffer, "%.3f", duration); -#else - sprintf(buffer, "%.3f", duration); -#endif - return std::string(buffer); - } - } - - struct StreamingReporterBase : SharedImpl { - - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual ~StreamingReporterBase() CATCH_OVERRIDE; - - virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { - currentTestRunInfo = _testRunInfo; - } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { - currentGroupInfo = _groupInfo; - } - - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { - currentTestCaseInfo = _testInfo; - } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { - m_sectionStack.push_back( _sectionInfo ); - } - - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { - currentTestCaseInfo.reset(); - } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { - currentGroupInfo.reset(); - } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } - - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { - // Don't do anything with this by default. - // It can optionally be overridden in the derived class. - } - - Ptr m_config; - std::ostream& stream; - - LazyStat currentTestRunInfo; - LazyStat currentGroupInfo; - LazyStat currentTestCaseInfo; - - std::vector m_sectionStack; - ReporterPreferences m_reporterPrefs; - }; - - struct CumulativeReporterBase : SharedImpl { - template - struct Node : SharedImpl<> { - explicit Node( T const& _value ) : value( _value ) {} - virtual ~Node() {} - - typedef std::vector > ChildNodes; - T value; - ChildNodes children; - }; - struct SectionNode : SharedImpl<> { - explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} - virtual ~SectionNode(); - - bool operator == ( SectionNode const& other ) const { - return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; - } - bool operator == ( Ptr const& other ) const { - return operator==( *other ); - } - - SectionStats stats; - typedef std::vector > ChildSections; - typedef std::vector Assertions; - ChildSections childSections; - Assertions assertions; - std::string stdOut; - std::string stdErr; - }; - - struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() ( Ptr const& node ) const { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; - } - private: - void operator=( BySectionInfo const& ); - SectionInfo const& m_other; - }; - - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; - - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } - ~CumulativeReporterBase(); - - virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { - return m_reporterPrefs; - } - - virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} - virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - - virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = new SectionNode( incompleteStats ); - node = m_rootSection; - } - else { - SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = new SectionNode( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; - } - m_sectionStack.push_back( node ); - m_deepestSection = node; - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - assert( !m_sectionStack.empty() ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back( assertionStats ); - // AssertionResult holds a pointer to a temporary DecomposedExpression, - // which getExpandedExpression() calls to build the expression string. - // Our section stack copy of the assertionResult will likely outlive the - // temporary, so it must be expanded or discarded now to avoid calling - // a destroyed object later. - prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); - return true; - } - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - assert( !m_sectionStack.empty() ); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - Ptr node = new TestCaseNode( testCaseStats ); - assert( m_sectionStack.size() == 0 ); - node->children.push_back( m_rootSection ); - m_testCases.push_back( node ); - m_rootSection.reset(); - - assert( m_deepestSection ); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - Ptr node = new TestGroupNode( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - Ptr node = new TestRunNode( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEndedCumulative(); - } - virtual void testRunEndedCumulative() = 0; - - virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} - - virtual void prepareExpandedExpression( AssertionResult& result ) const { - if( result.isOk() ) - result.discardDecomposedExpression(); - else - result.expandDecomposedExpression(); - } - - Ptr m_config; - std::ostream& stream; - std::vector m_assertions; - std::vector > > m_sections; - std::vector > m_testCases; - std::vector > m_testGroups; - - std::vector > m_testRuns; - - Ptr m_rootSection; - Ptr m_deepestSection; - std::vector > m_sectionStack; - ReporterPreferences m_reporterPrefs; - - }; - - template - char const* getLineOfChars() { - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if( !*line ) { - std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - } - return line; - } - - struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { - return false; - } - }; - -} // end namespace Catch - -// #included from: ../internal/catch_reporter_registrars.hpp -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED - -namespace Catch { - - template - class LegacyReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - class ReporterRegistrar { - - class ReporterFactory : public SharedImpl { - - // *** Please Note ***: - // - If you end up here looking at a compiler error because it's trying to register - // your custom reporter class be aware that the native reporter interface has changed - // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via - // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. - // However please consider updating to the new interface as the old one is now - // deprecated and will probably be removed quite soon! - // Please contact me via github if you have any questions at all about this. - // In fact, ideally, please contact me anyway to let me know you've hit this - as I have - // no idea who is actually using custom reporters at all (possibly no-one!). - // The new interface is designed to minimise exposure to interface changes in the future. - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - - template - class ListenerRegistrar { - - class ListenerFactory : public SharedImpl { - - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); - } - virtual std::string getDescription() const { - return std::string(); - } - }; - - public: - - ListenerRegistrar() { - getMutableRegistryHub().registerListener( new ListenerFactory() ); - } - }; -} - -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - -// Deprecated - use the form without INTERNAL_ -#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - -#define CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - -// #included from: ../internal/catch_xmlwriter.hpp -#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED - -#include -#include -#include -#include - -namespace Catch { - - class XmlEncode { - public: - enum ForWhat { ForTextNodes, ForAttributes }; - - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) - : m_str( str ), - m_forWhat( forWhat ) - {} - - void encodeTo( std::ostream& os ) const { - - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: http://www.w3.org/TR/xml/#syntax) - - for( std::size_t i = 0; i < m_str.size(); ++ i ) { - char c = m_str[i]; - switch( c ) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: http://www.w3.org/TR/xml/#syntax - if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) - os << ">"; - else - os << c; - break; - - case '\"': - if( m_forWhat == ForAttributes ) - os << """; - else - os << c; - break; - - default: - // Escape control chars - based on contribution by @espenalb in PR #465 and - // by @mrpi PR #588 - if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast( c ); - } - else - os << c; - } - } - } - - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } - - private: - std::string m_str; - ForWhat m_forWhat; - }; - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = CATCH_NULL; - } - - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } - - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer; - }; - - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( Catch::cout() ) - { - writeDeclaration(); - } - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( os ) - { - writeDeclaration(); - } - - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::ostringstream oss; - oss << attribute; - return writeAttribute( name, oss.str() ); - } - - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - m_os << m_indent << ""; - m_needsNewline = true; - return *this; - } - - void writeStylesheetRef( std::string const& url ) { - m_os << "\n"; - } - - XmlWriter& writeBlankLine() { - ensureTagClosed(); - m_os << '\n'; - return *this; - } - - void ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } - - private: - XmlWriter( XmlWriter const& ); - void operator=( XmlWriter const& ); - - void writeDeclaration() { - m_os << "\n"; - } - - void newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } - - bool m_tagIsOpen; - bool m_needsNewline; - std::vector m_tags; - std::string m_indent; - std::ostream& m_os; - }; - -} -// #included from: catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - - -namespace Catch { - class XmlReporter : public StreamingReporterBase { - public: - XmlReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_xml(_config.stream()), - m_sectionDepth( 0 ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~XmlReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results as an XML document"; - } - - virtual std::string getStylesheetRef() const { - return std::string(); - } - - void writeSourceInfo( SourceLineInfo const& sourceInfo ) { - m_xml - .writeAttribute( "filename", sourceInfo.file ) - .writeAttribute( "line", sourceInfo.line ); - } - - public: // StreamingReporterBase - - virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { - StreamingReporterBase::noMatchingTestCases( s ); - } - - virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testRunStarting( testInfo ); - std::string stylesheetRef = getStylesheetRef(); - if( !stylesheetRef.empty() ) - m_xml.writeStylesheetRef( stylesheetRef ); - m_xml.startElement( "Catch" ); - if( !m_config->name().empty() ) - m_xml.writeAttribute( "name", m_config->name() ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupStarting( groupInfo ); - m_xml.startElement( "Group" ) - .writeAttribute( "name", groupInfo.name ); - } - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseStarting(testInfo); - m_xml.startElement( "TestCase" ) - .writeAttribute( "name", trim( testInfo.name ) ) - .writeAttribute( "description", testInfo.description ) - .writeAttribute( "tags", testInfo.tagsAsString ); - - writeSourceInfo( testInfo.lineInfo ); - - if ( m_config->showDurations() == ShowDurations::Always ) - m_testCaseTimer.start(); - m_xml.ensureTagClosed(); - } - - virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { - StreamingReporterBase::sectionStarting( sectionInfo ); - if( m_sectionDepth++ > 0 ) { - m_xml.startElement( "Section" ) - .writeAttribute( "name", trim( sectionInfo.name ) ) - .writeAttribute( "description", sectionInfo.description ); - writeSourceInfo( sectionInfo.lineInfo ); - m_xml.ensureTagClosed(); - } - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - - AssertionResult const& result = assertionStats.assertionResult; - - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); - - if( includeResults ) { - // Print any info messages in tags. - for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); - it != itEnd; - ++it ) { - if( it->type == ResultWas::Info ) { - m_xml.scopedElement( "Info" ) - .writeText( it->message ); - } else if ( it->type == ResultWas::Warning ) { - m_xml.scopedElement( "Warning" ) - .writeText( it->message ); - } - } - } - - // Drop out if result was successful but we're not printing them. - if( !includeResults && result.getResultType() != ResultWas::Warning ) - return true; - - // Print the expression if there is one. - if( result.hasExpression() ) { - m_xml.startElement( "Expression" ) - .writeAttribute( "success", result.succeeded() ) - .writeAttribute( "type", result.getTestMacroName() ); - - writeSourceInfo( result.getSourceInfo() ); - - m_xml.scopedElement( "Original" ) - .writeText( result.getExpression() ); - m_xml.scopedElement( "Expanded" ) - .writeText( result.getExpandedExpression() ); - } - - // And... Print a result applicable to each result type. - switch( result.getResultType() ) { - case ResultWas::ThrewException: - m_xml.startElement( "Exception" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::FatalErrorCondition: - m_xml.startElement( "FatalErrorCondition" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - case ResultWas::Info: - m_xml.scopedElement( "Info" ) - .writeText( result.getMessage() ); - break; - case ResultWas::Warning: - // Warning will already have been written - break; - case ResultWas::ExplicitFailure: - m_xml.startElement( "Failure" ); - writeSourceInfo( result.getSourceInfo() ); - m_xml.writeText( result.getMessage() ); - m_xml.endElement(); - break; - default: - break; - } - - if( result.hasExpression() ) - m_xml.endElement(); - - return true; - } - - virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { - StreamingReporterBase::sectionEnded( sectionStats ); - if( --m_sectionDepth > 0 ) { - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); - e.writeAttribute( "successes", sectionStats.assertions.passed ); - e.writeAttribute( "failures", sectionStats.assertions.failed ); - e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); - - m_xml.endElement(); - } - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( testCaseStats ); - XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); - e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); - - if ( m_config->showDurations() == ShowDurations::Always ) - e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); - - if( !testCaseStats.stdOut.empty() ) - m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); - if( !testCaseStats.stdErr.empty() ) - m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); - - m_xml.endElement(); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - StreamingReporterBase::testGroupEnded( testGroupStats ); - // TODO: Check testGroupStats.aborting and act accordingly. - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) - .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { - StreamingReporterBase::testRunEnded( testRunStats ); - m_xml.scopedElement( "OverallResults" ) - .writeAttribute( "successes", testRunStats.totals.assertions.passed ) - .writeAttribute( "failures", testRunStats.totals.assertions.failed ) - .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); - m_xml.endElement(); - } - - private: - Timer m_testCaseTimer; - XmlWriter m_xml; - int m_sectionDepth; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_junit.hpp -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED - -#include - -namespace Catch { - - namespace { - std::string getCurrentTimestamp() { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); - -#ifdef _MSC_VER - std::tm timeInfo = {}; - gmtime_s(&timeInfo, &rawtime); -#else - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); -#endif - - char timeStamp[timeStampSize]; - const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; - -#ifdef _MSC_VER - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); -#else - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); -#endif - return std::string(timeStamp); - } - - } - - class JunitReporter : public CumulativeReporterBase { - public: - JunitReporter( ReporterConfig const& _config ) - : CumulativeReporterBase( _config ), - xml( _config.stream() ), - m_okToFail( false ) - { - m_reporterPrefs.shouldRedirectStdOut = true; - } - - virtual ~JunitReporter() CATCH_OVERRIDE; - - static std::string getDescription() { - return "Reports test results in an XML format that looks like Ant's junitreport target"; - } - - virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - - virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { - CumulativeReporterBase::testRunStarting( runInfo ); - xml.startElement( "testsuites" ); - } - - virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { - suiteTimer.start(); - stdOutForSuite.str(""); - stdErrForSuite.str(""); - unexpectedExceptions = 0; - CumulativeReporterBase::testGroupStarting( groupInfo ); - } - - virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { - m_okToFail = testCaseInfo.okToFail(); - } - virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { - if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) - unexpectedExceptions++; - return CumulativeReporterBase::assertionEnded( assertionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { - stdOutForSuite << testCaseStats.stdOut; - stdErrForSuite << testCaseStats.stdErr; - CumulativeReporterBase::testCaseEnded( testCaseStats ); - } - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { - double suiteTime = suiteTimer.getElapsedSeconds(); - CumulativeReporterBase::testGroupEnded( testGroupStats ); - writeGroup( *m_testGroups.back(), suiteTime ); - } - - virtual void testRunEndedCumulative() CATCH_OVERRIDE { - xml.endElement(); - } - - void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); - TestGroupStats const& stats = groupNode.value; - xml.writeAttribute( "name", stats.groupInfo.name ); - xml.writeAttribute( "errors", unexpectedExceptions ); - xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); - xml.writeAttribute( "tests", stats.totals.assertions.total() ); - xml.writeAttribute( "hostname", "tbd" ); // !TBD - if( m_config->showDurations() == ShowDurations::Never ) - xml.writeAttribute( "time", "" ); - else - xml.writeAttribute( "time", suiteTime ); - xml.writeAttribute( "timestamp", getCurrentTimestamp() ); - - // Write test cases - for( TestGroupNode::ChildNodes::const_iterator - it = groupNode.children.begin(), itEnd = groupNode.children.end(); - it != itEnd; - ++it ) - writeTestCase( **it ); - - xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); - xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); - } - - void writeTestCase( TestCaseNode const& testCaseNode ) { - TestCaseStats const& stats = testCaseNode.value; - - // All test cases have exactly one section - which represents the - // test case itself. That section may have 0-n nested sections - assert( testCaseNode.children.size() == 1 ); - SectionNode const& rootSection = *testCaseNode.children.front(); - - std::string className = stats.testInfo.className; - - if( className.empty() ) { - if( rootSection.childSections.empty() ) - className = "global"; - } - writeSection( className, "", rootSection ); - } - - void writeSection( std::string const& className, - std::string const& rootName, - SectionNode const& sectionNode ) { - std::string name = trim( sectionNode.stats.sectionInfo.name ); - if( !rootName.empty() ) - name = rootName + '/' + name; - - if( !sectionNode.assertions.empty() || - !sectionNode.stdOut.empty() || - !sectionNode.stdErr.empty() ) { - XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); - if( className.empty() ) { - xml.writeAttribute( "classname", name ); - xml.writeAttribute( "name", "root" ); - } - else { - xml.writeAttribute( "classname", className ); - xml.writeAttribute( "name", name ); - } - xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); - - writeAssertions( sectionNode ); - - if( !sectionNode.stdOut.empty() ) - xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); - if( !sectionNode.stdErr.empty() ) - xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); - } - for( SectionNode::ChildSections::const_iterator - it = sectionNode.childSections.begin(), - itEnd = sectionNode.childSections.end(); - it != itEnd; - ++it ) - if( className.empty() ) - writeSection( name, "", **it ); - else - writeSection( className, name, **it ); - } - - void writeAssertions( SectionNode const& sectionNode ) { - for( SectionNode::Assertions::const_iterator - it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); - it != itEnd; - ++it ) - writeAssertion( *it ); - } - void writeAssertion( AssertionStats const& stats ) { - AssertionResult const& result = stats.assertionResult; - if( !result.isOk() ) { - std::string elementName; - switch( result.getResultType() ) { - case ResultWas::ThrewException: - case ResultWas::FatalErrorCondition: - elementName = "error"; - break; - case ResultWas::ExplicitFailure: - elementName = "failure"; - break; - case ResultWas::ExpressionFailed: - elementName = "failure"; - break; - case ResultWas::DidntThrowException: - elementName = "failure"; - break; - - // We should never see these here: - case ResultWas::Info: - case ResultWas::Warning: - case ResultWas::Ok: - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - elementName = "internalError"; - break; - } - - XmlWriter::ScopedElement e = xml.scopedElement( elementName ); - - xml.writeAttribute( "message", result.getExpandedExpression() ); - xml.writeAttribute( "type", result.getTestMacroName() ); - - std::ostringstream oss; - if( !result.getMessage().empty() ) - oss << result.getMessage() << '\n'; - for( std::vector::const_iterator - it = stats.infoMessages.begin(), - itEnd = stats.infoMessages.end(); - it != itEnd; - ++it ) - if( it->type == ResultWas::Info ) - oss << it->message << '\n'; - - oss << "at " << result.getSourceInfo(); - xml.writeText( oss.str(), false ); - } - } - - XmlWriter xml; - Timer suiteTimer; - std::ostringstream stdOutForSuite; - std::ostringstream stdErrForSuite; - unsigned int unexpectedExceptions; - bool m_okToFail; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_console.hpp -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED - -#include -#include - -namespace Catch { - - struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ) - {} - - virtual ~ConsoleReporter() CATCH_OVERRIDE; - static std::string getDescription() { - return "Reports test results as plain lines of text"; - } - - virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { - stream << "No test cases matched '" << spec << '\'' << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { - } - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { - AssertionResult const& result = _assertionStats.assertionResult; - - bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); - - // Drop out if result was successful but we're not printing them. - if( !includeResults && result.getResultType() != ResultWas::Warning ) - return false; - - lazyPrint(); - - AssertionPrinter printer( stream, _assertionStats, includeResults ); - printer.print(); - stream << std::endl; - return true; - } - - virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { - m_headerPrinted = false; - StreamingReporterBase::sectionStarting( _sectionInfo ); - } - virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { - if( _sectionStats.missingAssertions ) { - lazyPrint(); - Colour colour( Colour::ResultError ); - if( m_sectionStack.size() > 1 ) - stream << "\nNo assertions in section"; - else - stream << "\nNo assertions in test case"; - stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; - } - if( m_config->showDurations() == ShowDurations::Always ) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; - } - if( m_headerPrinted ) { - m_headerPrinted = false; - } - StreamingReporterBase::sectionEnded( _sectionStats ); - } - - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { - StreamingReporterBase::testCaseEnded( _testCaseStats ); - m_headerPrinted = false; - } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { - if( currentGroupInfo.used ) { - printSummaryDivider(); - stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; - printTotals( _testGroupStats.totals ); - stream << '\n' << std::endl; - } - StreamingReporterBase::testGroupEnded( _testGroupStats ); - } - virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { - printTotalsDivider( _testRunStats.totals ); - printTotals( _testRunStats.totals ); - stream << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ), - stats( _stats ), - result( _stats.assertionResult ), - colour( Colour::None ), - message( result.getMessage() ), - messages( _stats.infoMessages ), - printInfoMessages( _printInfoMessages ) - { - switch( result.getResultType() ) { - case ResultWas::Ok: - colour = Colour::Success; - passOrFail = "PASSED"; - //if( result.hasMessage() ) - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) { - colour = Colour::Success; - passOrFail = "FAILED - but was ok"; - } - else { - colour = Colour::Error; - passOrFail = "FAILED"; - } - if( _stats.infoMessages.size() == 1 ) - messageLabel = "with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "with messages"; - break; - case ResultWas::ThrewException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to unexpected exception with "; - if (_stats.infoMessages.size() == 1) - messageLabel += "message"; - if (_stats.infoMessages.size() > 1) - messageLabel += "messages"; - break; - case ResultWas::FatalErrorCondition: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "due to a fatal error condition"; - break; - case ResultWas::DidntThrowException: - colour = Colour::Error; - passOrFail = "FAILED"; - messageLabel = "because no exception was thrown where one was expected"; - break; - case ResultWas::Info: - messageLabel = "info"; - break; - case ResultWas::Warning: - messageLabel = "warning"; - break; - case ResultWas::ExplicitFailure: - passOrFail = "FAILED"; - colour = Colour::Error; - if( _stats.infoMessages.size() == 1 ) - messageLabel = "explicitly with message"; - if( _stats.infoMessages.size() > 1 ) - messageLabel = "explicitly with messages"; - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - passOrFail = "** internal error **"; - colour = Colour::Error; - break; - } - } - - void print() const { - printSourceInfo(); - if( stats.totals.assertions.total() > 0 ) { - if( result.isOk() ) - stream << '\n'; - printResultType(); - printOriginalExpression(); - printReconstructedExpression(); - } - else { - stream << '\n'; - } - printMessage(); - } - - private: - void printResultType() const { - if( !passOrFail.empty() ) { - Colour colourGuard( colour ); - stream << passOrFail << ":\n"; - } - } - void printOriginalExpression() const { - if( result.hasExpression() ) { - Colour colourGuard( Colour::OriginalExpression ); - stream << " "; - stream << result.getExpressionInMacro(); - stream << '\n'; - } - } - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - stream << "with expansion:\n"; - Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; - } - } - void printMessage() const { - if( !messageLabel.empty() ) - stream << messageLabel << ':' << '\n'; - for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); - it != itEnd; - ++it ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || it->type != ResultWas::Info ) - stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; - } - } - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ": "; - } - - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - Colour::Code colour; - std::string passOrFail; - std::string messageLabel; - std::string message; - std::vector messages; - bool printInfoMessages; - }; - - void lazyPrint() { - - if( !currentTestRunInfo.used ) - lazyPrintRunInfo(); - if( !currentGroupInfo.used ) - lazyPrintGroupInfo(); - - if( !m_headerPrinted ) { - printTestCaseAndSectionHeader(); - m_headerPrinted = true; - } - } - void lazyPrintRunInfo() { - stream << '\n' << getLineOfChars<'~'>() << '\n'; - Colour colour( Colour::SecondaryText ); - stream << currentTestRunInfo->name - << " is a Catch v" << libraryVersion() << " host application.\n" - << "Run with -? for options\n\n"; - - if( m_config->rngSeed() != 0 ) - stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; - - currentTestRunInfo.used = true; - } - void lazyPrintGroupInfo() { - if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { - printClosedHeader( "Group: " + currentGroupInfo->name ); - currentGroupInfo.used = true; - } - } - void printTestCaseAndSectionHeader() { - assert( !m_sectionStack.empty() ); - printOpenHeader( currentTestCaseInfo->name ); - - if( m_sectionStack.size() > 1 ) { - Colour colourGuard( Colour::Headers ); - - std::vector::const_iterator - it = m_sectionStack.begin()+1, // Skip first section (test case) - itEnd = m_sectionStack.end(); - for( ; it != itEnd; ++it ) - printHeaderString( it->name, 2 ); - } - - SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; - - if( !lineInfo.empty() ){ - stream << getLineOfChars<'-'>() << '\n'; - Colour colourGuard( Colour::FileName ); - stream << lineInfo << '\n'; - } - stream << getLineOfChars<'.'>() << '\n' << std::endl; - } - - void printClosedHeader( std::string const& _name ) { - printOpenHeader( _name ); - stream << getLineOfChars<'.'>() << '\n'; - } - void printOpenHeader( std::string const& _name ) { - stream << getLineOfChars<'-'>() << '\n'; - { - Colour colourGuard( Colour::Headers ); - printHeaderString( _name ); - } - } - - // if string has a : in first line will set indent to follow it on - // subsequent lines - void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { - std::size_t i = _string.find( ": " ); - if( i != std::string::npos ) - i+=2; - else - i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << '\n'; - } - - struct SummaryColumn { - - SummaryColumn( std::string const& _label, Colour::Code _colour ) - : label( _label ), - colour( _colour ) - {} - SummaryColumn addRow( std::size_t count ) { - std::ostringstream oss; - oss << count; - std::string row = oss.str(); - for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { - while( it->size() < row.size() ) - *it = ' ' + *it; - while( it->size() > row.size() ) - row = ' ' + row; - } - rows.push_back( row ); - return *this; - } - - std::string label; - Colour::Code colour; - std::vector rows; - - }; - - void printTotals( Totals const& totals ) { - if( totals.testCases.total() == 0 ) { - stream << Colour( Colour::Warning ) << "No tests ran\n"; - } - else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { - stream << Colour( Colour::ResultSuccess ) << "All tests passed"; - stream << " (" - << pluralise( totals.assertions.passed, "assertion" ) << " in " - << pluralise( totals.testCases.passed, "test case" ) << ')' - << '\n'; - } - else { - - std::vector columns; - columns.push_back( SummaryColumn( "", Colour::None ) - .addRow( totals.testCases.total() ) - .addRow( totals.assertions.total() ) ); - columns.push_back( SummaryColumn( "passed", Colour::Success ) - .addRow( totals.testCases.passed ) - .addRow( totals.assertions.passed ) ); - columns.push_back( SummaryColumn( "failed", Colour::ResultError ) - .addRow( totals.testCases.failed ) - .addRow( totals.assertions.failed ) ); - columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) - .addRow( totals.testCases.failedButOk ) - .addRow( totals.assertions.failedButOk ) ); - - printSummaryRow( "test cases", columns, 0 ); - printSummaryRow( "assertions", columns, 1 ); - } - } - void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { - for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { - std::string value = it->rows[row]; - if( it->label.empty() ) { - stream << label << ": "; - if( value != "0" ) - stream << value; - else - stream << Colour( Colour::Warning ) << "- none -"; - } - else if( value != "0" ) { - stream << Colour( Colour::LightGrey ) << " | "; - stream << Colour( it->colour ) - << value << ' ' << it->label; - } - } - stream << '\n'; - } - - static std::size_t makeRatio( std::size_t number, std::size_t total ) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; - return ( ratio == 0 && number > 0 ) ? 1 : ratio; - } - static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { - if( i > j && i > k ) - return i; - else if( j > k ) - return j; - else - return k; - } - - void printTotalsDivider( Totals const& totals ) { - if( totals.testCases.total() > 0 ) { - std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); - std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); - std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); - while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )++; - while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) - findMax( failedRatio, failedButOkRatio, passedRatio )--; - - stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); - stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); - if( totals.testCases.allPassed() ) - stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); - else - stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); - } - else { - stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); - } - stream << '\n'; - } - void printSummaryDivider() { - stream << getLineOfChars<'-'>() << '\n'; - } - - private: - bool m_headerPrinted; - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) - -} // end namespace Catch - -// #included from: ../reporters/catch_reporter_compact.hpp -#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED - -namespace Catch { - - struct CompactReporter : StreamingReporterBase { - - CompactReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} - - virtual ~CompactReporter(); - - static std::string getDescription() { - return "Reports test results on a single line, suitable for IDEs"; - } - - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - - virtual void noMatchingTestCases( std::string const& spec ) { - stream << "No test cases matched '" << spec << '\'' << std::endl; - } - - virtual void assertionStarting( AssertionInfo const& ) {} - - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { - AssertionResult const& result = _assertionStats.assertionResult; - - bool printInfoMessages = true; - - // Drop out if result was successful and we're not printing those - if( !m_config->includeSuccessfulResults() && result.isOk() ) { - if( result.getResultType() != ResultWas::Warning ) - return false; - printInfoMessages = false; - } - - AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); - printer.print(); - - stream << std::endl; - return true; - } - - virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { - if (m_config->showDurations() == ShowDurations::Always) { - stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; - } - } - - virtual void testRunEnded( TestRunStats const& _testRunStats ) { - printTotals( _testRunStats.totals ); - stream << '\n' << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } - - private: - class AssertionPrinter { - void operator= ( AssertionPrinter const& ); - public: - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) - : stream( _stream ) - , stats( _stats ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( _printInfoMessages ) - {} - - void print() { - printSourceInfo(); - - itMessage = messages.begin(); - - switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( Colour::ResultSuccess, passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if( result.isOk() ) - printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); - else - printResultType( Colour::Error, failedString() ); - printOriginalExpression(); - printReconstructedExpression(); - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType( Colour::Error, failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType( Colour::Error, failedString() ); - printIssue( "fatal error condition with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( Colour::Error, failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( Colour::None, "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( Colour::None, "warning" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType( Colour::Error, failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType( Colour::Error, "** internal error **" ); - break; - } - } - - private: - // Colour::LightGrey - - static Colour::Code dimColour() { return Colour::FileName; } - -#ifdef CATCH_PLATFORM_MAC - static const char* failedString() { return "FAILED"; } - static const char* passedString() { return "PASSED"; } -#else - static const char* failedString() { return "failed"; } - static const char* passedString() { return "passed"; } -#endif - - void printSourceInfo() const { - Colour colourGuard( Colour::FileName ); - stream << result.getSourceInfo() << ':'; - } - - void printResultType( Colour::Code colour, std::string const& passOrFail ) const { - if( !passOrFail.empty() ) { - { - Colour colourGuard( colour ); - stream << ' ' << passOrFail; - } - stream << ':'; - } - } - - void printIssue( std::string const& issue ) const { - stream << ' ' << issue; - } - - void printExpressionWas() { - if( result.hasExpression() ) { - stream << ';'; - { - Colour colour( dimColour() ); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const { - if( result.hasExpression() ) { - stream << ' ' << result.getExpression(); - } - } - - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - { - Colour colour( dimColour() ); - stream << " for: "; - } - stream << result.getExpandedExpression(); - } - } - - void printMessage() { - if ( itMessage != messages.end() ) { - stream << " '" << itMessage->message << '\''; - ++itMessage; - } - } - - void printRemainingMessages( Colour::Code colour = dimColour() ) { - if ( itMessage == messages.end() ) - return; - - // using messages.end() directly yields compilation error: - std::vector::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); - - { - Colour colourGuard( colour ); - stream << " with " << pluralise( N, "message" ) << ':'; - } - - for(; itMessage != itEnd; ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || itMessage->type != ResultWas::Info ) { - stream << " '" << itMessage->message << '\''; - if ( ++itMessage != itEnd ) { - Colour colourGuard( dimColour() ); - stream << " and"; - } - } - } - } - - private: - std::ostream& stream; - AssertionStats const& stats; - AssertionResult const& result; - std::vector messages; - std::vector::const_iterator itMessage; - bool printInfoMessages; - }; - - // Colour, message variants: - // - white: No tests ran. - // - red: Failed [both/all] N test cases, failed [both/all] M assertions. - // - white: Passed [both/all] N test cases (no assertions). - // - red: Failed N tests cases, failed M assertions. - // - green: Passed [both/all] N tests cases with M assertions. - - std::string bothOrAll( std::size_t count ) const { - return count == 1 ? std::string() : count == 2 ? "both " : "all " ; - } - - void printTotals( const Totals& totals ) const { - if( totals.testCases.total() == 0 ) { - stream << "No tests ran."; - } - else if( totals.testCases.failed == totals.testCases.total() ) { - Colour colour( Colour::ResultError ); - const std::string qualify_assertions_failed = - totals.assertions.failed == totals.assertions.total() ? - bothOrAll( totals.assertions.failed ) : std::string(); - stream << - "Failed " << bothOrAll( totals.testCases.failed ) - << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << qualify_assertions_failed << - pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else if( totals.assertions.total() == 0 ) { - stream << - "Passed " << bothOrAll( totals.testCases.total() ) - << pluralise( totals.testCases.total(), "test case" ) - << " (no assertions)."; - } - else if( totals.assertions.failed ) { - Colour colour( Colour::ResultError ); - stream << - "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " - "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; - } - else { - Colour colour( Colour::ResultSuccess ); - stream << - "Passed " << bothOrAll( totals.testCases.passed ) - << pluralise( totals.testCases.passed, "test case" ) << - " with " << pluralise( totals.assertions.passed, "assertion" ) << '.'; - } - } - }; - - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) - -} // end namespace Catch - -namespace Catch { - // These are all here to avoid warnings about not having any out of line - // virtual methods - NonCopyable::~NonCopyable() {} - IShared::~IShared() {} - IStream::~IStream() CATCH_NOEXCEPT {} - FileStream::~FileStream() CATCH_NOEXCEPT {} - CoutStream::~CoutStream() CATCH_NOEXCEPT {} - DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} - StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} - IContext::~IContext() {} - IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - CompactReporter::~CompactReporter() {} - IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} - IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} - WildcardPattern::~WildcardPattern() {} - TestSpec::Pattern::~Pattern() {} - TestSpec::NamePattern::~NamePattern() {} - TestSpec::TagPattern::~TagPattern() {} - TestSpec::ExcludedPattern::~ExcludedPattern() {} - Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} - - void Config::dummy() {} - - namespace TestCaseTracking { - ITracker::~ITracker() {} - TrackerBase::~TrackerBase() {} - SectionTracker::~SectionTracker() {} - IndexTracker::~IndexTracker() {} - } -} - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif - -#ifdef CATCH_CONFIG_MAIN -// #included from: internal/catch_default_main.hpp -#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED - -#ifndef __OBJC__ - -// Standard C/C++ main entry point -int main (int argc, char * argv[]) { - int result = Catch::Session().run( argc, argv ); - return ( result < 0xff ? result : 0xff ); -} - -#else // __OBJC__ - -// Objective-C entry point -int main (int argc, char * const argv[]) { -#if !CATCH_ARC_ENABLED - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; -#endif - - Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); - -#if !CATCH_ARC_ENABLED - [pool drain]; -#endif - - return ( result < 0xff ? result : 0xff ); -} - -#endif // __OBJC__ - -#endif - -#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED -# undef CLARA_CONFIG_MAIN -#endif - -////// - -// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ -#ifdef CATCH_CONFIG_PREFIX_ALL - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#else -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#endif - -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) -#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) - -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) - -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) -#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) - -#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif - -#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) -#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS - #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) - #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) - #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) - #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) - #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) - #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) - #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else - #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) - #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) -#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) - -// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required -#else - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) - -#else -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) -#endif - -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) -#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) - -#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) - -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) -#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) - -#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) - -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif - -#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) -#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) - -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) -#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) -#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) -#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) -#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) -#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#else -#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) - #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) - #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) - #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) - #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) - #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) - #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) -#endif -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) - -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) - -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - -#endif - -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) - -// "BDD-style" convenience wrappers -#ifdef CATCH_CONFIG_VARIADIC_MACROS -#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) -#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#else -#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) -#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) -#endif -#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) -#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) -#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) -#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) -#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) - -using Catch::Detail::Approx; - -#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED - From b245eaa7d1f0043026a1e50631db12ca6804b0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 17:48:28 +0200 Subject: [PATCH 018/398] Fix double-to-float conversion warning in tests --- projects/SelfTest/ToStringTuple.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/SelfTest/ToStringTuple.cpp b/projects/SelfTest/ToStringTuple.cpp index 86f68d37..9c855715 100644 --- a/projects/SelfTest/ToStringTuple.cpp +++ b/projects/SelfTest/ToStringTuple.cpp @@ -21,7 +21,7 @@ TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) { typedef std::tuple type; CHECK( "1.2f" == Catch::toString(float(1.2)) ); - CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) ); + CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2f,0}) ); } TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) From 53864dee7b7571e6c18c1400b1792f1e4b875398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 19:54:22 +0200 Subject: [PATCH 019/398] Fix MSVC compilation error MSVC's `std::vector` requires its allocator to have copy constructor from the same allocator kind, but templated over different type. --- projects/SelfTest/ToStringVector.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/projects/SelfTest/ToStringVector.cpp b/projects/SelfTest/ToStringVector.cpp index 002d8ef4..eafe886d 100644 --- a/projects/SelfTest/ToStringVector.cpp +++ b/projects/SelfTest/ToStringVector.cpp @@ -27,8 +27,14 @@ namespace { /* Minimal Allocator */ template struct minimal_allocator { - typedef T value_type; - typedef std::size_t size_type; + using value_type = T; + using size_type = std::size_t; + + minimal_allocator() = default; + template + minimal_allocator(const minimal_allocator&) {} + + T *allocate( size_type n ) { return static_cast( ::operator new( n * sizeof(T) ) ); } @@ -52,8 +58,8 @@ TEST_CASE( "vector -> toString", "[toString][vector,allocator][c+ } TEST_CASE( "vec> -> toString", "[toString][vector,allocator][c++11][.]" ) { - typedef std::vector > inner; - typedef std::vector vector; + using inner = std::vector>; + using vector = std::vector; vector v; REQUIRE( Catch::toString(v) == "{ }" ); v.push_back( inner { "hello" } ); From e1bca7017da336faad0d91d291348a5b0d63fdfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 20:20:46 +0200 Subject: [PATCH 020/398] Most of Assertion macros are now variadic This means that `REQUIRE(std::vector{1, 2} == std::vector{1, 2});` works as expected. Note that assertion macros taking more than 1 argument are currently not variadic, because variadic args have to come last, which would make the interface of these ugly: `REQUIRE_THROWS_AS(std::exception const&, .... )` --- include/catch.hpp | 52 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 2182ba8c..f90150e9 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -92,28 +92,28 @@ LeakDetector leakDetector; #ifdef CATCH_CONFIG_PREFIX_ALL #if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) #else -#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) #endif -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) +#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) +#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) +#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) -#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) +#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) @@ -159,29 +159,29 @@ LeakDetector leakDetector; #else #if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#define REQUIRE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) #else -#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) -#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) +#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) #endif -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) +#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) -#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) +#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) -#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) +#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) +#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) -#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) From cc8206f4c35cfcfdf1e6e61172800d122d69469e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 14:46:48 +0000 Subject: [PATCH 021/398] Removed SafeBool --- include/internal/catch_common.h | 11 ----------- include/internal/catch_option.hpp | 4 ++-- include/internal/catch_ptr.hpp | 2 +- projects/SelfTest/TrickyTests.cpp | 4 ++-- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index c207d8e8..bcb6bd51 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -44,17 +44,6 @@ namespace Catch { virtual ~NonCopyable(); }; - class SafeBool { - public: - typedef void (SafeBool::*type)() const; - - static type makeSafe( bool value ) { - return value ? &SafeBool::trueValue : 0; - } - private: - void trueValue() const {} - }; - template inline void deleteAll( ContainerT& container ) { for( auto p : container ) diff --git a/include/internal/catch_option.hpp b/include/internal/catch_option.hpp index c9c3c165..8b146da6 100644 --- a/include/internal/catch_option.hpp +++ b/include/internal/catch_option.hpp @@ -61,8 +61,8 @@ namespace Catch { bool none() const { return nullableValue == nullptr; } bool operator !() const { return nullableValue == nullptr; } - operator SafeBool::type() const { - return SafeBool::makeSafe( some() ); + explicit operator bool() const { + return some(); } private: diff --git a/include/internal/catch_ptr.hpp b/include/internal/catch_ptr.hpp index 5da73aa1..4197cf79 100644 --- a/include/internal/catch_ptr.hpp +++ b/include/internal/catch_ptr.hpp @@ -56,7 +56,7 @@ namespace Catch { T& operator*() const { return *m_p; } T* operator->() const { return m_p; } bool operator !() const { return m_p == nullptr; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != nullptr ); } + explicit operator bool() const { return m_p != nullptr; } private: T* m_p; diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 70c56965..05053fe3 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -293,8 +293,8 @@ struct Boolable { explicit Boolable( bool value ) : m_value( value ) {} - operator Catch::SafeBool::type() const { - return Catch::SafeBool::makeSafe( m_value ); + explicit operator bool() const { + return m_value; } bool m_value; From e749724a11e02308a3b8869cdca703cfddc04d89 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 18:56:53 +0100 Subject: [PATCH 022/398] A load more C++11 tweaks - mostly moving initialisations from constructors to inline --- include/internal/catch_approx.hpp | 7 +-- include/internal/catch_assertionresult.h | 13 ++--- include/internal/catch_config.hpp | 55 ++++++------------- include/internal/catch_context_impl.hpp | 10 +--- include/internal/catch_expression_lhs.hpp | 4 +- include/internal/catch_list.hpp | 3 +- include/internal/catch_result_builder.h | 8 +-- include/internal/catch_result_builder.hpp | 5 +- include/internal/catch_run_context.hpp | 8 +-- include/internal/catch_section.h | 2 +- include/internal/catch_suppress_warnings.h | 2 - .../catch_test_case_registry_impl.hpp | 8 +-- include/internal/catch_test_case_tracker.hpp | 20 ++----- include/internal/catch_timer.h | 3 +- include/internal/catch_totals.hpp | 8 +-- include/internal/catch_wildcard_pattern.hpp | 3 +- include/internal/catch_xmlwriter.hpp | 17 +----- include/reporters/catch_reporter_compact.hpp | 4 +- include/reporters/catch_reporter_console.hpp | 7 +-- include/reporters/catch_reporter_junit.hpp | 5 +- include/reporters/catch_reporter_tap.hpp | 7 +-- include/reporters/catch_reporter_teamcity.hpp | 5 +- include/reporters/catch_reporter_xml.hpp | 5 +- 23 files changed, 64 insertions(+), 145 deletions(-) diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index 406c7ef1..66576428 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -27,12 +27,7 @@ namespace Detail { m_value( value ) {} - Approx( Approx const& other ) - : m_epsilon( other.m_epsilon ), - m_margin( other.m_margin ), - m_scale( other.m_scale ), - m_value( other.m_value ) - {} + Approx( Approx const& other ) = default; static Approx custom() { return Approx( 0 ); diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index c729e8d0..24ab4f62 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -53,11 +53,6 @@ namespace Catch { struct AssertionResultData { - AssertionResultData() : decomposedExpression( nullptr ) - , resultType( ResultWas::Unknown ) - , negated( false ) - , parenthesized( false ) {} - void negate( bool parenthesize ) { negated = !negated; parenthesized = parenthesize; @@ -82,12 +77,12 @@ namespace Catch { return reconstructedExpression; } - mutable DecomposedExpression const* decomposedExpression; + mutable DecomposedExpression const* decomposedExpression = nullptr; mutable std::string reconstructedExpression; std::string message; - ResultWas::OfType resultType; - bool negated; - bool parenthesized; + ResultWas::OfType resultType = ResultWas::Unknown; + bool negated = false; + bool parenthesized = false; }; class AssertionResult { diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 64141e7f..24afda6e 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -25,47 +25,26 @@ namespace Catch { struct ConfigData { + bool listTests = false; + bool listTags = false; + bool listReporters = false; + bool listTestNamesOnly = false; - ConfigData() - : listTests( false ), - listTags( false ), - listReporters( false ), - listTestNamesOnly( false ), - showSuccessfulTests( false ), - shouldDebugBreak( false ), - noThrow( false ), - showHelp( false ), - showInvisibles( false ), - filenamesAsTags( false ), - abortAfter( -1 ), - rngSeed( 0 ), - verbosity( Verbosity::Normal ), - warnings( WarnAbout::Nothing ), - showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ), - useColour( UseColour::Auto ) - {} + bool showSuccessfulTests = false; + bool shouldDebugBreak = false; + bool noThrow = false; + bool showHelp = false; + bool showInvisibles = false; + bool filenamesAsTags = false; - bool listTests; - bool listTags; - bool listReporters; - bool listTestNamesOnly; + int abortAfter = -1; + unsigned int rngSeed = 0; - bool showSuccessfulTests; - bool shouldDebugBreak; - bool noThrow; - bool showHelp; - bool showInvisibles; - bool filenamesAsTags; - - int abortAfter; - unsigned int rngSeed; - - Verbosity::Level verbosity; - WarnAbout::What warnings; - ShowDurations::OrNot showDurations; - RunTests::InWhatOrder runOrder; - UseColour::YesOrNo useColour; + Verbosity::Level verbosity = Verbosity::Normal; + WarnAbout::What warnings = WarnAbout::Nothing; + ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; + RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; + UseColour::YesOrNo useColour = UseColour::Auto; std::string outputFilename; std::string name; diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index 84f1ca1c..b9488c6e 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -16,11 +16,7 @@ namespace Catch { - class Context : public IMutableContext { - - Context() : m_config( nullptr ), m_runner( nullptr ), m_resultCapture( nullptr ) {} - Context( Context const& ); - void operator=( Context const& ); + class Context : public IMutableContext, NonCopyable { public: virtual ~Context() { @@ -84,8 +80,8 @@ namespace Catch { private: Ptr m_config; - IRunner* m_runner; - IResultCapture* m_resultCapture; + IRunner* m_runner = nullptr; + IResultCapture* m_resultCapture = nullptr; std::map m_generatorsByTestName; }; diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 8cf41409..756a07f6 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -25,7 +25,7 @@ class MatchExpression; template class ExpressionLhs : public DecomposedExpression { public: - ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} ExpressionLhs& operator = ( const ExpressionLhs& ); @@ -98,7 +98,7 @@ private: private: ResultBuilder& m_rb; T m_lhs; - bool m_truthy; + bool m_truthy = false; }; template diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index fc1cc91a..f90767d1 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -71,7 +71,6 @@ namespace Catch { } struct TagInfo { - TagInfo() : count ( 0 ) {} void add( std::string const& spelling ) { ++count; spellings.insert( spelling ); @@ -83,7 +82,7 @@ namespace Catch { return out; } std::set spellings; - std::size_t count; + std::size_t count = 0; }; inline std::size_t listTags( Config const& config ) { diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index a2cf596d..65483198 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -20,7 +20,7 @@ namespace Catch { template class ExpressionLhs; struct CopyableStream { - CopyableStream() {} + CopyableStream() = default; CopyableStream( CopyableStream const& other ) { oss << other.oss.str(); } @@ -82,9 +82,9 @@ namespace Catch { AssertionResultData m_data; CopyableStream m_stream; - bool m_shouldDebugBreak; - bool m_shouldThrow; - bool m_guardException; + bool m_shouldDebugBreak = false; + bool m_shouldThrow = false; + bool m_guardException = false; }; } // namespace Catch diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index 2874c568..4eea95fe 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -28,10 +28,7 @@ namespace Catch { char const* capturedExpression, ResultDisposition::Flags resultDisposition, char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), - m_shouldDebugBreak( false ), - m_shouldThrow( false ), - m_guardException( false ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ) {} ResultBuilder::~ResultBuilder() { diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 12435cdc..23c4654a 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -62,10 +62,8 @@ namespace Catch { explicit RunContext( Ptr const& _config, Ptr const& reporter ) : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), - m_activeTestCase( nullptr ), m_config( _config ), - m_reporter( reporter ), - m_shouldReportUnexpected ( true ) + m_reporter( reporter ) { m_context.setRunner( this ); m_context.setConfig( m_config ); @@ -350,7 +348,7 @@ namespace Catch { TestRunInfo m_runInfo; IMutableContext& m_context; - TestCase const* m_activeTestCase; + TestCase const* m_activeTestCase = nullptr; ITracker* m_testCaseTracker; ITracker* m_currentSectionTracker; AssertionResult m_lastResult; @@ -363,7 +361,7 @@ namespace Catch { std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; - bool m_shouldReportUnexpected; + bool m_shouldReportUnexpected = true; }; IResultCapture& getResultCapture() { diff --git a/include/internal/catch_section.h b/include/internal/catch_section.h index 2667b74e..e3b14564 100644 --- a/include/internal/catch_section.h +++ b/include/internal/catch_section.h @@ -22,7 +22,7 @@ namespace Catch { ~Section(); // This indicates whether the section should be executed or not - operator bool() const; + explicit operator bool() const; private: SectionInfo m_info; diff --git a/include/internal/catch_suppress_warnings.h b/include/internal/catch_suppress_warnings.h index ad405922..65ed6a62 100644 --- a/include/internal/catch_suppress_warnings.h +++ b/include/internal/catch_suppress_warnings.h @@ -16,8 +16,6 @@ # pragma clang diagnostic ignored "-Wunused-variable" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 5900d6f0..e5b1f281 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -91,10 +91,6 @@ namespace Catch { class TestRegistry : public ITestCaseRegistry { public: - TestRegistry() - : m_currentSortOrder( RunTests::InDeclarationOrder ), - m_unnamedCount( 0 ) - {} virtual ~TestRegistry(); virtual void registerTest( TestCase const& testCase ) { @@ -123,9 +119,9 @@ namespace Catch { private: std::vector m_functions; - mutable RunTests::InWhatOrder m_currentSortOrder; + mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; mutable std::vector m_sortedFunctions; - size_t m_unnamedCount; + size_t m_unnamedCount = 0; std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 6654734f..6da8ff53 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -69,8 +69,8 @@ namespace TestCaseTracking { }; Ptr m_rootTracker; - ITracker* m_currentTracker; - RunState m_runState; + ITracker* m_currentTracker = nullptr; + RunState m_runState = NotStarted; public: @@ -79,12 +79,6 @@ namespace TestCaseTracking { return s_instance; } - TrackerContext() - : m_currentTracker( nullptr ), - m_runState( NotStarted ) - {} - - ITracker& startRun(); void endRun() { @@ -137,13 +131,12 @@ namespace TestCaseTracking { TrackerContext& m_ctx; ITracker* m_parent; Children m_children; - CycleState m_runState; + CycleState m_runState = NotStarted; public: TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) : m_nameAndLocation( nameAndLocation ), m_ctx( ctx ), - m_parent( parent ), - m_runState( NotStarted ) + m_parent( parent ) {} virtual ~TrackerBase(); @@ -302,12 +295,11 @@ namespace TestCaseTracking { class IndexTracker : public TrackerBase { int m_size; - int m_index; + int m_index = -1; public: IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ), - m_index( -1 ) + m_size( size ) {} virtual ~IndexTracker(); diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 81b9fdb7..60115c80 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -13,14 +13,13 @@ namespace Catch { class Timer { public: - Timer() : m_microSeconds( 0 ) {} void start(); unsigned int getElapsedMicroseconds() const; unsigned int getElapsedMilliseconds() const; double getElapsedSeconds() const; private: - uint64_t m_microSeconds; + uint64_t m_microSeconds = 0; }; } // namespace Catch diff --git a/include/internal/catch_totals.hpp b/include/internal/catch_totals.hpp index 551e2947..8c26263c 100644 --- a/include/internal/catch_totals.hpp +++ b/include/internal/catch_totals.hpp @@ -13,8 +13,6 @@ namespace Catch { struct Counts { - Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} - Counts operator - ( Counts const& other ) const { Counts diff; diff.passed = passed - other.passed; @@ -39,9 +37,9 @@ namespace Catch { return failed == 0; } - std::size_t passed; - std::size_t failed; - std::size_t failedButOk; + std::size_t passed = 0; + std::size_t failed = 0; + std::size_t failedButOk = 0; }; struct Totals { diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp index a922912d..b9827b96 100644 --- a/include/internal/catch_wildcard_pattern.hpp +++ b/include/internal/catch_wildcard_pattern.hpp @@ -27,7 +27,6 @@ namespace Catch WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), - m_wildcard( NoWildcard ), m_pattern( adjustCase( pattern ) ) { if( startsWith( m_pattern, '*' ) ) { @@ -66,7 +65,7 @@ namespace Catch return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; } CaseSensitive::Choice m_caseSensitivity; - WildcardPosition m_wildcard; + WildcardPosition m_wildcard = NoWildcard; std::string m_pattern; }; } diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index b39a2fd7..0b951c71 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -112,18 +112,7 @@ namespace Catch { mutable XmlWriter* m_writer; }; - XmlWriter() - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( Catch::cout() ) - { - writeDeclaration(); - } - - XmlWriter( std::ostream& os ) - : m_tagIsOpen( false ), - m_needsNewline( false ), - m_os( os ) + XmlWriter( std::ostream& os = Catch::cout() ) : m_os( os ) { writeDeclaration(); } @@ -233,8 +222,8 @@ namespace Catch { } } - bool m_tagIsOpen; - bool m_needsNewline; + bool m_tagIsOpen = false; + bool m_needsNewline = false; std::vector m_tags; std::string m_indent; std::ostream& m_os; diff --git a/include/reporters/catch_reporter_compact.hpp b/include/reporters/catch_reporter_compact.hpp index 3987d37c..1579a608 100644 --- a/include/reporters/catch_reporter_compact.hpp +++ b/include/reporters/catch_reporter_compact.hpp @@ -17,9 +17,7 @@ namespace Catch { struct CompactReporter : StreamingReporterBase { - CompactReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} + using StreamingReporterBase::StreamingReporterBase; virtual ~CompactReporter(); diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.hpp index 29951fcf..bbe38a87 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.hpp @@ -20,10 +20,7 @@ namespace Catch { struct ConsoleReporter : StreamingReporterBase { - ConsoleReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrinted( false ) - {} + using StreamingReporterBase::StreamingReporterBase; virtual ~ConsoleReporter() override; static std::string getDescription() { @@ -435,7 +432,7 @@ namespace Catch { } private: - bool m_headerPrinted; + bool m_headerPrinted = false; }; INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index acc5664c..f5cbc47d 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -51,8 +51,7 @@ namespace Catch { public: JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), - xml( _config.stream() ), - m_okToFail( false ) + xml( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = true; } @@ -233,7 +232,7 @@ namespace Catch { std::ostringstream stdOutForSuite; std::ostringstream stdErrForSuite; unsigned int unexpectedExceptions; - bool m_okToFail; + bool m_okToFail = false; }; INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index 8f8896a6..b34acac3 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -21,10 +21,7 @@ namespace Catch { struct TAPReporter : StreamingReporterBase { - TAPReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - counter(0) - {} + using StreamingReporterBase::StreamingReporterBase; virtual ~TAPReporter(); @@ -62,7 +59,7 @@ namespace Catch { } private: - size_t counter; + size_t counter = 0; class AssertionPrinter { void operator= ( AssertionPrinter const& ); public: diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index ae2efd88..79f40f92 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -25,8 +25,7 @@ namespace Catch { struct TeamCityReporter : StreamingReporterBase { TeamCityReporter( ReporterConfig const& _config ) - : StreamingReporterBase( _config ), - m_headerPrintedForThisSection( false ) + : StreamingReporterBase( _config ) { m_reporterPrefs.shouldRedirectStdOut = true; } @@ -198,7 +197,7 @@ namespace Catch { .setInitialIndent( indent ) ) << "\n"; } private: - bool m_headerPrintedForThisSection; + bool m_headerPrintedForThisSection = false; }; #ifdef CATCH_IMPL diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.hpp index cf26834f..b99ec11f 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.hpp @@ -20,8 +20,7 @@ namespace Catch { public: XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), - m_xml(_config.stream()), - m_sectionDepth( 0 ) + m_xml(_config.stream()) { m_reporterPrefs.shouldRedirectStdOut = true; } @@ -219,7 +218,7 @@ namespace Catch { private: Timer m_testCaseTimer; XmlWriter m_xml; - int m_sectionDepth; + int m_sectionDepth = 0; }; INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) From c1835ec2032d7090612d3aec58c5a0849f0b5ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 21:27:29 +0200 Subject: [PATCH 023/398] Removed gcc 4.7 from travis It wasn't able to deal with C++11 properly --- .travis.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 277431a5..5036d053 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,20 +62,6 @@ matrix: # 2/ Linux GCC Builds - - os: linux - compiler: gcc - addons: &gcc47 - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-4.7'] - env: COMPILER='g++-4.7' BUILD_TYPE='Release' - - - os: linux - compiler: gcc - addons: *gcc47 - env: COMPILER='g++-4.7' BUILD_TYPE='Debug' - - - os: linux compiler: gcc addons: &gcc48 From de348b9bdd0af29b9450d6145cfe95a336f3757c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Apr 2017 21:28:12 +0200 Subject: [PATCH 024/398] Removed VS 2013 from AppVeyor Does not support C++11 properly enough --- appveyor.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index f6fce08a..40bbb5bf 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,6 @@ version: "{build}" os: - Visual Studio 2017 - Visual Studio 2015 - - Visual Studio 2013 environment: matrix: From 602b62f03797f6a9cf93c28b483b06dad7e06b44 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 19:49:50 +0100 Subject: [PATCH 025/398] Removed legacy reporter support --- include/catch.hpp | 2 - include/internal/catch_impl.hpp | 2 - .../internal/catch_legacy_reporter_adapter.h | 60 -------------- .../catch_legacy_reporter_adapter.hpp | 82 ------------------- .../internal/catch_reporter_registrars.hpp | 35 -------- 5 files changed, 181 deletions(-) delete mode 100644 include/internal/catch_legacy_reporter_adapter.h delete mode 100644 include/internal/catch_legacy_reporter_adapter.hpp diff --git a/include/catch.hpp b/include/catch.hpp index f90150e9..0527ccde 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -142,7 +142,6 @@ LeakDetector leakDetector; #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) @@ -209,7 +208,6 @@ LeakDetector leakDetector; #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index e28a8902..9dca5084 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -27,7 +27,6 @@ #include "catch_test_spec.hpp" #include "catch_version.hpp" #include "catch_message.hpp" -#include "catch_legacy_reporter_adapter.hpp" #include "catch_timer.hpp" #include "catch_common.hpp" #include "catch_section.hpp" @@ -62,7 +61,6 @@ namespace Catch { IMutableRegistryHub::~IMutableRegistryHub() {} IExceptionTranslator::~IExceptionTranslator() {} IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporter::~IReporter() {} IReporterFactory::~IReporterFactory() {} IReporterRegistry::~IReporterRegistry() {} IStreamingReporter::~IStreamingReporter() {} diff --git a/include/internal/catch_legacy_reporter_adapter.h b/include/internal/catch_legacy_reporter_adapter.h deleted file mode 100644 index 72c43d7d..00000000 --- a/include/internal/catch_legacy_reporter_adapter.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Created by Phil on 6th April 2013. - * Copyright 2013 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) - */ -#ifndef TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED - -#include "catch_interfaces_reporter.h" - -namespace Catch -{ - // Deprecated - struct IReporter : IShared { - virtual ~IReporter(); - - virtual bool shouldRedirectStdout() const = 0; - - virtual void StartTesting() = 0; - virtual void EndTesting( Totals const& totals ) = 0; - virtual void StartGroup( std::string const& groupName ) = 0; - virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; - virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; - virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; - virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; - virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; - virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; - virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; - virtual void Aborted() = 0; - virtual void Result( AssertionResult const& result ) = 0; - }; - - class LegacyReporterAdapter : public SharedImpl - { - public: - LegacyReporterAdapter( Ptr const& legacyReporter ); - virtual ~LegacyReporterAdapter(); - - virtual ReporterPreferences getPreferences() const; - virtual void noMatchingTestCases( std::string const& ); - virtual void testRunStarting( TestRunInfo const& ); - virtual void testGroupStarting( GroupInfo const& groupInfo ); - virtual void testCaseStarting( TestCaseInfo const& testInfo ); - virtual void sectionStarting( SectionInfo const& sectionInfo ); - virtual void assertionStarting( AssertionInfo const& ); - virtual bool assertionEnded( AssertionStats const& assertionStats ); - virtual void sectionEnded( SectionStats const& sectionStats ); - virtual void testCaseEnded( TestCaseStats const& testCaseStats ); - virtual void testGroupEnded( TestGroupStats const& testGroupStats ); - virtual void testRunEnded( TestRunStats const& testRunStats ); - virtual void skipTest( TestCaseInfo const& ); - - private: - Ptr m_legacyReporter; - }; -} - -#endif // TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED diff --git a/include/internal/catch_legacy_reporter_adapter.hpp b/include/internal/catch_legacy_reporter_adapter.hpp deleted file mode 100644 index 17a59181..00000000 --- a/include/internal/catch_legacy_reporter_adapter.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Created by Phil on 6th April 2013. - * Copyright 2013 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) - */ -#ifndef TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED - -#include "catch_legacy_reporter_adapter.h" - -namespace Catch -{ - LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) - : m_legacyReporter( legacyReporter ) - {} - LegacyReporterAdapter::~LegacyReporterAdapter() {} - - ReporterPreferences LegacyReporterAdapter::getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); - return prefs; - } - - void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} - void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { - m_legacyReporter->StartTesting(); - } - void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { - m_legacyReporter->StartGroup( groupInfo.name ); - } - void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { - m_legacyReporter->StartTestCase( testInfo ); - } - void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { - m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); - } - void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { - // Not on legacy interface - } - - bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { - if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { - for( auto const& messageInfo : assertionStats.infoMessages ) { - if( messageInfo.type == ResultWas::Info ) { - ResultBuilder rb( messageInfo.macroName.c_str(), messageInfo.lineInfo, "", ResultDisposition::Normal ); - rb << messageInfo.message; - rb.setResultType( ResultWas::Info ); - AssertionResult result = rb.build(); - m_legacyReporter->Result( result ); - } - } - } - m_legacyReporter->Result( assertionStats.assertionResult ); - return true; - } - void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { - if( sectionStats.missingAssertions ) - m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); - m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); - } - void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { - m_legacyReporter->EndTestCase - ( testCaseStats.testInfo, - testCaseStats.totals, - testCaseStats.stdOut, - testCaseStats.stdErr ); - } - void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { - if( testGroupStats.aborting ) - m_legacyReporter->Aborted(); - m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); - } - void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { - m_legacyReporter->EndTesting( testRunStats.totals ); - } - void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { - } -} - -#endif // TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 1a47d192..b12bbc6b 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -9,46 +9,14 @@ #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED #include "catch_interfaces_registry_hub.h" -#include "catch_legacy_reporter_adapter.h" namespace Catch { - template - class LegacyReporterRegistrar { - - class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new LegacyReporterAdapter( new T( config ) ); - } - - virtual std::string getDescription() const { - return T::getDescription(); - } - }; - - public: - - LegacyReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); - } - }; - template class ReporterRegistrar { class ReporterFactory : public SharedImpl { - // *** Please Note ***: - // - If you end up here looking at a compiler error because it's trying to register - // your custom reporter class be aware that the native reporter interface has changed - // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via - // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. - // However please consider updating to the new interface as the old one is now - // deprecated and will probably be removed quite soon! - // Please contact me via github if you have any questions at all about this. - // In fact, ideally, please contact me anyway to let me know you've hit this - as I have - // no idea who is actually using custom reporters at all (possibly no-one!). - // The new interface is designed to minimise exposure to interface changes in the future. virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); } @@ -86,9 +54,6 @@ namespace Catch { }; } -#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ - namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } - #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } From 41afd0c3d44c83c5754dbe0a8713a54efe9c699c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 20:17:37 +0100 Subject: [PATCH 026/398] Removed copy ctor, assignment operator and swap from TestCaseInfo --- include/internal/catch_test_case_info.h | 5 ---- include/internal/catch_test_case_info.hpp | 32 ----------------------- 2 files changed, 37 deletions(-) diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index b821abd3..08519c5c 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -39,8 +39,6 @@ namespace Catch { std::set const& _tags, SourceLineInfo const& _lineInfo ); - TestCaseInfo( TestCaseInfo const& other ); - friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); bool isHidden() const; @@ -62,7 +60,6 @@ namespace Catch { public: TestCase( ITestCase* testCase, TestCaseInfo const& info ); - TestCase( TestCase const& other ); TestCase withName( std::string const& _newName ) const; @@ -70,10 +67,8 @@ namespace Catch { TestCaseInfo const& getTestCaseInfo() const; - void swap( TestCase& other ); bool operator == ( TestCase const& other ) const; bool operator < ( TestCase const& other ) const; - TestCase& operator = ( TestCase const& other ); private: Ptr test; diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 1c73699b..0ee14c82 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -122,17 +122,6 @@ namespace Catch { setTags( *this, _tags ); } - TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) - : name( other.name ), - className( other.className ), - description( other.description ), - tags( other.tags ), - lcaseTags( other.lcaseTags ), - tagsAsString( other.tagsAsString ), - lineInfo( other.lineInfo ), - properties( other.properties ) - {} - bool TestCaseInfo::isHidden() const { return ( properties & IsHidden ) != 0; } @@ -149,10 +138,6 @@ namespace Catch { TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} - TestCase::TestCase( TestCase const& other ) - : TestCaseInfo( other ), - test( other.test ) - {} TestCase TestCase::withName( std::string const& _newName ) const { TestCase other( *this ); @@ -160,18 +145,6 @@ namespace Catch { return other; } - void TestCase::swap( TestCase& other ) { - test.swap( other.test ); - name.swap( other.name ); - className.swap( other.className ); - description.swap( other.description ); - tags.swap( other.tags ); - lcaseTags.swap( other.lcaseTags ); - tagsAsString.swap( other.tagsAsString ); - std::swap( TestCaseInfo::properties, static_cast( other ).properties ); - std::swap( lineInfo, other.lineInfo ); - } - void TestCase::invoke() const { test->invoke(); } @@ -185,11 +158,6 @@ namespace Catch { bool TestCase::operator < ( TestCase const& other ) const { return name < other.name; } - TestCase& TestCase::operator = ( TestCase const& other ) { - TestCase temp( other ); - swap( temp ); - return *this; - } TestCaseInfo const& TestCase::getTestCaseInfo() const { From 338ba6b9baa4ee01e2653a12cd1f33234b88bd87 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 20:18:02 +0100 Subject: [PATCH 027/398] Migrated Config and IConfig to shared_ptr (from Ptr) --- include/catch_session.hpp | 16 ++++++++-------- include/internal/catch_config.hpp | 5 +---- include/internal/catch_console_colour_impl.hpp | 4 ++-- include/internal/catch_context.h | 6 ++++-- include/internal/catch_context_impl.hpp | 6 +++--- include/internal/catch_interfaces_config.h | 5 +++-- include/internal/catch_interfaces_reporter.h | 10 +++++----- include/internal/catch_reporter_registry.hpp | 2 +- include/internal/catch_run_context.hpp | 6 +++--- include/reporters/catch_reporter_bases.hpp | 4 ++-- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 8d200aa6..91aff563 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -21,8 +21,8 @@ namespace Catch { - Ptr createReporter( std::string const& reporterName, Ptr const& config ) { - Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + Ptr createReporter( std::string const& reporterName, IConfigPtr const& config ) { + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); if( !reporter ) { std::ostringstream oss; oss << "No reporter registered with name: '" << reporterName << "'"; @@ -31,7 +31,7 @@ namespace Catch { return reporter; } - Ptr makeReporter( Ptr const& config ) { + Ptr makeReporter( std::shared_ptr const& config ) { std::vector reporters = config->getReporterNames(); if( reporters.empty() ) reporters.push_back( "console" ); @@ -41,7 +41,7 @@ namespace Catch { reporter = addReporter( reporter, createReporter( name, config ) ); return reporter; } - Ptr addListeners( Ptr const& config, Ptr reporters ) { + Ptr addListeners( IConfigPtr const& config, Ptr reporters ) { IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); for( auto const& listener : listeners ) reporters = addReporter(reporters, listener->create( ReporterConfig( config ) ) ); @@ -49,9 +49,9 @@ namespace Catch { } - Totals runTests( Ptr const& config ) { + Totals runTests( std::shared_ptr const& config ) { - Ptr iconfig = config.get(); + IConfigPtr iconfig = config; Ptr reporter = makeReporter( config ); reporter = addListeners( iconfig, reporter ); @@ -195,14 +195,14 @@ namespace Catch { } Config& config() { if( !m_config ) - m_config = new Config( m_configData ); + m_config = std::make_shared( m_configData ); return *m_config; } private: Clara::CommandLine m_cli; std::vector m_unusedTokens; ConfigData m_configData; - Ptr m_config; + std::shared_ptr m_config; }; bool Session::alreadyInstantiated = false; diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 24afda6e..8be68a81 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -56,10 +56,7 @@ namespace Catch { }; - class Config : public SharedImpl { - private: - Config( Config const& other ); - Config& operator = ( Config const& other ); + class Config : public IConfig { virtual void dummy(); public: diff --git a/include/internal/catch_console_colour_impl.hpp b/include/internal/catch_console_colour_impl.hpp index 426bba29..f15494ab 100644 --- a/include/internal/catch_console_colour_impl.hpp +++ b/include/internal/catch_console_colour_impl.hpp @@ -89,7 +89,7 @@ namespace { IColourImpl* platformColourInstance() { static Win32ColourImpl s_instance; - Ptr config = getCurrentContext().getConfig(); + IConfigPtr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; @@ -150,7 +150,7 @@ namespace { IColourImpl* platformColourInstance() { ErrnoGuard guard; - Ptr config = getCurrentContext().getConfig(); + IConfigPtr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 8b683864..77a7d3ac 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -21,6 +21,8 @@ namespace Catch { struct IGeneratorsForTest; struct IConfig; + using IConfigPtr = std::shared_ptr; + struct IContext { virtual ~IContext(); @@ -29,7 +31,7 @@ namespace Catch { virtual IRunner* getRunner() = 0; virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; virtual bool advanceGeneratorsForCurrentTest() = 0; - virtual Ptr getConfig() const = 0; + virtual IConfigPtr getConfig() const = 0; }; struct IMutableContext : IContext @@ -37,7 +39,7 @@ namespace Catch { virtual ~IMutableContext(); virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( Ptr const& config ) = 0; + virtual void setConfig( IConfigPtr const& config ) = 0; }; IContext& getCurrentContext(); diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index b9488c6e..43210693 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -40,7 +40,7 @@ namespace Catch { return generators && generators->moveNext(); } - virtual Ptr getConfig() const { + virtual IConfigPtr getConfig() const { return m_config; } @@ -51,7 +51,7 @@ namespace Catch { virtual void setRunner( IRunner* runner ) { m_runner = runner; } - virtual void setConfig( Ptr const& config ) { + virtual void setConfig( IConfigPtr const& config ) { m_config = config; } @@ -79,7 +79,7 @@ namespace Catch { } private: - Ptr m_config; + IConfigPtr m_config; IRunner* m_runner = nullptr; IResultCapture* m_resultCapture = nullptr; std::map m_generatorsByTestName; diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index 5730a8cd..d9479e07 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -45,7 +45,7 @@ namespace Catch { class TestSpec; - struct IConfig : IShared { + struct IConfig : NonCopyable { virtual ~IConfig(); @@ -63,8 +63,9 @@ namespace Catch { virtual unsigned int rngSeed() const = 0; virtual UseColour::YesOrNo useColour() const = 0; virtual std::vector const& getSectionsToRun() const = 0; - }; + + using IConfigPtr = std::shared_ptr; } #endif // TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index a1c5aa57..07524b93 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -25,18 +25,18 @@ namespace Catch { struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) + explicit ReporterConfig( IConfigPtr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } + IConfigPtr fullConfig() const { return m_fullConfig; } private: std::ostream* m_stream; - Ptr m_fullConfig; + IConfigPtr m_fullConfig; }; struct ReporterPreferences { @@ -247,7 +247,7 @@ namespace Catch typedef std::vector > Listeners; virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual IStreamingReporter* create( std::string const& name, IConfigPtr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; }; diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index 7a0c783a..ad212437 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -20,7 +20,7 @@ namespace Catch { virtual ~ReporterRegistry() override {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const override { + virtual IStreamingReporter* create( std::string const& name, IConfigPtr const& config ) const override { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return nullptr; diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 23c4654a..78051d21 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -59,7 +59,7 @@ namespace Catch { public: - explicit RunContext( Ptr const& _config, Ptr const& reporter ) + explicit RunContext( IConfigPtr const& _config, Ptr const& reporter ) : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), m_config( _config ), @@ -128,7 +128,7 @@ namespace Catch { return deltaTotals; } - Ptr config() const { + IConfigPtr config() const { return m_config; } @@ -353,7 +353,7 @@ namespace Catch { ITracker* m_currentSectionTracker; AssertionResult m_lastResult; - Ptr m_config; + IConfigPtr m_config; Totals m_totals; Ptr m_reporter; std::vector m_messages; diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index d94c15b4..6c8e4541 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -92,7 +92,7 @@ namespace Catch { // It can optionally be overridden in the derived class. } - Ptr m_config; + IConfigPtr m_config; std::ostream& stream; LazyStat currentTestRunInfo; @@ -244,7 +244,7 @@ namespace Catch { result.expandDecomposedExpression(); } - Ptr m_config; + IConfigPtr m_config; std::ostream& stream; std::vector m_assertions; std::vector > > m_sections; From dd78824697ec42e87b5623f0fb99200d7c83c4b4 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 20:28:53 +0100 Subject: [PATCH 028/398] Migrated IReporterFactory to std::shared_ptr --- include/internal/catch_interfaces_registry_hub.h | 6 ++++-- include/internal/catch_interfaces_reporter.h | 7 ++++--- include/internal/catch_registry_hub.hpp | 4 ++-- include/internal/catch_reporter_registrars.hpp | 8 ++++---- include/internal/catch_reporter_registry.hpp | 4 ++-- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index 5e0a7f01..9a42fbad 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -22,6 +22,8 @@ namespace Catch { struct IReporterFactory; struct ITagAliasRegistry; + using IReporterFactoryPtr = std::shared_ptr; + struct IRegistryHub { virtual ~IRegistryHub(); @@ -34,8 +36,8 @@ namespace Catch { struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; - virtual void registerListener( Ptr const& factory ) = 0; + virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; + virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 07524b93..6a38528b 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -236,15 +236,16 @@ namespace Catch }; - struct IReporterFactory : IShared { + struct IReporterFactory { virtual ~IReporterFactory(); virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; + using IReporterFactoryPtr = std::shared_ptr; struct IReporterRegistry { - typedef std::map > FactoryMap; - typedef std::vector > Listeners; + using FactoryMap = std::map; + using Listeners = std::vector; virtual ~IReporterRegistry(); virtual IStreamingReporter* create( std::string const& name, IConfigPtr const& config ) const = 0; diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index b9e42b72..d51306fd 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -42,10 +42,10 @@ namespace Catch { public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr const& factory ) override { + virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerListener( Ptr const& factory ) override { + virtual void registerListener( IReporterFactoryPtr const& factory ) override { m_reporterRegistry.registerListener( factory ); } virtual void registerTest( TestCase const& testInfo ) override { diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index b12bbc6b..086c5df2 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -15,7 +15,7 @@ namespace Catch { template class ReporterRegistrar { - class ReporterFactory : public SharedImpl { + class ReporterFactory : public IReporterFactory { virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); @@ -29,14 +29,14 @@ namespace Catch { public: ReporterRegistrar( std::string const& name ) { - getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + getMutableRegistryHub().registerReporter( name, std::make_shared() ); } }; template class ListenerRegistrar { - class ListenerFactory : public SharedImpl { + class ListenerFactory : public IReporterFactory { virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); @@ -49,7 +49,7 @@ namespace Catch { public: ListenerRegistrar() { - getMutableRegistryHub().registerListener( new ListenerFactory() ); + getMutableRegistryHub().registerListener( std::make_shared() ); } }; } diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index ad212437..3d503321 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -27,10 +27,10 @@ namespace Catch { return it->second->create( ReporterConfig( config ) ); } - void registerReporter( std::string const& name, Ptr const& factory ) { + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { m_factories.insert( std::make_pair( name, factory ) ); } - void registerListener( Ptr const& factory ) { + void registerListener( IReporterFactoryPtr const& factory ) { m_listeners.push_back( factory ); } From a96f25c7169840b71f1cfc8f1c5f111e7176a361 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 20:35:38 +0100 Subject: [PATCH 029/398] Some listener and factory clean-ups --- include/catch_session.hpp | 2 +- include/internal/catch_list.hpp | 5 ++--- include/internal/catch_reporter_registry.hpp | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 91aff563..e07b11cf 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -42,7 +42,7 @@ namespace Catch { return reporter; } Ptr addListeners( IConfigPtr const& config, Ptr reporters ) { - IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); for( auto const& listener : listeners ) reporters = addReporter(reporters, listener->create( ReporterConfig( config ) ) ); return reporters; diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index f90767d1..3cfd294b 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -123,12 +123,11 @@ namespace Catch { inline std::size_t listReporters( Config const& /*config*/ ) { Catch::cout() << "Available reporters:\n"; IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); - IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; std::size_t maxNameLen = 0; - for( auto const factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) + for( auto const& factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); - for( auto const factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) { + for( auto const& factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) { Text wrapper( factoryKvp.second->getDescription(), TextAttributes() .setInitialIndent( 0 ) .setIndent( 7+maxNameLen ) diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index 3d503321..e316ee4e 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -28,7 +28,7 @@ namespace Catch { } void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { - m_factories.insert( std::make_pair( name, factory ) ); + m_factories.insert( { name, factory } ); } void registerListener( IReporterFactoryPtr const& factory ) { m_listeners.push_back( factory ); From 0844d6e8677d400f1c363f2d48dc6cf74075b8d5 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 20:42:01 +0100 Subject: [PATCH 030/398] Migrated IStreamingReporter from Ptr to std::shared_ptr --- include/catch_session.hpp | 12 ++++++------ include/internal/catch_interfaces_reporter.h | 10 +++++----- include/internal/catch_reporter_registrars.hpp | 8 ++++---- include/internal/catch_reporter_registry.hpp | 2 +- include/internal/catch_run_context.hpp | 4 ++-- include/reporters/catch_reporter_multi.hpp | 10 +++++----- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index e07b11cf..7c674fba 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -21,8 +21,8 @@ namespace Catch { - Ptr createReporter( std::string const& reporterName, IConfigPtr const& config ) { - Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); + IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { + IStreamingReporterPtr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); if( !reporter ) { std::ostringstream oss; oss << "No reporter registered with name: '" << reporterName << "'"; @@ -31,17 +31,17 @@ namespace Catch { return reporter; } - Ptr makeReporter( std::shared_ptr const& config ) { + IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { std::vector reporters = config->getReporterNames(); if( reporters.empty() ) reporters.push_back( "console" ); - Ptr reporter; + IStreamingReporterPtr reporter; for( auto const& name : reporters ) reporter = addReporter( reporter, createReporter( name, config ) ); return reporter; } - Ptr addListeners( IConfigPtr const& config, Ptr reporters ) { + IStreamingReporterPtr addListeners( IConfigPtr const& config, IStreamingReporterPtr reporters ) { auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); for( auto const& listener : listeners ) reporters = addReporter(reporters, listener->create( ReporterConfig( config ) ) ); @@ -53,7 +53,7 @@ namespace Catch { IConfigPtr iconfig = config; - Ptr reporter = makeReporter( config ); + IStreamingReporterPtr reporter = makeReporter( config ); reporter = addListeners( iconfig, reporter ); RunContext context( iconfig, reporter ); diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 6a38528b..b0af150f 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -204,7 +204,7 @@ namespace Catch class MultipleReporters; - struct IStreamingReporter : IShared { + struct IStreamingReporter { virtual ~IStreamingReporter(); // Implementing class must also provide the following static method: @@ -234,11 +234,11 @@ namespace Catch virtual MultipleReporters* tryAsMulti() { return nullptr; } }; - + using IStreamingReporterPtr = std::shared_ptr; struct IReporterFactory { virtual ~IReporterFactory(); - virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; using IReporterFactoryPtr = std::shared_ptr; @@ -248,12 +248,12 @@ namespace Catch using Listeners = std::vector; virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, IConfigPtr const& config ) const = 0; + virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; }; - Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + IStreamingReporterPtr addReporter( IStreamingReporterPtr const& existingReporter, IStreamingReporterPtr const& additionalReporter ); } diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 086c5df2..759b0edb 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -17,8 +17,8 @@ namespace Catch { class ReporterFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const { + return std::make_shared( config ); } virtual std::string getDescription() const { @@ -38,8 +38,8 @@ namespace Catch { class ListenerFactory : public IReporterFactory { - virtual IStreamingReporter* create( ReporterConfig const& config ) const { - return new T( config ); + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const { + return std::make_shared( config ); } virtual std::string getDescription() const { return std::string(); diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index e316ee4e..9556fb31 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -20,7 +20,7 @@ namespace Catch { virtual ~ReporterRegistry() override {} - virtual IStreamingReporter* create( std::string const& name, IConfigPtr const& config ) const override { + virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return nullptr; diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 78051d21..7f38eb4a 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -59,7 +59,7 @@ namespace Catch { public: - explicit RunContext( IConfigPtr const& _config, Ptr const& reporter ) + explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr const& reporter ) : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), m_config( _config ), @@ -355,7 +355,7 @@ namespace Catch { IConfigPtr m_config; Totals m_totals; - Ptr m_reporter; + IStreamingReporterPtr m_reporter; std::vector m_messages; AssertionInfo m_lastAssertionInfo; std::vector m_unfinishedSections; diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 6b460bf0..0fbba771 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -13,11 +13,11 @@ namespace Catch { class MultipleReporters : public SharedImpl { - typedef std::vector > Reporters; + typedef std::vector Reporters; Reporters m_reporters; public: - void add( Ptr const& reporter ) { + void add( IStreamingReporterPtr const& reporter ) { m_reporters.push_back( reporter ); } @@ -101,14 +101,14 @@ public: // IStreamingReporter }; -Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { - Ptr resultingReporter; +IStreamingReporterPtr addReporter( IStreamingReporterPtr const& existingReporter, IStreamingReporterPtr const& additionalReporter ) { + IStreamingReporterPtr resultingReporter; if( existingReporter ) { MultipleReporters* multi = existingReporter->tryAsMulti(); if( !multi ) { multi = new MultipleReporters; - resultingReporter = Ptr( multi ); + resultingReporter = IStreamingReporterPtr( multi ); if( existingReporter ) multi->add( existingReporter ); } From 44cccde8b96894da8bac001ca788ff6c63c8de42 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 20:45:31 +0100 Subject: [PATCH 031/398] Migrated ITestCase to std::shared_ptr --- include/internal/catch_interfaces_testcase.h | 5 +++-- include/internal/catch_test_case_info.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_interfaces_testcase.h b/include/internal/catch_interfaces_testcase.h index a1052b71..0c759166 100644 --- a/include/internal/catch_interfaces_testcase.h +++ b/include/internal/catch_interfaces_testcase.h @@ -16,12 +16,13 @@ namespace Catch { class TestSpec; - struct ITestCase : IShared { + struct ITestCase { virtual void invoke () const = 0; - protected: virtual ~ITestCase(); }; + using ITestCasePtr = std::shared_ptr; + class TestCase; struct IConfig; diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index 08519c5c..ac83cb3f 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -71,7 +71,7 @@ namespace Catch { bool operator < ( TestCase const& other ) const; private: - Ptr test; + std::shared_ptr test; }; TestCase makeTestCase( ITestCase* testCase, From 0807a6910f56a940874d5d01d39f3d43129eac8e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 20:57:43 +0100 Subject: [PATCH 032/398] migrated ITracker to std::shared_ptr --- include/internal/catch_test_case_tracker.hpp | 40 +++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 6da8ff53..8b74e249 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -32,7 +32,11 @@ namespace TestCaseTracking { {} }; - struct ITracker : SharedImpl<> { + struct ITracker; + + using ITrackerPtr = std::shared_ptr; + + struct ITracker { virtual ~ITracker(); // static queries @@ -51,8 +55,8 @@ namespace TestCaseTracking { virtual void fail() = 0; virtual void markAsNeedingAnotherRun() = 0; - virtual void addChild( Ptr const& child ) = 0; - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void addChild( ITrackerPtr const& child ) = 0; + virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; virtual void openChild() = 0; // Debug/ checking @@ -68,7 +72,7 @@ namespace TestCaseTracking { CompletedCycle }; - Ptr m_rootTracker; + ITrackerPtr m_rootTracker; ITracker* m_currentTracker = nullptr; RunState m_runState = NotStarted; @@ -120,13 +124,13 @@ namespace TestCaseTracking { NameAndLocation m_nameAndLocation; public: TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} - bool operator ()( Ptr const& tracker ) { + bool operator ()( ITrackerPtr const& tracker ) { return tracker->nameAndLocation().name == m_nameAndLocation.name && tracker->nameAndLocation().location == m_nameAndLocation.location; } }; - typedef std::vector > Children; + typedef std::vector Children; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; @@ -157,14 +161,14 @@ namespace TestCaseTracking { } - virtual void addChild( Ptr const& child ) override { + virtual void addChild( ITrackerPtr const& child ) override { m_children.push_back( child ); } - virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) override { + virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); return( it != m_children.end() ) - ? it->get() + ? *it : nullptr; } virtual ITracker& parent() override { @@ -258,16 +262,16 @@ namespace TestCaseTracking { virtual bool isSectionTracker() const override { return true; } static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - SectionTracker* section = nullptr; + std::shared_ptr section; ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isSectionTracker() ); - section = static_cast( childTracker ); + section = std::dynamic_pointer_cast( childTracker ); } else { - section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); + section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); currentTracker.addChild( section ); } if( !ctx.completedCycle() ) @@ -306,16 +310,16 @@ namespace TestCaseTracking { virtual bool isIndexTracker() const override { return true; } static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - IndexTracker* tracker = nullptr; + std::shared_ptr tracker; ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isIndexTracker() ); - tracker = static_cast( childTracker ); + tracker = std::dynamic_pointer_cast( childTracker ); } else { - tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); + tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); currentTracker.addChild( tracker ); } @@ -343,7 +347,7 @@ namespace TestCaseTracking { }; inline ITracker& TrackerContext::startRun() { - m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); + m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); m_currentTracker = nullptr; m_runState = Executing; return *m_rootTracker; From 851e40a4bb0d83e48d34a04fb93d454d3865536e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 21:01:40 +0100 Subject: [PATCH 033/398] migrated Pattern to std::shared_ptr --- include/internal/catch_test_spec.hpp | 10 ++++++---- include/internal/catch_test_spec_parser.hpp | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index 8565661a..6ca31b2c 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -22,10 +22,12 @@ namespace Catch { class TestSpec { - struct Pattern : SharedImpl<> { + struct Pattern { virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; + using PatternPtr = std::shared_ptr; + class NamePattern : public Pattern { public: NamePattern( std::string const& name ) @@ -52,15 +54,15 @@ namespace Catch { class ExcludedPattern : public Pattern { public: - ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} virtual ~ExcludedPattern(); virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } private: - Ptr m_underlyingPattern; + PatternPtr m_underlyingPattern; }; struct Filter { - std::vector > m_patterns; + std::vector m_patterns; bool matches( TestCaseInfo const& testCase ) const { // All patterns in a filter must match for the filter to be a match diff --git a/include/internal/catch_test_spec_parser.hpp b/include/internal/catch_test_spec_parser.hpp index 05bdcf4c..c2c797ce 100644 --- a/include/internal/catch_test_spec_parser.hpp +++ b/include/internal/catch_test_spec_parser.hpp @@ -104,9 +104,9 @@ namespace Catch { token = token.substr( 8 ); } if( !token.empty() ) { - Ptr pattern = new T( token ); + TestSpec::PatternPtr pattern = std::make_shared( token ); if( m_exclusion ) - pattern = new TestSpec::ExcludedPattern( pattern ); + pattern = std::make_shared( pattern ); m_currentFilter.m_patterns.push_back( pattern ); } m_exclusion = false; From e6094a9503f513480d6b01bc174d8ff725c809b3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 21:08:41 +0100 Subject: [PATCH 034/398] migrated (Reporter) Nodes to std::shared_ptr --- include/reporters/catch_reporter_bases.hpp | 46 +++++++++++----------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 6c8e4541..371f9624 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -105,28 +105,28 @@ namespace Catch { struct CumulativeReporterBase : SharedImpl { template - struct Node : SharedImpl<> { + struct Node { explicit Node( T const& _value ) : value( _value ) {} virtual ~Node() {} - typedef std::vector > ChildNodes; + using ChildNodes = std::vector>; T value; ChildNodes children; }; - struct SectionNode : SharedImpl<> { + struct SectionNode { explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} virtual ~SectionNode(); bool operator == ( SectionNode const& other ) const { return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; } - bool operator == ( Ptr const& other ) const { + bool operator == ( std::shared_ptr const& other ) const { return operator==( *other ); } SectionStats stats; - typedef std::vector > ChildSections; - typedef std::vector Assertions; + using ChildSections = std::vector>; + using Assertions = std::vector; ChildSections childSections; Assertions assertions; std::string stdOut; @@ -136,7 +136,7 @@ namespace Catch { struct BySectionInfo { BySectionInfo( SectionInfo const& other ) : m_other( other ) {} BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() ( Ptr const& node ) const { + bool operator() ( std::shared_ptr const& node ) const { return node->stats.sectionInfo.lineInfo == m_other.lineInfo; } private: @@ -145,9 +145,9 @@ namespace Catch { }; - typedef Node TestCaseNode; - typedef Node TestGroupNode; - typedef Node TestRunNode; + using TestCaseNode = Node; + using TestGroupNode = Node; + using TestRunNode = Node; CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), @@ -168,10 +168,10 @@ namespace Catch { virtual void sectionStarting( SectionInfo const& sectionInfo ) override { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - Ptr node; + std::shared_ptr node; if( m_sectionStack.empty() ) { if( !m_rootSection ) - m_rootSection = new SectionNode( incompleteStats ); + m_rootSection = std::make_shared( incompleteStats ); node = m_rootSection; } else { @@ -181,7 +181,7 @@ namespace Catch { parentNode.childSections.end(), BySectionInfo( sectionInfo ) ); if( it == parentNode.childSections.end() ) { - node = new SectionNode( incompleteStats ); + node = std::make_shared( incompleteStats ); parentNode.childSections.push_back( node ); } else @@ -212,7 +212,7 @@ namespace Catch { m_sectionStack.pop_back(); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { - Ptr node = new TestCaseNode( testCaseStats ); + auto node = std::make_shared( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); m_testCases.push_back( node ); @@ -223,12 +223,12 @@ namespace Catch { m_deepestSection->stdErr = testCaseStats.stdErr; } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { - Ptr node = new TestGroupNode( testGroupStats ); + auto node = std::make_shared( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } virtual void testRunEnded( TestRunStats const& testRunStats ) override { - Ptr node = new TestRunNode( testRunStats ); + auto node = std::make_shared( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); testRunEndedCumulative(); @@ -247,15 +247,15 @@ namespace Catch { IConfigPtr m_config; std::ostream& stream; std::vector m_assertions; - std::vector > > m_sections; - std::vector > m_testCases; - std::vector > m_testGroups; + std::vector>> m_sections; + std::vector> m_testCases; + std::vector> m_testGroups; - std::vector > m_testRuns; + std::vector> m_testRuns; - Ptr m_rootSection; - Ptr m_deepestSection; - std::vector > m_sectionStack; + std::shared_ptr m_rootSection; + std::shared_ptr m_deepestSection; + std::vector> m_sectionStack; ReporterPreferences m_reporterPrefs; }; From 8ccbf63f28efe0cd8672dfc1d0b993027cb02ab3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 25 Apr 2017 21:51:44 +0100 Subject: [PATCH 035/398] Removed Ptr, Shared and SharedImpl --- CMakeLists.txt | 4 - include/internal/catch_context.h | 2 +- include/internal/catch_impl.hpp | 1 - include/internal/catch_interfaces_config.h | 5 +- .../internal/catch_interfaces_registry_hub.h | 3 +- include/internal/catch_interfaces_reporter.h | 1 - include/internal/catch_interfaces_testcase.h | 3 +- include/internal/catch_ptr.hpp | 93 ------------------- include/internal/catch_test_case_info.h | 2 +- .../catch_test_case_registry_impl.hpp | 2 +- include/internal/catch_test_case_tracker.hpp | 2 +- include/internal/catch_test_registry.hpp | 2 +- include/reporters/catch_reporter_bases.hpp | 4 +- include/reporters/catch_reporter_multi.hpp | 2 +- projects/SelfTest/SurrogateCpps/catch_ptr.cpp | 3 - 15 files changed, 14 insertions(+), 115 deletions(-) delete mode 100644 include/internal/catch_ptr.hpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_ptr.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 61cdc09c..dfea23cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,6 @@ set(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_message.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_ptr.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp @@ -152,8 +151,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_interfaces_runner.h ${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h ${HEADER_DIR}/internal/catch_interfaces_testcase.h - ${HEADER_DIR}/internal/catch_legacy_reporter_adapter.h - ${HEADER_DIR}/internal/catch_legacy_reporter_adapter.hpp ${HEADER_DIR}/internal/catch_list.hpp ${HEADER_DIR}/internal/catch_matchers.hpp ${HEADER_DIR}/internal/catch_matchers_string.h @@ -167,7 +164,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_objc_arc.hpp ${HEADER_DIR}/internal/catch_option.hpp ${HEADER_DIR}/internal/catch_platform.h - ${HEADER_DIR}/internal/catch_ptr.hpp ${HEADER_DIR}/internal/catch_reenable_warnings.h ${HEADER_DIR}/internal/catch_registry_hub.hpp ${HEADER_DIR}/internal/catch_reporter_registrars.hpp diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 77a7d3ac..4dd48a2f 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -9,8 +9,8 @@ #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED #include "catch_interfaces_generators.h" -#include "catch_ptr.hpp" +#include namespace Catch { diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 9dca5084..978ca1a4 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -47,7 +47,6 @@ namespace Catch { // These are all here to avoid warnings about not having any out of line // virtual methods NonCopyable::~NonCopyable() {} - IShared::~IShared() {} IStream::~IStream() noexcept {} FileStream::~FileStream() noexcept {} CoutStream::~CoutStream() noexcept {} diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index d9479e07..4f64f4e3 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -8,11 +8,12 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED +#include "catch_common.h" + #include #include #include - -#include "catch_ptr.hpp" +#include namespace Catch { diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index 9a42fbad..fb7d87cf 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -8,9 +8,10 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED -#include "catch_ptr.hpp" +#include "catch_common.h" #include +#include namespace Catch { diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index b0af150f..7679c07a 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -11,7 +11,6 @@ #include "catch_section_info.h" #include "catch_common.h" #include "catch_totals.hpp" -#include "catch_ptr.hpp" #include "catch_config.hpp" #include "catch_test_case_info.h" #include "catch_assertionresult.h" diff --git a/include/internal/catch_interfaces_testcase.h b/include/internal/catch_interfaces_testcase.h index 0c759166..c9ab3238 100644 --- a/include/internal/catch_interfaces_testcase.h +++ b/include/internal/catch_interfaces_testcase.h @@ -8,9 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED -#include "catch_ptr.hpp" - #include +#include namespace Catch { diff --git a/include/internal/catch_ptr.hpp b/include/internal/catch_ptr.hpp deleted file mode 100644 index 4197cf79..00000000 --- a/include/internal/catch_ptr.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Created by Phil on 02/05/2012. - * Copyright 2012 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) - */ -#ifndef TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED - -#include "catch_common.h" - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - -namespace Catch { - - // An intrusive reference counting smart pointer. - // T must implement addRef() and release() methods - // typically implementing the IShared interface - template - class Ptr { - public: - Ptr() : m_p( nullptr ){} - Ptr( T* p ) : m_p( p ){ - if( m_p ) - m_p->addRef(); - } - Ptr( Ptr const& other ) : m_p( other.m_p ){ - if( m_p ) - m_p->addRef(); - } - ~Ptr(){ - if( m_p ) - m_p->release(); - } - void reset() { - if( m_p ) - m_p->release(); - m_p = nullptr; - } - Ptr& operator = ( T* p ){ - Ptr temp( p ); - swap( temp ); - return *this; - } - Ptr& operator = ( Ptr const& other ){ - Ptr temp( other ); - swap( temp ); - return *this; - } - void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() const{ return m_p; } - T& operator*() const { return *m_p; } - T* operator->() const { return m_p; } - bool operator !() const { return m_p == nullptr; } - explicit operator bool() const { return m_p != nullptr; } - - private: - T* m_p; - }; - - struct IShared : NonCopyable { - virtual ~IShared(); - virtual void addRef() const = 0; - virtual void release() const = 0; - }; - - template - struct SharedImpl : T { - - SharedImpl() : m_rc( 0 ){} - - virtual void addRef() const { - ++m_rc; - } - virtual void release() const { - if( --m_rc == 0 ) - delete this; - } - - mutable unsigned int m_rc; - }; - -} // end namespace Catch - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -#endif // TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index ac83cb3f..1ff0c819 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -9,10 +9,10 @@ #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED #include "catch_common.h" -#include "catch_ptr.hpp" #include #include +#include #ifdef __clang__ #pragma clang diagnostic push diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index e5b1f281..cecbc253 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -127,7 +127,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// - class FreeFunctionTestCase : public SharedImpl { + class FreeFunctionTestCase : public ITestCase { public: FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 8b74e249..c7631384 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -9,7 +9,7 @@ #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED #include "catch_compiler_capabilities.h" -#include "catch_ptr.hpp" +#include "catch_common.h" #include #include diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index b6d423c8..5be6f6d7 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -15,7 +15,7 @@ namespace Catch { template -class MethodTestCase : public SharedImpl { +class MethodTestCase : public ITestCase { public: MethodTestCase( void (C::*method)() ) : m_method( method ) {} diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 371f9624..6782e8b3 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -41,7 +41,7 @@ namespace Catch { } - struct StreamingReporterBase : SharedImpl { + struct StreamingReporterBase : IStreamingReporter { StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), @@ -103,7 +103,7 @@ namespace Catch { ReporterPreferences m_reporterPrefs; }; - struct CumulativeReporterBase : SharedImpl { + struct CumulativeReporterBase : IStreamingReporter { template struct Node { explicit Node( T const& _value ) : value( _value ) {} diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 0fbba771..859e3f83 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -12,7 +12,7 @@ namespace Catch { -class MultipleReporters : public SharedImpl { +class MultipleReporters : public IStreamingReporter { typedef std::vector Reporters; Reporters m_reporters; diff --git a/projects/SelfTest/SurrogateCpps/catch_ptr.cpp b/projects/SelfTest/SurrogateCpps/catch_ptr.cpp deleted file mode 100644 index 90796ca1..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_ptr.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// This file is only here to verify (to the extent possible) the self sufficiency of the header -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_ptr.hpp" From d17d94e45d3223985158ac7cda8b9fead191da4f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 26 Apr 2017 16:10:18 +0100 Subject: [PATCH 036/398] Made INTERNAL_CATCH_TEST variadic so commas in assertions work --- include/internal/catch_capture.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index ee3dd598..b0418d46 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -65,19 +65,19 @@ /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ +#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ try { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ + ( __catchResult <= __VA_ARGS__ ).endExpression(); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ } \ catch( ... ) { \ __catchResult.useActiveException( resultDisposition ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// From 51c143b2c61ba4d7124e0e58a07d8b7db5965e4c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 26 Apr 2017 16:12:48 +0100 Subject: [PATCH 037/398] Added test for assertion with comma --- .../SelfTest/Baselines/console.std.approved.txt | 4 ++-- .../SelfTest/Baselines/console.sw.approved.txt | 16 ++++++++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 3 ++- projects/SelfTest/Baselines/xml.sw.approved.txt | 15 +++++++++++++-- projects/SelfTest/TrickyTests.cpp | 5 +++++ 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 2e76ce75..b07d6f3a 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -940,6 +940,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 168 | 120 passed | 44 failed | 4 failed as expected -assertions: 968 | 860 passed | 87 failed | 21 failed as expected +test cases: 169 | 121 passed | 44 failed | 4 failed as expected +assertions: 969 | 861 passed | 87 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 41693f3a..b62a9a3c 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -8461,6 +8461,18 @@ PASSED: with expansion: "[\x7F]" == "[\x7F]" +------------------------------------------------------------------------------- +assertions with commas are allowed +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + ------------------------------------------------------------------------------- atomic if ------------------------------------------------------------------------------- @@ -9480,6 +9492,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 168 | 119 passed | 45 failed | 4 failed as expected -assertions: 970 | 860 passed | 89 failed | 21 failed as expected +test cases: 169 | 120 passed | 45 failed | 4 failed as expected +assertions: 971 | 861 passed | 89 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index ee691ce0..fc9528f7 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -608,6 +608,7 @@ ExceptionTests.cpp: + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 1373c6d3..001ad64b 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -9085,6 +9085,17 @@ there" + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + @@ -10128,7 +10139,7 @@ spanner - + - + diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 05053fe3..129fc2a2 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -398,3 +398,8 @@ TEST_CASE( "has printf", "" ) { // This can cause problems as, currently, stdout itself is not redirect - only the cout (and cerr) buffer printf( "spanner" ); } + +TEST_CASE( "assertions with commas are allowed" ) { + + REQUIRE( std::vector{1, 2} == std::vector{1, 2} ); +} From 316cb28ea84b92913aafe6688cab08c78519a34c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 26 Apr 2017 17:04:00 +0100 Subject: [PATCH 038/398] Added missing includes --- include/catch_session.hpp | 1 + include/internal/catch_interfaces_reporter.h | 1 + include/internal/catch_test_case_tracker.hpp | 1 + include/internal/catch_test_spec.hpp | 1 + include/reporters/catch_reporter_bases.hpp | 1 + 5 files changed, 5 insertions(+) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 7c674fba..63dba448 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -14,6 +14,7 @@ #include "internal/catch_test_spec.hpp" #include "internal/catch_version.h" #include "internal/catch_text.h" +#include "internal/catch_interfaces_reporter.h" #include #include diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 7679c07a..b1f09f90 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -20,6 +20,7 @@ #include #include #include +#include namespace Catch { diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index c7631384..b3838e8c 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -16,6 +16,7 @@ #include #include #include +#include CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index 6ca31b2c..6571fdd5 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -18,6 +18,7 @@ #include #include +#include namespace Catch { diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 6782e8b3..bc8db1c5 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace Catch { From 40130e59b4b13f9e4c9962a8ffb19448c94b7c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 28 Apr 2017 18:33:52 +0200 Subject: [PATCH 039/398] Fix order of arguments in CATCH_FAIL macro --- include/catch.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/catch.hpp b/include/catch.hpp index 0527ccde..236ec38e 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -135,7 +135,7 @@ LeakDetector leakDetector; #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) -#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) +#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) From 33ed1773f40b406dbf3b7201bf52694bd86b1503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 2 May 2017 23:51:03 +0200 Subject: [PATCH 040/398] Reworked stringification layer, removed Catch::toString Now the order of stringification checks is 1) StringMaker specialization 2) operator<< toString overloads and specializations have been removed. --- include/catch.hpp | 8 +- include/internal/catch_approx.hpp | 10 +- include/internal/catch_expression_lhs.hpp | 8 +- include/internal/catch_matchers_vector.h | 6 +- include/internal/catch_tostring.h | 464 ++++++++++-------- include/internal/catch_tostring.hpp | 261 +++++----- include/reporters/catch_reporter_junit.hpp | 2 +- .../Baselines/console.sw.approved.txt | 124 ++--- .../Baselines/console.swa4.approved.txt | 2 +- .../SelfTest/Baselines/junit.sw.approved.txt | 6 +- .../SelfTest/Baselines/xml.sw.approved.txt | 118 ++--- projects/SelfTest/EnumToString.cpp | 26 +- projects/SelfTest/ExceptionTests.cpp | 2 +- projects/SelfTest/MessageTests.cpp | 2 +- projects/SelfTest/MiscTests.cpp | 8 +- projects/SelfTest/ToStringPair.cpp | 26 +- projects/SelfTest/ToStringTuple.cpp | 16 +- projects/SelfTest/ToStringVector.cpp | 22 +- projects/SelfTest/ToStringWhich.cpp | 62 +-- projects/SelfTest/TrickyTests.cpp | 10 +- 20 files changed, 626 insertions(+), 557 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 236ec38e..29132e0d 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -127,8 +127,8 @@ LeakDetector leakDetector; #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) @@ -194,8 +194,8 @@ LeakDetector leakDetector; #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index 66576428..9c974f6c 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -114,7 +114,7 @@ namespace Detail { std::string toString() const { std::ostringstream oss; - oss << "Approx( " << Catch::toString( m_value ) << " )"; + oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; return oss.str(); } @@ -127,9 +127,11 @@ namespace Detail { } template<> -inline std::string toString( Detail::Approx const& value ) { - return value.toString(); -} +struct StringMaker { + std::string operator()(Catch::Detail::Approx const& value) { + return value.toString(); + } +}; } // end namespace Catch diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 756a07f6..1ac339b4 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -81,7 +81,7 @@ public: } virtual void reconstructExpression( std::string& dest ) const override { - dest = Catch::toString( m_truthy ); + dest = ::Catch::Detail::stringify( m_truthy ); } private: @@ -120,8 +120,8 @@ public: } virtual void reconstructExpression( std::string& dest ) const override { - std::string lhs = Catch::toString( m_lhs ); - std::string rhs = Catch::toString( m_rhs ); + std::string lhs = ::Catch::Detail::stringify( m_lhs ); + std::string rhs = ::Catch::Detail::stringify( m_rhs ); char delim = lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && rhs.find('\n') == std::string::npos ? ' ' : '\n'; @@ -155,7 +155,7 @@ public: virtual void reconstructExpression( std::string& dest ) const override { std::string matcherAsString = m_matcher.toString(); - dest = Catch::toString( m_arg ); + dest = ::Catch::Detail::stringify( m_arg ); dest += ' '; if( matcherAsString == Detail::unprintableString ) dest += m_matcherString; diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 11aee020..e80f7e12 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -25,7 +25,7 @@ namespace Matchers { } virtual std::string describe() const override { - return "Contains: " + Catch::toString( m_comparator ); + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } T const& m_comparator; @@ -46,7 +46,7 @@ namespace Matchers { return true; } virtual std::string describe() const override { - return "Contains: " + Catch::toString( m_comparator ); + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } std::vector const& m_comparator; @@ -70,7 +70,7 @@ namespace Matchers { return true; } virtual std::string describe() const override { - return "Equals: " + Catch::toString( m_comparator ); + return "Equals: " + ::Catch::Detail::stringify( m_comparator ); } std::vector const& m_comparator; }; diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index f72eeca3..02eb0d6f 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -24,226 +24,296 @@ #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 { + // Bring in operator<< from global namespace into Catch namespace + using ::operator<<; -// Why we're here. -template -std::string toString( T const& value ); + namespace Detail { + std::string rawMemoryToString( const void *object, std::size_t size ); -// Built in overloads + template + std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } -std::string toString( std::string const& value ); -std::string toString( std::wstring const& value ); -std::string toString( const char* const value ); -std::string toString( char* const value ); -std::string toString( const wchar_t* const value ); -std::string toString( wchar_t* const value ); -std::string toString( int value ); -std::string toString( unsigned long value ); -std::string toString( unsigned int value ); -std::string toString( const double value ); -std::string toString( const float value ); -std::string toString( bool value ); -std::string toString( char value ); -std::string toString( signed char value ); -std::string toString( unsigned char value ); + template + class IsStreamInsertable { + template + static auto test(int) + -> decltype(std::declval() << std::declval(), std::true_type()); -std::string toString( long long value ); -std::string toString( unsigned long long value ); + template + static auto test(...)->std::false_type; -std::string toString( std::nullptr_t ); + public: + static const bool value = decltype(test(0))::value; + }; + + } // namespace Detail -#ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ); - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); - std::string toString( NSObject* const& nsObject ); -#endif + // If we decide for C++14, change these to enable_if_ts + template + struct StringMaker { + template + typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type + operator()(const Fake& t) { + std::stringstream sstr; + sstr << t; + return sstr.str(); + } - -namespace Detail { - - extern const std::string unprintableString; - - template - class IsStreamInsertable { - template - static auto test(int) - -> decltype( std::declval() << std::declval(), std::true_type() ); - - template - static auto test(...) -> std::false_type; - - public: - static const bool value = decltype(test(0))::value; - }; - - - template::value - > - struct EnumStringMaker - { - static std::string convert( T const& ) { return unprintableString; } - }; - - template - struct EnumStringMaker - { - static std::string convert( T const& v ) - { - return ::Catch::toString( - static_cast::type>(v) - ); + template + typename std::enable_if::value, std::string>::type + operator()(const Fake&) { + return "{?}"; } }; - template - struct StringMakerBase { - template - static std::string convert( T const& v ) - { - return EnumStringMaker::convert( v ); + namespace Detail { + + extern const std::string unprintableString; + + // 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>{}(e); + } + + } // namespace Detail + + + // Some predefined specializations + + template<> + struct StringMaker { + std::string operator()(const std::string& str); + }; + template<> + struct StringMaker { + std::string operator()(const std::wstring& wstr); + }; + + template<> + struct StringMaker { + std::string operator()(char const * str); + }; + template<> + struct StringMaker { + std::string operator()(char * str); + }; + template<> + struct StringMaker { + std::string operator()(wchar_t const * str); + }; + template<> + struct StringMaker { + std::string operator()(wchar_t * str); + }; + + template + struct StringMaker { + std::string operator()(const char* str) { + return ::Catch::Detail::stringify(std::string{ str }); + } + }; + template + struct StringMaker { + std::string operator()(const char* str) { + return ::Catch::Detail::stringify(std::string{ str }); + } + }; + template + struct StringMaker { + std::string operator()(const char* str) { + return ::Catch::Detail::stringify(std::string{ str }); } }; template<> - struct StringMakerBase { - template - static std::string convert( T const& _value ) { + struct StringMaker { + std::string operator()(int value); + }; + template<> + struct StringMaker { + std::string operator()(long value); + }; + template<> + struct StringMaker { + std::string operator()(long long value); + }; + template<> + struct StringMaker { + std::string operator()(unsigned int value); + }; + template<> + struct StringMaker { + std::string operator()(unsigned long value); + }; + template<> + struct StringMaker { + std::string operator()(unsigned long long value); + }; + + template<> + struct StringMaker { + std::string operator()(bool b); + }; + + template<> + struct StringMaker { + std::string operator()(char c); + }; + template<> + struct StringMaker { + std::string operator()(signed char c); + }; + template<> + struct StringMaker { + std::string operator()(unsigned char c); + }; + + template<> + struct StringMaker { + std::string operator()(std::nullptr_t); + }; + + template<> + struct StringMaker { + std::string operator()(float value); + }; + template<> + struct StringMaker { + std::string operator()(double value); + }; + + template + struct StringMaker { + template + std::string operator()(U* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + + template + struct StringMaker { + std::string operator()(R C::* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + + namespace Detail { + template + std::string rangeToString(InputIterator first, InputIterator last) { std::ostringstream oss; - oss << _value; + 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 > { + std::string operator()( std::vector const& v ) { + return ::Catch::Detail::rangeToString( v.begin(), v.end() ); + } + }; + + // === Pair === + template + struct StringMaker > { + std::string operator()(const std::pair& pair) { + std::ostringstream oss; + oss << "{ " + << ::Catch::Detail::stringify(pair.first) + << ", " + << ::Catch::Detail::stringify(pair.second) + << " }"; return oss.str(); } }; - std::string rawMemoryToString( const void *object, std::size_t size ); - - template - inline std::string rawMemoryToString( const T& object ) { - return rawMemoryToString( &object, sizeof(object) ); - } - -} // end namespace Detail - -template -struct StringMaker : - Detail::StringMakerBase::value> {}; - -template -struct StringMaker { - template - static std::string convert( U* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -template -struct StringMaker { - static std::string convert( R C::* p ) { - if( !p ) - return "NULL"; - else - return Detail::rawMemoryToString( p ); - } -}; - -namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ); -} - -//template -//struct StringMaker > { -// static std::string convert( std::vector const& v ) { -// return Detail::rangeToString( v.begin(), v.end() ); -// } -//}; - -template -std::string toString( std::vector const& v ) { - return Detail::rangeToString( v.begin(), v.end() ); -} - - - -// toString for tuples -namespace TupleDetail { - template< - typename Tuple, - std::size_t N = 0, - bool = (N < std::tuple_size::value) - > - struct ElementPrinter { - static void print( const Tuple& tuple, std::ostream& os ) - { - os << ( N ? ", " : " " ) - << Catch::toString(std::get(tuple)); - ElementPrinter::print(tuple,os); - } - }; - - template< - typename Tuple, - std::size_t N - > - struct ElementPrinter { - static void print( const Tuple&, std::ostream& ) {} - }; - -} - -template -struct StringMaker> { - - static std::string convert( const std::tuple& tuple ) - { - std::ostringstream os; - os << '{'; - TupleDetail::ElementPrinter>::print( tuple, os ); - os << " }"; - return os.str(); - } -}; - - -namespace Detail { - template - std::string makeString( T const& value ) { - return StringMaker::convert( value ); - } -} // end namespace Detail - -/// \brief converts any type to a string -/// -/// The default template forwards on to ostringstream - except when an -/// ostringstream overload does not exist - in which case it attempts to detect -/// that and writes {?}. -/// Overload (not specialise) this template for custom typs that you don't want -/// to provide an ostream overload for. -template -std::string toString( T const& value ) { - return StringMaker::convert( value ); -} namespace Detail { - template - std::string rangeToString( InputIterator first, InputIterator last ) { - std::ostringstream oss; - oss << "{ "; - if( first != last ) { - oss << Catch::toString( *first ); - for( ++first ; first != last ; ++first ) - oss << ", " << Catch::toString( *first ); - } - oss << " }"; - return oss.str(); - } -} + 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); + } + }; -} // end namespace Catch + template< + typename Tuple, + std::size_t N + > + struct TupleElementPrinter { + static void print(const Tuple&, std::ostream&) {} + }; + + } + + + template + struct StringMaker> { + std::string operator()(const std::tuple& tuple) { + std::ostringstream os; + os << '{'; + Detail::TupleElementPrinter>::print(tuple, os); + os << " }"; + return os.str(); + } + }; + + + template + struct EnumStringMaker { + std::string operator()(const T& t) { + return ::Catch::Detail::stringify(static_cast::type>(t)); + } + }; + +#ifdef __OBJC__ + template<> + struct StringMaker { + std::string operator()(NSString const* const& nsstring); + }; + template<> + struct StringMaker { + std::string operator()(NSString * CATCH_ARC_STRONG const& nsstring); + }; + template<> + struct StringMaker { + std::string operator()(NSObject* const& nsObject); + }; +#endif + + +} // namespace Catch #endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index f20c41a2..8fc3c89e 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -35,8 +35,7 @@ namespace Detail { }; } - std::string rawMemoryToString( const void *object, std::size_t size ) - { + std::string rawMemoryToString( const void *object, std::size_t size ) { // Reverse order for little endian architectures int i = 0, end = static_cast( size ), inc = 1; if( Endianness::which() == Endianness::Little ) { @@ -53,70 +52,6 @@ namespace Detail { } } -std::string toString( std::string const& value ) { - std::string s = value; - if( getCurrentContext().getConfig()->showInvisibles() ) { - for(size_t i = 0; i < s.size(); ++i ) { - std::string subs; - switch( s[i] ) { - case '\n': subs = "\\n"; break; - case '\t': subs = "\\t"; break; - default: break; - } - if( !subs.empty() ) { - s = s.substr( 0, i ) + subs + s.substr( i+1 ); - ++i; - } - } - } - return '"' + s + '"'; -} -std::string toString( std::wstring const& value ) { - - std::string s; - s.reserve( value.size() ); - for(size_t i = 0; i < value.size(); ++i ) - s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; - return Catch::toString( s ); -} - -std::string toString( const char* const value ) { - return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); -} - -std::string toString( char* const value ) { - return Catch::toString( static_cast( value ) ); -} - -std::string toString( const wchar_t* const value ) -{ - return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); -} - -std::string toString( wchar_t* const value ) -{ - return Catch::toString( static_cast( value ) ); -} - -std::string toString( int value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( unsigned int value ) { - return Catch::toString( static_cast( value ) ); -} template std::string fpToString( T value, int precision ) { @@ -134,74 +69,160 @@ std::string fpToString( T value, int precision ) { return d; } -std::string toString( const double value ) { - return fpToString( value, 10 ); -} -std::string toString( const float value ) { - return fpToString( value, 5 ) + 'f'; + +//// ======================================================= //// +// +// Out-of-line defs for full specialization of StringMaker +// +//// ======================================================= //// + +std::string StringMaker::operator()(const std::string& str) { + if (!getCurrentContext().getConfig()->showInvisibles()) { + return '"' + str + '"'; + } + + std::string s("\""); + for (char c : str) { + switch (c) { + case '\n': + s.append("\\n"); + break; + case '\t': + s.append("\\t"); + break; + default: + s.push_back(c); + break; + } + } + s.append("\""); + return s; } -std::string toString( bool value ) { - return value ? "true" : "false"; +std::string StringMaker::operator()(const std::wstring& wstr) { + std::string s; + s.reserve(wstr.size()); + for (auto c : wstr) { + s += (c <= 0xff) ? static_cast(c) : '?'; + } + return ::Catch::Detail::stringify(s); } -std::string toString( char value ) { - if ( value == '\r' ) +std::string StringMaker::operator()(char const* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::operator()(char* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::operator()(wchar_t const * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::operator()(wchar_t * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} + + +std::string StringMaker::operator()(int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::operator()(long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::operator()(long long value) { + std::ostringstream oss; + oss << value; + if (value > Detail::hexThreshold) { + oss << " (0x" << std::hex << value << ')'; + } + return oss.str(); +} + +std::string StringMaker::operator()(unsigned int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::operator()(unsigned long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::operator()(unsigned long long value) { + std::ostringstream oss; + oss << value; + if (value > Detail::hexThreshold) { + oss << " (0x" << std::hex << value << ')'; + } + return oss.str(); +} + + +std::string StringMaker::operator()(bool b) { + return b ? "true" : "false"; +} + +std::string StringMaker::operator()(char value) { + if (value == '\r') { return "'\\r'"; - if ( value == '\f' ) + } else if (value == '\f') { return "'\\f'"; - if ( value == '\n' ) + } else if (value == '\n') { return "'\\n'"; - if ( value == '\t' ) + } else if (value == '\t') { return "'\\t'"; - if ( '\0' <= value && value < ' ' ) - return toString( static_cast( value ) ); - char chstr[] = "' '"; - chstr[1] = value; - return chstr; + } else if ('\0' <= value && value < ' ') { + return ::Catch::Detail::stringify(static_cast(value)); + } else { + char chstr[] = "' '"; + chstr[1] = value; + return chstr; + } +} +std::string StringMaker::operator()(signed char c) { + return ::Catch::Detail::stringify(static_cast(c)); +} +std::string StringMaker::operator()(unsigned char c) { + return ::Catch::Detail::stringify(static_cast(c)); } -std::string toString( signed char value ) { - return toString( static_cast( value ) ); -} - -std::string toString( unsigned char value ) { - return toString( static_cast( value ) ); -} - -std::string toString( long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} -std::string toString( unsigned long long value ) { - std::ostringstream oss; - oss << value; - if( value > Detail::hexThreshold ) - oss << " (0x" << std::hex << value << ')'; - return oss.str(); -} - -std::string toString( std::nullptr_t ) { +std::string StringMaker::operator()(std::nullptr_t) { return "nullptr"; } +std::string StringMaker::operator()(float value) { + return fpToString(value, 5) + 'f'; +} +std::string StringMaker::operator()(double value) { + return fpToString(value, 10); +} + + #ifdef __OBJC__ - std::string toString( NSString const * const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { - if( !nsstring ) - return "nil"; - return "@" + toString([nsstring UTF8String]); - } - std::string toString( NSObject* const& nsObject ) { - return toString( [nsObject description] ); - } +std::string StringMaker::operator()(NSString const * const& nsstring) { + if (!nsstring) + return "nil"; + return "@" + toString([nsstring UTF8String]); +} +std::string StringMaker::operator()(NSString * CATCH_ARC_STRONG const& nsstring) { + if (!nsstring) + return "nil"; + return "@" + toString([nsstring UTF8String]); +} +std::string StringMaker::operator()(NSObject * const& nsObject) { + return ::Catch::Detail::stringify([nsObject description]); +} #endif } // end namespace Catch diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index f5cbc47d..874b0f97 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -160,7 +160,7 @@ namespace Catch { xml.writeAttribute( "classname", className ); xml.writeAttribute( "name", name ); } - xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); + xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); writeAssertions( sectionNode ); diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index b62a9a3c..9b857c4f 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -119,7 +119,7 @@ with expansion: MiscTests.cpp:: PASSED: - REQUIRE( (*__error()) == 1 ) + REQUIRE( (*__errno_location ()) == 1 ) with expansion: 1 == 1 @@ -5873,7 +5873,7 @@ TrickyTests.cpp:: PASSED: REQUIRE( (std::pair( 1, 2 )) == aNicePair ) with expansion: - std::pair( 1, 2 ) == std::pair( 1, 2 ) + { 1, 2 } == { 1, 2 } ------------------------------------------------------------------------------- Pointers can be compared to null @@ -5885,13 +5885,13 @@ ConditionTests.cpp:: PASSED: REQUIRE( p == 0 ) with expansion: - NULL == 0 + 0 == 0 ConditionTests.cpp:: PASSED: REQUIRE( p == pNULL ) with expansion: - NULL == NULL + 0 == 0 ConditionTests.cpp:: PASSED: @@ -8864,7 +8864,7 @@ ToStringPair.cpp: ToStringPair.cpp:: PASSED: - REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ) + REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ) with expansion: "{ { 42, "Arthur" }, { "Ford", 24 } }" == @@ -8880,7 +8880,7 @@ TrickyTests.cpp:: PASSED: REQUIRE( p == 0 ) with expansion: - NULL == 0 + 0 == 0 ------------------------------------------------------------------------------- random SECTION tests @@ -9078,7 +9078,7 @@ ToStringPair.cpp: ToStringPair.cpp:: PASSED: - REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" ) + REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" ) with expansion: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" @@ -9090,7 +9090,7 @@ ToStringPair.cpp: ToStringPair.cpp:: PASSED: - REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" ) + REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" ) with expansion: "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" @@ -9102,7 +9102,7 @@ ToStringPair.cpp: ToStringPair.cpp:: PASSED: - REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" ) + REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" ) with expansion: "{ { "green", 55 } }" == @@ -9119,6 +9119,48 @@ TrickyTests.cpp:: FAILED: with expansion: "first" == "second" +------------------------------------------------------------------------------- +stringify( has_maker ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ) +with expansion: + "StringMaker" + == + "StringMaker" + +------------------------------------------------------------------------------- +stringify( has_maker_and_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ) +with expansion: + "StringMaker" + == + "StringMaker" + +------------------------------------------------------------------------------- +stringify( has_operator ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" ) +with expansion: + "operator<<( has_operator )" + == + "operator<<( has_operator )" + ------------------------------------------------------------------------------- toString on const wchar_t const pointer returns the string contents ------------------------------------------------------------------------------- @@ -9167,48 +9209,6 @@ PASSED: with expansion: ""wide load"" == ""wide load"" -------------------------------------------------------------------------------- -toString( has_maker ) -------------------------------------------------------------------------------- -ToStringWhich.cpp: -............................................................................... - -ToStringWhich.cpp:: -PASSED: - REQUIRE( Catch::toString( item ) == "StringMaker" ) -with expansion: - "StringMaker" - == - "StringMaker" - -------------------------------------------------------------------------------- -toString( has_maker_and_toString ) -------------------------------------------------------------------------------- -ToStringWhich.cpp: -............................................................................... - -ToStringWhich.cpp:: -PASSED: - REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" ) -with expansion: - "toString( has_maker_and_toString )" - == - "toString( has_maker_and_toString )" - -------------------------------------------------------------------------------- -toString( has_toString ) -------------------------------------------------------------------------------- -ToStringWhich.cpp: -............................................................................... - -ToStringWhich.cpp:: -PASSED: - REQUIRE( Catch::toString( item ) == "toString( has_toString )" ) -with expansion: - "toString( has_toString )" - == - "toString( has_toString )" - ------------------------------------------------------------------------------- toString( vectors ToStringWhich.cpp:: PASSED: - REQUIRE( Catch::toString( v ) == "{ StringMaker }" ) + REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker }" ) with expansion: "{ StringMaker }" == @@ -9231,13 +9231,13 @@ EnumToString.cpp: EnumToString.cpp:: PASSED: - CHECK( Catch::toString(e0) == "E2{0}" ) + CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" ) with expansion: "E2{0}" == "E2{0}" EnumToString.cpp:: PASSED: - CHECK( Catch::toString(e1) == "E2{1}" ) + CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" ) with expansion: "E2{1}" == "E2{1}" @@ -9249,13 +9249,13 @@ EnumToString.cpp: EnumToString.cpp:: PASSED: - CHECK( Catch::toString(e0) == "0" ) + CHECK( ::Catch::Detail::stringify(e0) == "0" ) with expansion: "0" == "0" EnumToString.cpp:: PASSED: - CHECK( Catch::toString(e1) == "1" ) + CHECK( ::Catch::Detail::stringify(e1) == "1" ) with expansion: "1" == "1" @@ -9267,19 +9267,19 @@ ToStringVector.cpp: ToStringVector.cpp:: PASSED: - REQUIRE( Catch::toString(vv) == "{ }" ) + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) with expansion: "{ }" == "{ }" ToStringVector.cpp:: PASSED: - REQUIRE( Catch::toString(vv) == "{ 42 }" ) + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ) with expansion: "{ 42 }" == "{ 42 }" ToStringVector.cpp:: PASSED: - REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ) + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ) with expansion: "{ 42, 250 }" == "{ 42, 250 }" @@ -9291,19 +9291,19 @@ ToStringVector.cpp: ToStringVector.cpp:: PASSED: - REQUIRE( Catch::toString(vv) == "{ }" ) + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) with expansion: "{ }" == "{ }" ToStringVector.cpp:: PASSED: - REQUIRE( Catch::toString(vv) == "{ \"hello\" }" ) + REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" ) with expansion: "{ "hello" }" == "{ "hello" }" ToStringVector.cpp:: PASSED: - REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" ) + REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" ) with expansion: "{ "hello", "world" }" == diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index 6ce6850a..f35e745d 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -119,7 +119,7 @@ with expansion: MiscTests.cpp:: PASSED: - REQUIRE( (*__error()) == 1 ) + REQUIRE( (*__errno_location ()) == 1 ) with expansion: 1 == 1 diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index fc9528f7..ce6f7d23 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -715,13 +715,13 @@ MessageTests.cpp: TrickyTests.cpp: + + + - - - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 001ad64b..32d233a1 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -128,7 +128,7 @@ - (*__error()) == 1 + (*__errno_location ()) == 1 1 == 1 @@ -6214,7 +6214,7 @@ re>" (std::pair<int, int>( 1, 2 )) == aNicePair - std::pair( 1, 2 ) == std::pair( 1, 2 ) + { 1, 2 } == { 1, 2 } @@ -6225,7 +6225,7 @@ re>" p == 0 - NULL == 0 + 0 == 0 @@ -6233,7 +6233,7 @@ re>" p == pNULL - NULL == NULL + 0 == 0 @@ -9516,7 +9516,7 @@ spanner - Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" + ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" "{ { 42, "Arthur" }, { "Ford", 24 } }" @@ -9532,7 +9532,7 @@ spanner p == 0 - NULL == 0 + 0 == 0 @@ -9743,7 +9743,7 @@ spanner - Catch::toString(value) == "{ 34, \"xyzzy\" }" + ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" @@ -9754,7 +9754,7 @@ spanner - Catch::toString( value ) == "{ 34, \"xyzzy\" }" + ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" @@ -9765,7 +9765,7 @@ spanner - Catch::toString( pr ) == "{ { \"green\", 55 } }" + ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" "{ { "green", 55 } }" @@ -9786,6 +9786,45 @@ spanner + + + + ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" + + + "StringMaker<has_maker>" +== +"StringMaker<has_maker>" + + + + + + + + ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" + + + "StringMaker<has_maker_and_operator>" +== +"StringMaker<has_maker_and_operator>" + + + + + + + + ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" + + + "operator<<( has_operator )" +== +"operator<<( has_operator )" + + + + @@ -9830,49 +9869,10 @@ spanner - - - - Catch::toString( item ) == "StringMaker<has_maker>" - - - "StringMaker<has_maker>" -== -"StringMaker<has_maker>" - - - - - - - - Catch::toString( item ) == "toString( has_maker_and_toString )" - - - "toString( has_maker_and_toString )" -== -"toString( has_maker_and_toString )" - - - - - - - - Catch::toString( item ) == "toString( has_toString )" - - - "toString( has_toString )" -== -"toString( has_toString )" - - - - - Catch::toString( v ) == "{ StringMaker<has_maker> }" + ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" "{ StringMaker<has_maker> }" @@ -9885,7 +9885,7 @@ spanner - Catch::toString(e0) == "E2{0}" + ::Catch::Detail::stringify(e0) == "E2{0}" "E2{0}" == "E2{0}" @@ -9893,7 +9893,7 @@ spanner - Catch::toString(e1) == "E2{1}" + ::Catch::Detail::stringify(e1) == "E2{1}" "E2{1}" == "E2{1}" @@ -9904,7 +9904,7 @@ spanner - Catch::toString(e0) == "0" + ::Catch::Detail::stringify(e0) == "0" "0" == "0" @@ -9912,7 +9912,7 @@ spanner - Catch::toString(e1) == "1" + ::Catch::Detail::stringify(e1) == "1" "1" == "1" @@ -9923,7 +9923,7 @@ spanner - Catch::toString(vv) == "{ }" + ::Catch::Detail::stringify(vv) == "{ }" "{ }" == "{ }" @@ -9931,7 +9931,7 @@ spanner - Catch::toString(vv) == "{ 42 }" + ::Catch::Detail::stringify(vv) == "{ 42 }" "{ 42 }" == "{ 42 }" @@ -9939,7 +9939,7 @@ spanner - Catch::toString(vv) == "{ 42, 250 }" + ::Catch::Detail::stringify(vv) == "{ 42, 250 }" "{ 42, 250 }" == "{ 42, 250 }" @@ -9950,7 +9950,7 @@ spanner - Catch::toString(vv) == "{ }" + ::Catch::Detail::stringify(vv) == "{ }" "{ }" == "{ }" @@ -9958,7 +9958,7 @@ spanner - Catch::toString(vv) == "{ \"hello\" }" + ::Catch::Detail::stringify(vv) == "{ \"hello\" }" "{ "hello" }" == "{ "hello" }" @@ -9966,7 +9966,7 @@ spanner - Catch::toString(vv) == "{ \"hello\", \"world\" }" + ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" "{ "hello", "world" }" diff --git a/projects/SelfTest/EnumToString.cpp b/projects/SelfTest/EnumToString.cpp index 52a39812..eb80c747 100644 --- a/projects/SelfTest/EnumToString.cpp +++ b/projects/SelfTest/EnumToString.cpp @@ -1,32 +1,28 @@ #include "catch.hpp" -/* - TODO: maybe ought to check that user-provided specialisations of - Catch::toString also do the right thing -*/ // Enum without user-provided stream operator enum Enum1 { Enum1Value0, Enum1Value1 }; TEST_CASE( "toString(enum)", "[toString][enum]" ) { Enum1 e0 = Enum1Value0; - CHECK( Catch::toString(e0) == "0" ); + CHECK( ::Catch::Detail::stringify(e0) == "0" ); Enum1 e1 = Enum1Value1; - CHECK( Catch::toString(e1) == "1" ); + CHECK( ::Catch::Detail::stringify(e1) == "1" ); } // Enum with user-provided stream operator enum Enum2 { Enum2Value0, Enum2Value1 }; -inline std::ostream& operator<<( std::ostream& os, Enum2 v ) { +std::ostream& operator<<( std::ostream& os, Enum2 v ) { return os << "E2{" << static_cast(v) << "}"; } TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) { Enum2 e0 = Enum2Value0; - CHECK( Catch::toString(e0) == "E2{0}" ); + CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" ); Enum2 e1 = Enum2Value1; - CHECK( Catch::toString(e1) == "E2{1}" ); + CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" ); } // Enum class without user-provided stream operator @@ -34,15 +30,15 @@ enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 }; TEST_CASE( "toString(enum class)", "[toString][enum][enumClass][c++11][.]" ) { EnumClass1 e0 = EnumClass1::EnumClass1Value0; - CHECK( Catch::toString(e0) == "0" ); + CHECK( ::Catch::Detail::stringify(e0) == "0" ); EnumClass1 e1 = EnumClass1::EnumClass1Value1; - CHECK( Catch::toString(e1) == "1" ); + CHECK( ::Catch::Detail::stringify(e1) == "1" ); } // Enum class with user-provided stream operator enum class EnumClass2 : short { EnumClass2Value0, EnumClass2Value1 }; -inline std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) { +std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) { switch( static_cast( e2 ) ) { case static_cast( EnumClass2::EnumClass2Value0 ): return os << "E2/V0"; @@ -55,11 +51,11 @@ inline std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) { TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass][c++11][.]" ) { EnumClass2 e0 = EnumClass2::EnumClass2Value0; - CHECK( Catch::toString(e0) == "E2/V0" ); + CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" ); EnumClass2 e1 = EnumClass2::EnumClass2Value1; - CHECK( Catch::toString(e1) == "E2/V1" ); + CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" ); EnumClass2 e3 = static_cast(10); - CHECK( Catch::toString(e3) == "Unknown enum value 10" ); + CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" ); } diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index c9754d4a..50822ded 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -144,7 +144,7 @@ CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex ) CATCH_TRANSLATE_EXCEPTION( double& ex ) { - return Catch::toString( ex ); + return Catch::Detail::stringify( ex ); } TEST_CASE("Non-std exceptions can be translated", "[.][failing][!throws]" ) diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp index 1c944a3d..e0970886 100644 --- a/projects/SelfTest/MessageTests.cpp +++ b/projects/SelfTest/MessageTests.cpp @@ -134,5 +134,5 @@ TEST_CASE( "Pointers can be converted to strings", "[messages][.]" ) { int p; WARN( "actual address of p: " << &p ); - WARN( "toString(p): " << Catch::toString( &p ) ); + WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) ); } diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index aab0295f..efa5c76f 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -314,25 +314,25 @@ TEST_CASE( "Tabs and newlines show in output", "[.][whitespace][failing]" ) { TEST_CASE( "toString on const wchar_t const pointer returns the string contents", "[toString]" ) { const wchar_t * const s = L"wide load"; - std::string result = Catch::toString( s ); + std::string result = ::Catch::Detail::stringify( s ); CHECK( result == "\"wide load\"" ); } TEST_CASE( "toString on const wchar_t pointer returns the string contents", "[toString]" ) { const wchar_t * s = L"wide load"; - std::string result = Catch::toString( s ); + std::string result = ::Catch::Detail::stringify( s ); CHECK( result == "\"wide load\"" ); } TEST_CASE( "toString on wchar_t const pointer returns the string contents", "[toString]" ) { wchar_t * const s = const_cast( L"wide load" ); - std::string result = Catch::toString( s ); + std::string result = ::Catch::Detail::stringify( s ); CHECK( result == "\"wide load\"" ); } TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) { wchar_t * s = const_cast( L"wide load" ); - std::string result = Catch::toString( s ); + std::string result = ::Catch::Detail::stringify( s ); CHECK( result == "\"wide load\"" ); } diff --git a/projects/SelfTest/ToStringPair.cpp b/projects/SelfTest/ToStringPair.cpp index 8f510700..38f30854 100644 --- a/projects/SelfTest/ToStringPair.cpp +++ b/projects/SelfTest/ToStringPair.cpp @@ -1,37 +1,19 @@ #include "catch.hpp" -// === Pair === -namespace Catch { - // Note: If we put this in the right place in catch_tostring, then - // we can make it an overload of Catch::toString - template - struct StringMaker > { - static std::string convert( const std::pair& pair ) { - std::ostringstream oss; - oss << "{ " - << toString( pair.first ) - << ", " - << toString( pair.second ) - << " }"; - return oss.str(); - } - }; -} - TEST_CASE( "std::pair -> toString", "[toString][pair]" ) { std::pair value( 34, "xyzzy" ); - REQUIRE( Catch::toString( value ) == "{ 34, \"xyzzy\" }" ); + REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" ); } TEST_CASE( "std::pair -> toString", "[toString][pair]" ) { std::pair value( 34, "xyzzy" ); - REQUIRE( Catch::toString(value) == "{ 34, \"xyzzy\" }" ); + REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" ); } TEST_CASE( "std::vector > -> toString", "[toString][pair]" ) { std::vector > pr; pr.push_back( std::make_pair("green", 55 ) ); - REQUIRE( Catch::toString( pr ) == "{ { \"green\", 55 } }" ); + REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" ); } // This is pretty contrived - I figure if this works, anything will... @@ -43,5 +25,5 @@ TEST_CASE( "pair > -> toString", "[t right_t right( "Ford", 24 ); std::pair pair( left, right ); - REQUIRE( Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ); + REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ); } diff --git a/projects/SelfTest/ToStringTuple.cpp b/projects/SelfTest/ToStringTuple.cpp index 9c855715..dcd1d803 100644 --- a/projects/SelfTest/ToStringTuple.cpp +++ b/projects/SelfTest/ToStringTuple.cpp @@ -5,42 +5,42 @@ TEST_CASE( "tuple<>", "[toString][tuple][c++11][.]" ) { typedef std::tuple<> type; - CHECK( "{ }" == Catch::toString(type{}) ); + CHECK( "{ }" == ::Catch::Detail::stringify(type{}) ); type value {}; - CHECK( "{ }" == Catch::toString(value) ); + CHECK( "{ }" == ::Catch::Detail::stringify(value) ); } TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) { typedef std::tuple type; - CHECK( "{ 0 }" == Catch::toString(type{0}) ); + CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) ); } TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) { typedef std::tuple type; - CHECK( "1.2f" == Catch::toString(float(1.2)) ); - CHECK( "{ 1.2f, 0 }" == Catch::toString(type{1.2f,0}) ); + CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) ); + CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) ); } TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) { typedef std::tuple type; - CHECK( "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) ); + CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) ); } TEST_CASE( "tuple,tuple<>,float>", "[toString][tuple][c++11][.]" ) { typedef std::tuple,std::tuple<>,float> type; type value { std::tuple{42}, {}, 1.2f }; - CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) ); + CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) ); } TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) { typedef std::tuple type; type value { nullptr, 42, "Catch me" }; - CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) ); + CHECK( "{ nullptr, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) ); } diff --git a/projects/SelfTest/ToStringVector.cpp b/projects/SelfTest/ToStringVector.cpp index eafe886d..c70872c8 100644 --- a/projects/SelfTest/ToStringVector.cpp +++ b/projects/SelfTest/ToStringVector.cpp @@ -6,21 +6,21 @@ TEST_CASE( "vector -> toString", "[toString][vector]" ) { std::vector vv; - REQUIRE( Catch::toString(vv) == "{ }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ); vv.push_back( 42 ); - REQUIRE( Catch::toString(vv) == "{ 42 }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ); vv.push_back( 250 ); - REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ); } TEST_CASE( "vector -> toString", "[toString][vector]" ) { std::vector vv; - REQUIRE( Catch::toString(vv) == "{ }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ); vv.push_back( "hello" ); - REQUIRE( Catch::toString(vv) == "{ \"hello\" }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" ); vv.push_back( "world" ); - REQUIRE( Catch::toString(vv) == "{ \"hello\", \"world\" }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" ); } namespace { @@ -50,19 +50,19 @@ namespace { TEST_CASE( "vector -> toString", "[toString][vector,allocator][c++11][.]" ) { std::vector > vv; - REQUIRE( Catch::toString(vv) == "{ }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ); vv.push_back( 42 ); - REQUIRE( Catch::toString(vv) == "{ 42 }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ); vv.push_back( 250 ); - REQUIRE( Catch::toString(vv) == "{ 42, 250 }" ); + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ); } TEST_CASE( "vec> -> toString", "[toString][vector,allocator][c++11][.]" ) { using inner = std::vector>; using vector = std::vector; vector v; - REQUIRE( Catch::toString(v) == "{ }" ); + REQUIRE( ::Catch::Detail::stringify(v) == "{ }" ); v.push_back( inner { "hello" } ); v.push_back( inner { "world" } ); - REQUIRE( Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" ); + REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" ); } diff --git a/projects/SelfTest/ToStringWhich.cpp b/projects/SelfTest/ToStringWhich.cpp index a1d2a609..8bd1b6f9 100644 --- a/projects/SelfTest/ToStringWhich.cpp +++ b/projects/SelfTest/ToStringWhich.cpp @@ -5,67 +5,69 @@ */ -struct has_toString { }; +struct has_operator { }; struct has_maker {}; -struct has_maker_and_toString {}; +struct has_maker_and_operator {}; + +std::ostream& operator<<(std::ostream& os, const has_operator&) { + os << "operator<<( has_operator )"; + return os; +} + +std::ostream& operator<<(std::ostream& os, const has_maker_and_operator&) { + os << "operator<<( has_maker_and_operator )"; + return os; +} namespace Catch { - inline std::string toString( const has_toString& ) { - return "toString( has_toString )"; - } - inline std::string toString( const has_maker_and_toString& ) { - return "toString( has_maker_and_toString )"; - } template<> struct StringMaker { - static std::string convert( const has_maker& ) { + std::string operator()( const has_maker& ) { return "StringMaker"; } }; template<> - struct StringMaker { - static std::string convert( const has_maker_and_toString& ) { - return "StringMaker"; + struct StringMaker { + std::string operator()( const has_maker_and_operator& ) { + return "StringMaker"; } }; } -// Call the overload -TEST_CASE( "toString( has_toString )", "[toString]" ) { - has_toString item; - REQUIRE( Catch::toString( item ) == "toString( has_toString )" ); +// Call the operator +TEST_CASE( "stringify( has_operator )", "[toString]" ) { + has_operator item; + REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" ); } -// Call the overload -TEST_CASE( "toString( has_maker )", "toString]" ) { +// Call the stringmaker +TEST_CASE( "stringify( has_maker )", "[toString]" ) { has_maker item; - REQUIRE( Catch::toString( item ) == "StringMaker" ); + REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ); } -// Call the overload -TEST_CASE( "toString( has_maker_and_toString )", "[.][toString]" ) { - has_maker_and_toString item; - REQUIRE( Catch::toString( item ) == "toString( has_maker_and_toString )" ); +// Call the stringmaker +TEST_CASE( "stringify( has_maker_and_toString )", "[.][toString]" ) { + has_maker_and_operator item; + REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ); } // Vectors... // Don't run this in approval tests as it is sensitive to two phase lookup differences TEST_CASE( "toString( vectors v(1); - // This invokes template toString which actually gives us '{ ? }' - REQUIRE( Catch::toString( v ) == "{ {?} }" ); + std::vector v(1); + REQUIRE( ::Catch::Detail::stringify( v ) == "{ operator<<( has_operator ) }" ); } TEST_CASE( "toString( vectors v(1); - REQUIRE( Catch::toString( v ) == "{ StringMaker }" ); + REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker }" ); } // Don't run this in approval tests as it is sensitive to two phase lookup differences TEST_CASE( "toString( vectors v(1); - // Note: This invokes the template toString -> StringMaker - REQUIRE( Catch::toString( v ) == "{ StringMaker }" ); + std::vector v(1); + REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker }" ); } diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 129fc2a2..e5616d0e 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -14,15 +14,11 @@ #include "catch.hpp" -namespace Catch -{ - template<> - std::string toString >( const std::pair& value ) - { +namespace Catch { + std::string toString( const std::pair& value ) { std::ostringstream oss; oss << "std::pair( " << value.first << ", " << value.second << " )"; return oss.str(); - } } @@ -340,7 +336,7 @@ struct Awkward TEST_CASE( "non streamable - with conv. op", "[Tricky]" ) { Awkward awkward; - std::string s = Catch::toString( awkward ); + std::string s = ::Catch::Detail::stringify( awkward ); REQUIRE( s == "7" ); } From c5c3d368a2ef3c22467e708108b2bdbcae0fd71e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 3 May 2017 00:29:36 +0200 Subject: [PATCH 041/398] Added std:: qualification to nullptr_t Apparently Clang doesn't like it unqualfied :smile: --- include/internal/catch_tostring.h | 2 +- include/internal/catch_tostring.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 02eb0d6f..6a20f9ef 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -180,7 +180,7 @@ namespace Catch { }; template<> - struct StringMaker { + struct StringMaker { std::string operator()(std::nullptr_t); }; diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index 8fc3c89e..06046095 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -197,7 +197,7 @@ std::string StringMaker::operator()(unsigned char c) { return ::Catch::Detail::stringify(static_cast(c)); } -std::string StringMaker::operator()(std::nullptr_t) { +std::string StringMaker::operator()(std::nullptr_t) { return "nullptr"; } From a9128d0faca8bd0f0d323e5309c5322473fd7c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 3 May 2017 19:10:27 +0200 Subject: [PATCH 042/398] More macros are now variadic Also added tests for them --- include/internal/catch_capture.hpp | 20 ++-- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 84 ++++++++++--- .../SelfTest/Baselines/junit.sw.approved.txt | 4 +- .../SelfTest/Baselines/xml.sw.approved.txt | 111 ++++++++++++++++-- projects/SelfTest/TrickyTests.cpp | 29 ++++- 6 files changed, 212 insertions(+), 40 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index b0418d46..49673309 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -81,21 +81,21 @@ // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ +#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ if( Catch::getResultCapture().getLastResult()->succeeded() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ - INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ +#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ if( !Catch::getResultCapture().getLastResult()->succeeded() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ +#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ try { \ - static_cast(expr); \ + static_cast(__VA_ARGS__); \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ @@ -105,12 +105,12 @@ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ +#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition, #matcher ); \ if( __catchResult.allowThrows() ) \ try { \ - static_cast(expr); \ + static_cast(__VA_ARGS__); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index b07d6f3a..c35d3bd1 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -940,6 +940,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 169 | 121 passed | 44 failed | 4 failed as expected -assertions: 969 | 861 passed | 87 failed | 21 failed as expected +test cases: 170 | 122 passed | 44 failed | 4 failed as expected +assertions: 980 | 872 passed | 87 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 9b857c4f..68227089 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -823,6 +823,74 @@ PASSED: with expansion: 5 == 5 +------------------------------------------------------------------------------- +Commas in various macros are allowed +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ) + +TrickyTests.cpp:: +PASSED: + CHECK_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ) + +TrickyTests.cpp:: +PASSED: + REQUIRE_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ) + +TrickyTests.cpp:: +PASSED: + CHECK_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ) + +TrickyTests.cpp:: +PASSED: + REQUIRE( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + CHECK( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + REQUIRE_FALSE( std::vector{1, 2} == std::vector{1, 2, 3} ) +with expansion: + !({ 1, 2 } == { 1, 2, 3 }) + +TrickyTests.cpp:: +PASSED: + CHECK_FALSE( std::vector{1, 2} == std::vector{1, 2, 3} ) +with expansion: + !({ 1, 2 } == { 1, 2, 3 }) + +TrickyTests.cpp:: +PASSED: + CHECK_NOFAIL( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + CHECKED_IF( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + REQUIRE( true ) + +TrickyTests.cpp:: +PASSED: + CHECKED_ELSE( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + ------------------------------------------------------------------------------- Comparing function pointers ------------------------------------------------------------------------------- @@ -8461,18 +8529,6 @@ PASSED: with expansion: "[\x7F]" == "[\x7F]" -------------------------------------------------------------------------------- -assertions with commas are allowed -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( std::vector{1, 2} == std::vector{1, 2} ) -with expansion: - { 1, 2 } == { 1, 2 } - ------------------------------------------------------------------------------- atomic if ------------------------------------------------------------------------------- @@ -9492,6 +9548,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 169 | 120 passed | 45 failed | 4 failed as expected -assertions: 971 | 861 passed | 89 failed | 21 failed as expected +test cases: 170 | 121 passed | 45 failed | 4 failed as expected +assertions: 982 | 872 passed | 89 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index ce6f7d23..5de62625 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -109,6 +109,7 @@ ExceptionTests.cpp: + @@ -608,7 +609,6 @@ ExceptionTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 32d233a1..f0bfebd8 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -898,6 +898,105 @@ + + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + + + !({ 1, 2 } == { 1, 2, 3 }) + + + + + !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + + + !({ 1, 2 } == { 1, 2, 3 }) + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + true + + + true + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + @@ -9086,14 +9185,6 @@ there" - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - @@ -10139,7 +10230,7 @@ spanner - + - + diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index e5616d0e..4dfdf39e 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -396,6 +396,31 @@ TEST_CASE( "has printf", "" ) { } TEST_CASE( "assertions with commas are allowed" ) { - - REQUIRE( std::vector{1, 2} == std::vector{1, 2} ); +} + +namespace { + struct constructor_throws { + constructor_throws() { + throw 1; + } + }; +} + +TEST_CASE("Commas in various macros are allowed") { + REQUIRE_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ); + CHECK_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ); + REQUIRE_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ); + CHECK_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ); + + REQUIRE(std::vector{1, 2} == std::vector{1, 2}); + CHECK( std::vector{1, 2} == std::vector{1, 2} ); + REQUIRE_FALSE(std::vector{1, 2} == std::vector{1, 2, 3}); + CHECK_FALSE( std::vector{1, 2} == std::vector{1, 2, 3} ); + + CHECK_NOFAIL( std::vector{1, 2} == std::vector{1, 2} ); + CHECKED_IF( std::vector{1, 2} == std::vector{1, 2} ) { + REQUIRE(true); + } CHECKED_ELSE( std::vector{1, 2} == std::vector{1, 2} ) { + CHECK(true); + } } From ef8b72c94915c41ea1af2284805c8f740a7113de Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 29 Apr 2017 18:52:54 +0100 Subject: [PATCH 043/398] Changed dynamic_pointer_casts to static_pointer_casts --- include/internal/catch_test_case_tracker.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index b3838e8c..beba96bd 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -269,7 +269,7 @@ namespace TestCaseTracking { if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isSectionTracker() ); - section = std::dynamic_pointer_cast( childTracker ); + section = std::static_pointer_cast( childTracker ); } else { section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); @@ -317,7 +317,7 @@ namespace TestCaseTracking { if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isIndexTracker() ); - tracker = std::dynamic_pointer_cast( childTracker ); + tracker = std::static_pointer_cast( childTracker ); } else { tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); From 687437fcd1abe75b2cdc55c002f381e34eabbeca Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 29 Apr 2017 19:38:34 +0100 Subject: [PATCH 044/398] converted IStreamingReporter to unique_ptr --- include/catch_session.hpp | 34 +++++++-------- include/internal/catch_interfaces_reporter.h | 7 ++-- .../internal/catch_reporter_registrars.hpp | 2 +- include/internal/catch_run_context.hpp | 7 +++- include/reporters/catch_reporter_multi.hpp | 42 +++++++++---------- 5 files changed, 46 insertions(+), 46 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 63dba448..d0dc9e9d 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -23,30 +23,28 @@ namespace Catch { IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { - IStreamingReporterPtr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); - if( !reporter ) { - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); - } - return reporter; + if( auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ) ) + return reporter; + + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); } IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { - std::vector reporters = config->getReporterNames(); - if( reporters.empty() ) - reporters.push_back( "console" ); + auto const& reporterNames = config->getReporterNames(); + if( reporterNames.empty() ) + return createReporter( "console", config ); IStreamingReporterPtr reporter; - for( auto const& name : reporters ) - reporter = addReporter( reporter, createReporter( name, config ) ); + for( auto const& name : reporterNames ) + addReporter( reporter, createReporter( name, config ) ); return reporter; } - IStreamingReporterPtr addListeners( IConfigPtr const& config, IStreamingReporterPtr reporters ) { + void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) { auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); for( auto const& listener : listeners ) - reporters = addReporter(reporters, listener->create( ReporterConfig( config ) ) ); - return reporters; + addReporter(reporters, listener->create( ReporterConfig( config ) ) ); } @@ -55,9 +53,9 @@ namespace Catch { IConfigPtr iconfig = config; IStreamingReporterPtr reporter = makeReporter( config ); - reporter = addListeners( iconfig, reporter ); + addListeners( reporter, iconfig ); - RunContext context( iconfig, reporter ); + RunContext context( iconfig, std::move( reporter ) ); Totals totals; @@ -72,7 +70,7 @@ namespace Catch { if( !context.aborting() && matchTest( testCase, testSpec, *iconfig ) ) totals += context.runTest( testCase ); else - reporter->skipTest( testCase ); + context.reporter().skipTest( testCase ); } context.testGroupEnded( iconfig->name(), totals, 1, 1 ); diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index b1f09f90..7a42f097 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -232,9 +232,9 @@ namespace Catch virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - virtual MultipleReporters* tryAsMulti() { return nullptr; } + virtual bool isMulti() const { return false; } }; - using IStreamingReporterPtr = std::shared_ptr; + using IStreamingReporterPtr = std::unique_ptr; struct IReporterFactory { virtual ~IReporterFactory(); @@ -253,8 +253,7 @@ namespace Catch virtual Listeners const& getListeners() const = 0; }; - IStreamingReporterPtr addReporter( IStreamingReporterPtr const& existingReporter, IStreamingReporterPtr const& additionalReporter ); - + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); } #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 759b0edb..06c16cb5 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -18,7 +18,7 @@ namespace Catch { class ReporterFactory : public IReporterFactory { virtual IStreamingReporterPtr create( ReporterConfig const& config ) const { - return std::make_shared( config ); + return std::unique_ptr( new T( config ) ); } virtual std::string getDescription() const { diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 7f38eb4a..feb192ed 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -59,11 +59,11 @@ namespace Catch { public: - explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr const& reporter ) + explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ) : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), m_config( _config ), - m_reporter( reporter ) + m_reporter( std::move( reporter ) ) { m_context.setRunner( this ); m_context.setConfig( m_config ); @@ -131,6 +131,9 @@ namespace Catch { IConfigPtr config() const { return m_config; } + IStreamingReporter& reporter() const { + return *m_reporter; + } private: // IResultCapture diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 859e3f83..589c34e0 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -13,12 +13,12 @@ namespace Catch { class MultipleReporters : public IStreamingReporter { - typedef std::vector Reporters; + typedef std::vector Reporters; Reporters m_reporters; public: - void add( IStreamingReporterPtr const& reporter ) { - m_reporters.push_back( reporter ); + void add( IStreamingReporterPtr&& reporter ) { + m_reporters.push_back( std::move( reporter ) ); } public: // IStreamingReporter @@ -95,31 +95,31 @@ public: // IStreamingReporter reporter->skipTest( testInfo ); } - virtual MultipleReporters* tryAsMulti() override { - return this; + virtual bool isMulti() const override { + return true; } }; -IStreamingReporterPtr addReporter( IStreamingReporterPtr const& existingReporter, IStreamingReporterPtr const& additionalReporter ) { - IStreamingReporterPtr resultingReporter; +void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { - if( existingReporter ) { - MultipleReporters* multi = existingReporter->tryAsMulti(); - if( !multi ) { - multi = new MultipleReporters; - resultingReporter = IStreamingReporterPtr( multi ); - if( existingReporter ) - multi->add( existingReporter ); - } - else - resultingReporter = existingReporter; - multi->add( additionalReporter ); + if( !existingReporter ) { + existingReporter = std::move( additionalReporter ); + return; } - else - resultingReporter = additionalReporter; - return resultingReporter; + MultipleReporters* multi = nullptr; + + if( existingReporter->isMulti() ) { + multi = static_cast( existingReporter.get() ); + } + else { + auto newMulti = std::unique_ptr( new MultipleReporters ); + newMulti->add( std::move( existingReporter ) ); + multi = newMulti.get(); + existingReporter = std::move( newMulti ); + } + multi->add( std::move( additionalReporter ) ); } From 4c5af2089a526a5aa7b6d8c1df3f23212c3b06c9 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 5 May 2017 15:42:57 +0100 Subject: [PATCH 045/398] Added CATCH_ENFORCE (and updated CATCH_INTERNAL_ERROR to be stream based) replaced all ad-hoc exceptions (where appropriate) with CATCH_ENFORCE or CATCH_INTERNAL_ERROR - no explicit ostringstreams. --- include/catch_session.hpp | 15 ++++------- include/internal/catch_commandline.hpp | 25 ++++++++----------- include/internal/catch_common.h | 24 +++++++++++++++--- include/internal/catch_common.hpp | 7 ------ include/internal/catch_config.hpp | 2 +- .../internal/catch_console_colour_impl.hpp | 4 +-- include/internal/catch_run_context.hpp | 2 +- include/internal/catch_stream.hpp | 6 +---- include/internal/catch_tag_alias_registry.hpp | 25 ++++++------------- include/internal/catch_test_case_info.hpp | 11 +++----- .../catch_test_case_registry_impl.hpp | 18 +++++-------- include/internal/catch_test_case_tracker.hpp | 12 ++++----- include/internal/catch_wildcard_pattern.hpp | 11 ++------ 13 files changed, 65 insertions(+), 97 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index d0dc9e9d..dc356614 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -23,12 +23,10 @@ namespace Catch { IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { - if( auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ) ) - return reporter; + auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); + CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); - std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; - throw std::domain_error( oss.str() ); + return reporter; } IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { @@ -105,11 +103,8 @@ namespace Catch { Session() : m_cli( makeCommandLineParser() ) { - if( alreadyInstantiated ) { - std::string msg = "Only one instance of Catch::Session can ever be used"; - Catch::cerr() << msg << std::endl; - throw std::logic_error( msg ); - } + if( alreadyInstantiated ) + CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); alreadyInstantiated = true; } ~Session() { diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 742f01a4..89c55695 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -19,19 +19,16 @@ namespace Catch { inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } inline void abortAfterX( ConfigData& config, int x ) { - if( x < 1 ) - throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + CATCH_ENFORCE( x >=1, "Value after -x or --abortAfter must be greater than zero" ); config.abortAfter = x; } - inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addTestOrTags( ConfigData& config, std::string const& testSpec ) { config.testsOrTags.push_back( testSpec ); } inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } - inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } + inline void addReporterName( ConfigData& config, std::string const& reporterName ) { config.reporterNames.push_back( reporterName ); } - inline void addWarning( ConfigData& config, std::string const& _warning ) { - if( _warning == "NoAssertions" ) - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - else - throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' ); + inline void addWarning( ConfigData& config, std::string const& warning ) { + CATCH_ENFORCE( warning == "NoAssertions", "Unrecognised warning: '" << warning << "'" ); + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); } inline void setOrder( ConfigData& config, std::string const& order ) { if( startsWith( "declared", order ) ) @@ -41,7 +38,7 @@ namespace Catch { else if( startsWith( "random", order ) ) config.runOrder = RunTests::InRandomOrder; else - throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); + CATCH_ENFORCE( false, "Unrecognised ordering: '" << order << '\'' ); } inline void setRngSeed( ConfigData& config, std::string const& seed ) { if( seed == "time" ) { @@ -51,8 +48,7 @@ namespace Catch { std::stringstream ss; ss << seed; ss >> config.rngSeed; - if( ss.fail() ) - throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); + CATCH_ENFORCE( !ss.fail(), "Argument to --rng-seed should be the word 'time' or a number" ); } } inline void setVerbosity( ConfigData& config, int level ) { @@ -74,15 +70,14 @@ namespace Catch { else if( mode == "auto" ) config.useColour = UseColour::Auto; else - throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + CATCH_ENFORCE( false, "colour mode must be one of: auto, yes or no" ); } inline void forceColour( ConfigData& config ) { config.useColour = UseColour::Yes; } inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { std::ifstream f( _filename.c_str() ); - if( !f.is_open() ) - throw std::domain_error( "Unable to load input file: " + _filename ); + CATCH_ENFORCE( f.is_open(), "Unable to load input file: '" << _filename << "'" ); std::string line; while( std::getline( f, line ) ) { diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index bcb6bd51..c4ac2967 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -23,6 +23,7 @@ #include #include +#include namespace Catch { @@ -99,8 +100,6 @@ namespace Catch { inline bool alwaysTrue() { return true; } inline bool alwaysFalse() { return false; } - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); - void seedRng( IConfig const& config ); unsigned int rngSeed(); @@ -117,10 +116,29 @@ namespace Catch { T const& operator + ( T const& value, StreamEndStop ) { return value; } + + template + class Error { + std::ostringstream m_oss; + + public: + template + auto operator <<( T const& value ) -> Error& { + m_oss << value; + return *this; + } + + [[noreturn]] + void raise() { + throw ExceptionT( m_oss.str() ); + } + }; } #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); +#define CATCH_INTERNAL_ERROR( msg ) do{ ( ::Catch::Error() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).raise(); } while(false) +#define CATCH_ERROR( msg ) ( ::Catch::Error<>() << msg ).raise() +#define CATCH_ENFORCE( condition, msg ) do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED diff --git a/include/internal/catch_common.hpp b/include/internal/catch_common.hpp index 9f943777..fc82351e 100644 --- a/include/internal/catch_common.hpp +++ b/include/internal/catch_common.hpp @@ -106,13 +106,6 @@ namespace Catch { #endif return os; } - - void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { - std::ostringstream oss; - oss << locationInfo << ": Internal Catch error: '" << message << '\''; - if( alwaysTrue() ) - throw std::logic_error( oss.str() ); - } } #endif // TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 8be68a81..869e4c70 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -118,7 +118,7 @@ namespace Catch { if( m_data.outputFilename == "%debug" ) return new DebugOutStream(); else - throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" ); } else return new FileStream( m_data.outputFilename ); diff --git a/include/internal/catch_console_colour_impl.hpp b/include/internal/catch_console_colour_impl.hpp index f15494ab..07cb07b4 100644 --- a/include/internal/catch_console_colour_impl.hpp +++ b/include/internal/catch_console_colour_impl.hpp @@ -73,7 +73,7 @@ namespace { case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); - case Colour::Bright: throw std::logic_error( "not a colour" ); + case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); } } @@ -134,7 +134,7 @@ namespace { case Colour::BrightGreen: return setColour( "[1;32m" ); case Colour::BrightWhite: return setColour( "[1;37m" ); - case Colour::Bright: throw std::logic_error( "not a colour" ); + case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); } } static IColourImpl* instance() { diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index feb192ed..3d715c46 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -371,7 +371,7 @@ namespace Catch { if( IResultCapture* capture = getCurrentContext().getResultCapture() ) return *capture; else - throw std::logic_error( "No result capture instance" ); + CATCH_INTERNAL_ERROR( "No result capture instance" ); } } // end namespace Catch diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index cc6c38a1..b287548b 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -59,11 +59,7 @@ namespace Catch { FileStream::FileStream( std::string const& filename ) { m_ofs.open( filename.c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << filename << '\''; - throw std::domain_error( oss.str() ); - } + CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); } std::ostream& FileStream::stream() const { diff --git a/include/internal/catch_tag_alias_registry.hpp b/include/internal/catch_tag_alias_registry.hpp index f7928a64..fef96c35 100644 --- a/include/internal/catch_tag_alias_registry.hpp +++ b/include/internal/catch_tag_alias_registry.hpp @@ -40,24 +40,13 @@ namespace Catch { void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { - if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" - << Colour( Colour::FileName ) - << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } - if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { - std::ostringstream oss; - oss << Colour( Colour::Red ) - << "error: tag alias, \"" << alias << "\" already registered.\n" - << "\tFirst seen at " - << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' - << Colour( Colour::Red ) << "\tRedefined at " - << Colour( Colour::FileName) << lineInfo << '\n'; - throw std::domain_error( oss.str().c_str() ); - } + CATCH_ENFORCE( startsWith( alias, "[@" ) && endsWith( alias, ']' ), + "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); + + CATCH_ENFORCE( m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second, + "error: tag alias, '" << alias << "' already registered.\n" + << "\tFirst seen at: " << find(alias)->lineInfo << "\n" + << "\tRedefined at: " << lineInfo ); } ITagAliasRegistry::~ITagAliasRegistry() {} diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 0ee14c82..32c0e6e9 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -37,15 +37,10 @@ namespace Catch { return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); } inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - if( isReservedTag( tag ) ) { - std::ostringstream ss; - ss << Colour(Colour::Red) - << "Tag name [" << tag << "] not allowed.\n" + CATCH_ENFORCE( !isReservedTag( tag ), + "Tag name: [" << tag << "] is not allowed.\n" << "Tag names starting with non alpha-numeric characters are reserved\n" - << Colour(Colour::FileName) - << _lineInfo << '\n'; - throw std::runtime_error(ss.str()); - } + << _lineInfo ); } TestCase makeTestCase( ITestCase* _testCase, diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index cecbc253..5406c543 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -62,18 +62,12 @@ namespace Catch { void enforceNoDuplicateTestCases( std::vector const& functions ) { std::set seenFunctions; - for( auto const function : functions ) { - std::pair::const_iterator, bool> prev = seenFunctions.insert( function ); - if( !prev.second ) { - std::ostringstream ss; - - ss << Colour( Colour::Red ) - << "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' - << "\tRedefined at " << function.getTestCaseInfo().lineInfo << std::endl; - - throw std::runtime_error(ss.str()); - } + for( auto const& function : functions ) { + auto prev = seenFunctions.insert( function ); + CATCH_ENFORCE( prev.second, + "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); } } diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index beba96bd..d03fc936 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -202,11 +202,6 @@ namespace TestCaseTracking { m_ctx.currentTracker().close(); switch( m_runState ) { - case NotStarted: - case CompletedSuccessfully: - case Failed: - throw std::logic_error( "Illogical state" ); - case NeedsAnotherRun: break;; @@ -218,8 +213,13 @@ namespace TestCaseTracking { m_runState = CompletedSuccessfully; break; + case NotStarted: + case CompletedSuccessfully: + case Failed: + CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); + default: - throw std::logic_error( "Unexpected state" ); + CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); } moveToParent(); m_ctx.completeCycle(); diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp index b9827b96..04d70f12 100644 --- a/include/internal/catch_wildcard_pattern.hpp +++ b/include/internal/catch_wildcard_pattern.hpp @@ -49,16 +49,9 @@ namespace Catch return startsWith( adjustCase( str ), m_pattern ); case WildcardAtBothEnds: return contains( adjustCase( str ), m_pattern ); + default: + CATCH_INTERNAL_ERROR( "Unknown enum" ); } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif } private: std::string adjustCase( std::string const& str ) const { From bada67bb72e18149e2ecf0c39d419c9edbb33b1e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 5 May 2017 18:25:02 +0100 Subject: [PATCH 046/398] Rebased approvals --- .../Baselines/console.sw.approved.txt | 30 ++++++++----------- .../Baselines/console.swa4.approved.txt | 2 +- .../SelfTest/Baselines/xml.sw.approved.txt | 30 ++++++++----------- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 68227089..3b88aaa9 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -119,7 +119,7 @@ with expansion: MiscTests.cpp:: PASSED: - REQUIRE( (*__errno_location ()) == 1 ) + REQUIRE( (*__error()) == 1 ) with expansion: 1 == 1 @@ -6945,37 +6945,33 @@ TagAliasTests.cpp:: PASSED: CHECK_THAT( what, Contains( "[@zzz]" ) ) with expansion: - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 - " contains: "[@zzz]" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "[@zzz]" TagAliasTests.cpp:: PASSED: CHECK_THAT( what, Contains( "file" ) ) with expansion: - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 - " contains: "file" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "file" TagAliasTests.cpp:: PASSED: CHECK_THAT( what, Contains( "2" ) ) with expansion: - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 - " contains: "2" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "2" TagAliasTests.cpp:: PASSED: CHECK_THAT( what, Contains( "10" ) ) with expansion: - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 - " contains: "10" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "10" ------------------------------------------------------------------------------- Tag alias can be registered against tag patterns diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index f35e745d..6ce6850a 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -119,7 +119,7 @@ with expansion: MiscTests.cpp:: PASSED: - REQUIRE( (*__errno_location ()) == 1 ) + REQUIRE( (*__error()) == 1 ) with expansion: 1 == 1 diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index f0bfebd8..efbd8763 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -128,7 +128,7 @@ - (*__errno_location ()) == 1 + (*__error()) == 1 1 == 1 @@ -7486,10 +7486,9 @@ hello what, Contains( "[@zzz]" ) - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 -" contains: "[@zzz]" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "[@zzz]" @@ -7497,10 +7496,9 @@ hello what, Contains( "file" ) - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 -" contains: "file" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "file" @@ -7508,10 +7506,9 @@ hello what, Contains( "2" ) - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 -" contains: "2" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "2" @@ -7519,10 +7516,9 @@ hello what, Contains( "10" ) - "error: tag alias, "[@zzz]" already registered. - First seen at file:2 - Redefined at file:10 -" contains: "10" + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "10" From 8c757cc54253928f86c354f2936d8f7aef1d07fb Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 5 May 2017 18:39:49 +0100 Subject: [PATCH 047/398] Removed need for Error class to capture stream inserted strings into exceptions --- include/internal/catch_common.h | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index c4ac2967..ad393c52 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -116,29 +116,16 @@ namespace Catch { T const& operator + ( T const& value, StreamEndStop ) { return value; } - - template - class Error { - std::ostringstream m_oss; - - public: - template - auto operator <<( T const& value ) -> Error& { - m_oss << value; - return *this; - } - - [[noreturn]] - void raise() { - throw ExceptionT( m_oss.str() ); - } - }; } -#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_INTERNAL_ERROR( msg ) do{ ( ::Catch::Error() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).raise(); } while(false) -#define CATCH_ERROR( msg ) ( ::Catch::Error<>() << msg ).raise() -#define CATCH_ENFORCE( condition, msg ) do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) \ + throw std::logic_error( ( std::ostringstream() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).str() ) +#define CATCH_ERROR( msg ) \ + throw std::domain_error( ( std::ostringstream() << msg ).str() ) +#define CATCH_ENFORCE( condition, msg ) \ + do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED From d7eb041ab5e07ae2ad5328ceee2a6beedb1bfbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 8 May 2017 00:54:53 +0200 Subject: [PATCH 048/398] Fix compilation on non-OSX platforms --- include/internal/catch_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index ad393c52..d4f1dbbb 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -121,9 +121,9 @@ namespace Catch { #define CATCH_INTERNAL_LINEINFO \ ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) #define CATCH_INTERNAL_ERROR( msg ) \ - throw std::logic_error( ( std::ostringstream() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).str() ) + throw std::logic_error( static_cast( std::ostringstream() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).str() ) #define CATCH_ERROR( msg ) \ - throw std::domain_error( ( std::ostringstream() << msg ).str() ) + throw std::domain_error( static_cast( std::ostringstream() << msg ).str() ) #define CATCH_ENFORCE( condition, msg ) \ do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) From 7e142329243f372330895c6e0bd309487382b35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 8 May 2017 00:58:44 +0200 Subject: [PATCH 049/398] Fix C4702 (unreachable code) in generators Generators might get removed anyway, but at least compilation wont trigger Wx on MSVC in the meantime. --- include/internal/catch_generators.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/internal/catch_generators.hpp b/include/internal/catch_generators.hpp index e02691cf..71ae5e38 100644 --- a/include/internal/catch_generators.hpp +++ b/include/internal/catch_generators.hpp @@ -98,7 +98,6 @@ public: index += generator->size(); } CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so } void add( const IGenerator* generator ) { From bffef1bffa5d35c22168fe011bc7aad9a1e4c228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 8 May 2017 00:59:44 +0200 Subject: [PATCH 050/398] Fix alignment for Catch::Option This is so much easier in C++11... --- include/internal/catch_option.hpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/include/internal/catch_option.hpp b/include/internal/catch_option.hpp index 8b146da6..6653649e 100644 --- a/include/internal/catch_option.hpp +++ b/include/internal/catch_option.hpp @@ -67,15 +67,7 @@ namespace Catch { private: T *nullableValue; - union { - char storage[sizeof(T)]; - - // These are here to force alignment for the storage - long double dummy1; - void (*dummy2)(); - long double dummy3; - long long dummy4; - }; + alignas(alignof(T)) char storage[sizeof(T)]; }; } // end namespace Catch From f82e31255236420060c29b8d2a4cee465bf61ed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 8 May 2017 01:08:07 +0200 Subject: [PATCH 051/398] Attempt at fixing compilation on OSX Since I don't have actual access to OSX, this might be a tad optimistic. --- include/internal/catch_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index d4f1dbbb..630a65c9 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -121,9 +121,9 @@ namespace Catch { #define CATCH_INTERNAL_LINEINFO \ ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) #define CATCH_INTERNAL_ERROR( msg ) \ - throw std::logic_error( static_cast( std::ostringstream() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).str() ) + throw std::logic_error( static_cast( std::ostringstream() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).str() ) #define CATCH_ERROR( msg ) \ - throw std::domain_error( static_cast( std::ostringstream() << msg ).str() ) + throw std::domain_error( static_cast( std::ostringstream() << msg ).str() ) #define CATCH_ENFORCE( condition, msg ) \ do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) From 85aa7707019879e8047eb0945342d8b324d5ae7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 8 May 2017 01:26:06 +0200 Subject: [PATCH 052/398] Disable unreachable code warning for TrickyTests.cpp Somehow this only triggers for VS 2015, Win32 | Release configuration... --- projects/SelfTest/TrickyTests.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 4dfdf39e..ca8c4518 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -10,6 +10,11 @@ #pragma clang diagnostic ignored "-Wpadded" #endif +#ifdef _MSC_VER +#pragma warning (disable : 4702) // Disable unreachable code warning for the last test + // that is triggered when compiling as Win32|Release +#endif + #include #include "catch.hpp" From 31f5e2ed81fd38020bd9e0be2341f46556751821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 16 May 2017 13:38:52 +0200 Subject: [PATCH 053/398] Updated documentation about stringifying UDTs --- docs/tostring.md | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/docs/tostring.md b/docs/tostring.md index dbb6cb8d..f961ccc1 100644 --- a/docs/tostring.md +++ b/docs/tostring.md @@ -1,7 +1,7 @@ # String conversions Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). -Most built-in or std types are supported out of the box but there are three ways that you can tell Catch how to convert your own types (or other, third-party types) into strings. +Most built-in or std types are supported out of the box but there are two ways that you can tell Catch how to convert your own types (or other, third-party types) into strings. ## operator << overload for std::ostream @@ -16,42 +16,19 @@ std::ostream& operator << ( std::ostream& os, T const& value ) { (where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function). -You should put this function in the same namespace as your type. - -Alternatively you may prefer to write it as a member function: - -``` -std::ostream& T::operator << ( std::ostream& os ) const { - os << convertMyTypeToString( *this ); - return os; -} -``` - -## Catch::toString overload - -If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide an overload for ```Catch::toString()``` for your type. - -``` -namespace Catch { - std::string toString( T const& value ) { - return convertMyTypeToString( value ); - } -} -``` - -Again ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable. Note that the function must be in the Catch namespace, which itself must be in the global namespace. +You should put this function in the same namespace as your type and have it declared before including Catch's header. ## Catch::StringMaker specialisation - -There are some cases where overloading toString does not work as expected. Specialising StringMaker gives you more precise, and reliable, control - but at the cost of slightly more code and complexity: +If you don't want to provide an ```operator <<``` overload, or you want to convert your type differently for testing purposes, you can provide a specialization for `Catch::StringMaker`: ``` namespace Catch { - template<> struct StringMaker { - static std::string convert( T const& value ) { - return convertMyTypeToString( value ); - } - }; + template<> + struct StringMaker { + std::string operator()( T const& value ) { + return convertMyTypeToString( value ); + } + }; } ``` From 67914d8b8634da89cc8d37d65ca682bb14c484d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 21 May 2017 23:40:05 +0200 Subject: [PATCH 054/398] Move back to static StringMaker::convert This avoids some breakage from the modernization --- docs/tostring.md | 2 +- include/internal/catch_approx.hpp | 2 +- include/internal/catch_tostring.h | 78 +++++++++++++++-------------- include/internal/catch_tostring.hpp | 44 ++++++++-------- projects/SelfTest/ToStringWhich.cpp | 4 +- 5 files changed, 66 insertions(+), 64 deletions(-) diff --git a/docs/tostring.md b/docs/tostring.md index f961ccc1..05a6b79b 100644 --- a/docs/tostring.md +++ b/docs/tostring.md @@ -25,7 +25,7 @@ If you don't want to provide an ```operator <<``` overload, or you want to conve namespace Catch { template<> struct StringMaker { - std::string operator()( T const& value ) { + static std::string convert( T const& value ) { return convertMyTypeToString( value ); } }; diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index 9c974f6c..4235d0bc 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -128,7 +128,7 @@ namespace Detail { template<> struct StringMaker { - std::string operator()(Catch::Detail::Approx const& value) { + static std::string convert(Catch::Detail::Approx const& value) { return value.toString(); } }; diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 6a20f9ef..91fa9ed9 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -61,17 +61,19 @@ namespace Catch { template struct StringMaker { template + static typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type - operator()(const Fake& t) { - std::stringstream sstr; - sstr << t; - return sstr.str(); + convert(const Fake& t) { + std::stringstream sstr; + sstr << t; + return sstr.str(); } template + static typename std::enable_if::value, std::string>::type - operator()(const Fake&) { - return "{?}"; + convert(const Fake&) { + return "{?}"; } }; @@ -83,7 +85,7 @@ namespace Catch { // Should be preferably called fully qualified, like ::Catch::Detail::stringify template std::string stringify(const T& e) { - return ::Catch::StringMaker::type>::type>{}(e); + return ::Catch::StringMaker::type>::type>::convert(e); } } // namespace Detail @@ -93,110 +95,110 @@ namespace Catch { template<> struct StringMaker { - std::string operator()(const std::string& str); + static std::string convert(const std::string& str); }; template<> struct StringMaker { - std::string operator()(const std::wstring& wstr); + static std::string convert(const std::wstring& wstr); }; template<> struct StringMaker { - std::string operator()(char const * str); + static std::string convert(char const * str); }; template<> struct StringMaker { - std::string operator()(char * str); + static std::string convert(char * str); }; template<> struct StringMaker { - std::string operator()(wchar_t const * str); + static std::string convert(wchar_t const * str); }; template<> struct StringMaker { - std::string operator()(wchar_t * str); + static std::string convert(wchar_t * str); }; template struct StringMaker { - std::string operator()(const char* str) { + static std::string convert(const char* str) { return ::Catch::Detail::stringify(std::string{ str }); } }; template struct StringMaker { - std::string operator()(const char* str) { + static std::string convert(const char* str) { return ::Catch::Detail::stringify(std::string{ str }); } }; template struct StringMaker { - std::string operator()(const char* str) { + static std::string convert(const char* str) { return ::Catch::Detail::stringify(std::string{ str }); } }; template<> struct StringMaker { - std::string operator()(int value); + static std::string convert(int value); }; template<> struct StringMaker { - std::string operator()(long value); + static std::string convert(long value); }; template<> struct StringMaker { - std::string operator()(long long value); + static std::string convert(long long value); }; template<> struct StringMaker { - std::string operator()(unsigned int value); + static std::string convert(unsigned int value); }; template<> struct StringMaker { - std::string operator()(unsigned long value); + static std::string convert(unsigned long value); }; template<> struct StringMaker { - std::string operator()(unsigned long long value); + static std::string convert(unsigned long long value); }; template<> struct StringMaker { - std::string operator()(bool b); + static std::string convert(bool b); }; template<> struct StringMaker { - std::string operator()(char c); + static std::string convert(char c); }; template<> struct StringMaker { - std::string operator()(signed char c); + static std::string convert(signed char c); }; template<> struct StringMaker { - std::string operator()(unsigned char c); + static std::string convert(unsigned char c); }; template<> struct StringMaker { - std::string operator()(std::nullptr_t); + static std::string convert(std::nullptr_t); }; template<> struct StringMaker { - std::string operator()(float value); + static std::string convert(float value); }; template<> struct StringMaker { - std::string operator()(double value); + static std::string convert(double value); }; template struct StringMaker { template - std::string operator()(U* p) { + static std::string convert(U* p) { if (p) { return ::Catch::Detail::rawMemoryToString(p); } else { @@ -207,7 +209,7 @@ namespace Catch { template struct StringMaker { - std::string operator()(R C::* p) { + static std::string convert(R C::* p) { if (p) { return ::Catch::Detail::rawMemoryToString(p); } else { @@ -233,7 +235,7 @@ namespace Catch { template struct StringMaker > { - std::string operator()( std::vector const& v ) { + static std::string convert( std::vector const& v ) { return ::Catch::Detail::rangeToString( v.begin(), v.end() ); } }; @@ -241,7 +243,7 @@ namespace Catch { // === Pair === template struct StringMaker > { - std::string operator()(const std::pair& pair) { + static std::string convert(const std::pair& pair) { std::ostringstream oss; oss << "{ " << ::Catch::Detail::stringify(pair.first) @@ -281,7 +283,7 @@ namespace Catch { template struct StringMaker> { - std::string operator()(const std::tuple& tuple) { + static std::string convert(const std::tuple& tuple) { std::ostringstream os; os << '{'; Detail::TupleElementPrinter>::print(tuple, os); @@ -293,7 +295,7 @@ namespace Catch { template struct EnumStringMaker { - std::string operator()(const T& t) { + static std::string convert(const T& t) { return ::Catch::Detail::stringify(static_cast::type>(t)); } }; @@ -301,15 +303,15 @@ namespace Catch { #ifdef __OBJC__ template<> struct StringMaker { - std::string operator()(NSString const* const& nsstring); + static std::string convert(NSString const* const& nsstring); }; template<> struct StringMaker { - std::string operator()(NSString * CATCH_ARC_STRONG const& nsstring); + static std::string convert(NSString * CATCH_ARC_STRONG const& nsstring); }; template<> struct StringMaker { - std::string operator()(NSObject* const& nsObject); + static std::string convert(NSObject* const& nsObject); }; #endif diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index 06046095..03881249 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -76,7 +76,7 @@ std::string fpToString( T value, int precision ) { // //// ======================================================= //// -std::string StringMaker::operator()(const std::string& str) { +std::string StringMaker::convert(const std::string& str) { if (!getCurrentContext().getConfig()->showInvisibles()) { return '"' + str + '"'; } @@ -99,7 +99,7 @@ std::string StringMaker::operator()(const std::string& str) { return s; } -std::string StringMaker::operator()(const std::wstring& wstr) { +std::string StringMaker::convert(const std::wstring& wstr) { std::string s; s.reserve(wstr.size()); for (auto c : wstr) { @@ -108,28 +108,28 @@ std::string StringMaker::operator()(const std::wstring& wstr) { return ::Catch::Detail::stringify(s); } -std::string StringMaker::operator()(char const* str) { +std::string StringMaker::convert(char const* str) { if (str) { return ::Catch::Detail::stringify(std::string{ str }); } else { return{ "{null string}" }; } } -std::string StringMaker::operator()(char* str) { +std::string StringMaker::convert(char* str) { if (str) { return ::Catch::Detail::stringify(std::string{ str }); } else { return{ "{null string}" }; } } -std::string StringMaker::operator()(wchar_t const * str) { +std::string StringMaker::convert(wchar_t const * str) { if (str) { return ::Catch::Detail::stringify(std::wstring{ str }); } else { return{ "{null string}" }; } } -std::string StringMaker::operator()(wchar_t * str) { +std::string StringMaker::convert(wchar_t * str) { if (str) { return ::Catch::Detail::stringify(std::wstring{ str }); } else { @@ -138,13 +138,13 @@ std::string StringMaker::operator()(wchar_t * str) { } -std::string StringMaker::operator()(int value) { +std::string StringMaker::convert(int value) { return ::Catch::Detail::stringify(static_cast(value)); } -std::string StringMaker::operator()(long value) { +std::string StringMaker::convert(long value) { return ::Catch::Detail::stringify(static_cast(value)); } -std::string StringMaker::operator()(long long value) { +std::string StringMaker::convert(long long value) { std::ostringstream oss; oss << value; if (value > Detail::hexThreshold) { @@ -153,13 +153,13 @@ std::string StringMaker::operator()(long long value) { return oss.str(); } -std::string StringMaker::operator()(unsigned int value) { +std::string StringMaker::convert(unsigned int value) { return ::Catch::Detail::stringify(static_cast(value)); } -std::string StringMaker::operator()(unsigned long value) { +std::string StringMaker::convert(unsigned long value) { return ::Catch::Detail::stringify(static_cast(value)); } -std::string StringMaker::operator()(unsigned long long value) { +std::string StringMaker::convert(unsigned long long value) { std::ostringstream oss; oss << value; if (value > Detail::hexThreshold) { @@ -169,11 +169,11 @@ std::string StringMaker::operator()(unsigned long long value } -std::string StringMaker::operator()(bool b) { +std::string StringMaker::convert(bool b) { return b ? "true" : "false"; } -std::string StringMaker::operator()(char value) { +std::string StringMaker::convert(char value) { if (value == '\r') { return "'\\r'"; } else if (value == '\f') { @@ -190,37 +190,37 @@ std::string StringMaker::operator()(char value) { return chstr; } } -std::string StringMaker::operator()(signed char c) { +std::string StringMaker::convert(signed char c) { return ::Catch::Detail::stringify(static_cast(c)); } -std::string StringMaker::operator()(unsigned char c) { +std::string StringMaker::convert(unsigned char c) { return ::Catch::Detail::stringify(static_cast(c)); } -std::string StringMaker::operator()(std::nullptr_t) { +std::string StringMaker::convert(std::nullptr_t) { return "nullptr"; } -std::string StringMaker::operator()(float value) { +std::string StringMaker::convert(float value) { return fpToString(value, 5) + 'f'; } -std::string StringMaker::operator()(double value) { +std::string StringMaker::convert(double value) { return fpToString(value, 10); } #ifdef __OBJC__ -std::string StringMaker::operator()(NSString const * const& nsstring) { +std::string StringMaker::convert(NSString const * const& nsstring) { if (!nsstring) return "nil"; return "@" + toString([nsstring UTF8String]); } -std::string StringMaker::operator()(NSString * CATCH_ARC_STRONG const& nsstring) { +std::string StringMaker::convert(NSString * CATCH_ARC_STRONG const& nsstring) { if (!nsstring) return "nil"; return "@" + toString([nsstring UTF8String]); } -std::string StringMaker::operator()(NSObject * const& nsObject) { +std::string StringMaker::convert(NSObject * const& nsObject) { return ::Catch::Detail::stringify([nsObject description]); } #endif diff --git a/projects/SelfTest/ToStringWhich.cpp b/projects/SelfTest/ToStringWhich.cpp index 8bd1b6f9..fc658a7a 100644 --- a/projects/SelfTest/ToStringWhich.cpp +++ b/projects/SelfTest/ToStringWhich.cpp @@ -22,13 +22,13 @@ std::ostream& operator<<(std::ostream& os, const has_maker_and_operator&) { namespace Catch { template<> struct StringMaker { - std::string operator()( const has_maker& ) { + static std::string convert( const has_maker& ) { return "StringMaker"; } }; template<> struct StringMaker { - std::string operator()( const has_maker_and_operator& ) { + static std::string convert( const has_maker_and_operator& ) { return "StringMaker"; } }; From 169e260e8b73facff52a817b2b84c1431c017329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 22 May 2017 00:41:31 +0200 Subject: [PATCH 055/398] Enable colourized output while in debugger --- include/internal/catch_console_colour_impl.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_console_colour_impl.hpp b/include/internal/catch_console_colour_impl.hpp index 07cb07b4..fc3aaf50 100644 --- a/include/internal/catch_console_colour_impl.hpp +++ b/include/internal/catch_console_colour_impl.hpp @@ -94,9 +94,7 @@ namespace { ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = !isDebuggerActive() - ? UseColour::Yes - : UseColour::No; + colourMode = UseColour::Yes; return colourMode == UseColour::Yes ? &s_instance : NoColourImpl::instance(); @@ -155,7 +153,7 @@ namespace { ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + colourMode = isatty(STDOUT_FILENO) ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes From a64a0c6f06bd766896c84cbad5559454bbf9b84e Mon Sep 17 00:00:00 2001 From: Thomas Sondergaard Date: Tue, 30 May 2017 17:10:14 +0200 Subject: [PATCH 056/398] Consistent junit reporting regardless of internal SECTIONS Change it so the classname attribute on the element is the test fixture name or "global" regardless of whether the TEST_CASE contains SECTIONs. This way the output is not changed substantially, just because a SECTION is added to a TEST_CASE. --- include/reporters/catch_reporter_junit.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index a671c68f..c8f1238e 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -139,8 +139,7 @@ namespace Catch { std::string className = stats.testInfo.className; if( className.empty() ) { - if( rootSection.childSections.empty() ) - className = "global"; + className = "global"; } writeSection( className, "", rootSection ); } From 0020747420110545452a95ab37d04424118fcab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 4 Jun 2017 21:28:08 +0200 Subject: [PATCH 057/398] Generate single header even if output dir does not exist --- scripts/generateSingleHeader.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index 18a2612a..bef63b09 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -36,6 +36,8 @@ for arg in sys.argv[1:]: print( "\n** Unrecognised argument: " + arg + " **\n" ) exit(1) +# ensure that the output directory exists +os.makedirs(os.path.dirname(outputPath), exist_ok = True) out = open( outputPath, 'w' ) ifdefs = 0 implIfDefs = -1 From da0edcbe257c9b5f19e69906ce1b10f4dac4fa98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 4 Jun 2017 21:39:27 +0200 Subject: [PATCH 058/398] Collect startup exceptions instead of throwing them Previously, some errors in Catch configuration would cause exceptions to be thrown before main was even entered. This leads to call to `std::terminate`, which is not a particularly nice way of ending the binary. Now these exceptions are registered with a global collector and used once Catch enters main. They can also be optionally ignored, if user supplies his own main and opts not to check them (or ignored them intentionally). Closes #921 --- CMakeLists.txt | 2 ++ docs/own-main.md | 20 +++++++++++-- include/catch_session.hpp | 15 +++++++++- include/internal/catch_common.h | 6 ++-- include/internal/catch_impl.hpp | 1 + .../internal/catch_interfaces_registry_hub.h | 5 ++++ include/internal/catch_registry_hub.hpp | 9 +++++- .../catch_startup_exception_registry.h | 27 +++++++++++++++++ .../catch_startup_exception_registry.hpp | 24 +++++++++++++++ include/internal/catch_tag_alias_registry.hpp | 29 ++++++++++++++----- include/internal/catch_test_case_info.hpp | 15 +++++++--- 11 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 include/internal/catch_startup_exception_registry.h create mode 100644 include/internal/catch_startup_exception_registry.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index dfea23cb..e581becc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,8 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_section.hpp ${HEADER_DIR}/internal/catch_section_info.h ${HEADER_DIR}/internal/catch_section_info.hpp + ${HEADER_DIR}/internal/catch_startup_exception_registry.h + ${HEADER_DIR}/internal/catch_startup_exception_registry.hpp ${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_stream.hpp ${HEADER_DIR}/internal/catch_streambuf.h diff --git a/docs/own-main.md b/docs/own-main.md index 67e551f3..91a79b26 100644 --- a/docs/own-main.md +++ b/docs/own-main.md @@ -16,8 +16,7 @@ If you just need to have code that executes before and/ or after Catch this is t #define CATCH_CONFIG_RUNNER #include "catch.hpp" -int main( int argc, char* argv[] ) -{ +int main( int argc, char* argv[] ) { // global setup... int result = Catch::Session().run( argc, argv ); @@ -42,7 +41,22 @@ int main( int argc, char* argv[] ) // writing to session.configData() here sets defaults // this is the preferred way to set them - + + // Verify that all tests, aliases, etc registered properly + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch (std::exception const& ex) { + Catch::cerr() << ex.what(); + } + } + // Indicate that an error occured before main + return 1; + } + int returnCode = session.applyCommandLine( argc, argv ); if( returnCode != 0 ) // Indicates a command line error return returnCode; diff --git a/include/catch_session.hpp b/include/catch_session.hpp index dc356614..4fcdfafe 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -15,6 +15,7 @@ #include "internal/catch_version.h" #include "internal/catch_text.h" #include "internal/catch_interfaces_reporter.h" +#include "internal/catch_startup_exception_registry.h" #include #include @@ -146,7 +147,19 @@ namespace Catch { } int run( int argc, char const* const* const argv ) { - + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + Catch::cerr() << "Errors occured during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << ex.what() << '\n'; + } + } + return 1; + } int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 630a65c9..87b7020f 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -120,10 +120,12 @@ namespace Catch { #define CATCH_INTERNAL_LINEINFO \ ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_PREPARE_EXCEPTION( type, msg ) \ + type( static_cast( std::ostringstream() << msg ).str() ) #define CATCH_INTERNAL_ERROR( msg ) \ - throw std::logic_error( static_cast( std::ostringstream() << CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg ).str() ) + throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); #define CATCH_ERROR( msg ) \ - throw std::domain_error( static_cast( std::ostringstream() << msg ).str() ) + throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) #define CATCH_ENFORCE( condition, msg ) \ do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 978ca1a4..eb35ed11 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -36,6 +36,7 @@ #include "catch_tag_alias_registry.hpp" #include "catch_test_case_tracker.hpp" #include "catch_matchers_string.hpp" +#include "catch_startup_exception_registry.hpp" #include "../reporters/catch_reporter_multi.hpp" #include "../reporters/catch_reporter_xml.hpp" diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index fb7d87cf..8934d008 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -22,6 +22,7 @@ namespace Catch { struct IReporterRegistry; struct IReporterFactory; struct ITagAliasRegistry; + class StartupExceptionRegistry; using IReporterFactoryPtr = std::shared_ptr; @@ -33,6 +34,9 @@ namespace Catch { virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + + + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; }; struct IMutableRegistryHub { @@ -42,6 +46,7 @@ namespace Catch { virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; + virtual void registerStartupException( std::exception_ptr const& exception ) = 0; }; IRegistryHub& getRegistryHub(); diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index d51306fd..5e83203f 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -14,6 +14,7 @@ #include "catch_reporter_registry.hpp" #include "catch_exception_translator_registry.hpp" #include "catch_tag_alias_registry.h" +#include "catch_startup_exception_registry.h" namespace Catch { @@ -39,7 +40,9 @@ namespace Catch { virtual ITagAliasRegistry const& getTagAliasRegistry() const override { return m_tagAliasRegistry; } - + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const override { + return m_exceptionRegistry; + } public: // IMutableRegistryHub virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { @@ -57,12 +60,16 @@ namespace Catch { virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { m_tagAliasRegistry.add( alias, tag, lineInfo ); } + virtual void registerStartupException( std::exception_ptr const& exception ) override { + m_exceptionRegistry.add(exception); + } private: TestRegistry m_testCaseRegistry; ReporterRegistry m_reporterRegistry; ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; TagAliasRegistry m_tagAliasRegistry; + StartupExceptionRegistry m_exceptionRegistry; }; // Single, global, instance diff --git a/include/internal/catch_startup_exception_registry.h b/include/internal/catch_startup_exception_registry.h new file mode 100644 index 00000000..ece5e6ca --- /dev/null +++ b/include/internal/catch_startup_exception_registry.h @@ -0,0 +1,27 @@ +/* + * Created by Martin on 04/06/2017. + * Copyright 2017 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) + */ +#ifndef TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_H_INCLUDED +#define TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_H_INCLUDED + + +#include +#include + +namespace Catch { + + class StartupExceptionRegistry { + public: + void add(std::exception_ptr const& exception); + std::vector const& getExceptions() const; + private: + std::vector m_exceptions; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_H_INCLUDED diff --git a/include/internal/catch_startup_exception_registry.hpp b/include/internal/catch_startup_exception_registry.hpp new file mode 100644 index 00000000..caf5d894 --- /dev/null +++ b/include/internal/catch_startup_exception_registry.hpp @@ -0,0 +1,24 @@ +/* + * Created by Martin on 04/06/2017. + * Copyright 2017 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) + */ +#ifndef TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED + +#include "catch_startup_exception_registry.h" + +namespace Catch { + void StartupExceptionRegistry::add( std::exception_ptr const& exception ) { + m_exceptions.push_back(exception); + } + + std::vector const& StartupExceptionRegistry::getExceptions() const { + return m_exceptions; + } + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_tag_alias_registry.hpp b/include/internal/catch_tag_alias_registry.hpp index fef96c35..a078e3ce 100644 --- a/include/internal/catch_tag_alias_registry.hpp +++ b/include/internal/catch_tag_alias_registry.hpp @@ -39,14 +39,29 @@ namespace Catch { } void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { + // Do not throw when constructing global objects, instead register the exception to be processed later + if (!(startsWith( alias, "[@") && endsWith(alias, ']'))) { + getMutableRegistryHub().registerStartupException( + std::make_exception_ptr( + CATCH_PREPARE_EXCEPTION( std::domain_error, + "error: tag alias, '" + << alias + << "' is not of the form [@alias name].\n" + << lineInfo) + ) + ); + } - CATCH_ENFORCE( startsWith( alias, "[@" ) && endsWith( alias, ']' ), - "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); - - CATCH_ENFORCE( m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second, - "error: tag alias, '" << alias << "' already registered.\n" - << "\tFirst seen at: " << find(alias)->lineInfo << "\n" - << "\tRedefined at: " << lineInfo ); + if (!m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second) { + getMutableRegistryHub().registerStartupException( + std::make_exception_ptr( + CATCH_PREPARE_EXCEPTION(std::domain_error, + "error: tag alias, '" << alias << "' already registered.\n" + << "\tFirst seen at: " << find(alias)->lineInfo << "\n" + << "\tRedefined at: " << lineInfo) + ) + ); + } } ITagAliasRegistry::~ITagAliasRegistry() {} diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 32c0e6e9..0af74698 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -14,6 +14,7 @@ #include "catch_common.h" #include +#include namespace Catch { @@ -37,10 +38,16 @@ namespace Catch { return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); } inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - CATCH_ENFORCE( !isReservedTag( tag ), - "Tag name: [" << tag << "] is not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" - << _lineInfo ); + // Do not throw when constructing global objects, instead register the exception to be processed later + if (isReservedTag(tag)) { + getMutableRegistryHub().registerStartupException( + std::make_exception_ptr( + CATCH_PREPARE_EXCEPTION(std::domain_error, "Tag name: [" << tag << "] is not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n" + << _lineInfo) + ) + ); + } } TestCase makeTestCase( ITestCase* _testCase, From 860de28b8d87d97cd2405cecb28fb63fb8c73d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 4 Jun 2017 22:37:59 +0200 Subject: [PATCH 059/398] Catch and register startup exceptions in autoregistrars Previously they were registered where they would be thrown otherwise --- include/internal/catch_tag_alias_registry.hpp | 35 +++++++------------ include/internal/catch_test_case_info.hpp | 14 +++----- .../catch_test_case_registry_impl.hpp | 20 ++++++----- 3 files changed, 28 insertions(+), 41 deletions(-) diff --git a/include/internal/catch_tag_alias_registry.hpp b/include/internal/catch_tag_alias_registry.hpp index a078e3ce..7439c36d 100644 --- a/include/internal/catch_tag_alias_registry.hpp +++ b/include/internal/catch_tag_alias_registry.hpp @@ -39,29 +39,13 @@ namespace Catch { } void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { - // Do not throw when constructing global objects, instead register the exception to be processed later - if (!(startsWith( alias, "[@") && endsWith(alias, ']'))) { - getMutableRegistryHub().registerStartupException( - std::make_exception_ptr( - CATCH_PREPARE_EXCEPTION( std::domain_error, - "error: tag alias, '" - << alias - << "' is not of the form [@alias name].\n" - << lineInfo) - ) - ); - } + CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), + "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); - if (!m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second) { - getMutableRegistryHub().registerStartupException( - std::make_exception_ptr( - CATCH_PREPARE_EXCEPTION(std::domain_error, - "error: tag alias, '" << alias << "' already registered.\n" - << "\tFirst seen at: " << find(alias)->lineInfo << "\n" - << "\tRedefined at: " << lineInfo) - ) - ); - } + CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, + "error: tag alias, '" << alias << "' already registered.\n" + << "\tFirst seen at: " << find(alias)->lineInfo << "\n" + << "\tRedefined at: " << lineInfo ); } ITagAliasRegistry::~ITagAliasRegistry() {} @@ -71,7 +55,12 @@ namespace Catch { } RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); + try { + getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(std::current_exception()); + } } } // end namespace Catch diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 0af74698..8adf40c7 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -38,16 +38,10 @@ namespace Catch { return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); } inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { - // Do not throw when constructing global objects, instead register the exception to be processed later - if (isReservedTag(tag)) { - getMutableRegistryHub().registerStartupException( - std::make_exception_ptr( - CATCH_PREPARE_EXCEPTION(std::domain_error, "Tag name: [" << tag << "] is not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" - << _lineInfo) - ) - ); - } + CATCH_ENFORCE( !isReservedTag(tag), + "Tag name: [" << tag << "] is not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n" + << _lineInfo ); } TestCase makeTestCase( ITestCase* _testCase, diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 5406c543..eebde92c 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -154,14 +154,18 @@ namespace Catch { char const* classOrQualifiedMethodName, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase - ( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); + try { + getMutableRegistryHub().registerTest + (makeTestCase + (testCase, + extractClassName(classOrQualifiedMethodName), + nameAndDesc.name, + nameAndDesc.description, + lineInfo)); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException( std::current_exception() ); + } } void registerTestCaseFunction ( TestFunction function, From 47c8994a61e9bd8f39c34421b5a681f4a0e4e747 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 4 Jun 2017 22:56:57 +0200 Subject: [PATCH 060/398] Inherit from NonCopyable to disable RegisterHub copies --- include/internal/catch_registry_hub.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index 5e83203f..23c9628c 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -20,10 +20,8 @@ namespace Catch { namespace { - class RegistryHub : public IRegistryHub, public IMutableRegistryHub { - - RegistryHub( RegistryHub const& ); - void operator=( RegistryHub const& ); + class RegistryHub : public IRegistryHub, public IMutableRegistryHub, + private NonCopyable { public: // IRegistryHub RegistryHub() { From a6b03031ba56ffda9c2b655ac2d17ed9d49e3659 Mon Sep 17 00:00:00 2001 From: Thomas Sondergaard Date: Tue, 30 May 2017 17:26:46 +0200 Subject: [PATCH 061/398] Use [#filename] tag for junit testcase classname attribute If [#filename] is present in tags, use it for the classname attribute, rather than "global". If the test fixture is present that still takes precedence. --- include/reporters/catch_reporter_junit.hpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index c8f1238e..2b5a9bd5 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -128,6 +128,13 @@ namespace Catch { xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); } + static std::string fileNameTag( const std::set &tags ) { + std::set::const_iterator it = tags.lower_bound("#"); + if( it != tags.end() && !it->empty() && it->front() == '#' ) + return it->substr(1); + return std::string(); + } + void writeTestCase( TestCaseNode const& testCaseNode ) { TestCaseStats const& stats = testCaseNode.value; @@ -139,7 +146,9 @@ namespace Catch { std::string className = stats.testInfo.className; if( className.empty() ) { - className = "global"; + className = fileNameTag(stats.testInfo.tags); + if ( className.empty() ) + className = "global"; } writeSection( className, "", rootSection ); } From 69ff7fcf4243e2b874dda9a8ab34993c31c879f1 Mon Sep 17 00:00:00 2001 From: Thomas Sondergaard Date: Tue, 30 May 2017 21:40:28 +0200 Subject: [PATCH 062/398] Include suite name in junit classname attrib for grouping in jenkins Jenkins groups junit test results by loosely interpreting the classname attribute of the element as a package-qualified java class name such as java.util.String. It ignores the elements in the xml. To organize test results we therefore need to embed the suite name in the classname attribute as if it was a java package name. Fixes #922. --- include/reporters/catch_reporter_junit.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index 2b5a9bd5..5ade59b5 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -150,6 +150,10 @@ namespace Catch { if ( className.empty() ) className = "global"; } + + if ( !m_config->name().empty() ) + className = m_config->name() + "." + className; + writeSection( className, "", rootSection ); } From 1e16be0b9e2d2fb9f72675d344ad028de90471b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 5 Jun 2017 16:49:10 +0200 Subject: [PATCH 063/398] Purge deprecated generators --- CMakeLists.txt | 5 - include/catch.hpp | 1 - include/internal/catch_context.h | 5 - include/internal/catch_context_impl.hpp | 34 ---- include/internal/catch_generators.hpp | 186 ------------------ include/internal/catch_generators_impl.hpp | 84 -------- include/internal/catch_impl.hpp | 3 - .../internal/catch_interfaces_generators.h | 32 --- include/internal/catch_run_context.hpp | 18 +- projects/SelfTest/GeneratorTests.cpp | 42 ---- .../catch_interfaces_generators.cpp | 1 - 11 files changed, 7 insertions(+), 404 deletions(-) delete mode 100644 include/internal/catch_generators.hpp delete mode 100644 include/internal/catch_generators_impl.hpp delete mode 100644 include/internal/catch_interfaces_generators.h delete mode 100644 projects/SelfTest/GeneratorTests.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e581becc..371c487b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,6 @@ set(TEST_SOURCES ${SELF_TEST_DIR}/ConditionTests.cpp ${SELF_TEST_DIR}/EnumToString.cpp ${SELF_TEST_DIR}/ExceptionTests.cpp - ${SELF_TEST_DIR}/GeneratorTests.cpp ${SELF_TEST_DIR}/MessageTests.cpp ${SELF_TEST_DIR}/MiscTests.cpp ${SELF_TEST_DIR}/PartTrackerTests.cpp @@ -83,7 +82,6 @@ set(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_exception.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_generators.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_registry_hub.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp @@ -139,13 +137,10 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_exception_translator_registry.hpp ${HEADER_DIR}/internal/catch_expression_lhs.hpp ${HEADER_DIR}/internal/catch_fatal_condition.hpp - ${HEADER_DIR}/internal/catch_generators.hpp - ${HEADER_DIR}/internal/catch_generators_impl.hpp ${HEADER_DIR}/internal/catch_impl.hpp ${HEADER_DIR}/internal/catch_interfaces_capture.h ${HEADER_DIR}/internal/catch_interfaces_config.h ${HEADER_DIR}/internal/catch_interfaces_exception.h - ${HEADER_DIR}/internal/catch_interfaces_generators.h ${HEADER_DIR}/internal/catch_interfaces_registry_hub.h ${HEADER_DIR}/internal/catch_interfaces_reporter.h ${HEADER_DIR}/internal/catch_interfaces_runner.h diff --git a/include/catch.hpp b/include/catch.hpp index 29132e0d..4fccd7aa 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -33,7 +33,6 @@ #include "internal/catch_test_registry.hpp" #include "internal/catch_capture.hpp" #include "internal/catch_section.h" -#include "internal/catch_generators.hpp" #include "internal/catch_interfaces_exception.h" #include "internal/catch_approx.hpp" #include "internal/catch_matchers_string.h" diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 4dd48a2f..086b75fd 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -8,8 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED -#include "catch_interfaces_generators.h" - #include namespace Catch { @@ -18,7 +16,6 @@ namespace Catch { class Stream; struct IResultCapture; struct IRunner; - struct IGeneratorsForTest; struct IConfig; using IConfigPtr = std::shared_ptr; @@ -29,8 +26,6 @@ namespace Catch { virtual IResultCapture* getResultCapture() = 0; virtual IRunner* getRunner() = 0; - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; - virtual bool advanceGeneratorsForCurrentTest() = 0; virtual IConfigPtr getConfig() const = 0; }; diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index 43210693..10fd30ea 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -18,11 +18,6 @@ namespace Catch { class Context : public IMutableContext, NonCopyable { - public: - virtual ~Context() { - deleteAllValues( m_generatorsByTestName ); - } - public: // IContext virtual IResultCapture* getResultCapture() { return m_resultCapture; @@ -30,15 +25,6 @@ namespace Catch { virtual IRunner* getRunner() { return m_runner; } - virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { - return getGeneratorsForCurrentTest() - .getGeneratorInfo( fileInfo, totalSize ) - .getCurrentIndex(); - } - virtual bool advanceGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - return generators && generators->moveNext(); - } virtual IConfigPtr getConfig() const { return m_config; @@ -58,31 +44,11 @@ namespace Catch { friend IMutableContext& getCurrentMutableContext(); private: - IGeneratorsForTest* findGeneratorsForCurrentTest() { - std::string testName = getResultCapture()->getCurrentTestName(); - - std::map::const_iterator it = - m_generatorsByTestName.find( testName ); - return it != m_generatorsByTestName.end() - ? it->second - : nullptr; - } - - IGeneratorsForTest& getGeneratorsForCurrentTest() { - IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); - if( !generators ) { - std::string testName = getResultCapture()->getCurrentTestName(); - generators = createGeneratorsForTest(); - m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); - } - return *generators; - } private: IConfigPtr m_config; IRunner* m_runner = nullptr; IResultCapture* m_resultCapture = nullptr; - std::map m_generatorsByTestName; }; namespace { diff --git a/include/internal/catch_generators.hpp b/include/internal/catch_generators.hpp deleted file mode 100644 index 71ae5e38..00000000 --- a/include/internal/catch_generators.hpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Created by Phil on 27/01/2011. - * Copyright 2011 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) - */ -#ifndef TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED - -#include "catch_context.h" - -#include -#include -#include - -namespace Catch { - -template -struct IGenerator { - virtual ~IGenerator() {} - virtual T getValue( std::size_t index ) const = 0; - virtual std::size_t size () const = 0; -}; - -template -class BetweenGenerator : public IGenerator { -public: - BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} - - virtual T getValue( std::size_t index ) const { - return m_from+static_cast( index ); - } - - virtual std::size_t size() const { - return static_cast( 1+m_to-m_from ); - } - -private: - - T m_from; - T m_to; -}; - -template -class ValuesGenerator : public IGenerator { -public: - ValuesGenerator(){} - - void add( T value ) { - m_values.push_back( value ); - } - - virtual T getValue( std::size_t index ) const { - return m_values[index]; - } - - virtual std::size_t size() const { - return m_values.size(); - } - -private: - std::vector m_values; -}; - -template -class CompositeGenerator { -public: - CompositeGenerator() : m_totalSize( 0 ) {} - - // *** Move semantics, similar to auto_ptr *** - CompositeGenerator( CompositeGenerator& other ) - : m_fileInfo( other.m_fileInfo ), - m_totalSize( 0 ) - { - move( other ); - } - - CompositeGenerator& setFileInfo( const char* fileInfo ) { - m_fileInfo = fileInfo; - return *this; - } - - ~CompositeGenerator() { - deleteAll( m_composed ); - } - - operator T () const { - size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); - - size_t index = 0; - for( auto generator : m_composed ) - { - if( overallIndex >= index && overallIndex < index + generator->size() ) - { - return generator->getValue( overallIndex-index ); - } - index += generator->size(); - } - CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); - } - - void add( const IGenerator* generator ) { - m_totalSize += generator->size(); - m_composed.push_back( generator ); - } - - CompositeGenerator& then( CompositeGenerator& other ) { - move( other ); - return *this; - } - - CompositeGenerator& then( T value ) { - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( value ); - add( valuesGen ); - return *this; - } - -private: - - void move( CompositeGenerator& other ) { - m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); - m_totalSize += other.m_totalSize; - other.m_composed.clear(); - } - - std::vector*> m_composed; - std::string m_fileInfo; - size_t m_totalSize; -}; - -namespace Generators -{ - template - CompositeGenerator between( T from, T to ) { - CompositeGenerator generators; - generators.add( new BetweenGenerator( from, to ) ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3 ){ - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - generators.add( valuesGen ); - return generators; - } - - template - CompositeGenerator values( T val1, T val2, T val3, T val4 ) { - CompositeGenerator generators; - ValuesGenerator* valuesGen = new ValuesGenerator(); - valuesGen->add( val1 ); - valuesGen->add( val2 ); - valuesGen->add( val3 ); - valuesGen->add( val4 ); - generators.add( valuesGen ); - return generators; - } - -} // end namespace Generators - -using namespace Generators; - -} // end namespace Catch - -#define INTERNAL_CATCH_LINESTR2( line ) #line -#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) - -#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) - -#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED diff --git a/include/internal/catch_generators_impl.hpp b/include/internal/catch_generators_impl.hpp deleted file mode 100644 index 51eb80c4..00000000 --- a/include/internal/catch_generators_impl.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Created by Phil on 28/01/2011. - * Copyright 2011 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) - */ -#ifndef TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED - -#include "catch_interfaces_generators.h" - -#include "catch_common.h" - -#include -#include -#include - -namespace Catch { - - struct GeneratorInfo : IGeneratorInfo { - - GeneratorInfo( std::size_t size ) - : m_size( size ), - m_currentIndex( 0 ) - {} - - bool moveNext() { - if( ++m_currentIndex == m_size ) { - m_currentIndex = 0; - return false; - } - return true; - } - - std::size_t getCurrentIndex() const { - return m_currentIndex; - } - - std::size_t m_size; - std::size_t m_currentIndex; - }; - - /////////////////////////////////////////////////////////////////////////// - - class GeneratorsForTest : public IGeneratorsForTest { - - public: - ~GeneratorsForTest() { - deleteAll( m_generatorsInOrder ); - } - - IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { - std::map::const_iterator it = m_generatorsByName.find( fileInfo ); - if( it == m_generatorsByName.end() ) { - IGeneratorInfo* info = new GeneratorInfo( size ); - m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); - m_generatorsInOrder.push_back( info ); - return *info; - } - return *it->second; - } - - bool moveNext() { - for( auto generator : m_generatorsInOrder ) { - if( generator->moveNext() ) - return true; - } - return false; - } - - private: - std::map m_generatorsByName; - std::vector m_generatorsInOrder; - }; - - IGeneratorsForTest* createGeneratorsForTest() - { - return new GeneratorsForTest(); - } - -} // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index eb35ed11..4843dad6 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -21,7 +21,6 @@ #include "catch_notimplemented_exception.hpp" #include "catch_context_impl.hpp" #include "catch_console_colour_impl.hpp" -#include "catch_generators_impl.hpp" #include "catch_assertionresult.hpp" #include "catch_test_case_info.hpp" #include "catch_test_spec.hpp" @@ -82,8 +81,6 @@ namespace Catch { JunitReporter::~JunitReporter() {} TestRegistry::~TestRegistry() {} FreeFunctionTestCase::~FreeFunctionTestCase() {} - IGeneratorInfo::~IGeneratorInfo() {} - IGeneratorsForTest::~IGeneratorsForTest() {} WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} diff --git a/include/internal/catch_interfaces_generators.h b/include/internal/catch_interfaces_generators.h deleted file mode 100644 index d163d5a1..00000000 --- a/include/internal/catch_interfaces_generators.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Created by Phil on 7/8/2012. - * Copyright 2011 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) - */ -#ifndef TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED -#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED - -#include - -namespace Catch { - - struct IGeneratorInfo { - virtual ~IGeneratorInfo(); - virtual bool moveNext() = 0; - virtual std::size_t getCurrentIndex() const = 0; - }; - - struct IGeneratorsForTest { - virtual ~IGeneratorsForTest(); - - virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; - virtual bool moveNext() = 0; - }; - - IGeneratorsForTest* createGeneratorsForTest(); - -} // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 3d715c46..d262f78c 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -95,19 +95,15 @@ namespace Catch { m_activeTestCase = &testCase; + ITracker& rootTracker = m_trackerContext.startRun(); + assert( rootTracker.isSectionTracker() ); + static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); do { - ITracker& rootTracker = m_trackerContext.startRun(); - assert( rootTracker.isSectionTracker() ); - static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); + runCurrentTest( redirectedCout, redirectedCerr ); } - // !TBD: deprecated - this will be replaced by indexed trackers - while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { diff --git a/projects/SelfTest/GeneratorTests.cpp b/projects/SelfTest/GeneratorTests.cpp deleted file mode 100644 index af08b1d3..00000000 --- a/projects/SelfTest/GeneratorTests.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Created by Phil on 28/01/2011. - * Copyright 2011 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) - */ - -// This define means we have to prefix all the CATCH macros with CATCH_ -// We're using it here to test it out -#define CATCH_CONFIG_PREFIX_ALL -#include "catch.hpp" - -inline int multiply( int a, int b ) -{ - return a*b; -} - -CATCH_TEST_CASE( "Generators over two ranges", "[generators]" ) -{ - using namespace Catch::Generators; - - int i = CATCH_GENERATE( between( 1, 5 ).then( values( 15, 20, 21 ).then( 36 ) ) ); - int j = CATCH_GENERATE( between( 100, 107 ) ); - - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ); - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ); -} - -struct IntPair { int first, second; }; - -CATCH_TEST_CASE( "Generator over a range of pairs", "[generators]" ) -{ - using namespace Catch::Generators; - - IntPair p[] = { { 0, 1 }, { 2, 3 } }; - - IntPair* i = CATCH_GENERATE( between( p, &p[1] ) ); - - CATCH_REQUIRE( i->first == i->second-1 ); - -} diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp deleted file mode 100644 index 2eda9812..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_generators.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "internal/catch_interfaces_generators.h" From b459bb4c431670cb3031a68f4b3cf79f631d0c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 5 Jun 2017 16:59:31 +0200 Subject: [PATCH 064/398] Silence GCC's Wunused-function firing in compilation tests The whole GCC kinda sucks around warnings, this is yet another place where pragmas manipulating warnings don't work properly and thus a warning has to be disabled globally... luckily, this time it is happening in selftest file and thus it isn't too problematic to just turn that warning of for the entire file. --- projects/SelfTest/CompilationTests.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/projects/SelfTest/CompilationTests.cpp b/projects/SelfTest/CompilationTests.cpp index 06d361fb..3298c79e 100644 --- a/projects/SelfTest/CompilationTests.cpp +++ b/projects/SelfTest/CompilationTests.cpp @@ -55,6 +55,11 @@ TEST_CASE("#833") { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" #endif +#ifdef __GNUC__ +// Note that because -~GCC~-, this warning cannot be silenced temporarily, by pushing diagnostic stack... +// Luckily it is firing in test files and thus can be silenced for the whole file, without losing much. +#pragma GCC diagnostic ignored "-Wunused-function" +#endif // Test containing example where original stream insertable check breaks compilation namespace { From 950cae9040d2f1887cbc132828b55cacc742dae7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 5 Jun 2017 18:40:50 +0200 Subject: [PATCH 065/398] Added new assertion macros: `*_THROWS_WITH` It combines `*_THROWS_AS` and `*_THROWS_WITH` macros, so that the exception type matches expectetations and its contents match a specific matcher. --- docs/assertions.md | 7 ++++++- include/catch.hpp | 2 ++ include/internal/catch_capture.hpp | 22 ++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/docs/assertions.md b/docs/assertions.md index 02b4de98..5ff7836c 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -108,8 +108,13 @@ REQUIRE_THROWS_WITH( openThePodBayDoors(), Contains( "afraid" ) && Contains( "ca REQUIRE_THROWS_WITH( dismantleHal(), "My mind is going" ); ``` +* **REQUIRE_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)** and +* **CHECK_THROWS_MATCHES(** _expression_, _exception type_, _matcher for given exception type_ **)** -Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function. +Expects that exception of _exception type_ is thrown and it matches provided matcher (see next section for Matchers). + + +_Please note that the `THROW` family of assertions expects to be passed a single expression, not a statement or series of statements. If you want to check a more complicated sequence of operations, you can use a C++11 lambda function._ ```cpp REQUIRE_NOTHROW([&](){ diff --git a/include/catch.hpp b/include/catch.hpp index 4fccd7aa..65a77b8a 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -168,6 +168,7 @@ LeakDetector leakDetector; #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) @@ -179,6 +180,7 @@ LeakDetector leakDetector; #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 49673309..7816b50c 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -167,4 +167,26 @@ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, expr ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition, #matcher ); \ + if( __catchResult.allowThrows() ) \ + try { \ + static_cast(expr); \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ex ) { \ + __catchResult.captureMatch( ex, matcher, #matcher ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + + + #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED From c465fbd0ea88482ae57c1454e3bb000ece63c532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 5 Jun 2017 18:42:04 +0200 Subject: [PATCH 066/398] Slight documentation improvements --- docs/assertions.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/assertions.md b/docs/assertions.md index 5ff7836c..8c8bd198 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -95,7 +95,7 @@ Expects that an exception (of any type) is be thrown during evaluation of the ex * **REQUIRE_THROWS_AS(** _expression_, _exception type_ **)** and * **CHECK_THROWS_AS(** _expression_, _exception type_ **)** -Expects that an exception of the _specified type_ is thrown during evaluation of the expression. Note that the _exception type_ is used verbatim and you should include (const) reference. +Expects that an exception of the _specified type_ is thrown during evaluation of the expression. Note that the _exception type_ is used verbatim and you should include (const) reference (`const&`). * **REQUIRE_THROWS_WITH(** _expression_, _string or string matcher_ **)** and * **CHECK_THROWS_WITH(** _expression_, _string or string matcher_ **)** @@ -127,6 +127,8 @@ REQUIRE_NOTHROW([&](){ }()); ``` + + ## Matcher expressions To support Matchers a slightly different form is used. Matchers have [their own documentation](matchers.md). From 8fde7abf31a3aa3d37d9802b0b25a5eebbf18378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 5 Jun 2017 19:14:00 +0200 Subject: [PATCH 067/398] Add tests for *_THROWS_MATCHES Closes #641, closes #818 --- projects/SelfTest/MatchersTests.cpp | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/projects/SelfTest/MatchersTests.cpp b/projects/SelfTest/MatchersTests.cpp index 7bcd3cf8..5984eb3a 100644 --- a/projects/SelfTest/MatchersTests.cpp +++ b/projects/SelfTest/MatchersTests.cpp @@ -166,3 +166,60 @@ TEST_CASE( "Vector matchers that fail", "[matchers][vector][.][failing]" ) { CHECK_THAT( v, Equals( empty ) ); } } + +#ifdef _MSC_VER +#pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection +#endif + +#include + +struct SpecialException : std::exception { + SpecialException(int i):i(i) {} + int i; +}; + +void doesNotThrow() {} + +void throws(int i) { + throw SpecialException{ i }; +} + +void throwsAsInt(int i) { + throw i; +} + +class ExceptionMatcher : public Catch::MatcherBase { + int m_expected; +public: + ExceptionMatcher(int i):m_expected(i) {} + virtual bool match(SpecialException const& se) const override { + return se.i == m_expected; + } + + virtual std::string describe() const override { + std::ostringstream ss; + ss << "special exception has value of " << m_expected; + return ss.str(); + } +}; + + +TEST_CASE( "Exception matchers that succeed", "[matchers][exceptions][!throws]" ) { + CHECK_THROWS_MATCHES(throws(1), SpecialException const&, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(throws(2), SpecialException const&, ExceptionMatcher{ 2 }); +} + +TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") { + SECTION("No exception") { + CHECK_THROWS_MATCHES(doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 }); + } + SECTION("Type mismatch") { + CHECK_THROWS_MATCHES(throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 }); + } + SECTION("Contents are wrong") { + CHECK_THROWS_MATCHES(throws(3), SpecialException const&, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(throws(4), SpecialException const&, ExceptionMatcher{ 1 }); + } +} From 47eb9b3d68f33d825e1e9ff7b67ca2cbec7b43c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 6 Jun 2017 15:07:34 +0200 Subject: [PATCH 068/398] Fix #914 being removed during last merge --- include/internal/catch_expression_lhs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 1ac339b4..6173401b 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -81,7 +81,7 @@ public: } virtual void reconstructExpression( std::string& dest ) const override { - dest = ::Catch::Detail::stringify( m_truthy ); + dest = ::Catch::Detail::stringify( m_lhs ); } private: From 07ef028483dca3afad353655a3341be95bfd70be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 6 Jun 2017 15:07:57 +0200 Subject: [PATCH 069/398] Update baselines --- .../Baselines/console.std.approved.txt | 68 +- .../Baselines/console.sw.approved.txt | 1422 ++--------------- .../Baselines/console.swa4.approved.txt | 2 +- .../SelfTest/Baselines/junit.sw.approved.txt | 39 +- .../SelfTest/Baselines/xml.sw.approved.txt | 1300 ++------------- 5 files changed, 315 insertions(+), 2516 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index c35d3bd1..c7b1b566 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -274,6 +274,55 @@ MatchersTests.cpp:: FAILED: with expansion: "this string contains 'abc' as a substring" equals: "something else" +------------------------------------------------------------------------------- +Exception matchers that fail + No exception +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +------------------------------------------------------------------------------- +Exception matchers that fail + Type mismatch +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +------------------------------------------------------------------------------- +Exception matchers that fail + Contents are wrong +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throws(3), SpecialException const&, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throws(4), SpecialException const&, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + ------------------------------------------------------------------------------- Expected exceptions that don't throw or unexpected exceptions fail the test ------------------------------------------------------------------------------- @@ -368,7 +417,9 @@ MessageTests.cpp:: FAILED: CHECK( a == 0 ) with expansion: 2 == 0 -with message: +with messages: + this message may be logged later + this message should be logged and this, but later ------------------------------------------------------------------------------- @@ -593,6 +644,17 @@ MessageTests.cpp:: warning: toString(p): 0x +------------------------------------------------------------------------------- +Reconstruction should be based on stringification: #914 +------------------------------------------------------------------------------- +DecompositionTests.cpp: +............................................................................... + +DecompositionTests.cpp:: FAILED: + CHECK( truthy(false) ) +with expansion: + Hey, its truthy! + ------------------------------------------------------------------------------- SCOPED_INFO is reset for each loop ------------------------------------------------------------------------------- @@ -940,6 +1002,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 170 | 122 passed | 44 failed | 4 failed as expected -assertions: 980 | 872 passed | 87 failed | 21 failed as expected +test cases: 171 | 121 passed | 46 failed | 4 failed as expected +assertions: 843 | 728 passed | 94 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 3b88aaa9..f70bda98 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -119,7 +119,7 @@ with expansion: MiscTests.cpp:: PASSED: - REQUIRE( (*__error()) == 1 ) + REQUIRE( errno == 1 ) with expansion: 1 == 1 @@ -901,7 +901,7 @@ TrickyTests.cpp:: PASSED: REQUIRE( a ) with expansion: - true + 0x TrickyTests.cpp:: PASSED: @@ -1273,6 +1273,73 @@ MatchersTests.cpp:: FAILED: with expansion: "this string contains 'abc' as a substring" equals: "something else" +------------------------------------------------------------------------------- +Exception matchers that fail + No exception +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +------------------------------------------------------------------------------- +Exception matchers that fail + Type mismatch +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +------------------------------------------------------------------------------- +Exception matchers that fail + Contents are wrong +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throws(3), SpecialException const&, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throws(4), SpecialException const&, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +------------------------------------------------------------------------------- +Exception matchers that succeed +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THROWS_MATCHES( throws(1), SpecialException const&, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +MatchersTests.cpp:: +PASSED: + REQUIRE_THROWS_MATCHES( throws(2), SpecialException const&, ExceptionMatcher{ 2 } ) +with expansion: + {?} special exception has value of 2 + ------------------------------------------------------------------------------- Exception messages can be tested for exact match @@ -1406,1326 +1473,6 @@ PASSED: with expansion: 3628800 (0x) == 3628800 (0x) -------------------------------------------------------------------------------- -Generator over a range of pairs -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( i->first == i->second-1 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -Generator over a range of pairs -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( i->first == i->second-1 ) -with expansion: - 2 == 2 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 200 == 200 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 202 == 202 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 204 == 204 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 206 == 206 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 208 == 208 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 210 == 210 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 212 == 212 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 2 == 2 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 4 == 4 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 6 == 6 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 8 == 8 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 10 == 10 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 30 == 30 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 40 == 40 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 42 == 42 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - -------------------------------------------------------------------------------- -Generators over two ranges -------------------------------------------------------------------------------- -GeneratorTests.cpp: -............................................................................... - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( i, 2 ) == i*2 ) -with expansion: - 72 == 72 - -GeneratorTests.cpp:: -PASSED: - CATCH_REQUIRE( multiply( j, 2 ) == j*2 ) -with expansion: - 214 == 214 - ------------------------------------------------------------------------------- Greater-than inequalities with different epsilons ------------------------------------------------------------------------------- @@ -2799,14 +1546,17 @@ MessageTests.cpp:: FAILED: CHECK( a == 1 ) with expansion: 2 == 1 -with message: +with messages: + this message may be logged later this message should be logged MessageTests.cpp:: FAILED: CHECK( a == 0 ) with expansion: 2 == 0 -with message: +with messages: + this message may be logged later + this message should be logged and this, but later MessageTests.cpp:: @@ -2814,7 +1564,10 @@ PASSED: CHECK( a == 2 ) with expansion: 2 == 2 -with message: +with messages: + this message may be logged later + this message should be logged + and this, but later but not this ------------------------------------------------------------------------------- @@ -4647,7 +3400,7 @@ TrickyTests.cpp:: PASSED: CHECK( True ) with expansion: - true + {?} TrickyTests.cpp:: PASSED: @@ -4659,7 +3412,7 @@ TrickyTests.cpp:: PASSED: CHECK_FALSE( False ) with expansion: - !false + !{?} ------------------------------------------------------------------------------- Operators at different namespace levels not hijacked by Koenig lookup @@ -6513,6 +5266,17 @@ TestMain.cpp:: PASSED: REQUIRE_THROWS_WITH( parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) ) +------------------------------------------------------------------------------- +Reconstruction should be based on stringification: #914 +------------------------------------------------------------------------------- +DecompositionTests.cpp: +............................................................................... + +DecompositionTests.cpp:: FAILED: + CHECK( truthy(false) ) +with expansion: + Hey, its truthy! + ------------------------------------------------------------------------------- SCOPED_INFO is reset for each loop ------------------------------------------------------------------------------- @@ -9544,6 +8308,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 170 | 121 passed | 45 failed | 4 failed as expected -assertions: 982 | 872 passed | 89 failed | 21 failed as expected +test cases: 171 | 120 passed | 47 failed | 4 failed as expected +assertions: 845 | 728 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index 6ce6850a..b1cf14f3 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -119,7 +119,7 @@ with expansion: MiscTests.cpp:: PASSED: - REQUIRE( (*__error()) == 1 ) + REQUIRE( errno == 1 ) with expansion: 1 == 1 diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 5de62625..9e37840d 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -192,6 +192,33 @@ ConditionTests.cpp: MatchersTests.cpp: + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + +Unknown exception +MatchersTests.cpp: + + +Unknown exception +MatchersTests.cpp: + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + @@ -226,8 +253,6 @@ MessageTests.cpp: - - @@ -239,10 +264,13 @@ MessageTests.cpp: +this message may be logged later this message should be logged MessageTests.cpp: +this message may be logged later +this message should be logged and this, but later MessageTests.cpp: @@ -442,6 +470,11 @@ MessageTests.cpp: + + +DecompositionTests.cpp: + + current counter 10 diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index efbd8763..130cda8a 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -128,7 +128,7 @@ - (*__error()) == 1 + errno == 1 1 == 1 @@ -1003,7 +1003,7 @@ a - true + 0x @@ -1455,6 +1455,91 @@ + +
+ + + doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + + + doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + + + + + doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + + + doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + + + +
+
+ + + throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + + + throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + + + Unknown exception + + + + + throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + + + throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + + + Unknown exception + + + +
+
+ + + throws(3), SpecialException const&, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + + + throws(4), SpecialException const&, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + +
+ +
+ + + + throws(1), SpecialException const&, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + + + throws(2), SpecialException const&, ExceptionMatcher{ 2 } + + + {?} special exception has value of 2 + + + +
@@ -1610,1180 +1695,6 @@ - - - - i->first == i->second-1 - - - 0 == 0 - - - - - i->first == i->second-1 - - - 2 == 2 - - - - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 200 == 200 - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 202 == 202 - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 204 == 204 - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 206 == 206 - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 208 == 208 - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 210 == 210 - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 212 == 212 - - - - - multiply( i, 2 ) == i*2 - - - 2 == 2 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 4 == 4 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 6 == 6 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 8 == 8 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 10 == 10 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 30 == 30 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 40 == 40 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 42 == 42 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - - multiply( i, 2 ) == i*2 - - - 72 == 72 - - - - - multiply( j, 2 ) == j*2 - - - 214 == 214 - - - - @@ -2857,6 +1768,9 @@ 2 == 2 + + this message may be logged later + this message should be logged @@ -2868,6 +1782,12 @@ 2 == 1 + + this message may be logged later + + + this message should be logged + and this, but later @@ -2879,6 +1799,15 @@ 2 == 0 + + this message may be logged later + + + this message should be logged + + + and this, but later + but not this @@ -4790,7 +3719,7 @@ re>" True - true + {?} @@ -4806,7 +3735,7 @@ re>" !False - !false + !{?} @@ -7007,6 +5936,17 @@ re>"
+ + + + truthy(false) + + + Hey, its truthy! + + + + current counter 0 @@ -10226,7 +9166,7 @@ spanner - + - + From 6583284731e961065f007782eb89be41e6ef4e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 6 Jun 2017 15:12:03 +0200 Subject: [PATCH 070/398] Fix erroneous result disposition for {REQUIRE,CHECK}_THAT This fixes result disposition being ContinueOnFailure | ContinueOnFailure for CHECK_THAT (obviously an error) and Normal | ContinueOnFailure for REQUIRE_THAT (less obviously an error, but worse, as that signals to the pipeline that assertion failure should both abort and continue the test with ???? happening). --- include/internal/catch_capture.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 7816b50c..b25f13e8 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -162,7 +162,7 @@ try { \ __catchResult.captureMatch( arg, matcher, #matcher ); \ } catch( ... ) { \ - __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + __catchResult.useActiveException( resultDisposition ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) From b6d9976fbb3f67f5a6b3b48dec9de3f1c2b76a3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 6 Jun 2017 16:32:45 +0200 Subject: [PATCH 071/398] Make generateSingleHeader.py Python 2.7 compatible --- scripts/generateSingleHeader.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index bef63b09..bb267ff5 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -36,8 +36,11 @@ for arg in sys.argv[1:]: print( "\n** Unrecognised argument: " + arg + " **\n" ) exit(1) -# ensure that the output directory exists -os.makedirs(os.path.dirname(outputPath), exist_ok = True) + +# ensure that the output directory exists (hopefully no races) +outDir = os.path.dirname(outputPath) +if not os.path.exists(outDir): + os.makedirs(outDir) out = open( outputPath, 'w' ) ifdefs = 0 implIfDefs = -1 From 6d9171aadb884de187bacc486fed8ca0105c03f5 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 12 Jun 2017 22:30:33 +0100 Subject: [PATCH 072/398] Updated approvals following Junit changes --- .../SelfTest/Baselines/junit.sw.approved.txt | 600 +++++++++--------- 1 file changed, 300 insertions(+), 300 deletions(-) diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 9e37840d..8f2cd749 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,31 +1,31 @@ - - + + expected exception answer := 42 ExceptionTests.cpp: - + expected exception answer := 42 ExceptionTests.cpp: - - - - + + + + MiscTests.cpp: - - + + ConditionTests.cpp: @@ -51,32 +51,32 @@ ConditionTests.cpp: ConditionTests.cpp: - - - - - - - + + + + + + + ClassTests.cpp: - - + + ClassTests.cpp: - - + + to infinity and beyond MiscTests.cpp: - - + + TrickyTests.cpp: @@ -84,67 +84,67 @@ TrickyTests.cpp: TrickyTests.cpp: - - - - + + + + unexpected exception ExceptionTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + MatchersTests.cpp: - + custom exception - not std ExceptionTests.cpp: - + custom exception - not std ExceptionTests.cpp: - + custom std exception ExceptionTests.cpp: - - + + MatchersTests.cpp: - + ConditionTests.cpp: @@ -185,14 +185,14 @@ ConditionTests.cpp: ConditionTests.cpp: - - - + + + MatchersTests.cpp: - + MatchersTests.cpp: @@ -200,7 +200,7 @@ MatchersTests.cpp: MatchersTests.cpp: - + Unknown exception MatchersTests.cpp: @@ -210,7 +210,7 @@ Unknown exception MatchersTests.cpp: - + MatchersTests.cpp: @@ -218,11 +218,11 @@ MatchersTests.cpp: MatchersTests.cpp: - - - - - + + + + + expected exception ExceptionTests.cpp: @@ -235,34 +235,34 @@ expected exception ExceptionTests.cpp: - + This is a failure MessageTests.cpp: - + MessageTests.cpp: - + This is a failure MessageTests.cpp: - - - - + + + + this message should be logged so should this MessageTests.cpp: - + this message may be logged later this message should be logged @@ -275,7 +275,7 @@ and this, but later MessageTests.cpp: - + ConditionTests.cpp: @@ -292,54 +292,54 @@ ConditionTests.cpp: ConditionTests.cpp: - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + MatchersTests.cpp: - - + + MatchersTests.cpp: - + ExceptionTests.cpp: - - + + custom exception ExceptionTests.cpp: - - - - + + + + ConditionTests.cpp: @@ -398,102 +398,102 @@ ConditionTests.cpp: ConditionTests.cpp: - - + + Message from section one MessageTests.cpp: - + Message from section two MessageTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DecompositionTests.cpp: - + current counter 10 i := 10 MessageTests.cpp: - - - - - - - - - - - - + + + + + + + + + + + + A string sent directly to stdout @@ -501,26 +501,26 @@ A string sent directly to stdout A string sent directly to stderr - - + + Message from section one Message from section two - + MatchersTests.cpp: - - + + hello hello - + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + 3.14 ExceptionTests.cpp: - - - - - - + + + + + + MatchersTests.cpp: @@ -575,7 +575,7 @@ MatchersTests.cpp: MatchersTests.cpp: - + MatchersTests.cpp: @@ -583,7 +583,7 @@ MatchersTests.cpp: MatchersTests.cpp: - + MatchersTests.cpp: @@ -597,55 +597,55 @@ MatchersTests.cpp: MatchersTests.cpp: - - + + unexpected exception ExceptionTests.cpp: - + expected exception ExceptionTests.cpp: - + expected exception ExceptionTests.cpp: - + expected exception ExceptionTests.cpp: - + unexpected exception ExceptionTests.cpp: - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + MiscTests.cpp: @@ -653,8 +653,8 @@ MiscTests.cpp: MiscTests.cpp: - - + + MiscTests.cpp: @@ -662,23 +662,23 @@ MiscTests.cpp: MiscTests.cpp: - - - - - - + + + + + + Previous info should not be seen MessageTests.cpp: - + MiscTests.cpp: - + Testing if fib[0] (1) is even MiscTests.cpp: @@ -704,70 +704,70 @@ Testing if fib[7] (21) is even MiscTests.cpp: - + MiscTests.cpp: - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + 3 MiscTests.cpp: - + hi i := 7 MessageTests.cpp: - - - - + + + + TrickyTests.cpp: - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + A string sent directly to stdout Message from section one From 1c223b63ba8cf02be256ddb33c2ac336737adeb6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 12 Jun 2017 23:04:24 +0100 Subject: [PATCH 073/398] Integrated (all) new version of Clara --- CMakeLists.txt | 2 +- include/catch_session.hpp | 46 +- include/external/clara.h | 1054 --------------------- include/external/clara.hpp | 1189 ++++++++++++++++++++++++ include/internal/catch_clara.h | 5 +- include/internal/catch_commandline.hpp | 294 +++--- projects/SelfTest/TestMain.cpp | 293 +++--- 7 files changed, 1465 insertions(+), 1418 deletions(-) delete mode 100644 include/external/clara.h create mode 100644 include/external/clara.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0526ae0f..be37e4d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,7 +112,7 @@ CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR}) # Please keep these ordered alphabetically set(EXTERNAL_HEADERS - ${HEADER_DIR}/external/clara.h + ${HEADER_DIR}/external/clara.hpp ${HEADER_DIR}/external/tbc_text_format.h ) CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 486d093a..9b1d1e87 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -96,17 +96,14 @@ namespace Catch { } class Session : NonCopyable { - static bool alreadyInstantiated; - public: - struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; - - Session() - : m_cli( makeCommandLineParser() ) { + Session() { + static bool alreadyInstantiated = false; if( alreadyInstantiated ) CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); alreadyInstantiated = true; + m_cli = makeCommandLineParser( m_configData ); } ~Session() { Catch::cleanUp(); @@ -115,29 +112,27 @@ namespace Catch { void showHelp( std::string const& processName ) { Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; - m_cli.usage( Catch::cout(), processName ); + Catch::cout() << m_cli << std::endl; Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } - int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { - try { - m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); - if( m_configData.showHelp ) - showHelp( m_configData.processName ); - m_config.reset(); - } - catch( std::exception& ex ) { + int applyCommandLine( int argc, char* argv[] ) { + auto result = m_cli.parse( clara::Args( argc, argv ) ); + if( !result ) { { Colour colourGuard( Colour::Red ); Catch::cerr() << "\nError(s) in input:\n" - << Text( ex.what(), TextAttributes().setIndent(2) ) + << Text( result.errorMessage(), TextAttributes().setIndent(2) ) << "\n\n"; } - m_cli.usage( Catch::cout(), m_configData.processName ); + Catch::cerr() << m_cli << std::endl; return (std::numeric_limits::max)(); } + + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); return 0; } @@ -146,7 +141,7 @@ namespace Catch { m_config.reset(); } - int run( int argc, char const* const* const argv ) { + int run( int argc, char* argv[] ) { const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); if ( !exceptions.empty() ) { Catch::cerr() << "Errors occured during startup!" << '\n'; @@ -167,7 +162,7 @@ namespace Catch { } #if defined(WIN32) && defined(UNICODE) - int run( int argc, wchar_t const* const* const argv ) { + int run( int argc, wchar_t* const argv[] ) { char **utf8Argv = new char *[ argc ]; @@ -217,11 +212,11 @@ namespace Catch { } } - Clara::CommandLine const& cli() const { + clara::Parser const& cli() const { return m_cli; } - std::vector const& unusedTokens() const { - return m_unusedTokens; + void cli( clara::Parser const& newParser ) { + m_cli = newParser; } ConfigData& configData() { return m_configData; @@ -232,14 +227,11 @@ namespace Catch { return *m_config; } private: - Clara::CommandLine m_cli; - std::vector m_unusedTokens; + clara::Parser m_cli; ConfigData m_configData; std::shared_ptr m_config; }; - bool Session::alreadyInstantiated = false; - } // end namespace Catch #endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED diff --git a/include/external/clara.h b/include/external/clara.h deleted file mode 100644 index bf758eb5..00000000 --- a/include/external/clara.h +++ /dev/null @@ -1,1054 +0,0 @@ -/* - * Created by Phil on 25/05/2013. - * Copyright 2013 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) - */ - -// Version 0.0.2.4 - -// Only use header guard if we are not using an outer namespace -#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) - -#ifndef STITCH_CLARA_OPEN_NAMESPACE -#define TWOBLUECUBES_CLARA_H_INCLUDED -#define STITCH_CLARA_OPEN_NAMESPACE -#define STITCH_CLARA_CLOSE_NAMESPACE -#else -#define STITCH_CLARA_CLOSE_NAMESPACE } -#endif - - -#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE - -// ----------- #included from tbc_text_format.h ----------- - -/* - * Created by Phil on 18/4/2013. - * Copyright 2013 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) - */ -// Only use header guard if we are not using an outer namespace -#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) -#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -#define TBC_TEXT_FORMAT_H_INCLUDED -#endif - -#include -#include -#include -#include -#include - -// Use optional outer namespace -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ), - tabChar( '\t' ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - char tabChar; // If this char is seen the indent is changed to current pos - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::string wrappableChars = " [({.,/|\\-"; - std::size_t indent = _attr.initialIndent != std::string::npos - ? _attr.initialIndent - : _attr.indent; - std::string remainder = _str; - - while( !remainder.empty() ) { - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - std::size_t tabPos = std::string::npos; - std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); - std::size_t pos = remainder.find_first_of( '\n' ); - if( pos <= width ) { - width = pos; - } - pos = remainder.find_last_of( _attr.tabChar, width ); - if( pos != std::string::npos ) { - tabPos = pos; - if( remainder[width] == '\n' ) - width--; - remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); - } - - if( width == remainder.size() ) { - spliceLine( indent, remainder, width ); - } - else if( remainder[width] == '\n' ) { - spliceLine( indent, remainder, width ); - if( width <= 1 || remainder.size() != 1 ) - remainder = remainder.substr( 1 ); - indent = _attr.indent; - } - else { - pos = remainder.find_last_of( wrappableChars, width ); - if( pos != std::string::npos && pos > 0 ) { - spliceLine( indent, remainder, pos ); - if( remainder[0] == ' ' ) - remainder = remainder.substr( 1 ); - } - else { - spliceLine( indent, remainder, width-1 ); - lines.back() += "-"; - } - if( lines.size() == 1 ) - indent = _attr.indent; - if( tabPos != std::string::npos ) - indent += tabPos; - } - } - } - - void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { - lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); - _remainder = _remainder.substr( _pos ); - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - private: - std::string str; - TextAttributes attr; - std::vector lines; - }; - -} // end namespace Tbc - -#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TBC_TEXT_FORMAT_H_INCLUDED - -// ----------- end of #include from tbc_text_format.h ----------- -// ........... back in clara.h - -#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE - - -// ----------- #included from clara_compilers.h ----------- - -/* - * Created by Phil on 10/02/2016. - * Copyright 2016 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) - */ -#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED -#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - -// Detect a number of compiler features - mostly C++11/14 conformance - by compiler -// The following features are defined: -// -// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? -// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? -// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods -// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? -// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) - -// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? - -// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? - -// In general each macro has a _NO_ form -// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 - -#ifdef __clang__ - -#if __has_feature(cxx_nullptr) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#if __has_feature(cxx_noexcept) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -// - otherwise more recent versions define __cplusplus >= 201103L -// and will get picked up below - -#endif // __GNUC__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#ifdef _MSC_VER - -#if (_MSC_VER >= 1600) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - -#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#endif // _MSC_VER - - -//////////////////////////////////////////////////////////////////////////////// -// C++ language feature support - -// catch all support for C++11 -#if defined(__cplusplus) && __cplusplus >= 201103L - -#define CLARA_CPP11_OR_GREATER - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) -#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT -#endif - -#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS -#endif - -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) -#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE -#endif -#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) -#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR -#endif - - -#endif // __cplusplus >= 201103L - -// Now set the actual defines based on the above + anything the user has configured -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NULLPTR -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_NOEXCEPT -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_GENERATED_METHODS -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_OVERRIDE -#endif -#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) -#define CLARA_CONFIG_CPP11_UNIQUE_PTR -#endif - - -// noexcept support: -#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) -#define CLARA_NOEXCEPT noexcept -# define CLARA_NOEXCEPT_IS(x) noexcept(x) -#else -#define CLARA_NOEXCEPT throw() -# define CLARA_NOEXCEPT_IS(x) -#endif - -// nullptr support -#ifdef CLARA_CONFIG_CPP11_NULLPTR -#define CLARA_NULL nullptr -#else -#define CLARA_NULL NULL -#endif - -// override support -#ifdef CLARA_CONFIG_CPP11_OVERRIDE -#define CLARA_OVERRIDE override -#else -#define CLARA_OVERRIDE -#endif - -// unique_ptr support -#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR -# define CLARA_AUTO_PTR( T ) std::unique_ptr -#else -# define CLARA_AUTO_PTR( T ) std::auto_ptr -#endif - -#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED - - -// ----------- end of #include from clara_compilers.h ----------- -// ........... back in clara.h - - -#include -#include -#include - -#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define CLARA_PLATFORM_WINDOWS -#endif - - -// Use optional outer namespace -#ifdef STITCH_CLARA_OPEN_NAMESPACE -STITCH_CLARA_OPEN_NAMESPACE -#endif - -namespace Clara { - - struct UnpositionalTag {}; - - extern UnpositionalTag _; - -#ifdef CLARA_CONFIG_MAIN - UnpositionalTag _; -#endif - - namespace Detail { - -#ifdef CLARA_CONSOLE_WIDTH - const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - using namespace Tbc; - - inline bool startsWith( std::string const& str, std::string const& prefix ) { - return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; - } - - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - template struct RemoveConstRef{ typedef T type; }; - - template struct IsBool { static const bool value = false; }; - template<> struct IsBool { static const bool value = true; }; - - template - void convertInto( std::string const& _source, T& _dest ) { - std::stringstream ss; - ss << _source; - ss >> _dest; - if( ss.fail() ) - throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); - } - inline void convertInto( std::string const& _source, std::string& _dest ) { - _dest = _source; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - inline void convertInto( std::string const& _source, bool& _dest ) { - std::string sourceLC = _source; - std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); - if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) - _dest = true; - else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) - _dest = false; - else - throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); - } - - - template - struct IArgFunction { - virtual ~IArgFunction() {} -#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS - IArgFunction() = default; - IArgFunction( IArgFunction const& ) = default; -#endif - virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual bool takesArg() const = 0; - virtual IArgFunction* clone() const = 0; - }; - - template - class BoundArgFunction { - public: - BoundArgFunction() : functionObj( CLARA_NULL ) {} - BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} - BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; - delete functionObj; - functionObj = newFunctionObj; - return *this; - } - ~BoundArgFunction() { delete functionObj; } - - void set( ConfigT& config, std::string const& value ) const { - functionObj->set( config, value ); - } - bool takesArg() const { return functionObj->takesArg(); } - - bool isSet() const { - return functionObj != CLARA_NULL; - } - private: - IArgFunction* functionObj; - }; - - - template - struct NullBinder : IArgFunction{ - virtual void set( C&, std::string const& ) const {} - virtual bool takesArg() const { return true; } - virtual IArgFunction* clone() const { return new NullBinder( *this ); } - }; - - template - struct BoundDataMember : IArgFunction{ - BoundDataMember( M C::* _member ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - convertInto( stringValue, p.*member ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } - M C::* member; - }; - template - struct BoundUnaryMethod : IArgFunction{ - BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - (p.*member)( value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } - void (C::*member)( M ); - }; - template - struct BoundNullaryMethod : IArgFunction{ - BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} - virtual void set( C& p, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - (p.*member)(); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } - void (C::*member)(); - }; - - template - struct BoundUnaryFunction : IArgFunction{ - BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - bool value; - convertInto( stringValue, value ); - if( value ) - function( obj ); - } - virtual bool takesArg() const { return false; } - virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } - void (*function)( C& ); - }; - - template - struct BoundBinaryFunction : IArgFunction{ - BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} - virtual void set( C& obj, std::string const& stringValue ) const { - typename RemoveConstRef::type value; - convertInto( stringValue, value ); - function( obj, value ); - } - virtual bool takesArg() const { return !IsBool::value; } - virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } - void (*function)( C&, T ); - }; - - } // namespace Detail - - inline std::vector argsToVector( int argc, char const* const* const argv ) { - std::vector args( static_cast( argc ) ); - for( std::size_t i = 0; i < static_cast( argc ); ++i ) - args[i] = argv[i]; - - return args; - } - - class Parser { - enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; - Mode mode; - std::size_t from; - bool inQuotes; - public: - - struct Token { - enum Type { Positional, ShortOpt, LongOpt }; - Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} - Type type; - std::string data; - }; - - Parser() : mode( None ), from( 0 ), inQuotes( false ){} - - void parseIntoTokens( std::vector const& args, std::vector& tokens ) { - const std::string doubleDash = "--"; - for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) - parseIntoTokens( args[i], tokens); - } - - void parseIntoTokens( std::string const& arg, std::vector& tokens ) { - for( std::size_t i = 0; i < arg.size(); ++i ) { - char c = arg[i]; - if( c == '"' ) - inQuotes = !inQuotes; - mode = handleMode( i, c, arg, tokens ); - } - mode = handleMode( arg.size(), '\0', arg, tokens ); - } - Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - switch( mode ) { - case None: return handleNone( i, c ); - case MaybeShortOpt: return handleMaybeShortOpt( i, c ); - case ShortOpt: - case LongOpt: - case SlashOpt: return handleOpt( i, c, arg, tokens ); - case Positional: return handlePositional( i, c, arg, tokens ); - default: throw std::logic_error( "Unknown mode" ); - } - } - - Mode handleNone( std::size_t i, char c ) { - if( inQuotes ) { - from = i; - return Positional; - } - switch( c ) { - case '-': return MaybeShortOpt; -#ifdef CLARA_PLATFORM_WINDOWS - case '/': from = i+1; return SlashOpt; -#endif - default: from = i; return Positional; - } - } - Mode handleMaybeShortOpt( std::size_t i, char c ) { - switch( c ) { - case '-': from = i+1; return LongOpt; - default: from = i; return ShortOpt; - } - } - - Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) - return mode; - - std::string optName = arg.substr( from, i-from ); - if( mode == ShortOpt ) - for( std::size_t j = 0; j < optName.size(); ++j ) - tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); - else if( mode == SlashOpt && optName.size() == 1 ) - tokens.push_back( Token( Token::ShortOpt, optName ) ); - else - tokens.push_back( Token( Token::LongOpt, optName ) ); - return None; - } - Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { - if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) - return mode; - - std::string data = arg.substr( from, i-from ); - tokens.push_back( Token( Token::Positional, data ) ); - return None; - } - }; - - template - struct CommonArgProperties { - CommonArgProperties() {} - CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} - - Detail::BoundArgFunction boundField; - std::string description; - std::string detail; - std::string placeholder; // Only value if boundField takes an arg - - bool takesArg() const { - return !placeholder.empty(); - } - void validate() const { - if( !boundField.isSet() ) - throw std::logic_error( "option not bound" ); - } - }; - struct OptionArgProperties { - std::vector shortNames; - std::string longName; - - bool hasShortName( std::string const& shortName ) const { - return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); - } - bool hasLongName( std::string const& _longName ) const { - return _longName == longName; - } - }; - struct PositionalArgProperties { - PositionalArgProperties() : position( -1 ) {} - int position; // -1 means non-positional (floating) - - bool isFixedPositional() const { - return position != -1; - } - }; - - template - class CommandLine { - - struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { - Arg() {} - Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} - - using CommonArgProperties::placeholder; // !TBD - - std::string dbgName() const { - if( !longName.empty() ) - return "--" + longName; - if( !shortNames.empty() ) - return "-" + shortNames[0]; - return "positional args"; - } - std::string commands() const { - std::ostringstream oss; - bool first = true; - std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); - for(; it != itEnd; ++it ) { - if( first ) - first = false; - else - oss << ", "; - oss << "-" << *it; - } - if( !longName.empty() ) { - if( !first ) - oss << ", "; - oss << "--" << longName; - } - if( !placeholder.empty() ) - oss << " <" << placeholder << ">"; - return oss.str(); - } - }; - - typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; - - friend void addOptName( Arg& arg, std::string const& optName ) - { - if( optName.empty() ) - return; - if( Detail::startsWith( optName, "--" ) ) { - if( !arg.longName.empty() ) - throw std::logic_error( "Only one long opt may be specified. '" - + arg.longName - + "' already specified, now attempting to add '" - + optName + "'" ); - arg.longName = optName.substr( 2 ); - } - else if( Detail::startsWith( optName, "-" ) ) - arg.shortNames.push_back( optName.substr( 1 ) ); - else - throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); - } - friend void setPositionalArg( Arg& arg, int position ) - { - arg.position = position; - } - - - class ArgBuilder { - public: - ArgBuilder( Arg* arg ) : m_arg( arg ) {} - - // Bind a non-boolean data member (requires placeholder string) - template - void bind( M C::* field, std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - m_arg->placeholder = placeholder; - } - // Bind a boolean data member (no placeholder required) - template - void bind( bool C::* field ) { - m_arg->boundField = new Detail::BoundDataMember( field ); - } - - // Bind a method taking a single, non-boolean argument (requires a placeholder string) - template - void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - m_arg->placeholder = placeholder; - } - - // Bind a method taking a single, boolean argument (no placeholder string required) - template - void bind( void (C::* unaryMethod)( bool ) ) { - m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); - } - - // Bind a method that takes no arguments (will be called if opt is present) - template - void bind( void (C::* nullaryMethod)() ) { - m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); - } - - // Bind a free function taking a single argument - the object to operate on (no placeholder string required) - template - void bind( void (* unaryFunction)( C& ) ) { - m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); - } - - // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) - template - void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { - m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); - m_arg->placeholder = placeholder; - } - - ArgBuilder& describe( std::string const& description ) { - m_arg->description = description; - return *this; - } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; - return *this; - } - - protected: - Arg* m_arg; - }; - - class OptBuilder : public ArgBuilder { - public: - OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} - OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} - - OptBuilder& operator[]( std::string const& optName ) { - addOptName( *ArgBuilder::m_arg, optName ); - return *this; - } - }; - - public: - - CommandLine() - : m_boundProcessName( new Detail::NullBinder() ), - m_highestSpecifiedArgPosition( 0 ), - m_throwOnUnrecognisedTokens( false ) - {} - CommandLine( CommandLine const& other ) - : m_boundProcessName( other.m_boundProcessName ), - m_options ( other.m_options ), - m_positionalArgs( other.m_positionalArgs ), - m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), - m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) - { - if( other.m_floatingArg.get() ) - m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); - } - - CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { - m_throwOnUnrecognisedTokens = shouldThrow; - return *this; - } - - - OptBuilder operator[]( std::string const& optName ) { - m_options.push_back( Arg() ); - addOptName( m_options.back(), optName ); - OptBuilder builder( &m_options.back() ); - return builder; - } - - ArgBuilder operator[]( int position ) { - m_positionalArgs.insert( std::make_pair( position, Arg() ) ); - if( position > m_highestSpecifiedArgPosition ) - m_highestSpecifiedArgPosition = position; - setPositionalArg( m_positionalArgs[position], position ); - ArgBuilder builder( &m_positionalArgs[position] ); - return builder; - } - - // Invoke this with the _ instance - ArgBuilder operator[]( UnpositionalTag ) { - if( m_floatingArg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_floatingArg.reset( new Arg() ); - ArgBuilder builder( m_floatingArg.get() ); - return builder; - } - - template - void bindProcessName( M C::* field ) { - m_boundProcessName = new Detail::BoundDataMember( field ); - } - template - void bindProcessName( void (C::*_unaryMethod)( M ) ) { - m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); - } - - void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { - typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; - std::size_t maxWidth = 0; - for( it = itBegin; it != itEnd; ++it ) - maxWidth = (std::max)( maxWidth, it->commands().size() ); - - for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() - .setWidth( maxWidth+indent ) - .setIndent( indent ) ); - Detail::Text desc( it->description, Detail::TextAttributes() - .setWidth( width - maxWidth - 3 ) ); - - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; - os << usageCol; - - if( i < desc.size() && !desc[i].empty() ) - os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) - << desc[i]; - os << "\n"; - } - } - } - std::string optUsage() const { - std::ostringstream oss; - optUsage( oss ); - return oss.str(); - } - - void argSynopsis( std::ostream& os ) const { - for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { - if( i > 1 ) - os << " "; - typename std::map::const_iterator it = m_positionalArgs.find( i ); - if( it != m_positionalArgs.end() ) - os << "<" << it->second.placeholder << ">"; - else if( m_floatingArg.get() ) - os << "<" << m_floatingArg->placeholder << ">"; - else - throw std::logic_error( "non consecutive positional arguments with no floating args" ); - } - // !TBD No indication of mandatory args - if( m_floatingArg.get() ) { - if( m_highestSpecifiedArgPosition > 1 ) - os << " "; - os << "[<" << m_floatingArg->placeholder << "> ...]"; - } - } - std::string argSynopsis() const { - std::ostringstream oss; - argSynopsis( oss ); - return oss.str(); - } - - void usage( std::ostream& os, std::string const& procName ) const { - validate(); - os << "usage:\n " << procName << " "; - argSynopsis( os ); - if( !m_options.empty() ) { - os << " [options]\n\nwhere options are: \n"; - optUsage( os, 2 ); - } - os << "\n"; - } - std::string usage( std::string const& procName ) const { - std::ostringstream oss; - usage( oss, procName ); - return oss.str(); - } - - ConfigT parse( std::vector const& args ) const { - ConfigT config; - parseInto( args, config ); - return config; - } - - std::vector parseInto( std::vector const& args, ConfigT& config ) const { - std::string processName = args.empty() ? std::string() : args[0]; - std::size_t lastSlash = processName.find_last_of( "/\\" ); - if( lastSlash != std::string::npos ) - processName = processName.substr( lastSlash+1 ); - m_boundProcessName.set( config, processName ); - std::vector tokens; - Parser parser; - parser.parseIntoTokens( args, tokens ); - return populate( tokens, config ); - } - - std::vector populate( std::vector const& tokens, ConfigT& config ) const { - validate(); - std::vector unusedTokens = populateOptions( tokens, config ); - unusedTokens = populateFixedArgs( unusedTokens, config ); - unusedTokens = populateFloatingArgs( unusedTokens, config ); - return unusedTokens; - } - - std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - std::vector errors; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); - for(; it != itEnd; ++it ) { - Arg const& arg = *it; - - try { - if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || - ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { - if( arg.takesArg() ) { - if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) - errors.push_back( "Expected argument to option: " + token.data ); - else - arg.boundField.set( config, tokens[++i].data ); - } - else { - arg.boundField.set( config, "true" ); - } - break; - } - } - catch( std::exception& ex ) { - errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); - } - } - if( it == itEnd ) { - if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) - unusedTokens.push_back( token ); - else if( errors.empty() && m_throwOnUnrecognisedTokens ) - errors.push_back( "unrecognised option: " + token.data ); - } - } - if( !errors.empty() ) { - std::ostringstream oss; - for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); - it != itEnd; - ++it ) { - if( it != errors.begin() ) - oss << "\n"; - oss << *it; - } - throw std::runtime_error( oss.str() ); - } - return unusedTokens; - } - std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { - std::vector unusedTokens; - int position = 1; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - typename std::map::const_iterator it = m_positionalArgs.find( position ); - if( it != m_positionalArgs.end() ) - it->second.boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - if( token.type == Parser::Token::Positional ) - position++; - } - return unusedTokens; - } - std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { - if( !m_floatingArg.get() ) - return tokens; - std::vector unusedTokens; - for( std::size_t i = 0; i < tokens.size(); ++i ) { - Parser::Token const& token = tokens[i]; - if( token.type == Parser::Token::Positional ) - m_floatingArg->boundField.set( config, token.data ); - else - unusedTokens.push_back( token ); - } - return unusedTokens; - } - - void validate() const - { - if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) - throw std::logic_error( "No options or arguments specified" ); - - for( typename std::vector::const_iterator it = m_options.begin(), - itEnd = m_options.end(); - it != itEnd; ++it ) - it->validate(); - } - - private: - Detail::BoundArgFunction m_boundProcessName; - std::vector m_options; - std::map m_positionalArgs; - ArgAutoPtr m_floatingArg; - int m_highestSpecifiedArgPosition; - bool m_throwOnUnrecognisedTokens; - }; - -} // end namespace Clara - - -STITCH_CLARA_CLOSE_NAMESPACE -#undef STITCH_CLARA_OPEN_NAMESPACE -#undef STITCH_CLARA_CLOSE_NAMESPACE - - -#endif // TWOBLUECUBES_CLARA_H_INCLUDED diff --git a/include/external/clara.hpp b/include/external/clara.hpp new file mode 100644 index 00000000..1c0a6884 --- /dev/null +++ b/include/external/clara.hpp @@ -0,0 +1,1189 @@ +// v1.0 +// See https://github.com/philsquared/Clara + +#ifndef CATCH_CLARA_HPP_INCLUDED +#define CATCH_CLARA_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +#ifndef CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { +namespace clara { + +// Included from TextFlow.hpp +namespace TextFlow { + + inline auto isWhitespace( char c ) -> bool { + static std::string chars = " \t\n\r"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableBefore( char c ) -> bool { + static std::string chars = "[({<|"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableAfter( char c ) -> bool { + static std::string chars = "])}>.,:;*+-=&/\\"; + return chars.find( c ) != std::string::npos; + } + + class Columns; + + class Column { + std::vector m_strings; + size_t m_width = CLARA_CONFIG_CONSOLE_WIDTH; + size_t m_indent = 0; + size_t m_initialIndent = std::string::npos; + + public: + class iterator { + friend Column; + + Column const& m_column; + size_t m_stringIndex = 0; + size_t m_pos = 0; + + size_t m_len; + bool m_suffix = false; + + iterator( Column const& column, size_t stringIndex ) + : m_column( column ), + m_stringIndex( stringIndex ) + {} + + auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } + + auto isBoundary( size_t at ) const -> bool { + assert( at > 0 ); + assert( at <= line().size() ); + + return at == line().size() || + ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || + isBreakableBefore( line()[at] ) || + isBreakableAfter( line()[at-1] ); + } + + void calcLength() { + assert( m_stringIndex < m_column.m_strings.size() ); + + m_suffix = false; + auto width = m_column.m_width-indent(); + if( line().size() < m_pos + width ) { + m_len = line().size() - m_pos; + } + else { + size_t len = width; + while (len > 0 && !isBoundary(m_pos + len)) + --len; + while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) + --len; + + if (len > 0) { + m_len = len; + } else { + m_suffix = true; + m_len = width - 1; + } + } + } + + auto indent() const -> size_t { + auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; + return initial == std::string::npos ? m_column.m_indent : initial; + } + + auto addIndentAndSuffix(std::string const &plain) const -> std::string { + return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); + } + + public: + explicit iterator( Column const& column ) : m_column( column ) { + assert( m_column.m_width > m_column.m_indent ); + assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); + calcLength(); + if( m_len == 0 ) + m_stringIndex++; // Empty string + } + + auto operator *() const -> std::string { + assert( m_stringIndex < m_column.m_strings.size() ); + assert( m_pos < line().size() ); + if( m_pos + m_column.m_width < line().size() ) + return addIndentAndSuffix(line().substr(m_pos, m_len)); + else + return addIndentAndSuffix(line().substr(m_pos)); + } + + auto operator ++() -> iterator& { + m_pos += m_len; + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) + ++m_pos; + + if( m_pos == line().size() ) { + m_pos = 0; + ++m_stringIndex; + } + if( m_stringIndex < m_column.m_strings.size() ) + calcLength(); + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + + auto operator ==( iterator const& other ) const -> bool { + return + m_pos == other.m_pos && + m_stringIndex == other.m_stringIndex && + &m_column == &other.m_column; + } + auto operator !=( iterator const& other ) const -> bool { + return !operator==( other ); + } + }; + using const_iterator = iterator; + + explicit Column( std::string const& text ) { m_strings.push_back( text ); } + + auto width( size_t newWidth ) -> Column& { + assert( newWidth > 0 ); + m_width = newWidth; + return *this; + } + auto indent( size_t newIndent ) -> Column& { + m_indent = newIndent; + return *this; + } + auto initialIndent( size_t newIndent ) -> Column& { + m_initialIndent = newIndent; + return *this; + } + + auto width() const -> size_t { return m_width; } + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return iterator( *this, m_strings.size() ); } + + inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { + bool first = true; + for( auto line : col ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto operator + ( Column const& other ) -> Columns; + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + class Spacer : public Column { + + public: + Spacer( size_t spaceWidth ) : Column( "" ) { + width( spaceWidth ); + } + }; + + class Columns { + std::vector m_columns; + + public: + + class iterator { + friend Columns; + struct EndTag {}; + + std::vector const& m_columns; + std::vector m_iterators; + size_t m_activeIterators; + + iterator( Columns const& columns, EndTag ) + : m_columns( columns.m_columns ), + m_activeIterators( 0 ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.end() ); + } + + public: + iterator( Columns const& columns ) + : m_columns( columns.m_columns ), + m_activeIterators( m_columns.size() ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.begin() ); + } + + auto operator ==( iterator const& other ) const -> bool { + return m_iterators == other.m_iterators; + } + auto operator !=( iterator const& other ) const -> bool { + return m_iterators != other.m_iterators; + } + auto operator *() const -> std::string { + std::string row, padding; + + for( size_t i = 0; i < m_columns.size(); ++i ) { + auto width = m_columns[i].width(); + if( m_iterators[i] != m_columns[i].end() ) { + std::string col = *m_iterators[i]; + row += padding + col; + if( col.size() < width ) + padding = std::string( width - col.size(), ' ' ); + else + padding = ""; + } + else { + padding += std::string( width, ' ' ); + } + } + return row; + } + auto operator ++() -> iterator& { + for( size_t i = 0; i < m_columns.size(); ++i ) { + if (m_iterators[i] != m_columns[i].end()) + ++m_iterators[i]; + } + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + }; + using const_iterator = iterator; + + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return iterator( *this, iterator::EndTag() ); } + + auto operator += ( Column const& col ) -> Columns& { + m_columns.push_back( col ); + return *this; + } + auto operator + ( Column const& col ) -> Columns { + Columns combined = *this; + combined += col; + return combined; + } + + inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) { + + bool first = true; + for( auto line : cols ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + inline auto Column::operator + ( Column const& other ) -> Columns { + Columns cols; + cols += *this; + cols += other; + return cols; + } + +} // namespace TextFlow + +namespace detail { + + // Traits for extracting arg and return type of lambdas (for single argument lambdas) + template + struct UnaryLambdaTraits : UnaryLambdaTraits {}; + + template + struct UnaryLambdaTraits { + static const bool isValid = false; + }; + + template + struct UnaryLambdaTraits { + static const bool isValid = true; + using ArgType = typename std::remove_const::type>::type;; + using ReturnType = ReturnT; + }; + + class TokenStream; + + // Transport for raw args (copied from main args, or supplied via init list for testing) + class Args { + friend TokenStream; + std::string m_exeName; + std::vector m_args; + + public: + Args(int argc, char *argv[]) { + m_exeName = argv[0]; + for (int i = 1; i < argc; ++i) + m_args.push_back(argv[i]); + } + + Args(std::initializer_list args) + : m_exeName( *args.begin() ), + m_args( args.begin()+1, args.end() ) + {} + + auto exeName() const -> std::string { + return m_exeName; + } + }; + + // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string + // may encode an option + its argument if the : or = form is used + enum class TokenType { + Option, Argument + }; + struct Token { + TokenType type; + std::string token; + }; + + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled + class TokenStream { + using Iterator = std::vector::const_iterator; + Iterator it; + Iterator itEnd; + std::vector m_tokenBuffer; + + void loadBuffer() { + m_tokenBuffer.resize(0); + + // Skip any empty strings + while (it != itEnd && it->empty()) + ++it; + + if (it != itEnd) { + auto const &next = *it; + if (next[0] == '-' || next[0] == '/') { + auto delimiterPos = next.find_first_of(" :="); + if (delimiterPos != std::string::npos) { + m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)}); + m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)}); + } else { + if (next[1] != '-' && next.size() > 2) { + std::string opt = "- "; + for (size_t i = 1; i < next.size(); ++i) { + opt[1] = next[i]; + m_tokenBuffer.push_back({TokenType::Option, opt}); + } + } else { + m_tokenBuffer.push_back({TokenType::Option, next}); + } + } + } else { + m_tokenBuffer.push_back({TokenType::Argument, next}); + } + } + } + + public: + explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} + + TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + loadBuffer(); + } + + explicit operator bool() const { + return !m_tokenBuffer.empty() || it != itEnd; + } + + auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } + + auto operator*() const -> Token { + assert(!m_tokenBuffer.empty()); + return m_tokenBuffer.front(); + } + + auto operator->() const -> Token const * { + assert(!m_tokenBuffer.empty()); + return &m_tokenBuffer.front(); + } + + auto operator++() -> TokenStream & { + if (m_tokenBuffer.size() >= 2) { + m_tokenBuffer.erase(m_tokenBuffer.begin()); + } else { + if (it != itEnd) + ++it; + loadBuffer(); + } + return *this; + } + }; + + + class ResultBase { + public: + enum Type { + Ok, LogicError, RuntimeError + }; + + protected: + ResultBase(Type type) : m_type(type) {} + + virtual void enforceOk() const = 0; + + Type m_type; + }; + + template + class ResultValueBase : public ResultBase { + public: + auto value() const -> T const & { + enforceOk(); + return m_value; + } + + protected: + ResultValueBase(Type type) : ResultBase(type) {} + + ResultValueBase(ResultValueBase const &other) : ResultBase(other) { + if (m_type == ResultBase::Ok) + new(&m_value) T(other.m_value); + } + + ResultValueBase(Type type, T const &value) + : ResultBase(Ok) { + new(&m_value) T(value); + } + + auto operator=(ResultValueBase const &other) -> ResultValueBase & { + if (m_type == ResultBase::Ok) + m_value.~T(); + ResultBase::operator=(other); + if (m_type == ResultBase::Ok) + new(&m_value) T(other.m_value); + return *this; + } + + ~ResultValueBase() { + if (m_type == Ok) + m_value.~T(); + } + + union { + T m_value; + }; + }; + + template<> + class ResultValueBase : public ResultBase { + protected: + using ResultBase::ResultBase; + }; + + template + class BasicResult : public ResultValueBase { + public: + template + explicit BasicResult(BasicResult const &other) + : ResultValueBase(other.type()), + m_errorMessage(other.errorMessage()) { + assert(type() != ResultBase::Ok); + } + + static auto ok() -> BasicResult { return {ResultBase::Ok}; } + + template + static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; } + + static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; } + + static auto runtimeError(std::string const &message) -> BasicResult { + return {ResultBase::RuntimeError, message}; + } + + explicit operator bool() const { return m_type == ResultBase::Ok; } + + auto type() const -> ResultBase::Type { return m_type; } + + auto errorMessage() const -> std::string { return m_errorMessage; } + + protected: + virtual void enforceOk() const { + // !TBD: If no exceptions, std::terminate here or something + switch (m_type) { + case ResultBase::LogicError: + throw std::logic_error(m_errorMessage); + case ResultBase::RuntimeError: + throw std::runtime_error(m_errorMessage); + case ResultBase::Ok: + break; + } + } + + std::string m_errorMessage; // Only populated if resultType is an error + + BasicResult(ResultBase::Type type, std::string const &message) + : ResultValueBase(type), + m_errorMessage(message) { + assert(m_type != ResultBase::Ok); + } + + using ResultValueBase::ResultValueBase; + using ResultBase::m_type; + }; + + enum class ParseResultType { + Matched, NoMatch, ShortCircuitAll, ShortCircuitSame + }; + + class ParseState { + public: + + ParseState(ParseResultType type, TokenStream const &remainingTokens) + : m_type(type), + m_remainingTokens(remainingTokens) {} + + auto type() const -> ParseResultType { return m_type; } + + auto remainingTokens() const -> TokenStream { return m_remainingTokens; } + + private: + ParseResultType m_type; + TokenStream m_remainingTokens; + }; + + using Result = BasicResult; + using ParserResult = BasicResult; + using InternalParseResult = BasicResult; + + struct HelpColumns { + std::string left; + std::string right; + }; + + template + inline auto convertInto(std::string const &source, T& target) -> ParserResult { + std::stringstream ss; + ss << source; + ss >> target; + if (ss.fail()) + return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type"); + else + return ParserResult::ok(ParseResultType::Matched); + } + inline auto convertInto(std::string const &source, std::string& target) -> ParserResult { + target = source; + return ParserResult::ok(ParseResultType::Matched); + } + + inline auto convertInto(std::string const &source, bool &target) -> ParserResult { + std::string srcLC = source; + std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), ::tolower); + if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") + target = true; + else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") + target = false; + else + return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'"); + return ParserResult::ok(ParseResultType::Matched); + } + + struct BoundRefBase { + BoundRefBase() = default; + + BoundRefBase(BoundRefBase const &) = delete; + + BoundRefBase(BoundRefBase &&) = delete; + + BoundRefBase &operator=(BoundRefBase const &) = delete; + + BoundRefBase &operator=(BoundRefBase &&) = delete; + + virtual ~BoundRefBase() = default; + + virtual auto isFlag() const -> bool = 0; + + virtual auto isContainer() const -> bool { return false; } + + virtual auto setValue(std::string const &arg) -> ParserResult = 0; + + virtual auto setFlag(bool flag) -> ParserResult = 0; + }; + + struct BoundValueRefBase : BoundRefBase { + auto isFlag() const -> bool override { return false; } + + auto setFlag(bool) -> ParserResult override { + return ParserResult::logicError("Flags can only be set on boolean fields"); + } + }; + + struct BoundFlagRefBase : BoundRefBase { + auto isFlag() const -> bool override { return true; } + + auto setValue(std::string const &arg) -> ParserResult override { + bool flag; + auto result = convertInto(arg, flag); + if (result) + setFlag(flag); + return result; + } + }; + + template + struct BoundRef : BoundValueRefBase { + T &m_ref; + + explicit BoundRef(T &ref) : m_ref(ref) {} + + auto setValue(std::string const &arg) -> ParserResult override { + return convertInto(arg, m_ref); + } + }; + + template + struct BoundRef> : BoundValueRefBase { + std::vector &m_ref; + + explicit BoundRef(std::vector &ref) : m_ref(ref) {} + + auto isContainer() const -> bool override { return true; } + + auto setValue(std::string const &arg) -> ParserResult override { + T temp; + auto result = convertInto(arg, temp); + if (result) + m_ref.push_back(temp); + return result; + } + }; + + struct BoundFlagRef : BoundFlagRefBase { + bool &m_ref; + + explicit BoundFlagRef(bool &ref) : m_ref(ref) {} + + auto setFlag(bool flag) -> ParserResult override { + m_ref = flag; + return ParserResult::ok(ParseResultType::Matched); + } + }; + + template + struct LambdaInvoker { + static_assert(std::is_same::value, "Lambda must return void or clara::ParserResult"); + + template + static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { + return lambda(arg); + } + }; + + template<> + struct LambdaInvoker { + template + static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { + lambda(arg); + return ParserResult::ok(ParseResultType::Matched); + } + }; + + template + inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { + ArgType temp; + auto result = convertInto(arg, temp); + return !result + ? result + : LambdaInvoker::ReturnType>::invoke(lambda, temp); + }; + + + template + struct BoundLambda : BoundValueRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} + + auto setValue(std::string const &arg) -> ParserResult override { + return invokeLambda::ArgType>(m_lambda, arg); + } + }; + + template + struct BoundFlagLambda : BoundFlagRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); + + explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} + + auto setFlag(bool flag) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke(m_lambda, flag); + } + }; + + enum class Optionality { + Optional, Required + }; + + struct Parser; + + class ParserBase { + public: + virtual auto validate() const -> Result { return Result::ok(); } + + virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; + + virtual auto cardinality() const -> size_t { return 1; } + + auto parse(Args const &args) const -> InternalParseResult { + return parse( args.exeName(), TokenStream(args)); + } + }; + + template + class ComposableParserImpl : public ParserBase { + public: + template + auto operator+(T const &other) const -> Parser; + }; + + // Common code and state for Args and Opts + template + class ParserRefImpl : public ComposableParserImpl { + protected: + Optionality m_optionality = Optionality::Optional; + std::shared_ptr m_ref; + std::string m_hint; + std::string m_description; + + explicit ParserRefImpl(std::shared_ptr const &ref) : m_ref(ref) {} + + public: + template + ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), m_hint(hint) {} + + template + ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), + m_hint(hint) {} + + auto operator()(std::string const &description) -> DerivedT & { + m_description = description; + return static_cast( *this ); + } + + auto optional() -> DerivedT & { + m_optionality = Optionality::Optional; + return static_cast( *this ); + }; + + auto required() -> DerivedT & { + m_optionality = Optionality::Required; + return static_cast( *this ); + }; + + auto isOptional() const -> bool { + return m_optionality == Optionality::Optional; + } + + auto cardinality() const -> size_t override { + if (m_ref->isContainer()) + return 0; + else + return 1; + } + + auto hint() const -> std::string { return m_hint; } + }; + + class ExeName : public ComposableParserImpl { + std::shared_ptr m_name; + std::shared_ptr m_ref; + + template + static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { + return std::make_shared>(lambda); + } + + public: + ExeName() : m_name(std::make_shared("")) {} + + explicit ExeName(std::string &ref) : ExeName() { + m_ref = std::make_shared>( ref ); + } + + template + explicit ExeName( LambdaT const& lambda ) : ExeName() { + m_ref = std::make_shared>( lambda ); + } + + // The exe name is not parsed out of the normal tokens, but is handled specially + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + } + + auto name() const -> std::string { return *m_name; } + auto set( std::string const& newName ) -> ParserResult { + + auto lastSlash = newName.find_last_of( "\\/" ); + auto filename = (lastSlash == std::string::npos) + ? newName + : newName.substr( lastSlash+1 ); + + *m_name = filename; + if( m_ref ) + return m_ref->setValue( filename ); + else + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + class Arg : public ParserRefImpl { + public: + using ParserRefImpl::ParserRefImpl; + + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + auto result = validate(); + if (!result) + return InternalParseResult(result); + + auto remainingTokens = tokens; + auto const &token = *remainingTokens; + if (token.type != TokenType::Argument) + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + + result = m_ref->setValue(remainingTokens->token); + if (!result) + return InternalParseResult(result); + else + return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + } + }; + + inline auto normaliseOpt(std::string const &optName) -> std::string { + if (optName[0] == '/') + return "-" + optName.substr(1); + else + return optName; + } + + class Opt : public ParserRefImpl { + protected: + std::vector m_optNames; + + public: + using ParserRefImpl::ParserRefImpl; + + template + explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} + + explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + + auto operator[](std::string const &optName) -> Opt & { + m_optNames.push_back(optName); + return *this; + } + + auto getHelpColumns() const -> std::vector { + std::ostringstream oss; + bool first = true; + for (auto const &opt : m_optNames) { + if (first) + first = false; + else + oss << ", "; + oss << opt; + } + if (!m_hint.empty()) + oss << " <" << m_hint << ">"; + return {{oss.str(), m_description}}; + } + + auto isMatch(std::string const &optToken) const -> bool { +#ifdef CLARA_PLATFORM_WINDOWS + auto normalisedToken = normaliseOpt( optToken ); +#else + auto const &normalisedToken = optToken; +#endif + for (auto const &name : m_optNames) { + if (normaliseOpt(name) == normalisedToken) + return true; + } + return false; + } + + using ParserBase::parse; + + auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { + auto result = validate(); + if (!result) + return InternalParseResult(result); + + auto remainingTokens = tokens; + if (remainingTokens && remainingTokens->type == TokenType::Option) { + auto const &token = *remainingTokens; + if (isMatch(token.token)) { + if (m_ref->isFlag()) { + auto result = m_ref->setFlag(true); + if (!result) + return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + } else { + ++remainingTokens; + if (!remainingTokens) + return InternalParseResult::runtimeError("Expected argument following " + token.token); + auto const &argToken = *remainingTokens; + if (argToken.type != TokenType::Argument) + return InternalParseResult::runtimeError("Expected argument following " + token.token); + auto result = m_ref->setValue(argToken.token); + if (!result) + return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + } + return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + } + } + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + } + + auto validate() const -> Result override { + if (m_optNames.empty()) + return Result::logicError("No options supplied to Opt"); + for (auto const &name : m_optNames) { + if (name.empty()) + return Result::logicError("Option name cannot be empty"); + if (name[0] != '-' && name[0] != '/') + return Result::logicError("Option name must begin with '-' or '/'"); + } + return ParserRefImpl::validate(); + } + }; + + struct Help : Opt { + Help( bool &showHelpFlag ) + : Opt([&]( bool flag ) { + showHelpFlag = flag; + return ParserResult::ok(ParseResultType::ShortCircuitAll); + }) + { + static_cast(*this) + ("display usage information") + ["-?"]["-h"]["--help"] + .optional(); + } + }; + + + struct Parser : ParserBase { + + mutable ExeName m_exeName; + std::vector m_options; + std::vector m_args; + + auto operator+=(ExeName const &exeName) -> Parser & { + m_exeName = exeName; + return *this; + } + + auto operator+=(Arg const &arg) -> Parser & { + m_args.push_back(arg); + return *this; + } + + auto operator+=(Opt const &opt) -> Parser & { + m_options.push_back(opt); + return *this; + } + + auto operator+=(Parser const &other) -> Parser & { + m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); + m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); + return *this; + } + + template + auto operator+(T const &other) const -> Parser { + return Parser(*this) += other; + } + + auto getHelpColumns() const -> std::vector { + std::vector cols; + for (auto const &o : m_options) { + auto childCols = o.getHelpColumns(); + cols.insert(cols.end(), childCols.begin(), childCols.end()); + } + return cols; + } + + void writeToStream(std::ostream &os) const { + if (!m_exeName.name().empty()) { + os << "usage:\n" << " " << m_exeName.name() << " "; + bool required = true, first = true; + for (auto const &arg : m_args) { + if (first) + first = false; + else + os << " "; + if (arg.isOptional() && required) { + os << "["; + required = false; + } + os << "<" << arg.hint() << ">"; + if (arg.cardinality() == 0) + os << " ... "; + } + if (!required) + os << "]"; + if (!m_options.empty()) + os << " options"; + os << "\n\nwhere options are:" << std::endl; + } + + auto rows = getHelpColumns(); + size_t optWidth = 0; + for (auto const &cols : rows) + optWidth = std::max(optWidth, cols.left.size() + 2); + + for (auto const &cols : rows) { + auto row = + TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Spacer(4) + + TextFlow::Column(cols.right).width(73 - optWidth); + os << row << std::endl; + } + } + + friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { + parser.writeToStream(os); + return os; + } + + auto validate() const -> Result override { + for (auto const &opt : m_options) { + auto result = opt.validate(); + if (!result) + return result; + } + for (auto const &arg : m_args) { + auto result = arg.validate(); + if (!result) + return result; + } + return Result::ok(); + } + + using ParserBase::parse; + + auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override { + std::vector allParsers; + allParsers.reserve(m_args.size() + m_options.size()); + std::set requiredParsers; + + for (auto const &opt : m_options) { + allParsers.push_back(&opt); + if (!opt.isOptional()) + requiredParsers.insert(&opt); + } + + size_t optionalArgs = 0; + for (auto const &arg : m_args) { + allParsers.push_back(&arg); + if (!arg.isOptional()) { + if (optionalArgs > 0) + return InternalParseResult::logicError( + "Required arguments must preceed any optional arguments"); + else + ++optionalArgs; + requiredParsers.insert(&arg); + } + } + + m_exeName.set( exeName ); + + auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + while (result.value().remainingTokens()) { + int remainingTokenCount = result.value().remainingTokens().count(); + for (auto parser : allParsers) { + result = parser->parse( exeName, result.value().remainingTokens() ); + if (!result || result.value().type() != ParseResultType::NoMatch) { + if (parser->cardinality() == 1) + allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser), + allParsers.end()); + requiredParsers.erase(parser); + break; + } + } + if (!result || remainingTokenCount == result.value().remainingTokens().count()) + return result; + } + // !TBD Check missing required options + return result; + } + }; + + template + template + auto ComposableParserImpl::operator+(T const &other) const -> Parser { + return Parser() + static_cast( *this ) + other; + } +} // namespace detail + + +// A Combined parser +using detail::Parser; + +// A parser for options +using detail::Opt; + +// A parser for arguments +using detail::Arg; + +// Wrapper for argc, argv from main() +using detail::Args; + +// Specifies the name of the executable +using detail::ExeName; + +// Convenience wrapper for option parser that specifies the help option +using detail::Help; + +// enum of result types from a parse +using detail::ParseResultType; + +// Result type for parser operation +using detail::ParserResult; + + +} // namespace clara +} // namespace Catch + +#endif // CATCH_CLARA_HPP_INCLUDED diff --git a/include/internal/catch_clara.h b/include/internal/catch_clara.h index bfe2f4b7..9c66a55d 100644 --- a/include/internal/catch_clara.h +++ b/include/internal/catch_clara.h @@ -17,10 +17,7 @@ #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH -// Declare Clara inside the Catch namespace -#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -#include "../external/clara.h" -#undef STITCH_CLARA_OPEN_NAMESPACE +#include "../external/clara.hpp" // Restore Clara's value for console width, if present diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 89c55695..e3e32fa4 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -17,190 +17,128 @@ namespace Catch { - inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } - inline void abortAfterX( ConfigData& config, int x ) { - CATCH_ENFORCE( x >=1, "Value after -x or --abortAfter must be greater than zero" ); - config.abortAfter = x; - } - inline void addTestOrTags( ConfigData& config, std::string const& testSpec ) { config.testsOrTags.push_back( testSpec ); } - inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } - inline void addReporterName( ConfigData& config, std::string const& reporterName ) { config.reporterNames.push_back( reporterName ); } + inline clara::Parser makeCommandLineParser( ConfigData& config ) { - inline void addWarning( ConfigData& config, std::string const& warning ) { - CATCH_ENFORCE( warning == "NoAssertions", "Unrecognised warning: '" << warning << "'" ); - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - } - inline void setOrder( ConfigData& config, std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - CATCH_ENFORCE( false, "Unrecognised ordering: '" << order << '\'' ); - } - inline void setRngSeed( ConfigData& config, std::string const& seed ) { - if( seed == "time" ) { - config.rngSeed = static_cast( std::time(0) ); - } - else { - std::stringstream ss; - ss << seed; - ss >> config.rngSeed; - CATCH_ENFORCE( !ss.fail(), "Argument to --rng-seed should be the word 'time' or a number" ); - } - } - inline void setVerbosity( ConfigData& config, int level ) { - // !TBD: accept strings? - config.verbosity = static_cast( level ); - } - inline void setShowDurations( ConfigData& config, bool _showDurations ) { - config.showDurations = _showDurations - ? ShowDurations::Always - : ShowDurations::Never; - } - inline void setUseColour( ConfigData& config, std::string const& value ) { - std::string mode = toLower( value ); + auto const loadTestNamesFromFile = [&]( std::string const& filename ) { + std::ifstream f( filename.c_str() ); + if( !f.is_open() ) + return clara::ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - CATCH_ENFORCE( false, "colour mode must be one of: auto, yes or no" ); - } - inline void forceColour( ConfigData& config ) { - config.useColour = UseColour::Yes; - } - inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { - std::ifstream f( _filename.c_str() ); - CATCH_ENFORCE( f.is_open(), "Unable to load input file: '" << _filename << "'" ); + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, '#' ) ) { + if( !startsWith( line, '"' ) ) + line = '"' + line + '"'; + config.testsOrTags.push_back( line + ',' ); + } + } + return clara::ParserResult::ok( clara::ParseResultType::Matched ); + }; - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, '#' ) ) { - if( !startsWith( line, '"' ) ) - line = '"' + line + '"'; - addTestOrTags( config, line + ',' ); - } - } - } - inline Clara::CommandLine makeCommandLineParser() { + using namespace clara; + auto cli + = ExeName( config.processName ) + + Help( config.showHelp ) + + Opt( config.listTests ) + ["-l"]["--list-tests"] + ( "list all/matching test cases" ) + + Opt( config.listTags ) + ["-t"]["--list-tags"] + ( "list all/matching tags" ) + + Opt( config.showSuccessfulTests ) + ["-s"]["--success"] + ( "include successful tests in output" ) + + Opt( config.shouldDebugBreak ) + ["-b"]["--break"] + ( "break into debugger on failure" ) + + Opt( config.noThrow ) + ["-e"]["--nothrow"] + ( "skip exception tests" ) + + Opt( config.showInvisibles ) + ["-i"]["--invisibles"] + ( "show invisibles (tabs, newlines)" ) + + Opt( config.outputFilename, "filename" ) + ["-o"]["--out"] + ( "output filename" ) + + Opt( config.reporterNames, "name" ) + ["-r"]["--reporter"] + ( "reporter to use (defaults to console)" ) + + Opt( config.name, "name" ) + ["-n"]["--name"] + ( "suite name" ) + + Opt( [&]( bool ){ config.abortAfter = 1; } ) + ["-a"]["--abort"] + ( "abort at first failure" ) + + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + ["-x"]["--abortx"] + ( "abort after x failures" ) + + Opt( [&]( std::string const& warning ) { + if( warning != "NoAssertions" ) + return clara::ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + return clara::ParserResult::ok( ParseResultType::Matched ); + }, "warning name" ) + ["-w"]["--warn"] + ( "enable warnings" ) + + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) + ["-d"]["--durations"] + ( "show test durations" ) + + Opt( loadTestNamesFromFile, "filename" ) + ["-f"]["--input-file"] + ( "load test names to run from a file" ) + + Opt( config.filenamesAsTags ) + ["-#"]["--filenames-as-tags"] + ( "adds a tag for the filename" ) + + Opt( config.sectionsToRun, "section name" ) + ["-c"]["--section"] + ( "specify section to run" ) + + Opt( config.listTestNamesOnly ) + ["--list-test-names-only"] + ( "list all/matching test cases names only" ) + + Opt( config.listReporters ) + ["--list-reporters"] + ( "list all reporters" ) + + Opt( [&]( std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); + return clara::ParserResult::ok( ParseResultType::Matched ); + }, "decl|lex|rand" ) + ["--order"] + ( "test case order (defaults to decl)" ) + + Opt( [&]( std::string const& seed ) { + if( seed != "time" ) + return clara::detail::convertInto( seed, config.rngSeed ); + config.rngSeed = static_cast( std::time(0) ); + return clara::ParserResult::ok( ParseResultType::Matched ); + }, "'time'|number" ) + ["--rng-seed"] + ( "set a specific seed for random numbers" ) + + Opt( [&]( std::string const& useColour ) { + auto mode = toLower( useColour ); - using namespace Clara; - CommandLine cli; + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + return clara::ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); + return clara::ParserResult::ok( ParseResultType::Matched ); + }, "yes|no" ) + ["--use-colour"] + ( "should output be colourised" ) - cli.bindProcessName( &ConfigData::processName ); - - cli["-?"]["-h"]["--help"] - .describe( "display usage information" ) - .bind( &ConfigData::showHelp ); - - cli["-l"]["--list-tests"] - .describe( "list all/matching test cases" ) - .bind( &ConfigData::listTests ); - - cli["-t"]["--list-tags"] - .describe( "list all/matching tags" ) - .bind( &ConfigData::listTags ); - - cli["-s"]["--success"] - .describe( "include successful tests in output" ) - .bind( &ConfigData::showSuccessfulTests ); - - cli["-b"]["--break"] - .describe( "break into debugger on failure" ) - .bind( &ConfigData::shouldDebugBreak ); - - cli["-e"]["--nothrow"] - .describe( "skip exception tests" ) - .bind( &ConfigData::noThrow ); - - cli["-i"]["--invisibles"] - .describe( "show invisibles (tabs, newlines)" ) - .bind( &ConfigData::showInvisibles ); - - cli["-o"]["--out"] - .describe( "output filename" ) - .bind( &ConfigData::outputFilename, "filename" ); - - cli["-r"]["--reporter"] -// .placeholder( "name[:filename]" ) - .describe( "reporter to use (defaults to console)" ) - .bind( &addReporterName, "name" ); - - cli["-n"]["--name"] - .describe( "suite name" ) - .bind( &ConfigData::name, "name" ); - - cli["-a"]["--abort"] - .describe( "abort at first failure" ) - .bind( &abortAfterFirst ); - - cli["-x"]["--abortx"] - .describe( "abort after x failures" ) - .bind( &abortAfterX, "no. failures" ); - - cli["-w"]["--warn"] - .describe( "enable warnings" ) - .bind( &addWarning, "warning name" ); - -// - needs updating if reinstated -// cli.into( &setVerbosity ) -// .describe( "level of verbosity (0=no output)" ) -// .shortOpt( "v") -// .longOpt( "verbosity" ) -// .placeholder( "level" ); - - cli[_] - .describe( "which test or tests to use" ) - .bind( &addTestOrTags, "test name, pattern or tags" ); - - cli["-d"]["--durations"] - .describe( "show test durations" ) - .bind( &setShowDurations, "yes|no" ); - - cli["-f"]["--input-file"] - .describe( "load test names to run from a file" ) - .bind( &loadTestNamesFromFile, "filename" ); - - cli["-#"]["--filenames-as-tags"] - .describe( "adds a tag for the filename" ) - .bind( &ConfigData::filenamesAsTags ); - - cli["-c"]["--section"] - .describe( "specify section to run" ) - .bind( &addSectionToRun, "section name" ); - - // Less common commands which don't have a short form - cli["--list-test-names-only"] - .describe( "list all/matching test cases names only" ) - .bind( &ConfigData::listTestNamesOnly ); - - cli["--list-reporters"] - .describe( "list all reporters" ) - .bind( &ConfigData::listReporters ); - - cli["--order"] - .describe( "test case order (defaults to decl)" ) - .bind( &setOrder, "decl|lex|rand" ); - - cli["--rng-seed"] - .describe( "set a specific seed for random numbers" ) - .bind( &setRngSeed, "'time'|number" ); - - cli["--force-colour"] - .describe( "force colourised output (deprecated)" ) - .bind( &forceColour ); - - cli["--use-colour"] - .describe( "should output be colourised" ) - .bind( &setUseColour, "yes|no" ); + + Arg( config.testsOrTags, "test name|pattern|tags" ) + ( "which test or tests to use" ); return cli; } diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 8005a2eb..980d302c 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -25,24 +25,24 @@ CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" ) #endif -template -void parseIntoConfig( const char * (&argv)[size], Catch::ConfigData& config ) { - Catch::Clara::CommandLine parser = Catch::makeCommandLineParser(); - parser.parseInto( Catch::Clara::argsToVector( size, argv ), config ); -} - -template -std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::ConfigData& config ) { - try { - parseIntoConfig( argv, config ); - FAIL( "expected exception" ); - } - catch( std::exception& ex ) { - return ex.what(); - } - return ""; -} - +//template +//void parseIntoConfig( const char * (&argv)[size], Catch::ConfigData& config ) { +// auto parser = Catch::makeCommandLineParser(); +// parser.parseInto( Catch::Clara::argsToVector( size, argv ), config ); +//} +// +//template +//std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::ConfigData& config ) { +// try { +// parseIntoConfig( argv, config ); +// FAIL( "expected exception" ); +// } +// catch( std::exception& ex ) { +// return ex.what(); +// } +// return ""; +//} +// inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( nullptr, "", name, desc, CATCH_INTERNAL_LINEINFO ); } TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { @@ -50,197 +50,182 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" using namespace Catch::Matchers; Catch::ConfigData config; + auto cli = Catch::makeCommandLineParser(config); - SECTION( "empty args don't cause a crash" ) { - Catch::Clara::CommandLine parser = Catch::makeCommandLineParser(); - CHECK_NOTHROW( parser.parseInto( std::vector(), config ) ); - - CHECK( config.processName == "" ); + SECTION("empty args don't cause a crash") { + auto result = cli.parse({""}); + CHECK(result); + CHECK(config.processName == ""); } - SECTION( "default - no arguments", "" ) { - const char* argv[] = { "test" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - CHECK( config.processName == "test" ); - CHECK( config.shouldDebugBreak == false ); - CHECK( config.abortAfter == -1 ); - CHECK( config.noThrow == false ); - CHECK( config.reporterNames.empty() ); + SECTION("default - no arguments") { + auto result = cli.parse({"test"}); + CHECK(result); + CHECK(config.processName == "test"); + CHECK(config.shouldDebugBreak == false); + CHECK(config.abortAfter == -1); + CHECK(config.noThrow == false); + CHECK(config.reporterNames.empty()); } - SECTION( "test lists", "" ) { - SECTION( "1 test", "Specify one test case using" ) { - const char* argv[] = { "test", "test1" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("test lists") { + SECTION("1 test", "Specify one test case using") { + auto result = cli.parse({"test", "test1"}); + CHECK(result); - Catch::Config cfg( config ); - REQUIRE( cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false ); - REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) ); + Catch::Config cfg(config); + REQUIRE(cfg.testSpec().matches(fakeTestCase("notIncluded")) == false); + REQUIRE(cfg.testSpec().matches(fakeTestCase("test1"))); } - SECTION( "Specify one test case exclusion using exclude:", "" ) { - const char* argv[] = { "test", "exclude:test1" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("Specify one test case exclusion using exclude:") { + auto result = cli.parse({"test", "exclude:test1"}); + CHECK(result); - Catch::Config cfg( config ); - REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ); - REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ); + Catch::Config cfg(config); + REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")) == false); + REQUIRE(cfg.testSpec().matches(fakeTestCase("alwaysIncluded"))); } - SECTION( "Specify one test case exclusion using ~", "" ) { - const char* argv[] = { "test", "~test1" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("Specify one test case exclusion using ~") { + auto result = cli.parse({"test", "~test1"}); + CHECK(result); - Catch::Config cfg( config ); - REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ); - REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ); + Catch::Config cfg(config); + REQUIRE(cfg.testSpec().matches(fakeTestCase("test1")) == false); + REQUIRE(cfg.testSpec().matches(fakeTestCase("alwaysIncluded"))); } } - SECTION( "reporter", "" ) { - SECTION( "-r/console", "" ) { - const char* argv[] = { "test", "-r", "console" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("reporter") { + SECTION("-r/console") { + CHECK(cli.parse({"test", "-r", "console"})); - REQUIRE( config.reporterNames[0] == "console" ); + REQUIRE(config.reporterNames[0] == "console"); } - SECTION( "-r/xml", "" ) { - const char* argv[] = { "test", "-r", "xml" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("-r/xml") { + CHECK(cli.parse({"test", "-r", "xml"})); - REQUIRE( config.reporterNames[0] == "xml" ); + REQUIRE(config.reporterNames[0] == "xml"); } - SECTION( "-r xml and junit", "" ) { - const char* argv[] = { "test", "-r", "xml", "-r", "junit" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("-r xml and junit") { + CHECK(cli.parse({"test", "-r", "xml", "-r", "junit"})); - REQUIRE( config.reporterNames.size() == 2 ); - REQUIRE( config.reporterNames[0] == "xml" ); - REQUIRE( config.reporterNames[1] == "junit" ); + REQUIRE(config.reporterNames.size() == 2); + REQUIRE(config.reporterNames[0] == "xml"); + REQUIRE(config.reporterNames[1] == "junit"); } - SECTION( "--reporter/junit", "" ) { - const char* argv[] = { "test", "--reporter", "junit" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("--reporter/junit") { + CHECK(cli.parse({"test", "--reporter", "junit"})); - REQUIRE( config.reporterNames[0] == "junit" ); + REQUIRE(config.reporterNames[0] == "junit"); } } - SECTION( "debugger", "" ) { - SECTION( "-b", "" ) { - const char* argv[] = { "test", "-b" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - REQUIRE( config.shouldDebugBreak == true ); + SECTION("debugger") { + SECTION("-b") { + CHECK(cli.parse({"test", "-b"})); + + REQUIRE(config.shouldDebugBreak == true); } - SECTION( "--break", "" ) { - const char* argv[] = { "test", "--break" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("--break") { + CHECK(cli.parse({"test", "--break"})); - REQUIRE( config.shouldDebugBreak ); + REQUIRE(config.shouldDebugBreak); } } - SECTION( "abort", "" ) { - SECTION( "-a aborts after first failure", "" ) { - const char* argv[] = { "test", "-a" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - REQUIRE( config.abortAfter == 1 ); - } - SECTION( "-x 2 aborts after two failures", "" ) { - const char* argv[] = { "test", "-x", "2" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("abort") { + SECTION("-a aborts after first failure") { + CHECK(cli.parse({"test", "-a"})); - REQUIRE( config.abortAfter == 2 ); + REQUIRE(config.abortAfter == 1); } - SECTION( "-x must be greater than zero", "" ) { - const char* argv[] = { "test", "-x", "0" }; - REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ); + SECTION("-x 2 aborts after two failures") { + CHECK(cli.parse({"test", "-x", "2"})); + + REQUIRE(config.abortAfter == 2); } - SECTION( "-x must be numeric", "" ) { - const char* argv[] = { "test", "-x", "oops" }; - REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ); + SECTION("-x must be numeric") { + auto result = cli.parse({"test", "-x", "oops"}); + CHECK(!result); + + REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops")); } } - SECTION( "nothrow", "" ) { - SECTION( "-e", "" ) { - const char* argv[] = { "test", "-e" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("nothrow") { + SECTION("-e") { + CHECK(cli.parse({"test", "-e"})); - REQUIRE( config.noThrow == true ); + REQUIRE(config.noThrow); } - SECTION( "--nothrow", "" ) { - const char* argv[] = { "test", "--nothrow" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("--nothrow") { + CHECK(cli.parse({"test", "--nothrow"})); - REQUIRE( config.noThrow == true ); + REQUIRE(config.noThrow); } } - SECTION( "output filename", "" ) { - SECTION( "-o filename", "" ) { - const char* argv[] = { "test", "-o", "filename.ext" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("output filename") { + SECTION("-o filename") { + CHECK(cli.parse({"test", "-o", "filename.ext"})); - REQUIRE( config.outputFilename == "filename.ext" ); + REQUIRE(config.outputFilename == "filename.ext"); } - SECTION( "--out", "" ) { - const char* argv[] = { "test", "--out", "filename.ext" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("--out") { + CHECK(cli.parse({"test", "--out", "filename.ext"})); - REQUIRE( config.outputFilename == "filename.ext" ); + REQUIRE(config.outputFilename == "filename.ext"); } } - SECTION( "combinations", "" ) { - SECTION( "Single character flags can be combined", "" ) { - const char* argv[] = { "test", "-abe" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION("combinations") { + SECTION("Single character flags can be combined") { + CHECK(cli.parse({"test", "-abe"})); - CHECK( config.abortAfter == 1 ); - CHECK( config.shouldDebugBreak ); - CHECK( config.noThrow == true ); + CHECK(config.abortAfter == 1); + CHECK(config.shouldDebugBreak); + CHECK(config.noThrow == true); } } - SECTION( "use-colour", "") { + + SECTION( "use-colour") { using Catch::UseColour; - SECTION( "without option", "" ) { - const char* argv[] = { "test" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION( "without option" ) { + CHECK(cli.parse({"test"})); REQUIRE( config.useColour == UseColour::Auto ); } - SECTION( "auto", "" ) { - const char* argv[] = { "test", "--use-colour", "auto" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION( "auto" ) { + CHECK(cli.parse({"test", "--use-colour", "auto"})); REQUIRE( config.useColour == UseColour::Auto ); } - SECTION( "yes", "" ) { - const char* argv[] = { "test", "--use-colour", "yes" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION( "yes" ) { + CHECK(cli.parse({"test", "--use-colour", "yes"})); REQUIRE( config.useColour == UseColour::Yes ); } - SECTION( "no", "" ) { - const char* argv[] = { "test", "--use-colour", "no" }; - CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + SECTION( "no" ) { + CHECK(cli.parse({"test", "--use-colour", "no"})); REQUIRE( config.useColour == UseColour::No ); } - SECTION( "error", "" ) { - const char* argv[] = { "test", "--use-colour", "wrong" }; - REQUIRE_THROWS_WITH( parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) ); + SECTION( "error" ) { + auto result = cli.parse({"test", "--use-colour", "wrong"}); + CHECK( !result ); + CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) ); } } } @@ -249,31 +234,31 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { using namespace Catch; - SECTION( "plain string", "" ) { + SECTION( "plain string" ) { // guide: 123456789012345678 std::string testString = "one two three four"; - SECTION( "No wrapping", "" ) { + SECTION( "No wrapping" ) { CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); } - SECTION( "Wrapped once", "" ) { + SECTION( "Wrapped once" ) { CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ); } - SECTION( "Wrapped twice", "" ) { + SECTION( "Wrapped twice" ) { CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); } - SECTION( "Wrapped three times", "" ) { + SECTION( "Wrapped three times" ) { CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ); } - SECTION( "Short wrap", "" ) { + SECTION( "Short wrap" ) { CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ); CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ); CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ); @@ -281,7 +266,7 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ); } - SECTION( "As container", "" ) { + SECTION( "As container" ) { Text text( testString, TextAttributes().setWidth( 6 ) ); REQUIRE( text.size() == 4 ); CHECK( text[0] == "one" ); @@ -289,7 +274,7 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { CHECK( text[2] == "three" ); CHECK( text[3] == "four" ); } - SECTION( "Indent first line differently", "" ) { + SECTION( "Indent first line differently" ) { Text text( testString, TextAttributes() .setWidth( 10 ) .setIndent( 4 ) @@ -299,43 +284,43 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { } - SECTION( "With newlines", "" ) { + SECTION( "With newlines" ) { // guide: 1234567890123456789 std::string testString = "one two\nthree four"; - SECTION( "No wrapping" , "" ) { + SECTION( "No wrapping" ) { CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ); } - SECTION( "Trailing newline" , "" ) { + SECTION( "Trailing newline" ) { CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" ); CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ); CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ); CHECK( Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" ); } - SECTION( "Wrapped once", "" ) { + SECTION( "Wrapped once" ) { CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); } - SECTION( "Wrapped twice", "" ) { + SECTION( "Wrapped twice" ) { CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); } } - SECTION( "With wrap-before/ after characters", "" ) { + SECTION( "With wrap-before/ after characters" ) { std::string testString = "one,two(three) "; - SECTION( "No wrapping", "" ) { + SECTION( "No wrapping" ) { CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); CHECK( Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString ); } - SECTION( "Wrap before", "" ) { + SECTION( "Wrap before" ) { CHECK( Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n" ); } - SECTION( "Wrap after", "" ) { + SECTION( "Wrap after" ) { CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n" ); CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n" ); CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n" ); @@ -416,7 +401,7 @@ private: std::vector colours; }; -TEST_CASE( "replaceInPlace", "" ) { +TEST_CASE( "replaceInPlace" ) { std::string letters = "abcdefcg"; SECTION( "replace single char" ) { CHECK( replaceInPlace( letters, "b", "z" ) ); @@ -469,7 +454,7 @@ TEST_CASE( "Strings can be rendered with colour", "[.colour]" ) { } -TEST_CASE( "Text can be formatted using the Text class", "" ) { +TEST_CASE( "Text can be formatted using the Text class" ) { CHECK( Text( "hi there" ).toString() == "hi there" ); From c41a45e79ced6e3aeb7bcc64d986dc58305706bd Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 12 Jun 2017 23:13:27 +0100 Subject: [PATCH 074/398] Rebased following Clara changes --- .../Baselines/console.std.approved.txt | 2 +- .../Baselines/console.sw.approved.txt | 148 ++++++++----- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 208 +++++++++--------- 4 files changed, 202 insertions(+), 159 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index c7b1b566..49f184e9 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,5 +1003,5 @@ with expansion: =============================================================================== test cases: 171 | 121 passed | 46 failed | 4 failed as expected -assertions: 843 | 728 passed | 94 failed | 21 failed as expected +assertions: 844 | 729 passed | 94 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index f70bda98..e74a3348 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -4773,7 +4773,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parser.parseInto( std::vector(), config ) ) + CHECK( result ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -4790,7 +4792,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( result ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -4832,17 +4836,19 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( result ) +with expansion: + {?} TestMain.cpp:: PASSED: - REQUIRE( cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false ) + REQUIRE( cfg.testSpec().matches(fakeTestCase("notIncluded")) == false ) with expansion: false == false TestMain.cpp:: PASSED: - REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) ) + REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) ) with expansion: true @@ -4856,17 +4862,19 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( result ) +with expansion: + {?} TestMain.cpp:: PASSED: - REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ) + REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false ) with expansion: false == false TestMain.cpp:: PASSED: - REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ) + REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) ) with expansion: true @@ -4880,17 +4888,19 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( result ) +with expansion: + {?} TestMain.cpp:: PASSED: - REQUIRE( cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false ) + REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false ) with expansion: false == false TestMain.cpp:: PASSED: - REQUIRE( cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) ) + REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) ) with expansion: true @@ -4904,7 +4914,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-r", "console"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -4922,7 +4934,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-r", "xml"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -4940,7 +4954,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-r", "xml", "-r", "junit"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -4970,7 +4986,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "--reporter", "junit"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -4988,7 +5006,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-b"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5006,7 +5026,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "--break"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5024,7 +5046,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-a"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5042,7 +5066,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-x", "2"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5050,21 +5076,6 @@ PASSED: with expansion: 2 == 2 -------------------------------------------------------------------------------- -Process can be configured on command line - abort - -x must be greater than zero -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ) -with expansion: - "Value after -x or --abortAfter must be greater than zero - - while parsing: (-x, --abortx )" contains: "greater than zero" - ------------------------------------------------------------------------------- Process can be configured on command line abort @@ -5075,10 +5086,16 @@ TestMain.cpp: TestMain.cpp:: PASSED: - REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ) + CHECK( !result ) with expansion: - "Unable to convert oops to destination type - - while parsing: (-x, --abortx )" contains: "-x" + true + +TestMain.cpp:: +PASSED: + REQUIRE_THAT( result.errorMessage(), Contains("convert") && Contains("oops") ) +with expansion: + "Unable to convert 'oops' to destination type" ( contains: "convert" and + contains: "oops" ) ------------------------------------------------------------------------------- Process can be configured on command line @@ -5090,13 +5107,15 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-e"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: - REQUIRE( config.noThrow == true ) + REQUIRE( config.noThrow ) with expansion: - true == true + true ------------------------------------------------------------------------------- Process can be configured on command line @@ -5108,13 +5127,15 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "--nothrow"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: - REQUIRE( config.noThrow == true ) + REQUIRE( config.noThrow ) with expansion: - true == true + true ------------------------------------------------------------------------------- Process can be configured on command line @@ -5126,7 +5147,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-o", "filename.ext"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5144,7 +5167,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "--out", "filename.ext"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5162,7 +5187,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "-abe"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5192,7 +5219,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5210,7 +5239,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "--use-colour", "auto"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5228,7 +5259,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "--use-colour", "yes"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5246,7 +5279,9 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + CHECK( cli.parse({"test", "--use-colour", "no"}) ) +with expansion: + {?} TestMain.cpp:: PASSED: @@ -5264,7 +5299,16 @@ TestMain.cpp: TestMain.cpp:: PASSED: - REQUIRE_THROWS_WITH( parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) ) + CHECK( !result ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) ) +with expansion: + "colour mode must be one of: auto, yes or no. 'wrong' not recognised" + contains: "colour mode must be one of" ------------------------------------------------------------------------------- Reconstruction should be based on stringification: #914 @@ -8309,5 +8353,5 @@ PASSED: =============================================================================== test cases: 171 | 120 passed | 47 failed | 4 failed as expected -assertions: 845 | 728 passed | 96 failed | 21 failed as expected +assertions: 846 | 729 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 8f2cd749..cae1e4bf 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -458,7 +458,6 @@ MessageTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 130cda8a..948cff19 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -5325,12 +5325,12 @@ re>"
- + - parser.parseInto( std::vector<std::string>(), config ) + result - parser.parseInto( std::vector<std::string>(), config ) + {?} @@ -5344,12 +5344,12 @@ re>"
- + - parseIntoConfig( argv, config ) + result - parseIntoConfig( argv, config ) + {?} @@ -5396,17 +5396,17 @@ re>"
- + - parseIntoConfig( argv, config ) + result - parseIntoConfig( argv, config ) + {?} - cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false + cfg.testSpec().matches(fakeTestCase("notIncluded")) == false false == false @@ -5414,7 +5414,7 @@ re>" - cfg.testSpec().matches( fakeTestCase( "test1" ) ) + cfg.testSpec().matches(fakeTestCase("test1")) true @@ -5426,17 +5426,17 @@ re>"
- + - parseIntoConfig( argv, config ) + result - parseIntoConfig( argv, config ) + {?} - cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + cfg.testSpec().matches(fakeTestCase("test1")) == false false == false @@ -5444,7 +5444,7 @@ re>" - cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) true @@ -5456,17 +5456,17 @@ re>"
- + - parseIntoConfig( argv, config ) + result - parseIntoConfig( argv, config ) + {?} - cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + cfg.testSpec().matches(fakeTestCase("test1")) == false false == false @@ -5474,7 +5474,7 @@ re>" - cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) true @@ -5486,12 +5486,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-r", "console"}) - parseIntoConfig( argv, config ) + {?} @@ -5508,12 +5508,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-r", "xml"}) - parseIntoConfig( argv, config ) + {?} @@ -5530,12 +5530,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-r", "xml", "-r", "junit"}) - parseIntoConfig( argv, config ) + {?} @@ -5568,12 +5568,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "--reporter", "junit"}) - parseIntoConfig( argv, config ) + {?} @@ -5590,12 +5590,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-b"}) - parseIntoConfig( argv, config ) + {?} @@ -5612,12 +5612,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "--break"}) - parseIntoConfig( argv, config ) + {?} @@ -5634,12 +5634,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-a"}) - parseIntoConfig( argv, config ) + {?} @@ -5656,12 +5656,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-x", "2"}) - parseIntoConfig( argv, config ) + {?} @@ -5676,52 +5676,44 @@ re>"
-
-
- - - parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) - - - "Value after -x or --abortAfter must be greater than zero -- while parsing: (-x, --abortx <no. failures>)" contains: "greater than zero" - - - -
- -
- + - parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) + !result - "Unable to convert oops to destination type -- while parsing: (-x, --abortx <no. failures>)" contains: "-x" + true - + + + result.errorMessage(), Contains("convert") && Contains("oops") + + + "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" ) + + +
- +
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-e"}) - parseIntoConfig( argv, config ) + {?} - config.noThrow == true + config.noThrow - true == true + true @@ -5730,20 +5722,20 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "--nothrow"}) - parseIntoConfig( argv, config ) + {?} - config.noThrow == true + config.noThrow - true == true + true @@ -5752,12 +5744,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-o", "filename.ext"}) - parseIntoConfig( argv, config ) + {?} @@ -5774,12 +5766,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "--out", "filename.ext"}) - parseIntoConfig( argv, config ) + {?} @@ -5796,12 +5788,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "-abe"}) - parseIntoConfig( argv, config ) + {?} @@ -5834,12 +5826,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test"}) - parseIntoConfig( argv, config ) + {?} @@ -5856,12 +5848,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "--use-colour", "auto"}) - parseIntoConfig( argv, config ) + {?} @@ -5878,12 +5870,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "--use-colour", "yes"}) - parseIntoConfig( argv, config ) + {?} @@ -5900,12 +5892,12 @@ re>"
- + - parseIntoConfig( argv, config ) + cli.parse({"test", "--use-colour", "no"}) - parseIntoConfig( argv, config ) + {?} @@ -5922,17 +5914,25 @@ re>"
- + - parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) + !result - parseIntoConfig( argv, config ), Contains( "colour mode must be one of" ) + true - + + + result.errorMessage(), Contains( "colour mode must be one of" ) + + + "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" + + +
- +
@@ -9166,7 +9166,7 @@ spanner
- + - + From e62b3beef431fcb000b07de84a98519d24250ab3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 13 Jun 2017 08:29:56 +0100 Subject: [PATCH 075/398] Fixed issue with different result types in Clara --- include/external/clara.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 1c0a6884..f4ad627f 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -870,16 +870,16 @@ namespace detail { using ParserRefImpl::ParserRefImpl; auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - auto result = validate(); - if (!result) - return InternalParseResult(result); + auto validationResult = validate(); + if (!validationResult) + return InternalParseResult(validationResult); auto remainingTokens = tokens; auto const &token = *remainingTokens; if (token.type != TokenType::Argument) return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); - result = m_ref->setValue(remainingTokens->token); + auto result = m_ref->setValue(remainingTokens->token); if (!result) return InternalParseResult(result); else From ee0defb93900f1b8fdf65dfcbd2db1b1f33137bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 15 Jun 2017 11:34:29 +0200 Subject: [PATCH 076/398] Silence unused argument warning in Catch --- include/catch_session.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 9b1d1e87..09ca85f1 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -109,7 +109,7 @@ namespace Catch { Catch::cleanUp(); } - void showHelp( std::string const& processName ) { + void showHelp( std::string const& ) { Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; Catch::cout() << m_cli << std::endl; From da5964af782fc6dc1d7c8f19507e967f3a286ca9 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 20 Jun 2017 18:03:37 +0100 Subject: [PATCH 077/398] Updated version of Clara (should fix Windows compile issues) - embedded using new embed script --- include/external/clara.hpp | 102 ++- include/internal/catch_clara.h | 8 +- scripts/embed.py | 73 ++ scripts/embedClara.py | 24 + third_party/clara.hpp | 1211 ++++++++++++++++++++++++++++++++ 5 files changed, 1376 insertions(+), 42 deletions(-) create mode 100644 scripts/embed.py create mode 100644 scripts/embedClara.py create mode 100644 third_party/clara.hpp diff --git a/include/external/clara.hpp b/include/external/clara.hpp index f4ad627f..b2eced66 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -4,23 +4,40 @@ #ifndef CATCH_CLARA_HPP_INCLUDED #define CATCH_CLARA_HPP_INCLUDED + +#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 +#endif + + +// ----------- #included from clara_textflow.hpp ----------- + +// TextFlowCpp +// +// A single-header library for wrapping and laying out basic text, by Phil Nash +// +// This work is licensed under the BSD 2-Clause license. +// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause +// +// This project is hosted at https://github.com/philsquared/textflowcpp + +#ifndef CATCH_CLARA_TEXTFLOW_HPP_INCLUDED +#define CATCH_CLARA_TEXTFLOW_HPP_INCLUDED + + #include #include #include #include -#include -#include -#include -#ifndef CLARA_CONFIG_CONSOLE_WIDTH -#define CLARA_CONFIG_CONSOLE_WIDTH 80 +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH + #endif -namespace Catch { -namespace clara { -// Included from TextFlow.hpp -namespace TextFlow { +namespace Catch { namespace clara { namespace TextFlow +{ inline auto isWhitespace( char c ) -> bool { static std::string chars = " \t\n\r"; @@ -39,7 +56,7 @@ namespace TextFlow { class Column { std::vector m_strings; - size_t m_width = CLARA_CONFIG_CONSOLE_WIDTH; + size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; size_t m_indent = 0; size_t m_initialIndent = std::string::npos; @@ -51,12 +68,12 @@ namespace TextFlow { size_t m_stringIndex = 0; size_t m_pos = 0; - size_t m_len; + size_t m_len = 0; bool m_suffix = false; iterator( Column const& column, size_t stringIndex ) - : m_column( column ), - m_stringIndex( stringIndex ) + : m_column( column ), + m_stringIndex( stringIndex ) {} auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } @@ -143,9 +160,9 @@ namespace TextFlow { auto operator ==( iterator const& other ) const -> bool { return - m_pos == other.m_pos && - m_stringIndex == other.m_stringIndex && - &m_column == &other.m_column; + m_pos == other.m_pos && + m_stringIndex == other.m_stringIndex && + &m_column == &other.m_column; } auto operator !=( iterator const& other ) const -> bool { return !operator==( other ); @@ -171,7 +188,7 @@ namespace TextFlow { auto width() const -> size_t { return m_width; } auto begin() const -> iterator { return iterator( *this ); } - auto end() const -> iterator { return iterator( *this, m_strings.size() ); } + auto end() const -> iterator { return { *this, m_strings.size() }; } inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { bool first = true; @@ -197,7 +214,7 @@ namespace TextFlow { class Spacer : public Column { public: - Spacer( size_t spaceWidth ) : Column( "" ) { + explicit Spacer( size_t spaceWidth ) : Column( "" ) { width( spaceWidth ); } }; @@ -216,8 +233,8 @@ namespace TextFlow { size_t m_activeIterators; iterator( Columns const& columns, EndTag ) - : m_columns( columns.m_columns ), - m_activeIterators( 0 ) + : m_columns( columns.m_columns ), + m_activeIterators( 0 ) { m_iterators.reserve( m_columns.size() ); @@ -226,9 +243,9 @@ namespace TextFlow { } public: - iterator( Columns const& columns ) - : m_columns( columns.m_columns ), - m_activeIterators( m_columns.size() ) + explicit iterator( Columns const& columns ) + : m_columns( columns.m_columns ), + m_activeIterators( m_columns.size() ) { m_iterators.reserve( m_columns.size() ); @@ -277,7 +294,7 @@ namespace TextFlow { using const_iterator = iterator; auto begin() const -> iterator { return iterator( *this ); } - auto end() const -> iterator { return iterator( *this, iterator::EndTag() ); } + auto end() const -> iterator { return { *this, iterator::EndTag() }; } auto operator += ( Column const& col ) -> Columns& { m_columns.push_back( col ); @@ -315,9 +332,19 @@ namespace TextFlow { cols += other; return cols; } +}}} // namespace Catch::clara::TextFlow -} // namespace TextFlow +#endif // CATCH_CLARA_TEXTFLOW_HPP_INCLUDED +// ----------- end of #include from clara_textflow.hpp ----------- +// ........... back in clara.hpp + + +#include +#include +#include + +namespace Catch { namespace clara { namespace detail { // Traits for extracting arg and return type of lambdas (for single argument lambdas) @@ -475,8 +502,7 @@ namespace detail { new(&m_value) T(other.m_value); } - ResultValueBase(Type type, T const &value) - : ResultBase(Ok) { + ResultValueBase(Type, T const &value) : ResultBase(Ok) { new(&m_value) T(value); } @@ -600,10 +626,9 @@ namespace detail { target = source; return ParserResult::ok(ParseResultType::Matched); } - inline auto convertInto(std::string const &source, bool &target) -> ParserResult { std::string srcLC = source; - std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), ::tolower); + std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast( ::tolower(c) ); } ); if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") target = true; else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") @@ -869,7 +894,7 @@ namespace detail { public: using ParserRefImpl::ParserRefImpl; - auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { auto validationResult = validate(); if (!validationResult) return InternalParseResult(validationResult); @@ -941,10 +966,10 @@ namespace detail { using ParserBase::parse; - auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { - auto result = validate(); - if (!result) - return InternalParseResult(result); + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + auto validationResult = validate(); + if (!validationResult) + return InternalParseResult(validationResult); auto remainingTokens = tokens; if (remainingTokens && remainingTokens->type == TokenType::Option) { @@ -1069,6 +1094,7 @@ namespace detail { } auto rows = getHelpColumns(); + size_t consoleWidth = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; for (auto const &cols : rows) optWidth = std::max(optWidth, cols.left.size() + 2); @@ -1077,7 +1103,7 @@ namespace detail { auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + TextFlow::Spacer(4) + - TextFlow::Column(cols.right).width(73 - optWidth); + TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); os << row << std::endl; } } @@ -1131,7 +1157,7 @@ namespace detail { auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); while (result.value().remainingTokens()) { - int remainingTokenCount = result.value().remainingTokens().count(); + auto remainingTokenCount = result.value().remainingTokens().count(); for (auto parser : allParsers) { result = parser->parse( exeName, result.value().remainingTokens() ); if (!result || result.value().type() != ParseResultType::NoMatch) { @@ -1183,7 +1209,7 @@ using detail::ParseResultType; using detail::ParserResult; -} // namespace clara -} // namespace Catch +}} // namespace Catch::clara + #endif // CATCH_CLARA_HPP_INCLUDED diff --git a/include/internal/catch_clara.h b/include/internal/catch_clara.h index 9c66a55d..1aeb4658 100644 --- a/include/internal/catch_clara.h +++ b/include/internal/catch_clara.h @@ -11,10 +11,10 @@ // Use Catch's value for console width (store Clara's off to the side, if present) #ifdef CLARA_CONFIG_CONSOLE_WIDTH -#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH -#undef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH #endif -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #include "../external/clara.hpp" @@ -22,7 +22,7 @@ // Restore Clara's value for console width, if present #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH -#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #endif diff --git a/scripts/embed.py b/scripts/embed.py new file mode 100644 index 00000000..85a7fcfb --- /dev/null +++ b/scripts/embed.py @@ -0,0 +1,73 @@ +import re + +preprocessorRe = re.compile( r'\s*#.*' ) + +fdefineRe = re.compile( r'\s*#\s*define\s*(\S*)\s*\(' ) # #defines that take arguments +defineRe = re.compile( r'\s*#\s*define\s*(\S*)(\s+)(.*)' ) # all #defines +undefRe = re.compile( r'\s*#\s*undef\s*(\S*)' ) # all #undefs + +ifdefCommonRe = re.compile( r'\s*#\s*if' ) # all #ifdefs +ifdefRe = re.compile( r'\s*#\s*ifdef\s*(\S*)' ) +ifndefRe = re.compile( r'\s*#\s*ifndef\s*(\S*)' ) +endifRe = re.compile( r'\s*#\s*endif\s*//\s*(.*)' ) +elseRe = re.compile( r'\s*#\s*else' ) +ifRe = re.compile( r'\s*#\s*if\s+(.*)' ) + +nsRe = re.compile( r'(.*?\s*\s*namespace\s+)(\w+)(\s*{?)(.*)' ) +nsCloseRe = re.compile( r'(.*\s*})(\s*\/\/\s*namespace\s+)(\w+)(\s*)(.*)' ) + + +class LineMapper: + def __init__( self, idMap, outerNamespace ): + self.idMap = idMap + self.outerNamespace = outerNamespace + + def replaceId( self, lineNo, id ): + if not self.idMap.has_key( id ): + raise ValueError( "Unrecognised macro identifier: '{0}' on line: {1}".format( id, lineNo ) ) + subst = self.idMap[id] + if subst == "": + return id + else: + return subst + + # TBD: + # #if, #ifdef, comments after #else + def mapLine( self, lineNo, line ): + m = ifndefRe.match( line ) + if m: + return "#ifndef " + self.replaceId( lineNo, m.group(1)) + "\n" + m = defineRe.match( line ) + if m: + return "#define {0}{1}{2}\n".format( self.replaceId( lineNo, m.group(1)), m.group(2), m.group(3) ) + m = endifRe.match( line ) + if m: + return "#endif // " + self.replaceId( lineNo, m.group(1)) + "\n" + m = nsCloseRe.match( line ) + if m: + originalNs = m.group(3) + # print("[{0}] originalNs: '{1}' - closing".format(lineNo, originalNs)) + # print( " " + line ) + # print( " 1:[{0}]\n 2:[{1}]\n 3:[{2}]\n 4:[{3}]\n 5:[{4}]".format( m.group(1), m.group(2), m.group(3), m.group(4), m.group(5) ) ) + if self.outerNamespace.has_key(originalNs): + outerNs, innerNs = self.outerNamespace[originalNs] + return "{0}}}{1}{2}::{3}{4}{5}\n".format( m.group(1), m.group(2), outerNs, innerNs, m.group(4), m.group(5)) + m = nsRe.match( line ) + if m: + originalNs = m.group(2) + # print("[{0}] originalNs: '{1}'".format(lineNo, originalNs)) + # print( " " + line ) + # print( " 1:[{0}]\n 2:[{1}]\n 3:[{2}]\n 4:[{3}]".format( m.group(1), m.group(2), m.group(3), m.group(4) ) ) + if self.outerNamespace.has_key(originalNs): + outerNs, innerNs = self.outerNamespace[originalNs] + return "{0}{1} {{ namespace {2}{3}{4}\n".format( m.group(1), outerNs, innerNs, m.group(3), m.group(4) ) + return line + + def mapFile(self, filenameIn, filenameOut ): + print( "Embedding:\n {0}\nas:\n {1}".format( filenameIn, filenameOut ) ) + with open( filenameIn, 'r' ) as f, open( filenameOut, 'w' ) as outf: + lineNo = 1 + for line in f: + outf.write( self.mapLine( lineNo, line ) ) + lineNo = lineNo + 1 + print( "Written {0} lines".format( lineNo ) ) \ No newline at end of file diff --git a/scripts/embedClara.py b/scripts/embedClara.py new file mode 100644 index 00000000..a35c221e --- /dev/null +++ b/scripts/embedClara.py @@ -0,0 +1,24 @@ +# Execute this script any time you import a new copy of Clara into the third_party area +import os +import sys +import embed + +rootPath = os.path.dirname(os.path.realpath( os.path.dirname(sys.argv[0]))) + +filename = os.path.join( rootPath, "third_party", "clara.hpp" ) +outfilename = os.path.join( rootPath, "include", "external", "clara.hpp" ) + + +# Mapping of pre-processor identifiers +idMap = { + "CLARA_HPP_INCLUDED": "CATCH_CLARA_HPP_INCLUDED", + "CLARA_CONFIG_CONSOLE_WIDTH": "CATCH_CLARA_CONFIG_CONSOLE_WIDTH", + "CLARA_TEXTFLOW_HPP_INCLUDED": "CATCH_CLARA_TEXTFLOW_HPP_INCLUDED", + "CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH": "CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH" + } + +# outer namespace to add +outerNamespace = { "clara": ("Catch", "clara") } + +mapper = embed.LineMapper( idMap, outerNamespace ) +mapper.mapFile( filename, outfilename ) \ No newline at end of file diff --git a/third_party/clara.hpp b/third_party/clara.hpp new file mode 100644 index 00000000..5455e5af --- /dev/null +++ b/third_party/clara.hpp @@ -0,0 +1,1211 @@ +// v1.0 +// See https://github.com/philsquared/Clara + +#ifndef CLARA_HPP_INCLUDED +#define CLARA_HPP_INCLUDED + +#ifndef CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH 80 +#endif + + +// ----------- #included from clara_textflow.hpp ----------- + +// TextFlowCpp +// +// A single-header library for wrapping and laying out basic text, by Phil Nash +// +// This work is licensed under the BSD 2-Clause license. +// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause +// +// This project is hosted at https://github.com/philsquared/textflowcpp + +#ifndef CLARA_TEXTFLOW_HPP_INCLUDED +#define CLARA_TEXTFLOW_HPP_INCLUDED + +#include +#include +#include +#include + +#ifndef CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#endif + + +namespace clara { namespace TextFlow +{ + + inline auto isWhitespace( char c ) -> bool { + static std::string chars = " \t\n\r"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableBefore( char c ) -> bool { + static std::string chars = "[({<|"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableAfter( char c ) -> bool { + static std::string chars = "])}>.,:;*+-=&/\\"; + return chars.find( c ) != std::string::npos; + } + + class Columns; + + class Column { + std::vector m_strings; + size_t m_width = TEXTFLOW_CONFIG_CONSOLE_WIDTH; + size_t m_indent = 0; + size_t m_initialIndent = std::string::npos; + + public: + class iterator { + friend Column; + + Column const& m_column; + size_t m_stringIndex = 0; + size_t m_pos = 0; + + size_t m_len = 0; + bool m_suffix = false; + + iterator( Column const& column, size_t stringIndex ) + : m_column( column ), + m_stringIndex( stringIndex ) + {} + + auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } + + auto isBoundary( size_t at ) const -> bool { + assert( at > 0 ); + assert( at <= line().size() ); + + return at == line().size() || + ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || + isBreakableBefore( line()[at] ) || + isBreakableAfter( line()[at-1] ); + } + + void calcLength() { + assert( m_stringIndex < m_column.m_strings.size() ); + + m_suffix = false; + auto width = m_column.m_width-indent(); + if( line().size() < m_pos + width ) { + m_len = line().size() - m_pos; + } + else { + size_t len = width; + while (len > 0 && !isBoundary(m_pos + len)) + --len; + while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) + --len; + + if (len > 0) { + m_len = len; + } else { + m_suffix = true; + m_len = width - 1; + } + } + } + + auto indent() const -> size_t { + auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; + return initial == std::string::npos ? m_column.m_indent : initial; + } + + auto addIndentAndSuffix(std::string const &plain) const -> std::string { + return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); + } + + public: + explicit iterator( Column const& column ) : m_column( column ) { + assert( m_column.m_width > m_column.m_indent ); + assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); + calcLength(); + if( m_len == 0 ) + m_stringIndex++; // Empty string + } + + auto operator *() const -> std::string { + assert( m_stringIndex < m_column.m_strings.size() ); + assert( m_pos < line().size() ); + if( m_pos + m_column.m_width < line().size() ) + return addIndentAndSuffix(line().substr(m_pos, m_len)); + else + return addIndentAndSuffix(line().substr(m_pos)); + } + + auto operator ++() -> iterator& { + m_pos += m_len; + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) + ++m_pos; + + if( m_pos == line().size() ) { + m_pos = 0; + ++m_stringIndex; + } + if( m_stringIndex < m_column.m_strings.size() ) + calcLength(); + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + + auto operator ==( iterator const& other ) const -> bool { + return + m_pos == other.m_pos && + m_stringIndex == other.m_stringIndex && + &m_column == &other.m_column; + } + auto operator !=( iterator const& other ) const -> bool { + return !operator==( other ); + } + }; + using const_iterator = iterator; + + explicit Column( std::string const& text ) { m_strings.push_back( text ); } + + auto width( size_t newWidth ) -> Column& { + assert( newWidth > 0 ); + m_width = newWidth; + return *this; + } + auto indent( size_t newIndent ) -> Column& { + m_indent = newIndent; + return *this; + } + auto initialIndent( size_t newIndent ) -> Column& { + m_initialIndent = newIndent; + return *this; + } + + auto width() const -> size_t { return m_width; } + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, m_strings.size() }; } + + inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { + bool first = true; + for( auto line : col ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto operator + ( Column const& other ) -> Columns; + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + class Spacer : public Column { + + public: + explicit Spacer( size_t spaceWidth ) : Column( "" ) { + width( spaceWidth ); + } + }; + + class Columns { + std::vector m_columns; + + public: + + class iterator { + friend Columns; + struct EndTag {}; + + std::vector const& m_columns; + std::vector m_iterators; + size_t m_activeIterators; + + iterator( Columns const& columns, EndTag ) + : m_columns( columns.m_columns ), + m_activeIterators( 0 ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.end() ); + } + + public: + explicit iterator( Columns const& columns ) + : m_columns( columns.m_columns ), + m_activeIterators( m_columns.size() ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.begin() ); + } + + auto operator ==( iterator const& other ) const -> bool { + return m_iterators == other.m_iterators; + } + auto operator !=( iterator const& other ) const -> bool { + return m_iterators != other.m_iterators; + } + auto operator *() const -> std::string { + std::string row, padding; + + for( size_t i = 0; i < m_columns.size(); ++i ) { + auto width = m_columns[i].width(); + if( m_iterators[i] != m_columns[i].end() ) { + std::string col = *m_iterators[i]; + row += padding + col; + if( col.size() < width ) + padding = std::string( width - col.size(), ' ' ); + else + padding = ""; + } + else { + padding += std::string( width, ' ' ); + } + } + return row; + } + auto operator ++() -> iterator& { + for( size_t i = 0; i < m_columns.size(); ++i ) { + if (m_iterators[i] != m_columns[i].end()) + ++m_iterators[i]; + } + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + }; + using const_iterator = iterator; + + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, iterator::EndTag() }; } + + auto operator += ( Column const& col ) -> Columns& { + m_columns.push_back( col ); + return *this; + } + auto operator + ( Column const& col ) -> Columns { + Columns combined = *this; + combined += col; + return combined; + } + + inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) { + + bool first = true; + for( auto line : cols ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + inline auto Column::operator + ( Column const& other ) -> Columns { + Columns cols; + cols += *this; + cols += other; + return cols; + } +}} // namespace clara::TextFlow + +#endif // CLARA_TEXTFLOW_HPP_INCLUDED + +// ----------- end of #include from clara_textflow.hpp ----------- +// ........... back in clara.hpp + + +#include +#include +#include + +namespace clara { +namespace detail { + + // Traits for extracting arg and return type of lambdas (for single argument lambdas) + template + struct UnaryLambdaTraits : UnaryLambdaTraits {}; + + template + struct UnaryLambdaTraits { + static const bool isValid = false; + }; + + template + struct UnaryLambdaTraits { + static const bool isValid = true; + using ArgType = typename std::remove_const::type>::type;; + using ReturnType = ReturnT; + }; + + class TokenStream; + + // Transport for raw args (copied from main args, or supplied via init list for testing) + class Args { + friend TokenStream; + std::string m_exeName; + std::vector m_args; + + public: + Args(int argc, char *argv[]) { + m_exeName = argv[0]; + for (int i = 1; i < argc; ++i) + m_args.push_back(argv[i]); + } + + Args(std::initializer_list args) + : m_exeName( *args.begin() ), + m_args( args.begin()+1, args.end() ) + {} + + auto exeName() const -> std::string { + return m_exeName; + } + }; + + // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string + // may encode an option + its argument if the : or = form is used + enum class TokenType { + Option, Argument + }; + struct Token { + TokenType type; + std::string token; + }; + + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled + class TokenStream { + using Iterator = std::vector::const_iterator; + Iterator it; + Iterator itEnd; + std::vector m_tokenBuffer; + + void loadBuffer() { + m_tokenBuffer.resize(0); + + // Skip any empty strings + while (it != itEnd && it->empty()) + ++it; + + if (it != itEnd) { + auto const &next = *it; + if (next[0] == '-' || next[0] == '/') { + auto delimiterPos = next.find_first_of(" :="); + if (delimiterPos != std::string::npos) { + m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)}); + m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)}); + } else { + if (next[1] != '-' && next.size() > 2) { + std::string opt = "- "; + for (size_t i = 1; i < next.size(); ++i) { + opt[1] = next[i]; + m_tokenBuffer.push_back({TokenType::Option, opt}); + } + } else { + m_tokenBuffer.push_back({TokenType::Option, next}); + } + } + } else { + m_tokenBuffer.push_back({TokenType::Argument, next}); + } + } + } + + public: + explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} + + TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + loadBuffer(); + } + + explicit operator bool() const { + return !m_tokenBuffer.empty() || it != itEnd; + } + + auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } + + auto operator*() const -> Token { + assert(!m_tokenBuffer.empty()); + return m_tokenBuffer.front(); + } + + auto operator->() const -> Token const * { + assert(!m_tokenBuffer.empty()); + return &m_tokenBuffer.front(); + } + + auto operator++() -> TokenStream & { + if (m_tokenBuffer.size() >= 2) { + m_tokenBuffer.erase(m_tokenBuffer.begin()); + } else { + if (it != itEnd) + ++it; + loadBuffer(); + } + return *this; + } + }; + + + class ResultBase { + public: + enum Type { + Ok, LogicError, RuntimeError + }; + + protected: + ResultBase(Type type) : m_type(type) {} + + virtual void enforceOk() const = 0; + + Type m_type; + }; + + template + class ResultValueBase : public ResultBase { + public: + auto value() const -> T const & { + enforceOk(); + return m_value; + } + + protected: + ResultValueBase(Type type) : ResultBase(type) {} + + ResultValueBase(ResultValueBase const &other) : ResultBase(other) { + if (m_type == ResultBase::Ok) + new(&m_value) T(other.m_value); + } + + ResultValueBase(Type, T const &value) : ResultBase(Ok) { + new(&m_value) T(value); + } + + auto operator=(ResultValueBase const &other) -> ResultValueBase & { + if (m_type == ResultBase::Ok) + m_value.~T(); + ResultBase::operator=(other); + if (m_type == ResultBase::Ok) + new(&m_value) T(other.m_value); + return *this; + } + + ~ResultValueBase() { + if (m_type == Ok) + m_value.~T(); + } + + union { + T m_value; + }; + }; + + template<> + class ResultValueBase : public ResultBase { + protected: + using ResultBase::ResultBase; + }; + + template + class BasicResult : public ResultValueBase { + public: + template + explicit BasicResult(BasicResult const &other) + : ResultValueBase(other.type()), + m_errorMessage(other.errorMessage()) { + assert(type() != ResultBase::Ok); + } + + static auto ok() -> BasicResult { return {ResultBase::Ok}; } + + template + static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; } + + static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; } + + static auto runtimeError(std::string const &message) -> BasicResult { + return {ResultBase::RuntimeError, message}; + } + + explicit operator bool() const { return m_type == ResultBase::Ok; } + + auto type() const -> ResultBase::Type { return m_type; } + + auto errorMessage() const -> std::string { return m_errorMessage; } + + protected: + virtual void enforceOk() const { + // !TBD: If no exceptions, std::terminate here or something + switch (m_type) { + case ResultBase::LogicError: + throw std::logic_error(m_errorMessage); + case ResultBase::RuntimeError: + throw std::runtime_error(m_errorMessage); + case ResultBase::Ok: + break; + } + } + + std::string m_errorMessage; // Only populated if resultType is an error + + BasicResult(ResultBase::Type type, std::string const &message) + : ResultValueBase(type), + m_errorMessage(message) { + assert(m_type != ResultBase::Ok); + } + + using ResultValueBase::ResultValueBase; + using ResultBase::m_type; + }; + + enum class ParseResultType { + Matched, NoMatch, ShortCircuitAll, ShortCircuitSame + }; + + class ParseState { + public: + + ParseState(ParseResultType type, TokenStream const &remainingTokens) + : m_type(type), + m_remainingTokens(remainingTokens) {} + + auto type() const -> ParseResultType { return m_type; } + + auto remainingTokens() const -> TokenStream { return m_remainingTokens; } + + private: + ParseResultType m_type; + TokenStream m_remainingTokens; + }; + + using Result = BasicResult; + using ParserResult = BasicResult; + using InternalParseResult = BasicResult; + + struct HelpColumns { + std::string left; + std::string right; + }; + + template + inline auto convertInto(std::string const &source, T& target) -> ParserResult { + std::stringstream ss; + ss << source; + ss >> target; + if (ss.fail()) + return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type"); + else + return ParserResult::ok(ParseResultType::Matched); + } + inline auto convertInto(std::string const &source, std::string& target) -> ParserResult { + target = source; + return ParserResult::ok(ParseResultType::Matched); + } + inline auto convertInto(std::string const &source, bool &target) -> ParserResult { + std::string srcLC = source; + std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast( ::tolower(c) ); } ); + if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") + target = true; + else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") + target = false; + else + return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'"); + return ParserResult::ok(ParseResultType::Matched); + } + + struct BoundRefBase { + BoundRefBase() = default; + + BoundRefBase(BoundRefBase const &) = delete; + + BoundRefBase(BoundRefBase &&) = delete; + + BoundRefBase &operator=(BoundRefBase const &) = delete; + + BoundRefBase &operator=(BoundRefBase &&) = delete; + + virtual ~BoundRefBase() = default; + + virtual auto isFlag() const -> bool = 0; + + virtual auto isContainer() const -> bool { return false; } + + virtual auto setValue(std::string const &arg) -> ParserResult = 0; + + virtual auto setFlag(bool flag) -> ParserResult = 0; + }; + + struct BoundValueRefBase : BoundRefBase { + auto isFlag() const -> bool override { return false; } + + auto setFlag(bool) -> ParserResult override { + return ParserResult::logicError("Flags can only be set on boolean fields"); + } + }; + + struct BoundFlagRefBase : BoundRefBase { + auto isFlag() const -> bool override { return true; } + + auto setValue(std::string const &arg) -> ParserResult override { + bool flag; + auto result = convertInto(arg, flag); + if (result) + setFlag(flag); + return result; + } + }; + + template + struct BoundRef : BoundValueRefBase { + T &m_ref; + + explicit BoundRef(T &ref) : m_ref(ref) {} + + auto setValue(std::string const &arg) -> ParserResult override { + return convertInto(arg, m_ref); + } + }; + + template + struct BoundRef> : BoundValueRefBase { + std::vector &m_ref; + + explicit BoundRef(std::vector &ref) : m_ref(ref) {} + + auto isContainer() const -> bool override { return true; } + + auto setValue(std::string const &arg) -> ParserResult override { + T temp; + auto result = convertInto(arg, temp); + if (result) + m_ref.push_back(temp); + return result; + } + }; + + struct BoundFlagRef : BoundFlagRefBase { + bool &m_ref; + + explicit BoundFlagRef(bool &ref) : m_ref(ref) {} + + auto setFlag(bool flag) -> ParserResult override { + m_ref = flag; + return ParserResult::ok(ParseResultType::Matched); + } + }; + + template + struct LambdaInvoker { + static_assert(std::is_same::value, "Lambda must return void or clara::ParserResult"); + + template + static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { + return lambda(arg); + } + }; + + template<> + struct LambdaInvoker { + template + static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { + lambda(arg); + return ParserResult::ok(ParseResultType::Matched); + } + }; + + template + inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { + ArgType temp; + auto result = convertInto(arg, temp); + return !result + ? result + : LambdaInvoker::ReturnType>::invoke(lambda, temp); + }; + + + template + struct BoundLambda : BoundValueRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} + + auto setValue(std::string const &arg) -> ParserResult override { + return invokeLambda::ArgType>(m_lambda, arg); + } + }; + + template + struct BoundFlagLambda : BoundFlagRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); + + explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} + + auto setFlag(bool flag) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke(m_lambda, flag); + } + }; + + enum class Optionality { + Optional, Required + }; + + struct Parser; + + class ParserBase { + public: + virtual auto validate() const -> Result { return Result::ok(); } + + virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; + + virtual auto cardinality() const -> size_t { return 1; } + + auto parse(Args const &args) const -> InternalParseResult { + return parse( args.exeName(), TokenStream(args)); + } + }; + + template + class ComposableParserImpl : public ParserBase { + public: + template + auto operator+(T const &other) const -> Parser; + }; + + // Common code and state for Args and Opts + template + class ParserRefImpl : public ComposableParserImpl { + protected: + Optionality m_optionality = Optionality::Optional; + std::shared_ptr m_ref; + std::string m_hint; + std::string m_description; + + explicit ParserRefImpl(std::shared_ptr const &ref) : m_ref(ref) {} + + public: + template + ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), m_hint(hint) {} + + template + ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), + m_hint(hint) {} + + auto operator()(std::string const &description) -> DerivedT & { + m_description = description; + return static_cast( *this ); + } + + auto optional() -> DerivedT & { + m_optionality = Optionality::Optional; + return static_cast( *this ); + }; + + auto required() -> DerivedT & { + m_optionality = Optionality::Required; + return static_cast( *this ); + }; + + auto isOptional() const -> bool { + return m_optionality == Optionality::Optional; + } + + auto cardinality() const -> size_t override { + if (m_ref->isContainer()) + return 0; + else + return 1; + } + + auto hint() const -> std::string { return m_hint; } + }; + + class ExeName : public ComposableParserImpl { + std::shared_ptr m_name; + std::shared_ptr m_ref; + + template + static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { + return std::make_shared>(lambda); + } + + public: + ExeName() : m_name(std::make_shared("")) {} + + explicit ExeName(std::string &ref) : ExeName() { + m_ref = std::make_shared>( ref ); + } + + template + explicit ExeName( LambdaT const& lambda ) : ExeName() { + m_ref = std::make_shared>( lambda ); + } + + // The exe name is not parsed out of the normal tokens, but is handled specially + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + } + + auto name() const -> std::string { return *m_name; } + auto set( std::string const& newName ) -> ParserResult { + + auto lastSlash = newName.find_last_of( "\\/" ); + auto filename = (lastSlash == std::string::npos) + ? newName + : newName.substr( lastSlash+1 ); + + *m_name = filename; + if( m_ref ) + return m_ref->setValue( filename ); + else + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + class Arg : public ParserRefImpl { + public: + using ParserRefImpl::ParserRefImpl; + + auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { + auto validationResult = validate(); + if (!validationResult) + return InternalParseResult(validationResult); + + auto remainingTokens = tokens; + auto const &token = *remainingTokens; + if (token.type != TokenType::Argument) + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + + auto result = m_ref->setValue(remainingTokens->token); + if (!result) + return InternalParseResult(result); + else + return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + } + }; + + inline auto normaliseOpt(std::string const &optName) -> std::string { + if (optName[0] == '/') + return "-" + optName.substr(1); + else + return optName; + } + + class Opt : public ParserRefImpl { + protected: + std::vector m_optNames; + + public: + using ParserRefImpl::ParserRefImpl; + + template + explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} + + explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + + auto operator[](std::string const &optName) -> Opt & { + m_optNames.push_back(optName); + return *this; + } + + auto getHelpColumns() const -> std::vector { + std::ostringstream oss; + bool first = true; + for (auto const &opt : m_optNames) { + if (first) + first = false; + else + oss << ", "; + oss << opt; + } + if (!m_hint.empty()) + oss << " <" << m_hint << ">"; + return {{oss.str(), m_description}}; + } + + auto isMatch(std::string const &optToken) const -> bool { +#ifdef CLARA_PLATFORM_WINDOWS + auto normalisedToken = normaliseOpt( optToken ); +#else + auto const &normalisedToken = optToken; +#endif + for (auto const &name : m_optNames) { + if (normaliseOpt(name) == normalisedToken) + return true; + } + return false; + } + + using ParserBase::parse; + + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + auto validationResult = validate(); + if (!validationResult) + return InternalParseResult(validationResult); + + auto remainingTokens = tokens; + if (remainingTokens && remainingTokens->type == TokenType::Option) { + auto const &token = *remainingTokens; + if (isMatch(token.token)) { + if (m_ref->isFlag()) { + auto result = m_ref->setFlag(true); + if (!result) + return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + } else { + ++remainingTokens; + if (!remainingTokens) + return InternalParseResult::runtimeError("Expected argument following " + token.token); + auto const &argToken = *remainingTokens; + if (argToken.type != TokenType::Argument) + return InternalParseResult::runtimeError("Expected argument following " + token.token); + auto result = m_ref->setValue(argToken.token); + if (!result) + return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + } + return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + } + } + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + } + + auto validate() const -> Result override { + if (m_optNames.empty()) + return Result::logicError("No options supplied to Opt"); + for (auto const &name : m_optNames) { + if (name.empty()) + return Result::logicError("Option name cannot be empty"); + if (name[0] != '-' && name[0] != '/') + return Result::logicError("Option name must begin with '-' or '/'"); + } + return ParserRefImpl::validate(); + } + }; + + struct Help : Opt { + Help( bool &showHelpFlag ) + : Opt([&]( bool flag ) { + showHelpFlag = flag; + return ParserResult::ok(ParseResultType::ShortCircuitAll); + }) + { + static_cast(*this) + ("display usage information") + ["-?"]["-h"]["--help"] + .optional(); + } + }; + + + struct Parser : ParserBase { + + mutable ExeName m_exeName; + std::vector m_options; + std::vector m_args; + + auto operator+=(ExeName const &exeName) -> Parser & { + m_exeName = exeName; + return *this; + } + + auto operator+=(Arg const &arg) -> Parser & { + m_args.push_back(arg); + return *this; + } + + auto operator+=(Opt const &opt) -> Parser & { + m_options.push_back(opt); + return *this; + } + + auto operator+=(Parser const &other) -> Parser & { + m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); + m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); + return *this; + } + + template + auto operator+(T const &other) const -> Parser { + return Parser(*this) += other; + } + + auto getHelpColumns() const -> std::vector { + std::vector cols; + for (auto const &o : m_options) { + auto childCols = o.getHelpColumns(); + cols.insert(cols.end(), childCols.begin(), childCols.end()); + } + return cols; + } + + void writeToStream(std::ostream &os) const { + if (!m_exeName.name().empty()) { + os << "usage:\n" << " " << m_exeName.name() << " "; + bool required = true, first = true; + for (auto const &arg : m_args) { + if (first) + first = false; + else + os << " "; + if (arg.isOptional() && required) { + os << "["; + required = false; + } + os << "<" << arg.hint() << ">"; + if (arg.cardinality() == 0) + os << " ... "; + } + if (!required) + os << "]"; + if (!m_options.empty()) + os << " options"; + os << "\n\nwhere options are:" << std::endl; + } + + auto rows = getHelpColumns(); + size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; + size_t optWidth = 0; + for (auto const &cols : rows) + optWidth = std::max(optWidth, cols.left.size() + 2); + + for (auto const &cols : rows) { + auto row = + TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Spacer(4) + + TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); + os << row << std::endl; + } + } + + friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { + parser.writeToStream(os); + return os; + } + + auto validate() const -> Result override { + for (auto const &opt : m_options) { + auto result = opt.validate(); + if (!result) + return result; + } + for (auto const &arg : m_args) { + auto result = arg.validate(); + if (!result) + return result; + } + return Result::ok(); + } + + using ParserBase::parse; + + auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override { + std::vector allParsers; + allParsers.reserve(m_args.size() + m_options.size()); + std::set requiredParsers; + + for (auto const &opt : m_options) { + allParsers.push_back(&opt); + if (!opt.isOptional()) + requiredParsers.insert(&opt); + } + + size_t optionalArgs = 0; + for (auto const &arg : m_args) { + allParsers.push_back(&arg); + if (!arg.isOptional()) { + if (optionalArgs > 0) + return InternalParseResult::logicError( + "Required arguments must preceed any optional arguments"); + else + ++optionalArgs; + requiredParsers.insert(&arg); + } + } + + m_exeName.set( exeName ); + + auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + while (result.value().remainingTokens()) { + auto remainingTokenCount = result.value().remainingTokens().count(); + for (auto parser : allParsers) { + result = parser->parse( exeName, result.value().remainingTokens() ); + if (!result || result.value().type() != ParseResultType::NoMatch) { + if (parser->cardinality() == 1) + allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser), + allParsers.end()); + requiredParsers.erase(parser); + break; + } + } + if (!result || remainingTokenCount == result.value().remainingTokens().count()) + return result; + } + // !TBD Check missing required options + return result; + } + }; + + template + template + auto ComposableParserImpl::operator+(T const &other) const -> Parser { + return Parser() + static_cast( *this ) + other; + } +} // namespace detail + + +// A Combined parser +using detail::Parser; + +// A parser for options +using detail::Opt; + +// A parser for arguments +using detail::Arg; + +// Wrapper for argc, argv from main() +using detail::Args; + +// Specifies the name of the executable +using detail::ExeName; + +// Convenience wrapper for option parser that specifies the help option +using detail::Help; + +// enum of result types from a parse +using detail::ParseResultType; + +// Result type for parser operation +using detail::ParserResult; + + +} // namespace clara + +#endif // CLARA_HPP_INCLUDED From d81c1eb00699e469d13b998c222a929d121cb0d1 Mon Sep 17 00:00:00 2001 From: philsquared Date: Tue, 20 Jun 2017 22:35:35 +0100 Subject: [PATCH 078/398] added version of Clara that has virtual destructors (just to silence warnings - they are not actually needed) --- include/external/clara.hpp | 2 ++ third_party/clara.hpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index b2eced66..03fdf298 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -480,6 +480,7 @@ namespace detail { protected: ResultBase(Type type) : m_type(type) {} + virtual ~ResultBase() = default; virtual void enforceOk() const = 0; @@ -782,6 +783,7 @@ namespace detail { class ParserBase { public: + virtual ~ParserBase() = default; virtual auto validate() const -> Result { return Result::ok(); } virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 5455e5af..5ee18df1 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -477,6 +477,7 @@ namespace detail { protected: ResultBase(Type type) : m_type(type) {} + virtual ~ResultBase() = default; virtual void enforceOk() const = 0; @@ -779,6 +780,7 @@ namespace detail { class ParserBase { public: + virtual ~ParserBase() = default; virtual auto validate() const -> Result { return Result::ok(); } virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; From c43d5f673fe781f043119c2cb11e50069860b199 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 21 Jun 2017 08:54:34 +0100 Subject: [PATCH 079/398] Moved command line lambdas out-of-line in an attempt to fix VS ICEs --- include/internal/catch_commandline.hpp | 84 ++++++++++++++------------ 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index e3e32fa4..ea2d7e45 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -19,10 +19,18 @@ namespace Catch { inline clara::Parser makeCommandLineParser( ConfigData& config ) { + using namespace clara; + + auto const setWarning = [&]( std::string const& warning ) { + if( warning != "NoAssertions" ) + return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + return ParserResult::ok( ParseResultType::Matched ); + }; auto const loadTestNamesFromFile = [&]( std::string const& filename ) { std::ifstream f( filename.c_str() ); if( !f.is_open() ) - return clara::ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); + return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); std::string line; while( std::getline( f, line ) ) { @@ -33,11 +41,39 @@ namespace Catch { config.testsOrTags.push_back( line + ',' ); } } - return clara::ParserResult::ok( clara::ParseResultType::Matched ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setTestOrder = [&]( std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setRngSeed = [&]( std::string const& seed ) { + if( seed != "time" ) + return clara::detail::convertInto( seed, config.rngSeed ); + config.rngSeed = static_cast( std::time(0) ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setColourUsage = [&]( std::string const& useColour ) { + auto mode = toLower( useColour ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); }; - - using namespace clara; auto cli = ExeName( config.processName ) + Help( config.showHelp ) @@ -74,12 +110,7 @@ namespace Catch { + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) ["-x"]["--abortx"] ( "abort after x failures" ) - + Opt( [&]( std::string const& warning ) { - if( warning != "NoAssertions" ) - return clara::ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - return clara::ParserResult::ok( ParseResultType::Matched ); - }, "warning name" ) + + Opt( setWarning, "warning name" ) ["-w"]["--warn"] ( "enable warnings" ) + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) @@ -100,40 +131,13 @@ namespace Catch { + Opt( config.listReporters ) ["--list-reporters"] ( "list all reporters" ) - + Opt( [&]( std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); - return clara::ParserResult::ok( ParseResultType::Matched ); - }, "decl|lex|rand" ) + + Opt( setTestOrder, "decl|lex|rand" ) ["--order"] ( "test case order (defaults to decl)" ) - + Opt( [&]( std::string const& seed ) { - if( seed != "time" ) - return clara::detail::convertInto( seed, config.rngSeed ); - config.rngSeed = static_cast( std::time(0) ); - return clara::ParserResult::ok( ParseResultType::Matched ); - }, "'time'|number" ) + + Opt( setRngSeed, "'time'|number" ) ["--rng-seed"] ( "set a specific seed for random numbers" ) - + Opt( [&]( std::string const& useColour ) { - auto mode = toLower( useColour ); - - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - return clara::ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); - return clara::ParserResult::ok( ParseResultType::Matched ); - }, "yes|no" ) + + Opt( setColourUsage, "yes|no" ) ["--use-colour"] ( "should output be colourised" ) From e0c6c4aee7f22e8a47dbe07cd497d2e5fd5fe205 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 21 Jun 2017 09:40:52 +0100 Subject: [PATCH 080/398] Another attempt to fix VS ICEs - split cli parser up. --- include/internal/catch_commandline.hpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index ea2d7e45..66359a11 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -74,7 +74,7 @@ namespace Catch { return ParserResult::ok( ParseResultType::Matched ); }; - auto cli + auto cli1 = ExeName( config.processName ) + Help( config.showHelp ) + Opt( config.listTests ) @@ -94,8 +94,10 @@ namespace Catch { ( "skip exception tests" ) + Opt( config.showInvisibles ) ["-i"]["--invisibles"] - ( "show invisibles (tabs, newlines)" ) - + Opt( config.outputFilename, "filename" ) + ( "show invisibles (tabs, newlines)" ); + + auto cli2 + = Opt( config.outputFilename, "filename" ) ["-o"]["--out"] ( "output filename" ) + Opt( config.reporterNames, "name" ) @@ -118,8 +120,10 @@ namespace Catch { ( "show test durations" ) + Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] - ( "load test names to run from a file" ) - + Opt( config.filenamesAsTags ) + ( "load test names to run from a file" ); + + auto cli3 + = Opt( config.filenamesAsTags ) ["-#"]["--filenames-as-tags"] ( "adds a tag for the filename" ) + Opt( config.sectionsToRun, "section name" ) @@ -144,7 +148,8 @@ namespace Catch { + Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); - return cli; + // Assemble from smaller parsers because some VS versions give ICEs otherwise + return cli1 + cli2 + cli3; } } // end namespace Catch From 3bb16e8418d471c59c3ab1eca1281773c329403a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 21 Jun 2017 11:42:53 +0100 Subject: [PATCH 081/398] Reorganised CLI again in another attempt to get past VS ICEs --- include/internal/catch_commandline.hpp | 95 ++++++++++++-------------- 1 file changed, 45 insertions(+), 50 deletions(-) diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 66359a11..481c5d06 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -74,82 +74,77 @@ namespace Catch { return ParserResult::ok( ParseResultType::Matched ); }; - auto cli1 + auto cli = ExeName( config.processName ) - + Help( config.showHelp ) - + Opt( config.listTests ) + + Help( config.showHelp ); + + cli += Opt( config.listTests ) ["-l"]["--list-tests"] - ( "list all/matching test cases" ) - + Opt( config.listTags ) + ( "list all/matching test cases" ); + cli += Opt( config.listTags ) ["-t"]["--list-tags"] - ( "list all/matching tags" ) - + Opt( config.showSuccessfulTests ) + ( "list all/matching tags" ); + cli += Opt( config.showSuccessfulTests ) ["-s"]["--success"] - ( "include successful tests in output" ) - + Opt( config.shouldDebugBreak ) + ( "include successful tests in output" ); + cli += Opt( config.shouldDebugBreak ) ["-b"]["--break"] - ( "break into debugger on failure" ) - + Opt( config.noThrow ) + ( "break into debugger on failure" ); + cli += Opt( config.noThrow ) ["-e"]["--nothrow"] - ( "skip exception tests" ) - + Opt( config.showInvisibles ) + ( "skip exception tests" ); + cli += Opt( config.showInvisibles ) ["-i"]["--invisibles"] ( "show invisibles (tabs, newlines)" ); - - auto cli2 - = Opt( config.outputFilename, "filename" ) + cli += Opt( config.outputFilename, "filename" ) ["-o"]["--out"] - ( "output filename" ) - + Opt( config.reporterNames, "name" ) + ( "output filename" ); + cli += Opt( config.reporterNames, "name" ) ["-r"]["--reporter"] - ( "reporter to use (defaults to console)" ) - + Opt( config.name, "name" ) + ( "reporter to use (defaults to console)" ); + cli += Opt( config.name, "name" ) ["-n"]["--name"] - ( "suite name" ) - + Opt( [&]( bool ){ config.abortAfter = 1; } ) + ( "suite name" ); + cli += Opt( [&]( bool ){ config.abortAfter = 1; } ) ["-a"]["--abort"] - ( "abort at first failure" ) - + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + ( "abort at first failure" ); + cli += Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) ["-x"]["--abortx"] - ( "abort after x failures" ) - + Opt( setWarning, "warning name" ) + ( "abort after x failures" ); + cli += Opt( setWarning, "warning name" ) ["-w"]["--warn"] - ( "enable warnings" ) - + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) + ( "enable warnings" ); + cli += Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) ["-d"]["--durations"] - ( "show test durations" ) - + Opt( loadTestNamesFromFile, "filename" ) + ( "show test durations" ); + cli += Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] ( "load test names to run from a file" ); - - auto cli3 - = Opt( config.filenamesAsTags ) + cli += Opt( config.filenamesAsTags ) ["-#"]["--filenames-as-tags"] - ( "adds a tag for the filename" ) - + Opt( config.sectionsToRun, "section name" ) + ( "adds a tag for the filename" ); + cli += Opt( config.sectionsToRun, "section name" ) ["-c"]["--section"] - ( "specify section to run" ) - + Opt( config.listTestNamesOnly ) + ( "specify section to run" ); + cli += Opt( config.listTestNamesOnly ) ["--list-test-names-only"] - ( "list all/matching test cases names only" ) - + Opt( config.listReporters ) + ( "list all/matching test cases names only" ); + cli += Opt( config.listReporters ) ["--list-reporters"] - ( "list all reporters" ) - + Opt( setTestOrder, "decl|lex|rand" ) + ( "list all reporters" ); + cli += Opt( setTestOrder, "decl|lex|rand" ) ["--order"] - ( "test case order (defaults to decl)" ) - + Opt( setRngSeed, "'time'|number" ) + ( "test case order (defaults to decl)" ); + cli += Opt( setRngSeed, "'time'|number" ) ["--rng-seed"] - ( "set a specific seed for random numbers" ) - + Opt( setColourUsage, "yes|no" ) + ( "set a specific seed for random numbers" ); + cli += Opt( setColourUsage, "yes|no" ) ["--use-colour"] - ( "should output be colourised" ) - - + Arg( config.testsOrTags, "test name|pattern|tags" ) + ( "should output be colourised" ); + cli += Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); - // Assemble from smaller parsers because some VS versions give ICEs otherwise - return cli1 + cli2 + cli3; + return cli; } } // end namespace Catch From 0470b300a8100828b8a1de7e0aae089ca91f66b3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 22 Jun 2017 15:52:01 +0100 Subject: [PATCH 082/398] =?UTF-8?q?Reverted=20previous=20two=20commits=20a?= =?UTF-8?q?s=20they=20didn=E2=80=99t=20fix=20anything?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/internal/catch_commandline.hpp | 90 +++++++++++++------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 481c5d06..ea2d7e45 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -76,72 +76,72 @@ namespace Catch { auto cli = ExeName( config.processName ) - + Help( config.showHelp ); - - cli += Opt( config.listTests ) + + Help( config.showHelp ) + + Opt( config.listTests ) ["-l"]["--list-tests"] - ( "list all/matching test cases" ); - cli += Opt( config.listTags ) + ( "list all/matching test cases" ) + + Opt( config.listTags ) ["-t"]["--list-tags"] - ( "list all/matching tags" ); - cli += Opt( config.showSuccessfulTests ) + ( "list all/matching tags" ) + + Opt( config.showSuccessfulTests ) ["-s"]["--success"] - ( "include successful tests in output" ); - cli += Opt( config.shouldDebugBreak ) + ( "include successful tests in output" ) + + Opt( config.shouldDebugBreak ) ["-b"]["--break"] - ( "break into debugger on failure" ); - cli += Opt( config.noThrow ) + ( "break into debugger on failure" ) + + Opt( config.noThrow ) ["-e"]["--nothrow"] - ( "skip exception tests" ); - cli += Opt( config.showInvisibles ) + ( "skip exception tests" ) + + Opt( config.showInvisibles ) ["-i"]["--invisibles"] - ( "show invisibles (tabs, newlines)" ); - cli += Opt( config.outputFilename, "filename" ) + ( "show invisibles (tabs, newlines)" ) + + Opt( config.outputFilename, "filename" ) ["-o"]["--out"] - ( "output filename" ); - cli += Opt( config.reporterNames, "name" ) + ( "output filename" ) + + Opt( config.reporterNames, "name" ) ["-r"]["--reporter"] - ( "reporter to use (defaults to console)" ); - cli += Opt( config.name, "name" ) + ( "reporter to use (defaults to console)" ) + + Opt( config.name, "name" ) ["-n"]["--name"] - ( "suite name" ); - cli += Opt( [&]( bool ){ config.abortAfter = 1; } ) + ( "suite name" ) + + Opt( [&]( bool ){ config.abortAfter = 1; } ) ["-a"]["--abort"] - ( "abort at first failure" ); - cli += Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + ( "abort at first failure" ) + + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) ["-x"]["--abortx"] - ( "abort after x failures" ); - cli += Opt( setWarning, "warning name" ) + ( "abort after x failures" ) + + Opt( setWarning, "warning name" ) ["-w"]["--warn"] - ( "enable warnings" ); - cli += Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) + ( "enable warnings" ) + + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) ["-d"]["--durations"] - ( "show test durations" ); - cli += Opt( loadTestNamesFromFile, "filename" ) + ( "show test durations" ) + + Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] - ( "load test names to run from a file" ); - cli += Opt( config.filenamesAsTags ) + ( "load test names to run from a file" ) + + Opt( config.filenamesAsTags ) ["-#"]["--filenames-as-tags"] - ( "adds a tag for the filename" ); - cli += Opt( config.sectionsToRun, "section name" ) + ( "adds a tag for the filename" ) + + Opt( config.sectionsToRun, "section name" ) ["-c"]["--section"] - ( "specify section to run" ); - cli += Opt( config.listTestNamesOnly ) + ( "specify section to run" ) + + Opt( config.listTestNamesOnly ) ["--list-test-names-only"] - ( "list all/matching test cases names only" ); - cli += Opt( config.listReporters ) + ( "list all/matching test cases names only" ) + + Opt( config.listReporters ) ["--list-reporters"] - ( "list all reporters" ); - cli += Opt( setTestOrder, "decl|lex|rand" ) + ( "list all reporters" ) + + Opt( setTestOrder, "decl|lex|rand" ) ["--order"] - ( "test case order (defaults to decl)" ); - cli += Opt( setRngSeed, "'time'|number" ) + ( "test case order (defaults to decl)" ) + + Opt( setRngSeed, "'time'|number" ) ["--rng-seed"] - ( "set a specific seed for random numbers" ); - cli += Opt( setColourUsage, "yes|no" ) + ( "set a specific seed for random numbers" ) + + Opt( setColourUsage, "yes|no" ) ["--use-colour"] - ( "should output be colourised" ); - cli += Arg( config.testsOrTags, "test name|pattern|tags" ) + ( "should output be colourised" ) + + + Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); return cli; From 2462dff088c3c51225f571c3961119649c86d31d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 22 Jun 2017 16:07:05 +0100 Subject: [PATCH 083/398] Updated Clara with VS ICE workaround --- include/external/clara.hpp | 15 ++++++++------- third_party/clara.hpp | 14 ++++++++------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 03fdf298..12a64522 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -31,8 +31,7 @@ #include #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH - +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 #endif @@ -785,9 +784,7 @@ namespace detail { public: virtual ~ParserBase() = default; virtual auto validate() const -> Result { return Result::ok(); } - virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; - virtual auto cardinality() const -> size_t { return 1; } auto parse(Args const &args) const -> InternalParseResult { @@ -926,13 +923,17 @@ namespace detail { std::vector m_optNames; public: - using ParserRefImpl::ParserRefImpl; - template explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + template + Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + template + Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + auto operator[](std::string const &optName) -> Opt & { m_optNames.push_back(optName); return *this; @@ -1096,7 +1097,7 @@ namespace detail { } auto rows = getHelpColumns(); - size_t consoleWidth = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; + size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; for (auto const &cols : rows) optWidth = std::max(optWidth, cols.left.size() + 2); diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 5ee18df1..95f28268 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -29,7 +29,7 @@ #include #ifndef CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH -#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 #endif @@ -53,7 +53,7 @@ namespace clara { namespace TextFlow class Column { std::vector m_strings; - size_t m_width = TEXTFLOW_CONFIG_CONSOLE_WIDTH; + size_t m_width = CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; size_t m_indent = 0; size_t m_initialIndent = std::string::npos; @@ -782,9 +782,7 @@ namespace detail { public: virtual ~ParserBase() = default; virtual auto validate() const -> Result { return Result::ok(); } - virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; - virtual auto cardinality() const -> size_t { return 1; } auto parse(Args const &args) const -> InternalParseResult { @@ -923,13 +921,17 @@ namespace detail { std::vector m_optNames; public: - using ParserRefImpl::ParserRefImpl; - template explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + template + Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + template + Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + auto operator[](std::string const &optName) -> Opt & { m_optNames.push_back(optName); return *this; From 0eb101e165df425a4f15bf5e8e8c371e3b790d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 22 Jun 2017 18:13:05 +0200 Subject: [PATCH 084/398] Remove "second argument" from result builder and assertion result This is not quite complete removal (it doesn't pass approval tests), but it should be representative of full perf improvements from doing so --- include/internal/catch_assertionresult.h | 4 +--- include/internal/catch_assertionresult.hpp | 17 ++++++++--------- include/internal/catch_capture.hpp | 2 +- include/internal/catch_result_builder.h | 3 +-- include/internal/catch_result_builder.hpp | 9 ++++----- 5 files changed, 15 insertions(+), 20 deletions(-) diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 5d6c86d1..87e85990 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -43,14 +43,12 @@ namespace Catch { AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition, - char const * _secondArg = ""); + ResultDisposition::Flags _resultDisposition); char const * macroName; SourceLineInfo lineInfo; char const * capturedExpression; ResultDisposition::Flags resultDisposition; - char const * secondArg; }; struct AssertionResultData diff --git a/include/internal/catch_assertionresult.hpp b/include/internal/catch_assertionresult.hpp index 2fa3373d..b4038ade 100644 --- a/include/internal/catch_assertionresult.hpp +++ b/include/internal/catch_assertionresult.hpp @@ -16,13 +16,11 @@ namespace Catch { AssertionInfo::AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition, - char const * _secondArg) + ResultDisposition::Flags _resultDisposition) : macroName( _macroName ), lineInfo( _lineInfo ), capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ), - secondArg( _secondArg ) + resultDisposition( _resultDisposition ) {} AssertionResult::AssertionResult() {} @@ -63,16 +61,17 @@ namespace Catch { } std::string AssertionResult::getExpression() const { - if( isFalseTest( m_info.resultDisposition ) ) - return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); + if (isFalseTest(m_info.resultDisposition)) + return '!' + std::string(m_info.capturedExpression); else - return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); + return std::string(m_info.capturedExpression); } + std::string AssertionResult::getExpressionInMacro() const { if( m_info.macroName[0] == 0 ) - return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); + return std::string(m_info.capturedExpression); else - return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; + return std::string(m_info.macroName) + "( " + m_info.capturedExpression + " )"; } bool AssertionResult::hasExpandedExpression() const { diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index a6d25dad..968bf79e 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -107,7 +107,7 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #matcher, resultDisposition); \ if( __catchResult.allowThrows() ) \ try { \ static_cast(expr); \ diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 82494566..1e8bff52 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -37,8 +37,7 @@ namespace Catch { ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg = "" ); + ResultDisposition::Flags resultDisposition); ~ResultBuilder(); template diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index 510fbc3b..f3688de5 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -21,9 +21,8 @@ namespace Catch { ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition, - char const* secondArg ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ), + ResultDisposition::Flags resultDisposition) + : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition), m_shouldDebugBreak( false ), m_shouldThrow( false ), m_guardException( false ) @@ -77,7 +76,7 @@ namespace Catch { assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; - data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); + data.reconstructedExpression = m_assertionInfo.capturedExpression; std::string actualMessage = Catch::translateActiveException(); if( !matcher.match( actualMessage ) ) { @@ -149,7 +148,7 @@ namespace Catch { } void ResultBuilder::reconstructExpression( std::string& dest ) const { - dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); + dest = m_assertionInfo.capturedExpression; } void ResultBuilder::setExceptionGuard() { From af661065007abe7fe3cafbdc986f581eb58add2a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 23 Jun 2017 09:08:44 +0100 Subject: [PATCH 085/398] Updated Clara with handling for / on Windows --- include/external/clara.hpp | 5 +++++ scripts/embedClara.py | 3 ++- third_party/clara.hpp | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 12a64522..5a13080c 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -343,6 +343,11 @@ namespace Catch { namespace clara { namespace TextFlow #include #include +#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CLARA_PLATFORM_WINDOWS + +#endif + namespace Catch { namespace clara { namespace detail { diff --git a/scripts/embedClara.py b/scripts/embedClara.py index a35c221e..3a861549 100644 --- a/scripts/embedClara.py +++ b/scripts/embedClara.py @@ -14,7 +14,8 @@ idMap = { "CLARA_HPP_INCLUDED": "CATCH_CLARA_HPP_INCLUDED", "CLARA_CONFIG_CONSOLE_WIDTH": "CATCH_CLARA_CONFIG_CONSOLE_WIDTH", "CLARA_TEXTFLOW_HPP_INCLUDED": "CATCH_CLARA_TEXTFLOW_HPP_INCLUDED", - "CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH": "CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH" + "CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH": "CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH", + "CLARA_PLATFORM_WINDOWS": "" } # outer namespace to add diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 95f28268..5d7f6f4e 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -341,6 +341,10 @@ namespace clara { namespace TextFlow #include #include +#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CLARA_PLATFORM_WINDOWS +#endif + namespace clara { namespace detail { From 059a33d5551153afc1a5e728627f3275a0d30e0c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 26 Jun 2017 16:47:40 +0100 Subject: [PATCH 086/398] Fixed indentation --- include/internal/catch_capture.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index b25f13e8..e5bf2963 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -143,13 +143,13 @@ /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) +#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ From e62a9aa444abff8e309878b26c74d6f5f38b1321 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 26 Jun 2017 16:48:38 +0100 Subject: [PATCH 087/398] Removed const refs from NSString/ NSObject overloads (effectively reapplies PR #855 originally applied to "1.x" master) --- include/internal/catch_tostring.h | 10 +++++----- include/internal/catch_tostring.hpp | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 91fa9ed9..2828be1a 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -302,16 +302,16 @@ namespace Catch { #ifdef __OBJC__ template<> - struct StringMaker { - static std::string convert(NSString const* const& nsstring); + struct StringMaker { + static std::string convert(NSString* nsstring); }; template<> - struct StringMaker { - static std::string convert(NSString * CATCH_ARC_STRONG const& nsstring); + struct StringMaker { + static std::string convert(NSString * CATCH_ARC_STRONG nsstring); }; template<> struct StringMaker { - static std::string convert(NSObject* const& nsObject); + static std::string convert(NSObject* nsObject); }; #endif diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index 03881249..d383ba0a 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -210,17 +210,17 @@ std::string StringMaker::convert(double value) { #ifdef __OBJC__ -std::string StringMaker::convert(NSString const * const& nsstring) { +std::string StringMaker::convert(NSString* nsstring) { if (!nsstring) return "nil"; return "@" + toString([nsstring UTF8String]); } -std::string StringMaker::convert(NSString * CATCH_ARC_STRONG const& nsstring) { +std::string StringMaker::convert(NSString* CATCH_ARC_STRONG nsstring) { if (!nsstring) return "nil"; return "@" + toString([nsstring UTF8String]); } -std::string StringMaker::convert(NSObject * const& nsObject) { +std::string StringMaker::convert(NSObject* nsObject) { return ::Catch::Detail::stringify([nsObject description]); } #endif From 8d5f6c8e2e5fdf355014f410c173ad5cd38e0bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 13 Jun 2017 18:20:59 +0200 Subject: [PATCH 088/398] Fix how GCC version is detected when checking for __COUNTER__ Fixes #928 --- include/internal/catch_compiler_capabilities.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index 9684cf8f..b9f3fb1e 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -112,7 +112,7 @@ // Use __COUNTER__ if the compiler supports it #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ ( defined __clang__ && __clang_major__ >= 3 ) #define CATCH_INTERNAL_CONFIG_COUNTER From 7bcfdf8e9441ddf38667f2a10f671d122147f0fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 15 Jun 2017 11:43:31 +0200 Subject: [PATCH 089/398] Disable deprecation warning of std::uncaught_exception We might prefer to use `std::uncaught_exceptions` in the future, but I would prefer not to bring in more configuration into Catch Classic Closes #927 --- include/internal/catch_section.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/internal/catch_section.hpp b/include/internal/catch_section.hpp index a5d1b6d5..aab721f6 100644 --- a/include/internal/catch_section.hpp +++ b/include/internal/catch_section.hpp @@ -30,6 +30,10 @@ namespace Catch { m_timer.start(); } +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 +#endif Section::~Section() { if( m_sectionIncluded ) { SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); @@ -39,6 +43,9 @@ namespace Catch { getResultCapture().sectionEnded( endInfo ); } } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif // This indicates whether the section should be executed or not Section::operator bool() const { From 9382534d598de9cfbea0c51612567ede5ee5bd15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 22 Jun 2017 18:55:17 +0200 Subject: [PATCH 090/398] Added "How to test changes in PR" section to documentation Also linked it from PR template. Closes #936 --- .github/pull_request_template.md | 3 +++ docs/contributing.md | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 95e3ccd2..368f41fb 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,6 +2,9 @@ Please do not submit pull requests changing the `version.hpp` or the single-include `catch.hpp` file, these are changed only when a new release is made. + +Before submitting a PR you should probably read the contributor documentation +at docs/contributing.md. It will tell you how to properly test your changes. --> diff --git a/docs/contributing.md b/docs/contributing.md index 28d0643d..1bcef99b 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -18,8 +18,8 @@ Ongoing development is currently on _master_. At some point an integration branc _Users_ of Catch primarily use the single header version. _Maintainers_ should work with the full source (which is still, primarily, in headers). This can be found in the `include` folder. There are a set of test files, currently under `projects/SelfTest`. The test app can be built via CMake from the `CMakeLists.txt` file in the root, or you can generate -project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion -that can work with the CMake file directly. +project files for Visual Studio, XCode, and others (instructions in the `projects` folder). If you have access to CLion, +it can work with the CMake file directly. As well as the runtime test files you'll also see a `SurrogateCpps` directory under `projects/SelfTest`. This contains a set of .cpp files that each `#include` a single header. @@ -34,6 +34,25 @@ __When submitting a pull request please do not include changes to the single inc as these are managed by the scripts!__ +## Testing your changes + +Obviously all changes to Catch's code should be tested. If you added new functionality, you should add tests covering and +showcasing it. Even if you have only made changes to Catch internals (ie you implemented some performance improvements), +you should still test your changes. + +This means 3 things + +* Compiling Catch's SelfTest project -- code that does not compile is evidently incorrect. Obviously, you are not expected to +have access to all compilers and platforms Catch supports, Catch's CI pipeline will compile your code using supported compilers +once you open a PR. +* Running the SelfTest binary. There should be no unexpected failures on simple run. +* Running Catch's approval tests. Approval tests compare current output of the SelfTest binary in various configurations against +known good output. Catch's repository provides utility scripts `approvalTests.py` to help you with this. It needs to be passed +the SelfTest binary compiled with your changes, like so: `$ ./scripts/approvalTests.py clang-build/SelfTest`. The output should +be fairly self-explanatory. + + + *this document is still in-progress...* --- From 1e7000ed559973a44031e21967c56ed7bf29747c Mon Sep 17 00:00:00 2001 From: Baruch Burstein Date: Tue, 20 Jun 2017 22:14:38 +0300 Subject: [PATCH 091/398] Merged implemention of #934, but using 'verbose' option on command line instead. (see 616f7235efc875ee239c1dc6ddb48025e05e57ff on master for original merge) --- include/internal/catch_commandline.hpp | 15 ++++++++++ include/internal/catch_config.hpp | 34 ++++++++++++---------- include/internal/catch_interfaces_config.h | 10 +++---- include/internal/catch_list.hpp | 17 +++++++++-- 4 files changed, 52 insertions(+), 24 deletions(-) diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index ea2d7e45..b81e9931 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -73,6 +73,18 @@ namespace Catch { return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); return ParserResult::ok( ParseResultType::Matched ); }; + auto const setVerbosity = [&]( std::string const& verbosity ) { + auto lcVerbosity = toLower( verbosity ); + if( lcVerbosity == "quiet" ) + config.verbosity = Verbosity::Quiet; + else if( lcVerbosity == "normal" ) + config.verbosity = Verbosity::Normal; + else if( lcVerbosity == "high" ) + config.verbosity = Verbosity::High; + else + return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; auto cli = ExeName( config.processName ) @@ -125,6 +137,9 @@ namespace Catch { + Opt( config.sectionsToRun, "section name" ) ["-c"]["--section"] ( "specify section to run" ) + + Opt( setVerbosity, "quiet|normal|high" ) + ["-v"]["--verbosity"] + ( "set output verbosity" ) + Opt( config.listTestNamesOnly ) ["--list-test-names-only"] ( "list all/matching test cases names only" ) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 869e4c70..bc1f5b26 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -40,7 +40,7 @@ namespace Catch { int abortAfter = -1; unsigned int rngSeed = 0; - Verbosity::Level verbosity = Verbosity::Normal; + Verbosity verbosity = Verbosity::Normal; WarnAbout::What warnings = WarnAbout::Nothing; ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; @@ -81,10 +81,12 @@ namespace Catch { return m_data.outputFilename ; } - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + Verbosity verbosity() const { return m_data.verbosity; } std::string getProcessName() const { return m_data.processName; } @@ -96,18 +98,18 @@ namespace Catch { bool showHelp() const { return m_data.showHelp; } // IConfig interface - virtual bool allowThrows() const override { return !m_data.noThrow; } - virtual std::ostream& stream() const override { return m_stream->stream(); } - virtual std::string name() const override { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const override { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const override { return m_data.warnings & WarnAbout::NoAssertions; } + virtual bool allowThrows() const override { return !m_data.noThrow; } + virtual std::ostream& stream() const override { return m_stream->stream(); } + virtual std::string name() const override { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const override { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const override { return m_data.warnings & WarnAbout::NoAssertions; } virtual ShowDurations::OrNot showDurations() const override { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const override { return m_data.runOrder; } - virtual unsigned int rngSeed() const override { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const override { return m_data.useColour; } - virtual bool shouldDebugBreak() const override { return m_data.shouldDebugBreak; } - virtual int abortAfter() const override { return m_data.abortAfter; } - virtual bool showInvisibles() const override { return m_data.showInvisibles; } + virtual RunTests::InWhatOrder runOrder() const override { return m_data.runOrder; } + virtual unsigned int rngSeed() const override { return m_data.rngSeed; } + virtual UseColour::YesOrNo useColour() const override { return m_data.useColour; } + virtual bool shouldDebugBreak() const override { return m_data.shouldDebugBreak; } + virtual int abortAfter() const override { return m_data.abortAfter; } + virtual bool showInvisibles() const override { return m_data.showInvisibles; } private: diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index 4f64f4e3..75499014 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -17,11 +17,11 @@ namespace Catch { - struct Verbosity { enum Level { - NoOutput = 0, - Quiet, - Normal - }; }; + enum class Verbosity { + Quiet = 0, + Normal, + High + }; struct WarnAbout { enum What { Nothing = 0x00, diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index 3cfd294b..5d9d8ed4 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -30,8 +30,9 @@ namespace Catch { } std::size_t matchedTests = 0; - TextAttributes nameAttr, tagsAttr; + TextAttributes nameAttr, descAttr, tagsAttr; nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + descAttr.setIndent( 4 ); tagsAttr.setIndent( 6 ); std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); @@ -43,6 +44,13 @@ namespace Catch { Colour colourGuard( colour ); Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( config.verbosity() >= Verbosity::High ) { + Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; + std::string description = testCaseInfo.description; + if( description == "" ) + description = "(NO DESCRIPTION)"; + Catch::cout() << Text( description, descAttr ) << std::endl; + } if( !testCaseInfo.tags.empty() ) Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; } @@ -63,9 +71,12 @@ namespace Catch { for( auto const& testCaseInfo : matchedTestCases ) { matchedTests++; if( startsWith( testCaseInfo.name, '#' ) ) - Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl; + Catch::cout() << '"' << testCaseInfo.name << '"'; else - Catch::cout() << testCaseInfo.name << std::endl; + Catch::cout() << testCaseInfo.name; + if ( config.verbosity() >= Verbosity::High ) + Catch::cout() << "\t@" << testCaseInfo.lineInfo; + Catch::cout() << std::endl; } return matchedTests; } From 4c1880b35fb28559fe81fd35af1077d9c53b1ace Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 27 Jun 2017 11:37:42 +0100 Subject: [PATCH 092/398] =?UTF-8?q?Clamp=20exit=20code=20internally,=20so?= =?UTF-8?q?=20it=20doesn=E2=80=99t=20have=20to=20be=20done=20in=20every=20?= =?UTF-8?q?main()=20implies?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/own-main.md | 10 +++++----- include/catch_session.hpp | 15 ++++++++------- include/internal/catch_default_main.hpp | 5 ++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/own-main.md b/docs/own-main.md index 91a79b26..8ab0077e 100644 --- a/docs/own-main.md +++ b/docs/own-main.md @@ -23,7 +23,7 @@ int main( int argc, char* argv[] ) { // global clean-up... - return ( result < 0xff ? result : 0xff ); + return result; } ``` @@ -66,10 +66,10 @@ int main( int argc, char* argv[] ) // only do this if you know you need to int numFailed = session.run(); - // Note that on unices only the lower 8 bits are usually used, clamping - // the return value to 255 prevents false negative when some multiple - // of 256 tests has failed - return ( numFailed < 0xff ? numFailed : 0xff ); + // numFailed is clamped to 255 as some unices only use the lower 8 bits. + // This clamping has already been applied, so just return it here + // You can also do any post run clean-up here + return numFailed; } ``` diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 09ca85f1..ffd87c9d 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -96,6 +96,7 @@ namespace Catch { } class Session : NonCopyable { + static const int MaxExitCode; public: Session() { @@ -113,7 +114,7 @@ namespace Catch { Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; Catch::cout() << m_cli << std::endl; - Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; + Catch::cout() << "For more detailed usage please see the project docs\n" << std::endl; } int applyCommandLine( int argc, char* argv[] ) { @@ -127,7 +128,7 @@ namespace Catch { << "\n\n"; } Catch::cerr() << m_cli << std::endl; - return (std::numeric_limits::max)(); + return MaxExitCode; } if( m_configData.showHelp ) @@ -174,9 +175,7 @@ namespace Catch { WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); } - int returnCode = applyCommandLine( argc, utf8Argv ); - if( returnCode == 0 ) - returnCode = run(); + int returnCode = run( argc, utf8Argv ); for ( int i = 0; i < argc; ++i ) delete [] utf8Argv[ i ]; @@ -204,11 +203,11 @@ namespace Catch { if( Option listed = list( config() ) ) return static_cast( *listed ); - return static_cast( runTests( m_config ).assertions.failed ); + return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); } catch( std::exception& ex ) { Catch::cerr() << ex.what() << std::endl; - return (std::numeric_limits::max)(); + return MaxExitCode; } } @@ -232,6 +231,8 @@ namespace Catch { std::shared_ptr m_config; }; + const int Session::MaxExitCode = 255; + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED diff --git a/include/internal/catch_default_main.hpp b/include/internal/catch_default_main.hpp index e9f466c0..9b7c2890 100644 --- a/include/internal/catch_default_main.hpp +++ b/include/internal/catch_default_main.hpp @@ -18,8 +18,7 @@ extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { int main (int argc, char * argv[]) { #endif - int result = Catch::Session().run( argc, argv ); - return ( result < 0xff ? result : 0xff ); + return Catch::Session().run( argc, argv ); } #else // __OBJC__ @@ -37,7 +36,7 @@ int main (int argc, char * const argv[]) { [pool drain]; #endif - return ( result < 0xff ? result : 0xff ); + return result; } #endif // __OBJC__ From cb0a5194af7e092fde6f1f7deffb2758e28e65fe Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 27 Jun 2017 11:39:02 +0100 Subject: [PATCH 093/398] Updated overview docs a bit --- docs/why-catch.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/why-catch.md b/docs/why-catch.md index b77ca2c2..1dbc43bc 100644 --- a/docs/why-catch.md +++ b/docs/why-catch.md @@ -6,27 +6,27 @@ So what does Catch bring to the party that differentiates it from these? Apart f ## Key Features -* Really easy to get started. Just download catch.hpp, #include it and you're away. -* No external dependencies. As long as you can compile C++98 and have a C++ standard library available. -* Write test cases as, self-registering, functions or methods. -* Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures!) +* Really easy to get started. Just download catch.hpp, `#include` it and you're away. +* No external dependencies. As long as you can compile C++11 and have a C++ standard library available. +* Write test cases as, self-registering, functions (or methods, if you prefer). +* Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures). * Use BDD-style Given-When-Then sections as well as traditional unit test cases. * Only one core assertion macro for comparisons. Standard C/C++ operators are used for the comparison - yet the full expression is decomposed and lhs and rhs values are logged. +* Tests are named using free-form strings - no more couching names in legal identifiers. ## Other core features -* Tests are named using free-form strings - no more couching names in legal identifiers. * Tests can be tagged for easily running ad-hoc groups of tests. * Failures can (optionally) break into the debugger on Windows and Mac. * Output is through modular reporter objects. Basic textual and XML reporters are included. Custom reporters can easily be added. * JUnit xml output is supported for integration with third-party tools, such as CI servers. -* A default main() function is provided (in a header), but you can supply your own for complete control (e.g. integration into your own test runner GUI). +* A default main() function is provided, but you can supply your own for complete control (e.g. integration into your own test runner GUI). * A command line parser is provided and can still be used if you choose to provided your own main() function. * Catch can test itself. * Alternative assertion macro(s) report failures but don't abort the test case * Floating point tolerance comparisons are built in using an expressive Approx() syntax. * Internal and friendly macros are isolated so name clashes can be managed -* Support for Matchers (early stages) +* Matchers ## Objective-C-specific features @@ -39,7 +39,7 @@ So what does Catch bring to the party that differentiates it from these? Apart f See the list of [open source projects using Catch](opensource-users.md). -See the [tutorial](tutorial.md) to get more of a taste of using CATCH in practice +See the [tutorial](tutorial.md) to get more of a taste of using Catch in practice --- From 78e799443531a84c5f337109d462af53249ed49c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Jun 2017 11:18:14 +0100 Subject: [PATCH 094/398] Added string classes --- CMakeLists.txt | 13 ++ include/internal/catch_impl.hpp | 9 ++ include/internal/catch_string.cpp | 83 ++++++++++++ include/internal/catch_string.h | 48 +++++++ include/internal/catch_stringbuilder.cpp | 111 ++++++++++++++++ include/internal/catch_stringbuilder.h | 72 +++++++++++ include/internal/catch_stringdata.cpp | 49 +++++++ include/internal/catch_stringdata.h | 52 ++++++++ include/internal/catch_stringref.cpp | 140 ++++++++++++++++++++ include/internal/catch_stringref.h | 84 ++++++++++++ projects/SelfTest/String.tests.cpp | 20 +++ projects/SelfTest/StringBuilder.tests.cpp | 76 +++++++++++ projects/SelfTest/StringRef.tests.cpp | 151 ++++++++++++++++++++++ 13 files changed, 908 insertions(+) create mode 100644 include/internal/catch_string.cpp create mode 100644 include/internal/catch_string.h create mode 100644 include/internal/catch_stringbuilder.cpp create mode 100644 include/internal/catch_stringbuilder.h create mode 100644 include/internal/catch_stringdata.cpp create mode 100644 include/internal/catch_stringdata.h create mode 100644 include/internal/catch_stringref.cpp create mode 100644 include/internal/catch_stringref.h create mode 100644 projects/SelfTest/String.tests.cpp create mode 100644 projects/SelfTest/StringBuilder.tests.cpp create mode 100644 projects/SelfTest/StringRef.tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index be37e4d7..ed863deb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,9 @@ set(TEST_SOURCES ${SELF_TEST_DIR}/TrickyTests.cpp ${SELF_TEST_DIR}/VariadicMacrosTests.cpp ${SELF_TEST_DIR}/MatchersTests.cpp + ${SELF_TEST_DIR}/String.tests.cpp + ${SELF_TEST_DIR}/StringBuilder.tests.cpp + ${SELF_TEST_DIR}/StringRef.tests.cpp ) CheckFileList(TEST_SOURCES ${SELF_TEST_DIR}) @@ -181,6 +184,14 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_stream.hpp ${HEADER_DIR}/internal/catch_streambuf.h + ${HEADER_DIR}/internal/catch_string.cpp + ${HEADER_DIR}/internal/catch_string.h + ${HEADER_DIR}/internal/catch_stringbuilder.cpp + ${HEADER_DIR}/internal/catch_stringbuilder.h + ${HEADER_DIR}/internal/catch_stringdata.cpp + ${HEADER_DIR}/internal/catch_stringdata.h + ${HEADER_DIR}/internal/catch_stringref.cpp + ${HEADER_DIR}/internal/catch_stringref.h ${HEADER_DIR}/internal/catch_suppress_warnings.h ${HEADER_DIR}/internal/catch_tag_alias.h ${HEADER_DIR}/internal/catch_tag_alias_registry.h @@ -243,6 +254,8 @@ SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES}) # configure the executable include_directories(${HEADER_DIR}) +add_definitions( -DCATCH_CONFIG_FULL_PROJECT ) + # Projects consuming Catch via ExternalProject_Add might want to use install step # without building all of our selftests. if (NOT NO_SELFTEST) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 4843dad6..2306af7f 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -37,6 +37,15 @@ #include "catch_matchers_string.hpp" #include "catch_startup_exception_registry.hpp" +// These files are not included in the full (not single include) project +// as they are compiled as proper cpp files +#ifndef CATCH_CONFIG_FULL_PROJECT +# include "catch_stringref.cpp" +# include "catch_string.cpp" +# include "catch_stringbuilder.cpp" +# include "catch_stringdata.cpp" +#endif + #include "../reporters/catch_reporter_multi.hpp" #include "../reporters/catch_reporter_xml.hpp" #include "../reporters/catch_reporter_junit.hpp" diff --git a/include/internal/catch_string.cpp b/include/internal/catch_string.cpp new file mode 100644 index 00000000..f7cc53a5 --- /dev/null +++ b/include/internal/catch_string.cpp @@ -0,0 +1,83 @@ +/* + * Copyright 2016 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) + */ + +#include "catch_string.h" +#include "catch_stringref.h" +#include "catch_stringbuilder.h" + +#include "catch_stringdata.h" + +#include + +namespace Catch { + + String::String() + : m_data( StringData::getEmpty() ) + {} + + String::String( StringRef const& stringRef ) + : m_data( StringData::create( stringRef ) ) + {} + + String::String( char const* rawString ) + : String( StringRef( rawString ) ) + {} + + String::String( String const& other ) + : m_data( other.m_data ) + { + m_data->addRef(); + } + String::String( String&& other ) + : m_data( other.m_data ) + { + other.m_data = StringData::getEmpty(); + } + String::String( StringBuilder&& stringBuf ) + : m_data( stringBuf.m_data ) + { + // const_cast is ok here because we are taking ownership + const_cast( m_data )->size = stringBuf.size(); + stringBuf.m_data = StringData::getEmpty(); + stringBuf.m_size = 0; + } + + + String::~String() noexcept { + m_data->release(); + } + + auto String::operator = ( String const& other ) -> String& { + m_data = other.m_data; + m_data->addRef(); + return *this; + } + + + auto String::empty() const noexcept -> bool { + return m_data->size == 0; + } + auto String::size() const noexcept -> size_type { + return m_data->size; + } + auto String::c_str() const noexcept -> char const* { + return m_data->chars; + } + + auto String::operator == ( StringRef const& other ) const noexcept -> bool { + return other == StringRef( *this ); + } + auto String::operator == ( char const* other ) const noexcept -> bool { + return StringRef( other ) == StringRef( *this ); + } + + std::ostream& operator << ( std::ostream& os, String const& str ) { + os << str.c_str(); + return os; + } + +} // namespace Catch diff --git a/include/internal/catch_string.h b/include/internal/catch_string.h new file mode 100644 index 00000000..b9d310c9 --- /dev/null +++ b/include/internal/catch_string.h @@ -0,0 +1,48 @@ +/* + * Copyright 2016 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) + */ +#ifndef CATCH_STRING_H_INCLUDED +#define CATCH_STRING_H_INCLUDED + +namespace Catch { + + class StringData; + class StringRef; + class StringBuilder; + + /// An owning, ref-counted, immutable string type. + /// The ref count (not visible here as it is defined in StringData) is atomic + /// so instances should be safe to share across threads + class String { + friend class StringRef; + friend class StringBuilder; + + StringData const* m_data = nullptr; + public: + using size_type = unsigned long; + + String(); + String( StringRef const& stringRef ); + String( char const* rawString ); + String( String const& other ); + String( String&& other ); + String( StringBuilder&& stringBuf ); + + ~String() noexcept; + + auto operator = ( String const& other ) -> String&; + + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator == ( char const* other ) const noexcept -> bool; + + auto empty() const noexcept -> bool; + auto size() const noexcept -> size_type; + auto c_str() const noexcept -> char const*; + }; + +} // namespace Catch + +#endif // CATCH_STRING_H_INCLUDED diff --git a/include/internal/catch_stringbuilder.cpp b/include/internal/catch_stringbuilder.cpp new file mode 100644 index 00000000..80ba1bbd --- /dev/null +++ b/include/internal/catch_stringbuilder.cpp @@ -0,0 +1,111 @@ +/* + * Copyright 2016 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) + */ + +#include "catch_stringbuilder.h" +#include "catch_stringref.h" +#include "catch_stringdata.h" +#include "catch_string.h" + +#include +#include +#include +#include + +namespace Catch { + + static const StringBuilder::size_type s_minimumCapacity = 32; + + StringBuilder::StringBuilder() + : m_data( StringData::getEmpty() ) + {} + + StringBuilder::StringBuilder( size_type initialCapacity ) + : m_size( 0 ), + m_data( StringData::create( StringRef(), initialCapacity ) ) + {} + StringBuilder::StringBuilder( StringRef const& str, size_type initialCapacity ) + : m_size( str.size() ), + m_data( StringData::create( str, initialCapacity ) ) + {} + StringBuilder::StringBuilder( StringBuilder const& other, size_type initialCapacity ) + : StringBuilder( StringRef( other.m_data->chars, other.m_size ), initialCapacity ) + {} + StringBuilder::StringBuilder( StringBuilder&& other ) noexcept + : StringBuilder() + { + swap( other ); + } + StringBuilder::StringBuilder( String&& str ) + : m_size( str.size() ), + m_data( StringData::getEmpty() ) + { + if( str.m_data->isUniquelyOwned() ) + { + std::swap( m_data, const_cast( str.m_data ) ); + } + else + { + size_type initialCapacity = std::min( s_minimumCapacity, m_size ); + m_data = StringData::create( str, initialCapacity ); + } + } + StringBuilder::StringBuilder( String const& other ) + : StringBuilder( StringRef( other ), std::min( s_minimumCapacity, other.size() ) ) + {} + + StringBuilder::~StringBuilder() noexcept { + m_data->release(); + } + + auto StringBuilder::size() const noexcept -> size_type { + return m_size; + } + + void StringBuilder::swap( StringBuilder& other ) noexcept { + std::swap( m_size, other.m_size ); + std::swap( m_data, other.m_data ); + } + void StringBuilder::reserve( size_type minimumCapacity ) { + if( minimumCapacity > capacity() ) { + StringBuilder temp( *this, minimumCapacity ); + swap( temp ); + } + } + void StringBuilder::reserveExponential( size_type minimumCapacity ) { + if( minimumCapacity > capacity() ) { + size_type candidateCapacity = capacity() < s_minimumCapacity ? s_minimumCapacity : capacity()*2; + while( candidateCapacity < minimumCapacity ) + candidateCapacity = candidateCapacity * 3/2; // grow factor of 1.5 + StringBuilder temp( *this, candidateCapacity ); + swap( temp ); + } + } + auto StringBuilder::capacity() const noexcept -> size_type { + return m_data->size; + } + void StringBuilder::writeTo( size_type index, StringRef const& str ) { + assert( index + str.size() < capacity() ); + if( str.size() > 0 ) + std::memcpy( m_data->chars+index, str.data(), str.size() ); + } + void StringBuilder::append( StringRef const& str ) { + reserveExponential( m_size + str.size() + 1 ); + writeTo( m_size, str ); + m_size += str.size(); + m_data->chars[m_size] = '\0'; + } + + auto operator << ( StringBuilder& sb, StringRef sr ) -> StringBuilder& { + sb.append( sr ); + return sb; + } + auto operator << ( StringBuilder&& sb, StringRef sr ) -> StringBuilder&& { + sb.append( sr ); + return std::move( sb ); + } + +} // namespace Catch diff --git a/include/internal/catch_stringbuilder.h b/include/internal/catch_stringbuilder.h new file mode 100644 index 00000000..c3d99d81 --- /dev/null +++ b/include/internal/catch_stringbuilder.h @@ -0,0 +1,72 @@ +/* + * Copyright 2016 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) + */ +#ifndef CATCH_STRINGBUILDER_H_INCLUDED +#define CATCH_STRINGBUILDER_H_INCLUDED + +#include "catch_stringref.h" + +namespace Catch { + + class String; + class StringData; + + /// A mutable container for string data + /// Use to build up strings before transferring to an immutable String. + /// Construct the String using the rvalue reference constructor (which + /// will usually involve std::move-ing the StringBuilder). This will transfer + /// The underlying buffer without any extra allocations or ref counts. + class StringBuilder { + friend class String; + public: + using size_type = unsigned long; + + StringBuilder(); + StringBuilder( size_type initialCapacity ); + StringBuilder( StringRef const& str, size_type initialCapacity ); + StringBuilder( StringBuilder const& other, size_type initialCapacity ); + StringBuilder( StringBuilder&& other ) noexcept; + StringBuilder( String&& other ); + StringBuilder( String const& other ); + ~StringBuilder() noexcept; + + void swap( StringBuilder& other ) noexcept; + + auto size() const noexcept -> size_type; + auto capacity() const noexcept -> size_type; + + /// Grows the buffer to exactly the capacity requested, or + /// does nothing if it is already at least as big + void reserve(size_type capacity); + + /// Grows the buffer exponentially (from a baseline of 32 bytes) + /// until it is at least as large as the requested capacity - + /// or does nothing if already large enough + void reserveExponential(size_type capacity); + + /// Writes the string at the current insertion point then moves + /// the insertion point forward by the string length. + /// If the buffer needs to grow to accomodate the string it does so + /// using the exponential strategy + void append( StringRef const& str ); + + friend auto operator << ( StringBuilder& sb, StringRef sr ) -> StringBuilder&; + friend auto operator << ( StringBuilder&& sb, StringRef sr ) -> StringBuilder&&; + + /// Writes the contents of the string ref into the buffer at + /// the indexed location. + /// The bounds are not checked! Use append() to just add to the + /// end of the buffer, extending it if the capacity is not enough. + void writeTo( size_type index, StringRef const& str ); + + private: + size_type m_size = 0; + StringData* m_data; + }; + +} // namespace Catch + +#endif // CATCH_STRINGBUILDER_H_INCLUDED diff --git a/include/internal/catch_stringdata.cpp b/include/internal/catch_stringdata.cpp new file mode 100644 index 00000000..9f1625a8 --- /dev/null +++ b/include/internal/catch_stringdata.cpp @@ -0,0 +1,49 @@ +/* + * Copyright 2016 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) + */ + + +#include "catch_stringdata.h" +#include "catch_stringref.h" + +#include +#include +#include + +namespace Catch { + + auto StringData::getEmpty() -> StringData* { + static StringData s_empty( 0 ); + return &s_empty; + } + auto StringData::create( StringRef const& stringRef ) -> StringData* { + return create( stringRef, stringRef.size() ); + } + auto StringData::create( StringRef const& stringRef, unsigned long capacity ) -> StringData* { + if( capacity == 0 ) { + return getEmpty(); + } + else { + assert( stringRef.size() <= capacity ); + auto bufferLen = sizeof(StringData)+capacity; + void* buffer = new char[bufferLen]; + + return new(buffer) StringData( stringRef, capacity ); + } + } + StringData::StringData( unsigned int initialRef ) + : m_refs( initialRef ), + size( 0 ) + {} + StringData::StringData( StringRef const& stringRef, unsigned long capacity ) + : m_refs( 1 ), + size( capacity) + { + std::memcpy( chars, stringRef.data(), stringRef.size() ); + chars[stringRef.size() ] = 0; + } + +} // namespace Catch \ No newline at end of file diff --git a/include/internal/catch_stringdata.h b/include/internal/catch_stringdata.h new file mode 100644 index 00000000..5ffafad7 --- /dev/null +++ b/include/internal/catch_stringdata.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016 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) + */ +#ifndef CATCH_STRINGDATA_H_INCLUDED +#define CATCH_STRINGDATA_H_INCLUDED + +#include + +namespace Catch { + + class StringRef; + + class StringData { + mutable std::atomic m_refs; + public: + unsigned int size; + union { + char chars[1]; + }; + + auto isUniquelyOwned() const noexcept -> bool { + return m_refs == 1; + } + static auto getEmpty() -> StringData*; + static auto create( StringRef const& stringRef ) -> StringData*; + static auto create( StringRef const& stringRef, unsigned long capacity ) -> StringData*; + + void addRef() const noexcept { + if( m_refs > 0 ) + m_refs++; + } + void release() const noexcept { + unsigned int refs = m_refs; + if( refs > 1 ) + m_refs--; + else if( refs == 1 ) + delete[] reinterpret_cast( this ); + } + private: + StringData( unsigned int initialRef = 1 ); + StringData( StringRef const& stringRef, unsigned long capacity ); + + StringData( StringData const& ) = delete; + StringData& operator=( StringData const& ) = delete; + }; + +} // namespace Catch + +#endif // CATCH_STRINGDATA_H_INCLUDED diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp new file mode 100644 index 00000000..d577d3af --- /dev/null +++ b/include/internal/catch_stringref.cpp @@ -0,0 +1,140 @@ +/* + * Copyright 2016 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) + */ + +#include "catch_stringref.h" +#include "catch_stringbuilder.h" +#include "catch_string.h" +#include "catch_stringdata.h" + +#include +#include + +namespace Catch { + + StringRef StringRef::s_emptyStringRef = ""; + + StringRef::StringRef() + : StringRef( s_emptyStringRef ) + {} + + StringRef::StringRef( StringRef const& other ) + : m_start( other.m_start ), + m_size( other.m_size ), + m_data( other.m_data ) + { + if( m_data ) + m_data->addRef(); + } + + StringRef::StringRef( StringRef&& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ), + m_data( other.m_data ) + { + other.m_data = nullptr; + } + + StringRef::StringRef( char const* rawChars ) + : m_start( rawChars ), + m_size( std::strlen( rawChars ) ) + {} + + StringRef::StringRef( char const* rawChars, size_type size ) + : m_start( rawChars ), + m_size( size ) + { + size_type rawSize = rawChars == nullptr ? 0 : std::strlen( rawChars ); + if( rawSize < size ) + size = rawSize; + } + + StringRef::StringRef( String const& other ) + : m_start( other.c_str() ), + m_size( other.size() ), + m_data( nullptr ) + {} + + StringRef::StringRef( String&& str ) noexcept + : m_start( str.c_str() ), + m_size( str.size() ), + m_data( str.m_data ) + { + str.m_data = StringData::getEmpty(); + } + + StringRef::~StringRef() noexcept { + if( isOwned() ) + m_data->release(); + } + + auto StringRef::operator = ( StringRef other ) -> StringRef& { + swap( other ); + return *this; + } + + void StringRef::swap( StringRef& other ) noexcept { + std::swap( m_start, other.m_start ); + std::swap( m_size, other.m_size ); + std::swap( m_data, other.m_data ); + } + + auto StringRef::c_str() const -> char const* { + if( isSubstring() ) + const_cast( this )->takeOwnership(); + return m_start; + } + auto StringRef::data() const noexcept -> char const* { + return m_start; + } + + auto StringRef::isOwned() const noexcept -> bool { + return m_data != nullptr; + } + auto StringRef::isSubstring() const noexcept -> bool { + return m_start[m_size] != '\0'; + } + + void StringRef::takeOwnership() { + if( !isOwned() ) { + StringRef temp = String( *this ); + swap( temp ); + } + } + auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { + if( start < m_size ) + return StringRef( m_start+start, size ); + else + return StringRef(); + } + auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { + return + size() == other.size() && + (std::strncmp( m_start, other.m_start, size() ) == 0); + } + auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { + return !operator==( other ); + } + + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> String { + StringBuilder buf; + buf.reserve( lhs.size() + rhs.size() ); + buf.append( lhs ); + buf.append( rhs ); + return String( std::move( buf ) ); + } + auto operator + ( StringRef const& lhs, const char* rhs ) -> String { + return lhs + StringRef( rhs ); + } + auto operator + ( char const* lhs, StringRef const& rhs ) -> String { + return StringRef( lhs ) + rhs; + } + + std::ostream& operator << ( std::ostream& os, StringRef const& str ) { + return os << str.c_str(); + } + +} // namespace Catch diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h new file mode 100644 index 00000000..a0d8200b --- /dev/null +++ b/include/internal/catch_stringref.h @@ -0,0 +1,84 @@ +/* + * Copyright 2016 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) + */ +#ifndef CATCH_STRINGREF_H_INCLUDED +#define CATCH_STRINGREF_H_INCLUDED + +namespace Catch { + + class String; + 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 { + friend struct StringRefTestAccess; + friend class StringData; + friend class StringBuilder; + + using size_type = unsigned long; + + char const* m_start; + size_type m_size; + + StringData const* m_data = nullptr; + + static StringRef s_emptyStringRef; + + void takeOwnership(); + + public: // construction/ assignment + StringRef(); + StringRef( StringRef const& other ); + StringRef( StringRef&& other ) noexcept; + StringRef( char const* rawChars ); + StringRef( char const* rawChars, size_type size ); + StringRef( String const& other ); + StringRef( String&& other ) noexcept; + ~StringRef() noexcept; + + auto operator = ( StringRef other ) -> StringRef&; + + 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 { + return m_start[index]; + } + + public: // named queries + auto empty() const noexcept -> bool { + return m_size == 0; + } + auto size() const noexcept -> size_type { + return m_size; + } + auto c_str() const -> char const*; + + public: // substrings and searches + auto substr( size_type start, size_type size ) const noexcept -> StringRef; + + 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& lhs, StringRef const& rhs ) -> String; + auto operator + ( StringRef const& lhs, char const* rhs ) -> String; + auto operator + ( char const* lhs, StringRef const& rhs ) -> String; + +} // namespace Catch + +#endif // CATCH_STRINGREF_H_INCLUDED diff --git a/projects/SelfTest/String.tests.cpp b/projects/SelfTest/String.tests.cpp new file mode 100644 index 00000000..ccd90964 --- /dev/null +++ b/projects/SelfTest/String.tests.cpp @@ -0,0 +1,20 @@ +#include "../include/internal/catch_string.h" + +#include "catch.hpp" + +TEST_CASE( "String", "[Strings]" ) { + using Catch::String; + + SECTION( "empty string" ) { + String empty; + REQUIRE( empty.empty() ); + REQUIRE( empty.size() == 0 ); + REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ); + } + SECTION( "from literal" ) { + String s = "hello"; + REQUIRE( s.empty() == false ); + REQUIRE( s.size() == 5 ); + } + +} \ No newline at end of file diff --git a/projects/SelfTest/StringBuilder.tests.cpp b/projects/SelfTest/StringBuilder.tests.cpp new file mode 100644 index 00000000..e91d450d --- /dev/null +++ b/projects/SelfTest/StringBuilder.tests.cpp @@ -0,0 +1,76 @@ +#include "internal/catch_stringbuilder.h" +#include "../include/internal/catch_stringref.h" +#include "../include/internal/catch_string.h" + +#include "catch.hpp" + +TEST_CASE( "StringBuilder", "[Strings]" ) { + + using Catch::StringBuilder; + using Catch::String; + + StringBuilder sb; + + SECTION( "basic" ) { + REQUIRE( sb.capacity() == 0 ); + REQUIRE( sb.size() == 0 ); + + sb.reserve( 32 ); + REQUIRE( sb.capacity() == 32 ); + REQUIRE( sb.size() == 0 ); + + sb.append( "hello" ); + REQUIRE( sb.capacity() == 32 ); + REQUIRE( sb.size() == 5 ); + + String s = std::move( sb ); + REQUIRE( s == "hello" ); + REQUIRE( s.size() == 5 ); + } + + SECTION( "concatenation" ) { + sb << "hello" << " " << "world"; + String s = std::move( sb ); + REQUIRE( s == "hello world" ); + } + + SECTION( "concat & move" ) { + String s = StringBuilder() << "hello" << " " << "world"; + REQUIRE( s == "hello world" ); + } + + SECTION( "reserved" ) { + StringBuilder sb16( 16 ); + REQUIRE( sb16.capacity() == 16 ); + sb16 << "hello" << " " << "world"; + REQUIRE( sb16.capacity() == 16 ); + String s = std::move( sb16 ); + REQUIRE( s == "hello world" ); + } + + SECTION( "from String" ) { + String s = "hello"; + + SECTION( "copy" ) { + StringBuilder sb2 = s; + String s2( std::move(sb2) ); + REQUIRE( s2 == s ); + REQUIRE( s2.c_str() != s.c_str() ); + } + SECTION( "move from uniquely owned string" ) { + auto originalPointer = s.c_str(); + StringBuilder sb2( std::move( s ) ); + String s2( std::move(sb2) ); + REQUIRE( s2 == "hello" ); + REQUIRE( s2.c_str() == originalPointer ); + } + SECTION( "move from shared string (copies)" ) { + auto originalPointer = s.c_str(); + String keepAlive = s; + StringBuilder sb2( std::move( s ) ); + String s2( std::move(sb2) ); + REQUIRE( s2 == "hello" ); + REQUIRE( s2.c_str() != originalPointer ); + } + } +} diff --git a/projects/SelfTest/StringRef.tests.cpp b/projects/SelfTest/StringRef.tests.cpp new file mode 100644 index 00000000..e5da3f2a --- /dev/null +++ b/projects/SelfTest/StringRef.tests.cpp @@ -0,0 +1,151 @@ +#include "../include/internal/catch_stringref.h" +#include "../include/internal/catch_string.h" + +#include "catch.hpp" + +namespace Catch { + + // Implementation of test accessors + struct StringRefTestAccess { + static auto isOwned( StringRef const& stringRef ) -> bool { + return stringRef.isOwned(); + } + static auto isSubstring( StringRef const& stringRef ) -> bool { + return stringRef.isSubstring(); + } + static auto data( StringRef const& stringRef ) -> char const* { + return stringRef.data(); + } + }; + + auto isOwned( StringRef const& stringRef ) -> bool { + return StringRefTestAccess::isOwned( stringRef ); + } + auto isSubstring( StringRef const& stringRef ) -> bool { + return StringRefTestAccess::isSubstring( stringRef ); + } + auto data( StringRef const& stringRef ) -> char const* { + return StringRefTestAccess::data( stringRef ); + } +} // namespace Catch2 + +namespace Catch { + inline auto toString( Catch::StringRef const& stringRef ) -> std::string { + return std::string( data( stringRef ), stringRef.size() ); + } +} // namespace Catch + +TEST_CASE( "StringRef", "[Strings]" ) { + + using Catch::StringRef; + using Catch::String; + + SECTION( "Empty string" ) { + StringRef empty; + REQUIRE( empty.empty() ); + REQUIRE( empty.size() == 0 ); + REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ); + } + + SECTION( "From string literal" ) { + StringRef s = "hello"; + REQUIRE( s.empty() == false ); + REQUIRE( s.size() == 5 ); + REQUIRE( isSubstring( s ) == false ); + + auto rawChars = data( s ); + REQUIRE( std::strcmp( rawChars, "hello" ) == 0 ); + + SECTION( "c_str() does not cause copy" ) { + REQUIRE( isOwned( s ) == false ); + + REQUIRE( s.c_str() == rawChars ); + + REQUIRE( isOwned( s ) == false ); + } + } + SECTION( "From sub-string" ) { + StringRef original = StringRef( "original string" ).substr(0, 8); + REQUIRE( original == "original" ); + REQUIRE( isSubstring( original ) ); + REQUIRE( isOwned( original ) == false ); + + original.c_str(); // Forces it to take ownership + + REQUIRE( isSubstring( original ) == false ); + REQUIRE( isOwned( original ) ); + + } + + + SECTION( "Substrings" ) { + StringRef s = "hello world!"; + StringRef ss = s.substr(0, 5); + + SECTION( "zero-based substring" ) { + REQUIRE( ss.empty() == false ); + REQUIRE( ss.size() == 5 ); + REQUIRE( std::strcmp( ss.c_str(), "hello" ) == 0 ); + REQUIRE( ss == "hello" ); + } + SECTION( "c_str() causes copy" ) { + REQUIRE( isSubstring( ss ) ); + REQUIRE( isOwned( ss ) == false ); + + auto rawChars = data( ss ); + REQUIRE( rawChars == data( s ) ); // same pointer value + REQUIRE( ss.c_str() != rawChars ); + + REQUIRE( isSubstring( ss ) == false ); + REQUIRE( isOwned( ss ) ); + + REQUIRE( data( ss ) != data( s ) ); // different pointer value + } + + SECTION( "non-zero-based substring") { + ss = s.substr( 6, 6 ); + REQUIRE( ss.size() == 6 ); + REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 ); + } + + SECTION( "Pointer values of full refs should match" ) { + StringRef s2 = s; + REQUIRE( s.c_str() == s2.c_str() ); + } + + SECTION( "Pointer values of substring refs should not match" ) { + REQUIRE( s.c_str() != ss.c_str() ); + } + } + + SECTION( "Comparisons" ) { + REQUIRE( StringRef("hello") == StringRef("hello") ); + REQUIRE( StringRef("hello") != StringRef("cello") ); + } + + SECTION( "From string" ) { + String str = "hot potato"; + auto originalPointer = str.c_str(); + + SECTION( "Copied" ) { + // After a String is "copied" to a StringRef + // It has only copied the pointer and size + // - it does not take ownership + StringRef copied = str; + REQUIRE( copied == "hot potato" ); + REQUIRE( str == "hot potato" ); + REQUIRE( isOwned( copied ) == false ); + REQUIRE( data( copied ) == originalPointer ); + } + SECTION( "Moved" ) { + // After a String is *moved* to a StringRef + // The StringRef takes ownership of the underlying data + // and the String is left in an empty state + StringRef copied = std::move( str ); + REQUIRE( copied == "hot potato" ); + REQUIRE( isOwned( copied ) ); + REQUIRE( str.empty() ); + REQUIRE( data( copied ) == originalPointer ); + } + } +} From 60f25c7ffd9e5019207a62aa534d3ff2132c2f71 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Jun 2017 11:19:08 +0100 Subject: [PATCH 095/398] Added string tests to approvals --- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 546 +++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 23 +- .../SelfTest/Baselines/xml.sw.approved.txt | 618 +++++++++++++++++- 4 files changed, 1184 insertions(+), 7 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 49f184e9..4a061ae7 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1002,6 +1002,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 171 | 121 passed | 46 failed | 4 failed as expected -assertions: 844 | 729 passed | 94 failed | 21 failed as expected +test cases: 174 | 124 passed | 46 failed | 4 failed as expected +assertions: 908 | 793 passed | 94 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index e74a3348..c27c1098 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -5692,6 +5692,50 @@ MatchersTests.cpp:: FAILED: with expansion: "this string contains 'abc' as a substring" starts with: "string" +------------------------------------------------------------------------------- +String + empty string +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + +String.tests.cpp:: +PASSED: + REQUIRE( empty.empty() ) +with expansion: + true + +String.tests.cpp:: +PASSED: + REQUIRE( empty.size() == 0 ) +with expansion: + 0 == 0 + +String.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +String + from literal +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + +String.tests.cpp:: +PASSED: + REQUIRE( s.empty() == false ) +with expansion: + false == false + +String.tests.cpp:: +PASSED: + REQUIRE( s.size() == 5 ) +with expansion: + 5 == 5 + ------------------------------------------------------------------------------- String matchers ------------------------------------------------------------------------------- @@ -5722,6 +5766,504 @@ PASSED: with expansion: "this string contains 'abc' as a substring" ends with: "substring" +------------------------------------------------------------------------------- +StringBuilder + basic +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.capacity() == 0 ) +with expansion: + 0 == 0 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.size() == 0 ) +with expansion: + 0 == 0 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.capacity() == 32 ) +with expansion: + 32 == 32 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.size() == 0 ) +with expansion: + 0 == 0 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.capacity() == 32 ) +with expansion: + 32 == 32 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.size() == 5 ) +with expansion: + 5 == 5 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello" ) +with expansion: + {?} == "hello" + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s.size() == 5 ) +with expansion: + 5 == 5 + +------------------------------------------------------------------------------- +StringBuilder + concatenation +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello world" ) +with expansion: + {?} == "hello world" + +------------------------------------------------------------------------------- +StringBuilder + concat & move +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello world" ) +with expansion: + {?} == "hello world" + +------------------------------------------------------------------------------- +StringBuilder + reserved +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb16.capacity() == 16 ) +with expansion: + 16 == 16 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb16.capacity() == 16 ) +with expansion: + 16 == 16 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello world" ) +with expansion: + {?} == "hello world" + +------------------------------------------------------------------------------- +StringBuilder + from String + copy +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2 == s ) +with expansion: + {?} == {?} + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2.c_str() != s.c_str() ) +with expansion: + "hello" != "hello" + +------------------------------------------------------------------------------- +StringBuilder + from String + move from uniquely owned string +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2 == "hello" ) +with expansion: + {?} == "hello" + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2.c_str() == originalPointer ) +with expansion: + "hello" == "hello" + +------------------------------------------------------------------------------- +StringBuilder + from String + move from shared string (copies) +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2 == "hello" ) +with expansion: + {?} == "hello" + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2.c_str() != originalPointer ) +with expansion: + "hello" != "hello" + +------------------------------------------------------------------------------- +StringRef + Empty string +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( empty.empty() ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( empty.size() == 0 ) +with expansion: + 0 == 0 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +StringRef + From string literal +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.empty() == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.size() == 5 ) +with expansion: + 5 == 5 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( s ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( rawChars, "hello" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +StringRef + From string literal + c_str() does not cause copy +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( s ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.c_str() == rawChars ) +with expansion: + "hello" == "hello" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( s ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +StringRef + From sub-string +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( original == "original" ) +with expansion: + {?} == "original" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( original ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( original ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( original ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( original ) ) +with expansion: + true + +------------------------------------------------------------------------------- +StringRef + Substrings + zero-based substring +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.empty() == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.size() == 5 ) +with expansion: + 5 == 5 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( ss.c_str(), "hello" ) == 0 ) +with expansion: + 0 == 0 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss == "hello" ) +with expansion: + {?} == "hello" + +------------------------------------------------------------------------------- +StringRef + Substrings + c_str() causes copy +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( ss ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( ss ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( rawChars == data( s ) ) +with expansion: + "hello world!" == "hello world!" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.c_str() != rawChars ) +with expansion: + "hello" != "hello world!" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( ss ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( ss ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( data( ss ) != data( s ) ) +with expansion: + "hello" != "hello world!" + +------------------------------------------------------------------------------- +StringRef + Substrings + non-zero-based substring +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.size() == 6 ) +with expansion: + 6 == 6 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +StringRef + Substrings + Pointer values of full refs should match +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.c_str() == s2.c_str() ) +with expansion: + "hello world!" == "hello world!" + +------------------------------------------------------------------------------- +StringRef + Substrings + Pointer values of substring refs should not match +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.c_str() != ss.c_str() ) +with expansion: + "hello world!" != "hello" + +------------------------------------------------------------------------------- +StringRef + Comparisons +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( StringRef("hello") == StringRef("hello") ) +with expansion: + {?} == {?} + +StringRef.tests.cpp:: +PASSED: + REQUIRE( StringRef("hello") != StringRef("cello") ) +with expansion: + {?} != {?} + +------------------------------------------------------------------------------- +StringRef + From string + Copied +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( copied == "hot potato" ) +with expansion: + {?} == "hot potato" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( str == "hot potato" ) +with expansion: + {?} == "hot potato" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( copied ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( data( copied ) == originalPointer ) +with expansion: + "hot potato" == "hot potato" + +------------------------------------------------------------------------------- +StringRef + From string + Moved +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( copied == "hot potato" ) +with expansion: + {?} == "hot potato" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( copied ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( str.empty() ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( data( copied ) == originalPointer ) +with expansion: + "hot potato" == "hot potato" + hello hello ------------------------------------------------------------------------------- @@ -8352,6 +8894,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 171 | 120 passed | 47 failed | 4 failed as expected -assertions: 846 | 729 passed | 96 failed | 21 failed as expected +test cases: 174 | 123 passed | 47 failed | 4 failed as expected +assertions: 910 | 793 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index cae1e4bf..91e2307a 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -512,7 +512,28 @@ Message from section two MatchersTests.cpp: + + + + + + + + + + + + + + + + + + + + + hello diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 948cff19..4e65d8ce 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -6358,6 +6358,55 @@ Message from section two + +
+ + + empty.empty() + + + true + + + + + empty.size() == 0 + + + 0 == 0 + + + + + std::strcmp( empty.c_str(), "" ) == 0 + + + 0 == 0 + + + +
+
+ + + s.empty() == false + + + false == false + + + + + s.size() == 5 + + + 5 == 5 + + + +
+ +
@@ -6393,6 +6442,571 @@ Message from section two + +
+ + + sb.capacity() == 0 + + + 0 == 0 + + + + + sb.size() == 0 + + + 0 == 0 + + + + + sb.capacity() == 32 + + + 32 == 32 + + + + + sb.size() == 0 + + + 0 == 0 + + + + + sb.capacity() == 32 + + + 32 == 32 + + + + + sb.size() == 5 + + + 5 == 5 + + + + + s == "hello" + + + {?} == "hello" + + + + + s.size() == 5 + + + 5 == 5 + + + +
+
+ + + s == "hello world" + + + {?} == "hello world" + + + +
+
+ + + s == "hello world" + + + {?} == "hello world" + + + +
+
+ + + sb16.capacity() == 16 + + + 16 == 16 + + + + + sb16.capacity() == 16 + + + 16 == 16 + + + + + s == "hello world" + + + {?} == "hello world" + + + +
+
+
+ + + s2 == s + + + {?} == {?} + + + + + s2.c_str() != s.c_str() + + + "hello" != "hello" + + + +
+ +
+
+
+ + + s2 == "hello" + + + {?} == "hello" + + + + + s2.c_str() == originalPointer + + + "hello" == "hello" + + + +
+ +
+
+
+ + + s2 == "hello" + + + {?} == "hello" + + + + + s2.c_str() != originalPointer + + + "hello" != "hello" + + + +
+ +
+ +
+ +
+ + + empty.empty() + + + true + + + + + empty.size() == 0 + + + 0 == 0 + + + + + std::strcmp( empty.c_str(), "" ) == 0 + + + 0 == 0 + + + +
+
+ + + s.empty() == false + + + false == false + + + + + s.size() == 5 + + + 5 == 5 + + + + + isSubstring( s ) == false + + + false == false + + + + + std::strcmp( rawChars, "hello" ) == 0 + + + 0 == 0 + + +
+ + + isOwned( s ) == false + + + false == false + + + + + s.c_str() == rawChars + + + "hello" == "hello" + + + + + isOwned( s ) == false + + + false == false + + + +
+ +
+
+ + + original == "original" + + + {?} == "original" + + + + + isSubstring( original ) + + + true + + + + + isOwned( original ) == false + + + false == false + + + + + isSubstring( original ) == false + + + false == false + + + + + isOwned( original ) + + + true + + + +
+
+
+ + + ss.empty() == false + + + false == false + + + + + ss.size() == 5 + + + 5 == 5 + + + + + std::strcmp( ss.c_str(), "hello" ) == 0 + + + 0 == 0 + + + + + ss == "hello" + + + {?} == "hello" + + + +
+ +
+
+
+ + + isSubstring( ss ) + + + true + + + + + isOwned( ss ) == false + + + false == false + + + + + rawChars == data( s ) + + + "hello world!" == "hello world!" + + + + + ss.c_str() != rawChars + + + "hello" != "hello world!" + + + + + isSubstring( ss ) == false + + + false == false + + + + + isOwned( ss ) + + + true + + + + + data( ss ) != data( s ) + + + "hello" != "hello world!" + + + +
+ +
+
+
+ + + ss.size() == 6 + + + 6 == 6 + + + + + std::strcmp( ss.c_str(), "world!" ) == 0 + + + 0 == 0 + + + +
+ +
+
+
+ + + s.c_str() == s2.c_str() + + + "hello world!" == "hello world!" + + + +
+ +
+
+
+ + + s.c_str() != ss.c_str() + + + "hello world!" != "hello" + + + +
+ +
+
+ + + StringRef("hello") == StringRef("hello") + + + {?} == {?} + + + + + StringRef("hello") != StringRef("cello") + + + {?} != {?} + + + +
+
+
+ + + copied == "hot potato" + + + {?} == "hot potato" + + + + + str == "hot potato" + + + {?} == "hot potato" + + + + + isOwned( copied ) == false + + + false == false + + + + + data( copied ) == originalPointer + + + "hot potato" == "hot potato" + + + +
+ +
+
+
+ + + copied == "hot potato" + + + {?} == "hot potato" + + + + + isOwned( copied ) + + + true + + + + + str.empty() + + + true + + + + + data( copied ) == originalPointer + + + "hot potato" == "hot potato" + + + +
+ +
+ +
@@ -9166,7 +9780,7 @@ spanner
- + - + From f9ce8fd03b4fc99121262e5b55465332b8c1957a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Jun 2017 11:43:20 +0100 Subject: [PATCH 096/398] Added some missing cstring includes --- projects/SelfTest/String.tests.cpp | 2 ++ projects/SelfTest/StringRef.tests.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/projects/SelfTest/String.tests.cpp b/projects/SelfTest/String.tests.cpp index ccd90964..c27b7508 100644 --- a/projects/SelfTest/String.tests.cpp +++ b/projects/SelfTest/String.tests.cpp @@ -2,6 +2,8 @@ #include "catch.hpp" +#include + TEST_CASE( "String", "[Strings]" ) { using Catch::String; diff --git a/projects/SelfTest/StringRef.tests.cpp b/projects/SelfTest/StringRef.tests.cpp index e5da3f2a..4ebaa878 100644 --- a/projects/SelfTest/StringRef.tests.cpp +++ b/projects/SelfTest/StringRef.tests.cpp @@ -3,6 +3,8 @@ #include "catch.hpp" +#include + namespace Catch { // Implementation of test accessors From 03afbdfec9ce61cdb93f126d805b78bce9bbbe96 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Jun 2017 11:47:09 +0100 Subject: [PATCH 097/398] Made more of StringRef noexcept --- include/internal/catch_stringref.cpp | 12 ++++++------ include/internal/catch_stringref.h | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index d577d3af..147564de 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -17,11 +17,11 @@ namespace Catch { StringRef StringRef::s_emptyStringRef = ""; - StringRef::StringRef() + StringRef::StringRef() noexcept : StringRef( s_emptyStringRef ) {} - StringRef::StringRef( StringRef const& other ) + StringRef::StringRef( StringRef const& other ) noexcept : m_start( other.m_start ), m_size( other.m_size ), m_data( other.m_data ) @@ -38,12 +38,12 @@ namespace Catch { other.m_data = nullptr; } - StringRef::StringRef( char const* rawChars ) + StringRef::StringRef( char const* rawChars ) noexcept : m_start( rawChars ), m_size( std::strlen( rawChars ) ) {} - StringRef::StringRef( char const* rawChars, size_type size ) + StringRef::StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) { @@ -52,7 +52,7 @@ namespace Catch { size = rawSize; } - StringRef::StringRef( String const& other ) + StringRef::StringRef( String const& other ) noexcept : m_start( other.c_str() ), m_size( other.size() ), m_data( nullptr ) @@ -71,7 +71,7 @@ namespace Catch { m_data->release(); } - auto StringRef::operator = ( StringRef other ) -> StringRef& { + auto StringRef::operator = ( StringRef other ) noexcept -> StringRef& { swap( other ); return *this; } diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index a0d8200b..1cf5670f 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -36,16 +36,16 @@ namespace Catch { void takeOwnership(); public: // construction/ assignment - StringRef(); - StringRef( StringRef const& other ); + StringRef() noexcept; + StringRef( StringRef const& other ) noexcept; StringRef( StringRef&& other ) noexcept; - StringRef( char const* rawChars ); - StringRef( char const* rawChars, size_type size ); - StringRef( String const& other ); + StringRef( char const* rawChars ) noexcept; + StringRef( char const* rawChars, size_type size ) noexcept; + StringRef( String const& other ) noexcept; StringRef( String&& other ) noexcept; ~StringRef() noexcept; - auto operator = ( StringRef other ) -> StringRef&; + auto operator = ( StringRef other ) noexcept -> StringRef&; void swap( StringRef& other ) noexcept; From 63a8017ba7dd11ab585c50d6be1c100ccd286a2c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Jun 2017 14:27:42 +0100 Subject: [PATCH 098/398] Minor session tweaks --- include/catch_session.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index ffd87c9d..42080cd1 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -18,7 +18,7 @@ #include "internal/catch_startup_exception_registry.h" #include -#include +#include #include namespace Catch { @@ -86,7 +86,7 @@ namespace Catch { if( lastSlash != std::string::npos ) filename = filename.substr( lastSlash+1 ); - std::string::size_type lastDot = filename.find_last_of( "." ); + std::string::size_type lastDot = filename.find_last_of( '.' ); if( lastDot != std::string::npos ) filename = filename.substr( 0, lastDot ); @@ -106,11 +106,11 @@ namespace Catch { alreadyInstantiated = true; m_cli = makeCommandLineParser( m_configData ); } - ~Session() { + ~Session() override { Catch::cleanUp(); } - void showHelp( std::string const& ) { + void showHelp() { Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; Catch::cout() << m_cli << std::endl; @@ -132,7 +132,7 @@ namespace Catch { } if( m_configData.showHelp ) - showHelp( m_configData.processName ); + showHelp(); m_config.reset(); return 0; } From 0016362f69804ae18953a0ec11d0c108e8402e1d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Jun 2017 16:31:05 +0100 Subject: [PATCH 099/398] explicit conversion from size_t to size_type --- include/internal/catch_stringref.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 147564de..4ee4f7dd 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -40,14 +40,14 @@ namespace Catch { StringRef::StringRef( char const* rawChars ) noexcept : m_start( rawChars ), - m_size( std::strlen( rawChars ) ) + m_size( static_cast( std::strlen( rawChars ) ) ) {} StringRef::StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), m_size( size ) { - size_type rawSize = rawChars == nullptr ? 0 : std::strlen( rawChars ); + size_type rawSize = rawChars == nullptr ? 0 : static_cast( std::strlen( rawChars ) ); if( rawSize < size ) size = rawSize; } From 694fe61ae3f3d36b9fc11300eb133b467e7de8a5 Mon Sep 17 00:00:00 2001 From: Baruch Burstein Date: Sun, 2 Jul 2017 11:52:29 +0300 Subject: [PATCH 100/398] Add ability to format any streamable class This should probably be done at the source of this external file, but I couldn't find where that is. Perhaps it should be mentioned in the file header comment? --- include/external/tbc_text_format.h | 85 +++++++++++++++++------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/include/external/tbc_text_format.h b/include/external/tbc_text_format.h index 5209d804..39030ab0 100644 --- a/include/external/tbc_text_format.h +++ b/include/external/tbc_text_format.h @@ -53,13 +53,55 @@ namespace Tbc { public: Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) : attr( _attr ) + { + init( _str ); + } + + template + Text( T const& _val, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::ostringstream oss; + oss << _val; + init( oss.str() ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + + private: + TextAttributes attr; + std::vector lines; + + void init( std::string const& _str ) { const std::string wrappableBeforeChars = "[({<\t"; const std::string wrappableAfterChars = "])}>-,./|\\"; const std::string wrappableInsteadOfChars = " \n\r"; - std::string indent = _attr.initialIndent != std::string::npos - ? std::string( _attr.initialIndent, ' ' ) - : std::string( _attr.indent, ' ' ); + std::string indent = attr.initialIndent != std::string::npos + ? std::string( attr.initialIndent, ' ' ) + : std::string( attr.indent, ' ' ); typedef std::string::const_iterator iterator; iterator it = _str.begin(); @@ -74,7 +116,7 @@ namespace Tbc { std::string suffix; - std::size_t width = (std::min)( static_cast( strEnd-it ), _attr.width-static_cast( indent.size() ) ); + std::size_t width = (std::min)( static_cast( strEnd-it ), attr.width-static_cast( indent.size() ) ); iterator itEnd = it+width; iterator itNext = _str.end(); @@ -121,42 +163,11 @@ namespace Tbc { } lines.push_back( indent + std::string( it, itEnd ) + suffix ); - if( indent.size() != _attr.indent ) - indent = std::string( _attr.indent, ' ' ); + if( indent.size() != attr.indent ) + indent = std::string( attr.indent, ' ' ); it = itNext; } } - - - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - - private: - std::string str; - TextAttributes attr; - std::vector lines; }; } // end namespace Tbc From bb9f2bb3ad293971b376cd78a55b947ee62f07aa Mon Sep 17 00:00:00 2001 From: Baruch Burstein Date: Tue, 4 Jul 2017 18:16:42 +0300 Subject: [PATCH 101/398] Use new formatting capabilities --- include/internal/catch_list.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index 5d9d8ed4..a423f3b4 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -45,7 +45,7 @@ namespace Catch { Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; if( config.verbosity() >= Verbosity::High ) { - Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; + Catch::cout() << Text( testCaseInfo.lineInfo, descAttr ) << std::endl; std::string description = testCaseInfo.description; if( description == "" ) description = "(NO DESCRIPTION)"; From f7493475230aa25a4086bbd44af59f9705aea493 Mon Sep 17 00:00:00 2001 From: Baruch Burstein Date: Thu, 6 Jul 2017 01:25:49 +0300 Subject: [PATCH 102/398] Check that reporter supports requested verbosity --- include/internal/catch_config.hpp | 3 +-- include/internal/catch_interfaces_config.h | 1 + include/internal/catch_interfaces_reporter.h | 3 +++ include/reporters/catch_reporter_bases.hpp | 12 ++++++++++++ include/reporters/catch_reporter_multi.hpp | 18 ++++++++++++++++++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index bc1f5b26..3f967b93 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -86,8 +86,6 @@ namespace Catch { bool listTags() const { return m_data.listTags; } bool listReporters() const { return m_data.listReporters; } - Verbosity verbosity() const { return m_data.verbosity; } - std::string getProcessName() const { return m_data.processName; } std::vector const& getReporterNames() const { return m_data.reporterNames; } @@ -110,6 +108,7 @@ namespace Catch { virtual bool shouldDebugBreak() const override { return m_data.shouldDebugBreak; } virtual int abortAfter() const override { return m_data.abortAfter; } virtual bool showInvisibles() const override { return m_data.showInvisibles; } + virtual Verbosity verbosity() const override { return m_data.verbosity; } private: diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index 75499014..d2d7602c 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -64,6 +64,7 @@ namespace Catch { virtual unsigned int rngSeed() const = 0; virtual UseColour::YesOrNo useColour() const = 0; virtual std::vector const& getSectionsToRun() const = 0; + virtual Verbosity verbosity() const = 0; }; using IConfigPtr = std::shared_ptr; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 7a42f097..ea68aa54 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace Catch @@ -212,6 +213,8 @@ namespace Catch virtual ReporterPreferences getPreferences() const = 0; + virtual std::set const& getSupportedVerbosities() const = 0; + virtual void noMatchingTestCases( std::string const& spec ) = 0; virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 27767060..f6a8d28e 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -49,12 +49,18 @@ namespace Catch { stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; + CATCH_ENFORCE( getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); } virtual ReporterPreferences getPreferences() const override { return m_reporterPrefs; } + virtual std::set const& getSupportedVerbosities() const override { + static std::set supported{ Verbosity::Normal }; + return supported; + } + virtual ~StreamingReporterBase() override; virtual void noMatchingTestCases( std::string const& ) override {} @@ -155,6 +161,7 @@ namespace Catch { stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; + CATCH_ENFORCE( getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); } ~CumulativeReporterBase(); @@ -162,6 +169,11 @@ namespace Catch { return m_reporterPrefs; } + virtual std::set const& getSupportedVerbosities() const override { + static std::set supported{ Verbosity::Normal }; + return supported; + } + virtual void testRunStarting( TestRunInfo const& ) override {} virtual void testGroupStarting( GroupInfo const& ) override {} diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 589c34e0..57f0974c 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -15,9 +15,23 @@ namespace Catch { class MultipleReporters : public IStreamingReporter { typedef std::vector Reporters; Reporters m_reporters; + std::set m_verbosities; public: void add( IStreamingReporterPtr&& reporter ) { + if( m_reporters.empty() ) { + m_verbosities = reporter->getSupportedVerbosities(); + } + else { + for( auto it = m_verbosities.cbegin(); it != m_verbosities.cend(); ) { + if( reporter->getSupportedVerbosities().count( *it ) == 0 ) { + it = m_verbosities.erase(it); + } + else { + ++it; + } + } + } m_reporters.push_back( std::move( reporter ) ); } @@ -27,6 +41,10 @@ public: // IStreamingReporter return m_reporters[0]->getPreferences(); } + virtual std::set const& getSupportedVerbosities() const override { + return m_verbosities; + } + virtual void noMatchingTestCases( std::string const& spec ) override { for( auto const& reporter : m_reporters ) reporter->noMatchingTestCases( spec ); From fc32165d48f0a46a60ac02e0e52f8c89adafd8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 6 Jul 2017 22:28:42 +0200 Subject: [PATCH 103/398] Started work on splitting out .cpp files from header files --- CMakeLists.txt | 67 +++--- ...onresult.hpp => catch_assertionresult.cpp} | 10 - include/internal/catch_assertionresult.h | 1 + .../{catch_common.hpp => catch_common.cpp} | 7 +- ...lour_impl.hpp => catch_console_colour.cpp} | 10 +- ...tch_context_impl.hpp => catch_context.cpp} | 4 +- ...{catch_debugger.hpp => catch_debugger.cpp} | 7 +- include/internal/catch_errno_guard.cpp | 15 ++ ...ch_errno_guard.hpp => catch_errno_guard.h} | 13 +- .../catch_exception_translator_registry.hpp | 1 + include/internal/catch_fatal_condition.cpp | 181 ++++++++++++++++ include/internal/catch_fatal_condition.h | 92 ++++++++ include/internal/catch_fatal_condition.hpp | 200 ------------------ include/internal/catch_impl.hpp | 37 ++-- include/internal/catch_matchers.hpp | 2 + ...s_string.hpp => catch_matchers_string.cpp} | 2 +- .../{catch_message.hpp => catch_message.cpp} | 21 +- include/internal/catch_message.h | 12 +- ...hpp => catch_notimplemented_exception.cpp} | 4 - ...egistry_hub.hpp => catch_registry_hub.cpp} | 4 - ...t_builder.hpp => catch_result_builder.cpp} | 7 +- include/internal/catch_run_context.hpp | 2 +- .../{catch_section.hpp => catch_section.cpp} | 4 - ...ection_info.hpp => catch_section_info.cpp} | 8 +- ...p => catch_startup_exception_registry.cpp} | 4 - include/internal/catch_stream.h | 1 - include/internal/catch_stream.hpp | 1 + include/internal/catch_stringdata.cpp | 1 - ...istry.hpp => catch_tag_alias_registry.cpp} | 4 - ...case_info.hpp => catch_test_case_info.cpp} | 4 - .../catch_test_case_registry_impl.hpp | 7 + .../{catch_timer.hpp => catch_timer.cpp} | 0 ...{catch_tostring.hpp => catch_tostring.cpp} | 5 +- .../{catch_version.hpp => catch_version.cpp} | 7 +- include/internal/catch_version.h | 4 +- include/reporters/catch_reporter_bases.hpp | 2 +- .../SelfTest/SurrogateCpps/catch_common.cpp | 3 - .../SelfTest/SurrogateCpps/catch_message.cpp | 3 - 38 files changed, 403 insertions(+), 354 deletions(-) rename include/internal/{catch_assertionresult.hpp => catch_assertionresult.cpp} (86%) rename include/internal/{catch_common.hpp => catch_common.cpp} (96%) rename include/internal/{catch_console_colour_impl.hpp => catch_console_colour.cpp} (96%) rename include/internal/{catch_context_impl.hpp => catch_context.cpp} (96%) rename include/internal/{catch_debugger.hpp => catch_debugger.cpp} (95%) create mode 100644 include/internal/catch_errno_guard.cpp rename include/internal/{catch_errno_guard.hpp => catch_errno_guard.h} (53%) create mode 100644 include/internal/catch_fatal_condition.cpp create mode 100644 include/internal/catch_fatal_condition.h delete mode 100644 include/internal/catch_fatal_condition.hpp rename include/internal/{catch_matchers_string.hpp => catch_matchers_string.cpp} (99%) rename include/internal/{catch_message.hpp => catch_message.cpp} (67%) rename include/internal/{catch_notimplemented_exception.hpp => catch_notimplemented_exception.cpp} (78%) rename include/internal/{catch_registry_hub.hpp => catch_registry_hub.cpp} (95%) rename include/internal/{catch_result_builder.hpp => catch_result_builder.cpp} (97%) rename include/internal/{catch_section.hpp => catch_section.cpp} (91%) rename include/internal/{catch_section_info.hpp => catch_section_info.cpp} (92%) rename include/internal/{catch_startup_exception_registry.hpp => catch_startup_exception_registry.cpp} (75%) rename include/internal/{catch_tag_alias_registry.hpp => catch_tag_alias_registry.cpp} (93%) rename include/internal/{catch_test_case_info.hpp => catch_test_case_info.cpp} (96%) rename include/internal/{catch_timer.hpp => catch_timer.cpp} (100%) rename include/internal/{catch_tostring.hpp => catch_tostring.cpp} (97%) rename include/internal/{catch_version.hpp => catch_version.cpp} (87%) delete mode 100644 projects/SelfTest/SurrogateCpps/catch_common.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_message.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ed863deb..4f290cd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,8 +83,7 @@ CheckFileList(TEST_SOURCES ${SELF_TEST_DIR}) # A set of impl files that just #include a single header # Please keep these ordered alphabetically -set(IMPL_SOURCES - ${SELF_TEST_DIR}/SurrogateCpps/catch_common.cpp +set(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp @@ -94,7 +93,6 @@ set(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_message.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp @@ -102,7 +100,7 @@ set(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp ) -CheckFileList(IMPL_SOURCES ${SELF_TEST_DIR}/SurrogateCpps) +CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps) # Please keep these ordered alphabetically @@ -125,26 +123,21 @@ CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external) set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_approx.hpp ${HEADER_DIR}/internal/catch_assertionresult.h - ${HEADER_DIR}/internal/catch_assertionresult.hpp ${HEADER_DIR}/internal/catch_capture.hpp ${HEADER_DIR}/internal/catch_clara.h ${HEADER_DIR}/internal/catch_commandline.hpp ${HEADER_DIR}/internal/catch_common.h - ${HEADER_DIR}/internal/catch_common.hpp ${HEADER_DIR}/internal/catch_compiler_capabilities.h ${HEADER_DIR}/internal/catch_config.hpp ${HEADER_DIR}/internal/catch_console_colour.hpp - ${HEADER_DIR}/internal/catch_console_colour_impl.hpp ${HEADER_DIR}/internal/catch_context.h - ${HEADER_DIR}/internal/catch_context_impl.hpp ${HEADER_DIR}/internal/catch_debugger.h - ${HEADER_DIR}/internal/catch_debugger.hpp ${HEADER_DIR}/internal/catch_default_main.hpp - ${HEADER_DIR}/internal/catch_errno_guard.hpp + ${HEADER_DIR}/internal/catch_errno_guard.h ${HEADER_DIR}/internal/catch_evaluate.hpp ${HEADER_DIR}/internal/catch_exception_translator_registry.hpp ${HEADER_DIR}/internal/catch_expression_lhs.hpp - ${HEADER_DIR}/internal/catch_fatal_condition.hpp + ${HEADER_DIR}/internal/catch_fatal_condition.h ${HEADER_DIR}/internal/catch_impl.hpp ${HEADER_DIR}/internal/catch_interfaces_capture.h ${HEADER_DIR}/internal/catch_interfaces_config.h @@ -157,47 +150,33 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_list.hpp ${HEADER_DIR}/internal/catch_matchers.hpp ${HEADER_DIR}/internal/catch_matchers_string.h - ${HEADER_DIR}/internal/catch_matchers_string.hpp ${HEADER_DIR}/internal/catch_matchers_vector.h ${HEADER_DIR}/internal/catch_message.h - ${HEADER_DIR}/internal/catch_message.hpp ${HEADER_DIR}/internal/catch_notimplemented_exception.h - ${HEADER_DIR}/internal/catch_notimplemented_exception.hpp ${HEADER_DIR}/internal/catch_objc.hpp ${HEADER_DIR}/internal/catch_objc_arc.hpp ${HEADER_DIR}/internal/catch_option.hpp ${HEADER_DIR}/internal/catch_platform.h ${HEADER_DIR}/internal/catch_reenable_warnings.h - ${HEADER_DIR}/internal/catch_registry_hub.hpp ${HEADER_DIR}/internal/catch_reporter_registrars.hpp ${HEADER_DIR}/internal/catch_reporter_registry.hpp ${HEADER_DIR}/internal/catch_result_builder.h - ${HEADER_DIR}/internal/catch_result_builder.hpp ${HEADER_DIR}/internal/catch_result_type.h ${HEADER_DIR}/internal/catch_run_context.hpp ${HEADER_DIR}/internal/catch_section.h - ${HEADER_DIR}/internal/catch_section.hpp ${HEADER_DIR}/internal/catch_section_info.h - ${HEADER_DIR}/internal/catch_section_info.hpp ${HEADER_DIR}/internal/catch_startup_exception_registry.h - ${HEADER_DIR}/internal/catch_startup_exception_registry.hpp ${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_stream.hpp ${HEADER_DIR}/internal/catch_streambuf.h - ${HEADER_DIR}/internal/catch_string.cpp ${HEADER_DIR}/internal/catch_string.h - ${HEADER_DIR}/internal/catch_stringbuilder.cpp ${HEADER_DIR}/internal/catch_stringbuilder.h - ${HEADER_DIR}/internal/catch_stringdata.cpp ${HEADER_DIR}/internal/catch_stringdata.h - ${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_stringref.h ${HEADER_DIR}/internal/catch_suppress_warnings.h ${HEADER_DIR}/internal/catch_tag_alias.h ${HEADER_DIR}/internal/catch_tag_alias_registry.h - ${HEADER_DIR}/internal/catch_tag_alias_registry.hpp ${HEADER_DIR}/internal/catch_test_case_info.h - ${HEADER_DIR}/internal/catch_test_case_info.hpp ${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp ${HEADER_DIR}/internal/catch_test_case_tracker.hpp ${HEADER_DIR}/internal/catch_test_registry.hpp @@ -205,17 +184,41 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_test_spec_parser.hpp ${HEADER_DIR}/internal/catch_text.h ${HEADER_DIR}/internal/catch_timer.h - ${HEADER_DIR}/internal/catch_timer.hpp ${HEADER_DIR}/internal/catch_tostring.h - ${HEADER_DIR}/internal/catch_tostring.hpp ${HEADER_DIR}/internal/catch_totals.hpp ${HEADER_DIR}/internal/catch_version.h - ${HEADER_DIR}/internal/catch_version.hpp ${HEADER_DIR}/internal/catch_wildcard_pattern.hpp ${HEADER_DIR}/internal/catch_windows_h_proxy.h ${HEADER_DIR}/internal/catch_xmlwriter.hpp ) -CheckFileList(INTERNAL_HEADERS ${HEADER_DIR}/internal) +set(IMPL_SOURCES + ${HEADER_DIR}/internal/catch_assertionresult.cpp + ${HEADER_DIR}/internal/catch_common.cpp + ${HEADER_DIR}/internal/catch_console_colour.cpp + ${HEADER_DIR}/internal/catch_context.cpp + ${HEADER_DIR}/internal/catch_debugger.cpp + ${HEADER_DIR}/internal/catch_errno_guard.cpp + ${HEADER_DIR}/internal/catch_fatal_condition.cpp + ${HEADER_DIR}/internal/catch_matchers_string.cpp + ${HEADER_DIR}/internal/catch_message.cpp + ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp + ${HEADER_DIR}/internal/catch_registry_hub.cpp + ${HEADER_DIR}/internal/catch_result_builder.cpp + ${HEADER_DIR}/internal/catch_section.cpp + ${HEADER_DIR}/internal/catch_section_info.cpp + ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp + ${HEADER_DIR}/internal/catch_string.cpp + ${HEADER_DIR}/internal/catch_stringbuilder.cpp + ${HEADER_DIR}/internal/catch_stringdata.cpp + ${HEADER_DIR}/internal/catch_stringref.cpp + ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp + ${HEADER_DIR}/internal/catch_test_case_info.cpp + ${HEADER_DIR}/internal/catch_timer.cpp + ${HEADER_DIR}/internal/catch_tostring.cpp + ${HEADER_DIR}/internal/catch_version.cpp + ) +set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS}) +CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal) # Please keep these ordered alphabetically set(REPORTER_HEADERS @@ -248,7 +251,7 @@ CheckFileList(BENCH_SOURCES ${BENCHMARK_DIR}) # Provide some groupings for IDEs SOURCE_GROUP("Tests" FILES ${TEST_SOURCES}) -SOURCE_GROUP("Surrogates" FILES ${IMPL_SOURCES}) +SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES}) SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES}) # configure the executable @@ -259,8 +262,8 @@ add_definitions( -DCATCH_CONFIG_FULL_PROJECT ) # Projects consuming Catch via ExternalProject_Add might want to use install step # without building all of our selftests. if (NOT NO_SELFTEST) - add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${HEADERS}) - add_executable(Benchmark ${BENCH_SOURCES} ${HEADERS}) + add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${SURROGATE_SOURCES} ${HEADERS}) + add_executable(Benchmark ${BENCH_SOURCES} ${IMPL_SOURCES} ${HEADERS}) # Add desired warnings if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) diff --git a/include/internal/catch_assertionresult.hpp b/include/internal/catch_assertionresult.cpp similarity index 86% rename from include/internal/catch_assertionresult.hpp rename to include/internal/catch_assertionresult.cpp index a103d961..77c69281 100644 --- a/include/internal/catch_assertionresult.hpp +++ b/include/internal/catch_assertionresult.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED #include "catch_assertionresult.h" @@ -54,12 +52,6 @@ namespace Catch { return !m_resultData.message.empty(); } - std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) { - return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"') - ? capturedExpression - : std::string(capturedExpression) + ", " + secondArg; - } - std::string AssertionResult::getExpression() const { if (isFalseTest(m_info.resultDisposition)) return '!' + std::string(m_info.capturedExpression); @@ -102,5 +94,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 0b20a876..26546d38 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -10,6 +10,7 @@ #include #include "catch_result_type.h" +#include "catch_common.h" namespace Catch { diff --git a/include/internal/catch_common.hpp b/include/internal/catch_common.cpp similarity index 96% rename from include/internal/catch_common.hpp rename to include/internal/catch_common.cpp index fc82351e..12968515 100644 --- a/include/internal/catch_common.hpp +++ b/include/internal/catch_common.cpp @@ -5,10 +5,10 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED #include "catch_common.h" +#include "catch_context.h" +#include "catch_interfaces_config.h" #include #include @@ -107,6 +107,3 @@ namespace Catch { return os; } } - -#endif // TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED - diff --git a/include/internal/catch_console_colour_impl.hpp b/include/internal/catch_console_colour.cpp similarity index 96% rename from include/internal/catch_console_colour_impl.hpp rename to include/internal/catch_console_colour.cpp index fc3aaf50..5670b8bf 100644 --- a/include/internal/catch_console_colour_impl.hpp +++ b/include/internal/catch_console_colour.cpp @@ -5,11 +5,13 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED #include "catch_console_colour.hpp" -#include "catch_errno_guard.hpp" +#include "catch_errno_guard.h" +#include "catch_interfaces_config.h" +#include "catch_stream.h" +#include "catch_context.h" +#include "catch_platform.h" namespace Catch { namespace { @@ -186,5 +188,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context.cpp similarity index 96% rename from include/internal/catch_context_impl.hpp rename to include/internal/catch_context.cpp index 10fd30ea..44d8a99e 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context.cpp @@ -8,10 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED -#include "catch_run_context.hpp" - +#include "catch_stream.h" #include "catch_context.h" -#include "catch_stream.hpp" #include "catch_common.h" namespace Catch { diff --git a/include/internal/catch_debugger.hpp b/include/internal/catch_debugger.cpp similarity index 95% rename from include/internal/catch_debugger.hpp rename to include/internal/catch_debugger.cpp index 2048904a..e857717d 100644 --- a/include/internal/catch_debugger.hpp +++ b/include/internal/catch_debugger.cpp @@ -6,11 +6,10 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * */ -#ifndef TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED #include "catch_debugger.h" -#include "catch_errno_guard.hpp" +#include "catch_errno_guard.h" +#include "catch_stream.h" #ifdef CATCH_PLATFORM_MAC @@ -127,5 +126,3 @@ } } #endif // Platform - -#endif // TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED diff --git a/include/internal/catch_errno_guard.cpp b/include/internal/catch_errno_guard.cpp new file mode 100644 index 00000000..070583bc --- /dev/null +++ b/include/internal/catch_errno_guard.cpp @@ -0,0 +1,15 @@ +/* + * Created by Martin on 06/03/2017. + * + * 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) + */ + +#include "catch_errno_guard.h" + +#include + +namespace Catch { + ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} + ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } +} diff --git a/include/internal/catch_errno_guard.hpp b/include/internal/catch_errno_guard.h similarity index 53% rename from include/internal/catch_errno_guard.hpp rename to include/internal/catch_errno_guard.h index 48794b08..b1d1fc1c 100644 --- a/include/internal/catch_errno_guard.hpp +++ b/include/internal/catch_errno_guard.h @@ -4,22 +4,19 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED - -#include - +#ifndef TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED +#define TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED namespace Catch { class ErrnoGuard { public: - ErrnoGuard():m_oldErrno(errno){} - ~ErrnoGuard() { errno = m_oldErrno; } + ErrnoGuard(); + ~ErrnoGuard(); private: int m_oldErrno; }; } -#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED +#endif // TWOBLUECUBES_CATCH_ERRNO_GUARD_H_INCLUDED diff --git a/include/internal/catch_exception_translator_registry.hpp b/include/internal/catch_exception_translator_registry.hpp index c4bdb400..07d83f21 100644 --- a/include/internal/catch_exception_translator_registry.hpp +++ b/include/internal/catch_exception_translator_registry.hpp @@ -10,6 +10,7 @@ #include "catch_interfaces_exception.h" #include "catch_tostring.h" +#include "catch_result_builder.h" #ifdef __OBJC__ #import "Foundation/Foundation.h" diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp new file mode 100644 index 00000000..51773f42 --- /dev/null +++ b/include/internal/catch_fatal_condition.cpp @@ -0,0 +1,181 @@ +/* + * Created by Phil on 21/08/2014 + * Copyright 2014 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) + * + */ + +#include "catch_fatal_condition.h" + +#include "catch_context.h" +#include "catch_interfaces_capture.h" + +namespace Catch { + + // Report the error condition + void reportFatal( std::string const& message ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + void FatalConditionHandler::reset() {} +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + +namespace Catch { + struct SignalDefs { DWORD id; const char* name; }; + + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + SignalDefs signalDefs[] = { + { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, + { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, + { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, + { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, + }; + + LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + } + } + // If its not an exception we care about, pass it along. + // This stops us from eating debugger breaks etc. + return EXCEPTION_CONTINUE_SEARCH; + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + // 32k seems enough for Catch to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + exceptionHandlerHandle = nullptr; + // Register as first handler in current chain + exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + } + + void FatalConditionHandler::reset() { + if (isSet) { + // Unregister handler and restore the old guarantee + RemoveVectoredExceptionHandler(exceptionHandlerHandle); + SetThreadStackGuarantee(&guaranteeSize); + exceptionHandlerHandle = nullptr; + isSet = false; + } + } + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + +bool FatalConditionHandler::isSet = false; +ULONG FatalConditionHandler::guaranteeSize = 0; +PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; + + +} // namespace Catch + +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + void FatalConditionHandler::reset() {} +} + + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct SignalDefs { + int id; + const char* name; + }; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + + void FatalConditionHandler::handleSignal( int sig ) { + std::string name = ""; + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + SignalDefs &def = signalDefs[i]; + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise( sig ); + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = SIGSTKSZ; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = { }; + + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + + void FatalConditionHandler::reset() { + if( isSet ) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; + + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows diff --git a/include/internal/catch_fatal_condition.h b/include/internal/catch_fatal_condition.h new file mode 100644 index 00000000..97f371ae --- /dev/null +++ b/include/internal/catch_fatal_condition.h @@ -0,0 +1,92 @@ +/* + * Created by Phil on 21/08/2014 + * Copyright 2014 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) + * + */ +#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED +#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED + +#include +#include "catch_platform.h" +#include "catch_compiler_capabilities.h" + +namespace Catch { + + // Report the error condition + void reportFatal( std::string const& message ); + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// +#include "catch_windows_h_proxy.h" + +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + +namespace Catch { + + struct FatalConditionHandler { + + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); + FatalConditionHandler(); + static void reset(); + ~FatalConditionHandler(); + + private: + static bool isSet; + static ULONG guaranteeSize; + static PVOID exceptionHandlerHandle; + }; + +} // namespace Catch + +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct FatalConditionHandler { + + static bool isSet; + static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; + static stack_t oldSigStack; + static char altStackMem[]; + + static void handleSignal( int sig ); + + FatalConditionHandler(); + ~FatalConditionHandler(); + static void reset(); + }; + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows + +#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED diff --git a/include/internal/catch_fatal_condition.hpp b/include/internal/catch_fatal_condition.hpp deleted file mode 100644 index 26903fe7..00000000 --- a/include/internal/catch_fatal_condition.hpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Created by Phil on 21/08/2014 - * Copyright 2014 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) - * - */ -#ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED -#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED - - -namespace Catch { - - // Report the error condition - inline void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); - } - -} // namespace Catch - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// -#include "catch_windows_h_proxy.h" - -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - -# else // CATCH_CONFIG_WINDOWS_SEH is defined - -namespace Catch { - - struct SignalDefs { DWORD id; const char* name; }; - extern SignalDefs signalDefs[]; - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { - { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, - { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, - { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, - }; - - struct FatalConditionHandler { - - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - } - } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; - } - - FatalConditionHandler() { - isSet = true; - // 32k seems enough for Catch to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - exceptionHandlerHandle = nullptr; - // Register as first handler in current chain - exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - } - - static void reset() { - if (isSet) { - // Unregister handler and restore the old guarantee - RemoveVectoredExceptionHandler(exceptionHandlerHandle); - SetThreadStackGuarantee(&guaranteeSize); - exceptionHandlerHandle = nullptr; - isSet = false; - } - } - - ~FatalConditionHandler() { - reset(); - } - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; - - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; - -} // namespace Catch - -# endif // CATCH_CONFIG_WINDOWS_SEH - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - struct FatalConditionHandler { - void reset() {} - }; -} - - -# else // CATCH_CONFIG_POSIX_SIGNALS is defined - -#include - -namespace Catch { - - struct SignalDefs { - int id; - const char* name; - }; - extern SignalDefs signalDefs[]; - SignalDefs signalDefs[] = { - { SIGINT, "SIGINT - Terminal interrupt signal" }, - { SIGILL, "SIGILL - Illegal instruction signal" }, - { SIGFPE, "SIGFPE - Floating point error signal" }, - { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, - { SIGTERM, "SIGTERM - Termination request signal" }, - { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } - }; - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; - static stack_t oldSigStack; - static char altStackMem[SIGSTKSZ]; - - static void handleSignal( int sig ) { - std::string name = ""; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - SignalDefs &def = signalDefs[i]; - if (sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise( sig ); - } - - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = SIGSTKSZ; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = { 0 }; - - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - - ~FatalConditionHandler() { - reset(); - } - static void reset() { - if( isSet ) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } - }; - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; - - -} // namespace Catch - -# endif // CATCH_CONFIG_POSIX_SIGNALS - -#endif // not Windows - -#endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 2306af7f..934cd4d1 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -17,33 +17,34 @@ #endif #include "../catch_session.hpp" -#include "catch_registry_hub.hpp" -#include "catch_notimplemented_exception.hpp" -#include "catch_context_impl.hpp" -#include "catch_console_colour_impl.hpp" -#include "catch_assertionresult.hpp" -#include "catch_test_case_info.hpp" +#include "catch_stream.hpp" #include "catch_test_spec.hpp" -#include "catch_version.hpp" -#include "catch_message.hpp" -#include "catch_timer.hpp" -#include "catch_common.hpp" -#include "catch_section.hpp" -#include "catch_debugger.hpp" -#include "catch_tostring.hpp" -#include "catch_result_builder.hpp" -#include "catch_tag_alias_registry.hpp" #include "catch_test_case_tracker.hpp" -#include "catch_matchers_string.hpp" -#include "catch_startup_exception_registry.hpp" // These files are not included in the full (not single include) project // as they are compiled as proper cpp files #ifndef CATCH_CONFIG_FULL_PROJECT +# include "catch_assertionresult.cpp" +# include "catch_common.cpp" +# include "catch_console_colour.cpp" +# include "catch_context.cpp" +# include "catch_debugger.cpp" +# include "catch_matchers_string.cpp" +# include "catch_message.cpp" +# include "catch_notimplemented_exception.cpp" +# include "catch_registry_hub.cpp" +# include "catch_result_builder.hpp" +# include "catch_section.cpp" +# include "catch_startup_exception_registry.cpp" # include "catch_stringref.cpp" # include "catch_string.cpp" # include "catch_stringbuilder.cpp" # include "catch_stringdata.cpp" +# include "catch_tag_alias_registry.cpp" +# include "catch_test_case_info.cpp" +# include "catch_timer.cpp" +# include "catch_tostring.cpp" +# include "catch_version.cpp" #endif #include "../reporters/catch_reporter_multi.hpp" @@ -88,8 +89,6 @@ namespace Catch { IConfig::~IConfig() {} XmlReporter::~XmlReporter() {} JunitReporter::~JunitReporter() {} - TestRegistry::~TestRegistry() {} - FreeFunctionTestCase::~FreeFunctionTestCase() {} WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 21445347..ef039aa9 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -10,6 +10,8 @@ #include "catch_common.h" +#include + namespace Catch { namespace Matchers { namespace Impl { diff --git a/include/internal/catch_matchers_string.hpp b/include/internal/catch_matchers_string.cpp similarity index 99% rename from include/internal/catch_matchers_string.hpp rename to include/internal/catch_matchers_string.cpp index ca117eda..207193fb 100644 --- a/include/internal/catch_matchers_string.hpp +++ b/include/internal/catch_matchers_string.cpp @@ -6,7 +6,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_matchers.hpp" +#include "catch_matchers_string.h" namespace Catch { namespace Matchers { diff --git a/include/internal/catch_message.hpp b/include/internal/catch_message.cpp similarity index 67% rename from include/internal/catch_message.hpp rename to include/internal/catch_message.cpp index 11d07466..2f474a90 100644 --- a/include/internal/catch_message.hpp +++ b/include/internal/catch_message.cpp @@ -5,10 +5,9 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED #include "catch_message.h" +#include "catch_interfaces_capture.h" namespace Catch { @@ -21,12 +20,28 @@ namespace Catch { sequence( ++globalCount ) {} + bool MessageInfo::operator==( MessageInfo const& other ) const { + return sequence == other.sequence; + } + + bool MessageInfo::operator<( MessageInfo const& other ) const { + return sequence < other.sequence; + } + // This may need protecting if threading support is added unsigned int MessageInfo::globalCount = 0; //////////////////////////////////////////////////////////////////////////// + Catch::MessageBuilder::MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + :m_info(macroName, lineInfo, type) {} + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) : m_info( builder.m_info ) { @@ -45,5 +60,3 @@ namespace Catch { } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h index 84ff95ea..25d7c259 100644 --- a/include/internal/catch_message.h +++ b/include/internal/catch_message.h @@ -25,12 +25,8 @@ namespace Catch { std::string message; unsigned int sequence; - bool operator == ( MessageInfo const& other ) const { - return sequence == other.sequence; - } - bool operator < ( MessageInfo const& other ) const { - return sequence < other.sequence; - } + bool operator == ( MessageInfo const& other ) const; + bool operator < ( MessageInfo const& other ) const; private: static unsigned int globalCount; }; @@ -38,9 +34,7 @@ namespace Catch { struct MessageBuilder { MessageBuilder( std::string const& macroName, SourceLineInfo const& lineInfo, - ResultWas::OfType type ) - : m_info( macroName, lineInfo, type ) - {} + ResultWas::OfType type ); template MessageBuilder& operator << ( T const& value ) { diff --git a/include/internal/catch_notimplemented_exception.hpp b/include/internal/catch_notimplemented_exception.cpp similarity index 78% rename from include/internal/catch_notimplemented_exception.hpp rename to include/internal/catch_notimplemented_exception.cpp index f5b1ea66..62188ef3 100644 --- a/include/internal/catch_notimplemented_exception.hpp +++ b/include/internal/catch_notimplemented_exception.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED #include "catch_notimplemented_exception.h" #include @@ -26,5 +24,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.cpp similarity index 95% rename from include/internal/catch_registry_hub.hpp rename to include/internal/catch_registry_hub.cpp index 23c9628c..9f901085 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED #include "catch_interfaces_registry_hub.h" @@ -96,5 +94,3 @@ namespace Catch { } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.cpp similarity index 97% rename from include/internal/catch_result_builder.hpp rename to include/internal/catch_result_builder.cpp index 540e3a5a..727b42e7 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED #include "catch_result_builder.h" #include "catch_context.h" @@ -14,8 +12,11 @@ #include "catch_interfaces_runner.h" #include "catch_interfaces_capture.h" #include "catch_interfaces_registry_hub.h" +#include "catch_matchers_string.h" #include "catch_wildcard_pattern.hpp" +#include + namespace Catch { ResultBuilder::ResultBuilder( char const* macroName, @@ -158,5 +159,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index e4ae981b..574969c8 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -20,7 +20,7 @@ #include "catch_test_case_tracker.hpp" #include "catch_timer.h" #include "catch_result_builder.h" -#include "catch_fatal_condition.hpp" +#include "catch_fatal_condition.h" #include #include diff --git a/include/internal/catch_section.hpp b/include/internal/catch_section.cpp similarity index 91% rename from include/internal/catch_section.hpp rename to include/internal/catch_section.cpp index aab721f6..8c300415 100644 --- a/include/internal/catch_section.hpp +++ b/include/internal/catch_section.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED #include "catch_section.h" #include "catch_capture.hpp" @@ -54,5 +52,3 @@ namespace Catch { } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED diff --git a/include/internal/catch_section_info.hpp b/include/internal/catch_section_info.cpp similarity index 92% rename from include/internal/catch_section_info.hpp rename to include/internal/catch_section_info.cpp index b1ce0ba8..83eb4fef 100644 --- a/include/internal/catch_section_info.hpp +++ b/include/internal/catch_section_info.cpp @@ -5,11 +5,11 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED #include "catch_section_info.h" +#include + namespace Catch { class RunningSection { @@ -75,7 +75,7 @@ namespace Catch { RunningSection* findOrAddSubSection( std::string const& name, bool& changed ) { for( auto subSection : m_subSections ) if( subSection->getName() == name ) - return *it; + return subSection; RunningSection* subSection = new RunningSection( this, name ); m_subSections.push_back( subSection ); m_state = Branch; @@ -102,5 +102,3 @@ namespace Catch { SubSections m_subSections; }; } - -#endif // TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED diff --git a/include/internal/catch_startup_exception_registry.hpp b/include/internal/catch_startup_exception_registry.cpp similarity index 75% rename from include/internal/catch_startup_exception_registry.hpp rename to include/internal/catch_startup_exception_registry.cpp index caf5d894..088b6446 100644 --- a/include/internal/catch_startup_exception_registry.hpp +++ b/include/internal/catch_startup_exception_registry.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED #include "catch_startup_exception_registry.h" @@ -20,5 +18,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index 73aa9ace..baa10c44 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -9,7 +9,6 @@ #ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED -#include "catch_compiler_capabilities.h" #include "catch_streambuf.h" #include diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index b287548b..b0998e3f 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -9,6 +9,7 @@ #ifndef TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED +#include "catch_common.h" #include "catch_stream.h" #include "catch_debugger.h" diff --git a/include/internal/catch_stringdata.cpp b/include/internal/catch_stringdata.cpp index 9f1625a8..434368de 100644 --- a/include/internal/catch_stringdata.cpp +++ b/include/internal/catch_stringdata.cpp @@ -5,7 +5,6 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ - #include "catch_stringdata.h" #include "catch_stringref.h" diff --git a/include/internal/catch_tag_alias_registry.hpp b/include/internal/catch_tag_alias_registry.cpp similarity index 93% rename from include/internal/catch_tag_alias_registry.hpp rename to include/internal/catch_tag_alias_registry.cpp index 7439c36d..f8c25a10 100644 --- a/include/internal/catch_tag_alias_registry.hpp +++ b/include/internal/catch_tag_alias_registry.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED #include "catch_tag_alias_registry.h" #include "catch_console_colour.hpp" @@ -64,5 +62,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.cpp similarity index 96% rename from include/internal/catch_test_case_info.hpp rename to include/internal/catch_test_case_info.cpp index 8adf40c7..5ef88593 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED #include "catch_test_spec.hpp" #include "catch_test_case_info.h" @@ -161,5 +159,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index eebde92c..d50b3b28 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -12,6 +12,7 @@ #include "catch_test_case_info.h" #include "catch_test_spec.hpp" #include "catch_context.h" +#include "catch_interfaces_config.h" #include #include @@ -119,6 +120,9 @@ namespace Catch { std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; + TestRegistry::~TestRegistry() {} + + /////////////////////////////////////////////////////////////////////////// class FreeFunctionTestCase : public ITestCase { @@ -136,6 +140,9 @@ namespace Catch { TestFunction m_fun; }; + FreeFunctionTestCase::~FreeFunctionTestCase() {} + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { std::string className = classOrQualifiedMethodName; if( startsWith( className, '&' ) ) diff --git a/include/internal/catch_timer.hpp b/include/internal/catch_timer.cpp similarity index 100% rename from include/internal/catch_timer.hpp rename to include/internal/catch_timer.cpp diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.cpp similarity index 97% rename from include/internal/catch_tostring.hpp rename to include/internal/catch_tostring.cpp index d383ba0a..7599c053 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.cpp @@ -5,11 +5,10 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED #include "catch_tostring.h" #include "catch_interfaces_config.h" +#include "catch_context.h" namespace Catch { @@ -226,5 +225,3 @@ std::string StringMaker::convert(NSObject* nsObject) { #endif } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.cpp similarity index 87% rename from include/internal/catch_version.hpp rename to include/internal/catch_version.cpp index 8f515109..d2f234ea 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.cpp @@ -5,10 +5,9 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED #include "catch_version.h" +#include namespace Catch { @@ -37,11 +36,9 @@ namespace Catch { return os; } - inline Version libraryVersion() { + Version libraryVersion() { static Version version( 2, 0, 0, "develop", 1 ); return version; } } - -#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED diff --git a/include/internal/catch_version.h b/include/internal/catch_version.h index 9f6bc283..567ac253 100644 --- a/include/internal/catch_version.h +++ b/include/internal/catch_version.h @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_VERSION_H_INCLUDED #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED +#include + namespace Catch { // Versioning information @@ -32,7 +34,7 @@ namespace Catch { void operator=( Version const& ); }; - inline Version libraryVersion(); + Version libraryVersion(); } #endif // TWOBLUECUBES_CATCH_VERSION_H_INCLUDED diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 27767060..4724c611 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -9,7 +9,7 @@ #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #include "../internal/catch_interfaces_reporter.h" -#include "../internal/catch_errno_guard.hpp" +#include "../internal/catch_errno_guard.h" #include #include diff --git a/projects/SelfTest/SurrogateCpps/catch_common.cpp b/projects/SelfTest/SurrogateCpps/catch_common.cpp deleted file mode 100644 index 65377f30..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_common.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// This file is only here to verify (to the extent possible) the self sufficiency of the header -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_common.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_message.cpp b/projects/SelfTest/SurrogateCpps/catch_message.cpp deleted file mode 100644 index 40f4403c..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_message.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// This file is only here to verify (to the extent possible) the self sufficiency of the header -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_message.h" From 058b21e604dd3486fe4f7957e4a4485104943905 Mon Sep 17 00:00:00 2001 From: Baruch Burstein Date: Sun, 9 Jul 2017 12:46:53 +0300 Subject: [PATCH 104/398] Previous implementation didn't work It relied on calling a virtual method from a base constructer --- include/internal/catch_impl.hpp | 10 +++++---- include/internal/catch_interfaces_reporter.h | 5 ++--- include/reporters/catch_reporter_automake.hpp | 2 +- include/reporters/catch_reporter_bases.hpp | 21 +++++++++---------- include/reporters/catch_reporter_compact.hpp | 2 +- include/reporters/catch_reporter_console.hpp | 2 +- include/reporters/catch_reporter_junit.hpp | 2 +- include/reporters/catch_reporter_multi.hpp | 18 ++-------------- include/reporters/catch_reporter_tap.hpp | 2 +- include/reporters/catch_reporter_teamcity.hpp | 2 +- include/reporters/catch_reporter_xml.hpp | 2 +- 11 files changed, 27 insertions(+), 41 deletions(-) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 2306af7f..242d9f82 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -77,10 +77,12 @@ namespace Catch { TestCaseStats::~TestCaseStats() {} TestGroupStats::~TestGroupStats() {} TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - - StreamingReporterBase::~StreamingReporterBase() {} + template + CumulativeReporterBase::SectionNode::~SectionNode() {} + template + CumulativeReporterBase::~CumulativeReporterBase() {} + template + StreamingReporterBase::~StreamingReporterBase() {} ConsoleReporter::~ConsoleReporter() {} CompactReporter::~CompactReporter() {} IRunner::~IRunner() {} diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index ea68aa54..5eae83cc 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -208,13 +208,12 @@ namespace Catch struct IStreamingReporter { virtual ~IStreamingReporter(); - // Implementing class must also provide the following static method: + // Implementing class must also provide the following static methods: // static std::string getDescription(); + // static std::set getSupportedVerbosities() virtual ReporterPreferences getPreferences() const = 0; - virtual std::set const& getSupportedVerbosities() const = 0; - virtual void noMatchingTestCases( std::string const& spec ) = 0; virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; diff --git a/include/reporters/catch_reporter_automake.hpp b/include/reporters/catch_reporter_automake.hpp index 00478e1f..7a841a1a 100644 --- a/include/reporters/catch_reporter_automake.hpp +++ b/include/reporters/catch_reporter_automake.hpp @@ -16,7 +16,7 @@ namespace Catch { - struct AutomakeReporter : StreamingReporterBase { + struct AutomakeReporter : StreamingReporterBase { AutomakeReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ) {} diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index f6a8d28e..9089b616 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -41,7 +41,7 @@ namespace Catch { } } - + template struct StreamingReporterBase : IStreamingReporter { StreamingReporterBase( ReporterConfig const& _config ) @@ -49,16 +49,15 @@ namespace Catch { stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; - CATCH_ENFORCE( getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); + CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); } virtual ReporterPreferences getPreferences() const override { return m_reporterPrefs; } - virtual std::set const& getSupportedVerbosities() const override { - static std::set supported{ Verbosity::Normal }; - return supported; + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; } virtual ~StreamingReporterBase() override; @@ -110,6 +109,7 @@ namespace Catch { ReporterPreferences m_reporterPrefs; }; + template struct CumulativeReporterBase : IStreamingReporter { template struct Node { @@ -161,7 +161,7 @@ namespace Catch { stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; - CATCH_ENFORCE( getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); + CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); } ~CumulativeReporterBase(); @@ -169,9 +169,8 @@ namespace Catch { return m_reporterPrefs; } - virtual std::set const& getSupportedVerbosities() const override { - static std::set supported{ Verbosity::Normal }; - return supported; + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; } virtual void testRunStarting( TestRunInfo const& ) override {} @@ -189,7 +188,7 @@ namespace Catch { } else { SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = + typename SectionNode::ChildSections::const_iterator it = std::find_if( parentNode.childSections.begin(), parentNode.childSections.end(), BySectionInfo( sectionInfo ) ); @@ -284,7 +283,7 @@ namespace Catch { } - struct TestEventListenerBase : StreamingReporterBase { + struct TestEventListenerBase : StreamingReporterBase { TestEventListenerBase( ReporterConfig const& _config ) : StreamingReporterBase( _config ) {} diff --git a/include/reporters/catch_reporter_compact.hpp b/include/reporters/catch_reporter_compact.hpp index 1579a608..ff461f14 100644 --- a/include/reporters/catch_reporter_compact.hpp +++ b/include/reporters/catch_reporter_compact.hpp @@ -15,7 +15,7 @@ namespace Catch { - struct CompactReporter : StreamingReporterBase { + struct CompactReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.hpp index bbe38a87..3c2130f8 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.hpp @@ -19,7 +19,7 @@ namespace Catch { - struct ConsoleReporter : StreamingReporterBase { + struct ConsoleReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; virtual ~ConsoleReporter() override; diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index cebdf3c7..08652565 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -47,7 +47,7 @@ namespace Catch { } - class JunitReporter : public CumulativeReporterBase { + class JunitReporter : public CumulativeReporterBase { public: JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 57f0974c..36d56584 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -15,23 +15,9 @@ namespace Catch { class MultipleReporters : public IStreamingReporter { typedef std::vector Reporters; Reporters m_reporters; - std::set m_verbosities; public: void add( IStreamingReporterPtr&& reporter ) { - if( m_reporters.empty() ) { - m_verbosities = reporter->getSupportedVerbosities(); - } - else { - for( auto it = m_verbosities.cbegin(); it != m_verbosities.cend(); ) { - if( reporter->getSupportedVerbosities().count( *it ) == 0 ) { - it = m_verbosities.erase(it); - } - else { - ++it; - } - } - } m_reporters.push_back( std::move( reporter ) ); } @@ -41,8 +27,8 @@ public: // IStreamingReporter return m_reporters[0]->getPreferences(); } - virtual std::set const& getSupportedVerbosities() const override { - return m_verbosities; + static std::set getSupportedVerbosities() { + return { }; } virtual void noMatchingTestCases( std::string const& spec ) override { diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index b34acac3..40106649 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -19,7 +19,7 @@ namespace Catch { - struct TAPReporter : StreamingReporterBase { + struct TAPReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 623ae6a3..33548987 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -23,7 +23,7 @@ namespace Catch { - struct TeamCityReporter : StreamingReporterBase { + struct TeamCityReporter : StreamingReporterBase { TeamCityReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ) { diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.hpp index b99ec11f..d685e979 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.hpp @@ -16,7 +16,7 @@ #include "../internal/catch_timer.h" namespace Catch { - class XmlReporter : public StreamingReporterBase { + class XmlReporter : public StreamingReporterBase { public: XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), From 93f84b5b0d2ef8edc9dee0c22a2e662b9f4de512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 9 Jul 2017 20:58:51 +0200 Subject: [PATCH 105/398] Modified generateSingleHeader script to work with .cpp files better Also fixed the scripts to take into account renamed version file --- include/internal/catch_impl.hpp | 28 +++------------------------- scripts/generateSingleHeader.py | 16 +++++++++++++++- scripts/releaseCommon.py | 2 +- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 934cd4d1..b084dd5b 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -21,31 +21,9 @@ #include "catch_test_spec.hpp" #include "catch_test_case_tracker.hpp" -// These files are not included in the full (not single include) project -// as they are compiled as proper cpp files -#ifndef CATCH_CONFIG_FULL_PROJECT -# include "catch_assertionresult.cpp" -# include "catch_common.cpp" -# include "catch_console_colour.cpp" -# include "catch_context.cpp" -# include "catch_debugger.cpp" -# include "catch_matchers_string.cpp" -# include "catch_message.cpp" -# include "catch_notimplemented_exception.cpp" -# include "catch_registry_hub.cpp" -# include "catch_result_builder.hpp" -# include "catch_section.cpp" -# include "catch_startup_exception_registry.cpp" -# include "catch_stringref.cpp" -# include "catch_string.cpp" -# include "catch_stringbuilder.cpp" -# include "catch_stringdata.cpp" -# include "catch_tag_alias_registry.cpp" -# include "catch_test_case_info.cpp" -# include "catch_timer.cpp" -# include "catch_tostring.cpp" -# include "catch_version.cpp" -#endif +// Cpp files will be included in the single-header file here +// ~*~* CATCH_CPP_STITCH_PLACE *~*~ + #include "../reporters/catch_reporter_multi.hpp" #include "../reporters/catch_reporter_xml.hpp" diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index bb267ff5..3b6f722d 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -7,6 +7,7 @@ import sys import re import datetime import string +from glob import glob from scriptCommon import catchPath from releaseCommon import Version @@ -21,6 +22,7 @@ ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' ) commentParser1 = re.compile( r'^\s*/\*') commentParser2 = re.compile( r'^ \*') blankParser = re.compile( r'^\s*$') + seenHeaders = set([]) rootPath = os.path.join( catchPath, 'include/' ) outputPath = os.path.join( catchPath, 'single_include/catch.hpp' ) @@ -49,13 +51,25 @@ def write( line ): if includeImpl or implIfDefs == -1: out.write( line ) +def insertCpps(): + dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters']] + cppFiles = [] + for dir in dirs: + cppFiles += glob(os.path.join(dir, '*.cpp')) + for fname in cppFiles: + dir, name = fname.rsplit(os.path.sep, 1) + dir += os.path.sep + parseFile(dir, name) + def parseFile( path, filename ): global ifdefs global implIfDefs - f = open( path + filename, 'r' ) + f = open( os.path.join(path, filename), 'r' ) blanks = 0 for line in f: + if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line: + insertCpps() if ifParser.match( line ): ifdefs = ifdefs + 1 elif endIfParser.match( line ): diff --git a/scripts/releaseCommon.py b/scripts/releaseCommon.py index c49f7461..652985c9 100644 --- a/scripts/releaseCommon.py +++ b/scripts/releaseCommon.py @@ -9,7 +9,7 @@ from scriptCommon import catchPath versionParser = re.compile( r'(\s*static\sVersion\sversion)\s*\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*\"(.*)\"\s*,\s*(.*)\s*\).*' ) rootPath = os.path.join( catchPath, 'include/' ) -versionPath = os.path.join( rootPath, "internal/catch_version.hpp" ) +versionPath = os.path.join( rootPath, "internal/catch_version.cpp" ) readmePath = os.path.join( catchPath, "README.md" ) class Version: From 5f3f19de0845c9bc4358dbef51af6827b13c0889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 10 Jul 2017 11:33:18 +0200 Subject: [PATCH 106/398] Default included reporters are now also in .cpp files The non-default ones remain as header files. --- CMakeLists.txt | 20 +- include/internal/catch_impl.hpp | 20 +- include/reporters/catch_reporter_bases.cpp | 227 ++++++++++++++++++ include/reporters/catch_reporter_bases.hpp | 207 +++------------- ...compact.hpp => catch_reporter_compact.cpp} | 6 +- ...console.hpp => catch_reporter_console.cpp} | 11 +- ...ter_junit.hpp => catch_reporter_junit.cpp} | 6 +- ...ter_multi.hpp => catch_reporter_multi.cpp} | 4 - ...eporter_xml.hpp => catch_reporter_xml.cpp} | 7 +- 9 files changed, 297 insertions(+), 211 deletions(-) create mode 100644 include/reporters/catch_reporter_bases.cpp rename include/reporters/{catch_reporter_compact.hpp => catch_reporter_compact.cpp} (98%) rename include/reporters/{catch_reporter_console.hpp => catch_reporter_console.cpp} (99%) rename include/reporters/{catch_reporter_junit.hpp => catch_reporter_junit.cpp} (98%) rename include/reporters/{catch_reporter_multi.hpp => catch_reporter_multi.cpp} (95%) rename include/reporters/{catch_reporter_xml.hpp => catch_reporter_xml.cpp} (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f290cd2..599a874b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -224,15 +224,19 @@ CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal) set(REPORTER_HEADERS ${HEADER_DIR}/reporters/catch_reporter_automake.hpp ${HEADER_DIR}/reporters/catch_reporter_bases.hpp - ${HEADER_DIR}/reporters/catch_reporter_compact.hpp - ${HEADER_DIR}/reporters/catch_reporter_console.hpp - ${HEADER_DIR}/reporters/catch_reporter_junit.hpp - ${HEADER_DIR}/reporters/catch_reporter_multi.hpp ${HEADER_DIR}/reporters/catch_reporter_tap.hpp ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp - ${HEADER_DIR}/reporters/catch_reporter_xml.hpp ) -CheckFileList(REPORTER_HEADERS ${HEADER_DIR}/reporters) +set(REPORTER_SOURCES + ${HEADER_DIR}/reporters/catch_reporter_bases.cpp + ${HEADER_DIR}/reporters/catch_reporter_compact.cpp + ${HEADER_DIR}/reporters/catch_reporter_console.cpp + ${HEADER_DIR}/reporters/catch_reporter_junit.cpp + ${HEADER_DIR}/reporters/catch_reporter_multi.cpp + ${HEADER_DIR}/reporters/catch_reporter_xml.cpp + ) +set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES}) +CheckFileList(REPORTER_FILES ${HEADER_DIR}/reporters) # Specify the headers, too, so CLion recognises them as project files set(HEADERS @@ -262,8 +266,8 @@ add_definitions( -DCATCH_CONFIG_FULL_PROJECT ) # Projects consuming Catch via ExternalProject_Add might want to use install step # without building all of our selftests. if (NOT NO_SELFTEST) - add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${SURROGATE_SOURCES} ${HEADERS}) - add_executable(Benchmark ${BENCH_SOURCES} ${IMPL_SOURCES} ${HEADERS}) + add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS}) + add_executable(Benchmark ${BENCH_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${HEADERS}) # Add desired warnings if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index b084dd5b..b6249593 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -16,6 +16,12 @@ #pragma clang diagnostic ignored "-Wweak-vtables" #endif +// Temporary hack to fix separately provided reporters +#include "../reporters/catch_reporter_bases.hpp" +#include "catch_reporter_registrars.hpp" +// + + #include "../catch_session.hpp" #include "catch_stream.hpp" #include "catch_test_spec.hpp" @@ -24,13 +30,6 @@ // Cpp files will be included in the single-header file here // ~*~* CATCH_CPP_STITCH_PLACE *~*~ - -#include "../reporters/catch_reporter_multi.hpp" -#include "../reporters/catch_reporter_xml.hpp" -#include "../reporters/catch_reporter_junit.hpp" -#include "../reporters/catch_reporter_console.hpp" -#include "../reporters/catch_reporter_compact.hpp" - namespace Catch { // These are all here to avoid warnings about not having any out of line // virtual methods @@ -56,17 +55,10 @@ namespace Catch { TestCaseStats::~TestCaseStats() {} TestGroupStats::~TestGroupStats() {} TestRunStats::~TestRunStats() {} - CumulativeReporterBase::SectionNode::~SectionNode() {} - CumulativeReporterBase::~CumulativeReporterBase() {} - StreamingReporterBase::~StreamingReporterBase() {} - ConsoleReporter::~ConsoleReporter() {} - CompactReporter::~CompactReporter() {} IRunner::~IRunner() {} IMutableContext::~IMutableContext() {} IConfig::~IConfig() {} - XmlReporter::~XmlReporter() {} - JunitReporter::~JunitReporter() {} WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} diff --git a/include/reporters/catch_reporter_bases.cpp b/include/reporters/catch_reporter_bases.cpp new file mode 100644 index 00000000..b041e526 --- /dev/null +++ b/include/reporters/catch_reporter_bases.cpp @@ -0,0 +1,227 @@ +/* + * Created by Phil on 27/11/2013. + * Copyright 2013 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) + */ + +#include "../internal/catch_interfaces_reporter.h" +#include "../internal/catch_errno_guard.h" +#include "catch_reporter_bases.hpp" + +#include +#include +#include +#include +#include + +namespace Catch { + + // Because formatting using c++ streams is stateful, drop down to C is required + // Alternatively we could use stringstream, but its performance is... not good. + std::string getFormattedDuration( double duration ) { + // Max exponent + 1 is required to represent the whole part + // + 1 for decimal point + // + 3 for the 3 decimal places + // + 1 for null terminator + const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + char buffer[maxDoubleSize]; + + // Save previous errno, to prevent sprintf from overwriting it + ErrnoGuard guard; +#ifdef _MSC_VER + sprintf_s(buffer, "%.3f", duration); +#else + sprintf(buffer, "%.3f", duration); +#endif + return std::string(buffer); + } + + + StreamingReporterBase::StreamingReporterBase(ReporterConfig const& _config) + : m_config(_config.fullConfig()), + stream(_config.stream()) + { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + ReporterPreferences StreamingReporterBase::getPreferences() const { + return m_reporterPrefs; + } + + StreamingReporterBase::~StreamingReporterBase() {} + + void StreamingReporterBase::noMatchingTestCases(std::string const &) {} + + void StreamingReporterBase::testRunStarting(TestRunInfo const & _testRunInfo) { + currentTestRunInfo = _testRunInfo; + } + + void StreamingReporterBase::testGroupStarting(GroupInfo const & _groupInfo) { + currentGroupInfo = _groupInfo; + } + + void StreamingReporterBase::testCaseStarting(TestCaseInfo const & _testInfo) { + currentTestCaseInfo = _testInfo; + } + + void StreamingReporterBase::sectionStarting(SectionInfo const & _sectionInfo) { + m_sectionStack.push_back(_sectionInfo); + } + + void StreamingReporterBase::sectionEnded(SectionStats const &) { + m_sectionStack.pop_back(); + } + + void StreamingReporterBase::testCaseEnded(TestCaseStats const &) { + currentTestCaseInfo.reset(); + } + + void StreamingReporterBase::testGroupEnded(TestGroupStats const &) { + currentGroupInfo.reset(); + } + + void StreamingReporterBase::testRunEnded(TestRunStats const &) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + void StreamingReporterBase::skipTest(TestCaseInfo const &) { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + CumulativeReporterBase::CumulativeReporterBase(ReporterConfig const & _config) + : m_config(_config.fullConfig()), + stream(_config.stream()) { + m_reporterPrefs.shouldRedirectStdOut = false; + } + + CumulativeReporterBase::~CumulativeReporterBase() {} + + ReporterPreferences CumulativeReporterBase::getPreferences() const { + return m_reporterPrefs; + } + + void CumulativeReporterBase::testRunStarting(TestRunInfo const &) {} + + void CumulativeReporterBase::testGroupStarting(GroupInfo const &) {} + + void CumulativeReporterBase::testCaseStarting(TestCaseInfo const &) {} + + void CumulativeReporterBase::sectionStarting(SectionInfo const & sectionInfo) { + SectionStats incompleteStats(sectionInfo, Counts(), 0, false); + std::shared_ptr node; + if (m_sectionStack.empty()) { + if (!m_rootSection) + m_rootSection = std::make_shared(incompleteStats); + node = m_rootSection; + } else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if(parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo(sectionInfo)); + if (it == parentNode.childSections.end()) { + node = std::make_shared(incompleteStats); + parentNode.childSections.push_back(node); + } else + node = *it; + } + m_sectionStack.push_back(node); + m_deepestSection = node; + } + + void CumulativeReporterBase::assertionStarting(AssertionInfo const &) {} + + bool CumulativeReporterBase::assertionEnded(AssertionStats const & assertionStats) { + assert(!m_sectionStack.empty()); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back(assertionStats); + // AssertionResult holds a pointer to a temporary DecomposedExpression, + // which getExpandedExpression() calls to build the expression string. + // Our section stack copy of the assertionResult will likely outlive the + // temporary, so it must be expanded or discarded now to avoid calling + // a destroyed object later. + prepareExpandedExpression(sectionNode.assertions.back().assertionResult); + return true; + } + + void CumulativeReporterBase::sectionEnded(SectionStats const & sectionStats) { + assert(!m_sectionStack.empty()); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + + void CumulativeReporterBase::testCaseEnded(TestCaseStats const & testCaseStats) { + auto node = std::make_shared(testCaseStats); + assert(m_sectionStack.size() == 0); + node->children.push_back(m_rootSection); + m_testCases.push_back(node); + m_rootSection.reset(); + + assert(m_deepestSection); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + + void CumulativeReporterBase::testGroupEnded(TestGroupStats const & testGroupStats) { + auto node = std::make_shared(testGroupStats); + node->children.swap(m_testCases); + m_testGroups.push_back(node); + } + + void CumulativeReporterBase::testRunEnded(TestRunStats const & testRunStats) { + auto node = std::make_shared(testRunStats); + node->children.swap(m_testGroups); + m_testRuns.push_back(node); + testRunEndedCumulative(); + } + + void CumulativeReporterBase::skipTest(TestCaseInfo const &) {} + + void CumulativeReporterBase::prepareExpandedExpression(AssertionResult & result) const { + if (result.isOk()) + result.discardDecomposedExpression(); + else + result.expandDecomposedExpression(); + } + + CumulativeReporterBase::SectionNode::SectionNode(SectionStats const& _stats) + :stats(_stats) {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + + bool CumulativeReporterBase::SectionNode::operator==(SectionNode const & other) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + + bool CumulativeReporterBase::SectionNode::operator==(std::shared_ptr const& other) const { + return operator==(*other); + } + + + CumulativeReporterBase::BySectionInfo::BySectionInfo(SectionInfo const& other) + :m_other(other) {} + + CumulativeReporterBase::BySectionInfo::BySectionInfo(BySectionInfo const & other) + :m_other(other.m_other) {} + + bool CumulativeReporterBase::BySectionInfo::operator()(std::shared_ptr const & node) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + + + TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) + :StreamingReporterBase(_config) {} + + void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} + + bool TestEventListenerBase::assertionEnded(AssertionStats const &) { + return false; + } + + +} // end namespace Catch diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 4724c611..f633e693 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -9,7 +9,6 @@ #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #include "../internal/catch_interfaces_reporter.h" -#include "../internal/catch_errno_guard.h" #include #include @@ -19,79 +18,31 @@ namespace Catch { - namespace { - // Because formatting using c++ streams is stateful, drop down to C is required - // Alternatively we could use stringstream, but its performance is... not good. - std::string getFormattedDuration( double duration ) { - // Max exponent + 1 is required to represent the whole part - // + 1 for decimal point - // + 3 for the 3 decimal places - // + 1 for null terminator - const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; - char buffer[maxDoubleSize]; - - // Save previous errno, to prevent sprintf from overwriting it - ErrnoGuard guard; -#ifdef _MSC_VER - sprintf_s(buffer, "%.3f", duration); -#else - sprintf(buffer, "%.3f", duration); -#endif - return std::string(buffer); - } - } - + // Returns double formatted as %.3f (format expected on output) + std::string getFormattedDuration( double duration ); struct StreamingReporterBase : IStreamingReporter { - StreamingReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } + StreamingReporterBase(ReporterConfig const& _config); - virtual ReporterPreferences getPreferences() const override { - return m_reporterPrefs; - } + virtual ReporterPreferences getPreferences() const override; virtual ~StreamingReporterBase() override; - virtual void noMatchingTestCases( std::string const& ) override {} + virtual void noMatchingTestCases(std::string const&) override; - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) override { - currentTestRunInfo = _testRunInfo; - } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) override { - currentGroupInfo = _groupInfo; - } + virtual void testRunStarting(TestRunInfo const& _testRunInfo) override; + virtual void testGroupStarting(GroupInfo const& _groupInfo) override; - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) override { - currentTestCaseInfo = _testInfo; - } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) override { - m_sectionStack.push_back( _sectionInfo ); - } + virtual void testCaseStarting(TestCaseInfo const& _testInfo) override; + virtual void sectionStarting(SectionInfo const& _sectionInfo) override; - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) override { - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) override { - currentTestCaseInfo.reset(); - } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) override { - currentGroupInfo.reset(); - } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) override { - currentTestCaseInfo.reset(); - currentGroupInfo.reset(); - currentTestRunInfo.reset(); - } + virtual void sectionEnded(SectionStats const& /* _sectionStats */) override; + virtual void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override; + virtual void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override; + virtual void testRunEnded(TestRunStats const& /* _testRunStats */) override; - virtual void skipTest( TestCaseInfo const& ) override { - // Don't do anything with this by default. - // It can optionally be overridden in the derived class. - } + virtual void skipTest(TestCaseInfo const&) override; IConfigPtr m_config; std::ostream& stream; @@ -115,15 +66,11 @@ namespace Catch { ChildNodes children; }; struct SectionNode { - explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + explicit SectionNode(SectionStats const& _stats); virtual ~SectionNode(); - bool operator == ( SectionNode const& other ) const { - return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; - } - bool operator == ( std::shared_ptr const& other ) const { - return operator==( *other ); - } + bool operator == (SectionNode const& other) const; + bool operator == (std::shared_ptr const& other) const; SectionStats stats; using ChildSections = std::vector>; @@ -135,13 +82,12 @@ namespace Catch { }; struct BySectionInfo { - BySectionInfo( SectionInfo const& other ) : m_other( other ) {} - BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} - bool operator() ( std::shared_ptr const& node ) const { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; - } + BySectionInfo(SectionInfo const& other); + BySectionInfo(BySectionInfo const& other); + bool operator() (std::shared_ptr const& node) const; + void operator=(BySectionInfo const&) = delete; + private: - void operator=( BySectionInfo const& ); SectionInfo const& m_other; }; @@ -150,100 +96,30 @@ namespace Catch { using TestGroupNode = Node; using TestRunNode = Node; - CumulativeReporterBase( ReporterConfig const& _config ) - : m_config( _config.fullConfig() ), - stream( _config.stream() ) - { - m_reporterPrefs.shouldRedirectStdOut = false; - } + CumulativeReporterBase(ReporterConfig const& _config); ~CumulativeReporterBase(); - virtual ReporterPreferences getPreferences() const override { - return m_reporterPrefs; - } + virtual ReporterPreferences getPreferences() const override; - virtual void testRunStarting( TestRunInfo const& ) override {} - virtual void testGroupStarting( GroupInfo const& ) override {} + virtual void testRunStarting(TestRunInfo const&) override; + virtual void testGroupStarting(GroupInfo const&) override; - virtual void testCaseStarting( TestCaseInfo const& ) override {} + virtual void testCaseStarting(TestCaseInfo const&) override; - virtual void sectionStarting( SectionInfo const& sectionInfo ) override { - SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); - std::shared_ptr node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = std::make_shared( incompleteStats ); - node = m_rootSection; - } - else { - SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = - std::find_if( parentNode.childSections.begin(), - parentNode.childSections.end(), - BySectionInfo( sectionInfo ) ); - if( it == parentNode.childSections.end() ) { - node = std::make_shared( incompleteStats ); - parentNode.childSections.push_back( node ); - } - else - node = *it; - } - m_sectionStack.push_back( node ); - m_deepestSection = node; - } + virtual void sectionStarting(SectionInfo const& sectionInfo) override; - virtual void assertionStarting( AssertionInfo const& ) override {} + virtual void assertionStarting(AssertionInfo const&) override; - virtual bool assertionEnded( AssertionStats const& assertionStats ) override { - assert( !m_sectionStack.empty() ); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back( assertionStats ); - // AssertionResult holds a pointer to a temporary DecomposedExpression, - // which getExpandedExpression() calls to build the expression string. - // Our section stack copy of the assertionResult will likely outlive the - // temporary, so it must be expanded or discarded now to avoid calling - // a destroyed object later. - prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); - return true; - } - virtual void sectionEnded( SectionStats const& sectionStats ) override { - assert( !m_sectionStack.empty() ); - SectionNode& node = *m_sectionStack.back(); - node.stats = sectionStats; - m_sectionStack.pop_back(); - } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { - auto node = std::make_shared( testCaseStats ); - assert( m_sectionStack.size() == 0 ); - node->children.push_back( m_rootSection ); - m_testCases.push_back( node ); - m_rootSection.reset(); - - assert( m_deepestSection ); - m_deepestSection->stdOut = testCaseStats.stdOut; - m_deepestSection->stdErr = testCaseStats.stdErr; - } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { - auto node = std::make_shared( testGroupStats ); - node->children.swap( m_testCases ); - m_testGroups.push_back( node ); - } - virtual void testRunEnded( TestRunStats const& testRunStats ) override { - auto node = std::make_shared( testRunStats ); - node->children.swap( m_testGroups ); - m_testRuns.push_back( node ); - testRunEndedCumulative(); - } + virtual bool assertionEnded(AssertionStats const& assertionStats) override; + virtual void sectionEnded(SectionStats const& sectionStats) override; + virtual void testCaseEnded(TestCaseStats const& testCaseStats) override; + virtual void testGroupEnded(TestGroupStats const& testGroupStats) override; + virtual void testRunEnded(TestRunStats const& testRunStats) override; virtual void testRunEndedCumulative() = 0; - virtual void skipTest( TestCaseInfo const& ) override {} + virtual void skipTest(TestCaseInfo const&) override; - virtual void prepareExpandedExpression( AssertionResult& result ) const { - if( result.isOk() ) - result.discardDecomposedExpression(); - else - result.expandDecomposedExpression(); - } + virtual void prepareExpandedExpression(AssertionResult& result) const; IConfigPtr m_config; std::ostream& stream; @@ -258,7 +134,6 @@ namespace Catch { std::shared_ptr m_deepestSection; std::vector> m_sectionStack; ReporterPreferences m_reporterPrefs; - }; template @@ -273,14 +148,10 @@ namespace Catch { struct TestEventListenerBase : StreamingReporterBase { - TestEventListenerBase( ReporterConfig const& _config ) - : StreamingReporterBase( _config ) - {} + TestEventListenerBase(ReporterConfig const& _config); - virtual void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& ) override { - return false; - } + virtual void assertionStarting(AssertionInfo const&) override; + virtual bool assertionEnded(AssertionStats const&) override; }; } // end namespace Catch diff --git a/include/reporters/catch_reporter_compact.hpp b/include/reporters/catch_reporter_compact.cpp similarity index 98% rename from include/reporters/catch_reporter_compact.hpp rename to include/reporters/catch_reporter_compact.cpp index 1579a608..1ce307d0 100644 --- a/include/reporters/catch_reporter_compact.hpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED #include "catch_reporter_bases.hpp" @@ -297,8 +295,8 @@ namespace Catch { } }; + CompactReporter::~CompactReporter() {} + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.cpp similarity index 99% rename from include/reporters/catch_reporter_console.hpp rename to include/reporters/catch_reporter_console.cpp index bbe38a87..25ad3668 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.cpp @@ -5,23 +5,26 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED #include "catch_reporter_bases.hpp" #include "../internal/catch_reporter_registrars.hpp" #include "../internal/catch_console_colour.hpp" +#include "../internal/catch_version.h" +#include "../external/tbc_text_format.h" #include #include namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; struct ConsoleReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; + virtual ~ConsoleReporter() override; static std::string getDescription() { return "Reports test results as plain lines of text"; @@ -437,6 +440,6 @@ namespace Catch { INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) -} // end namespace Catch + ConsoleReporter::~ConsoleReporter() {} -#endif // TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED +} // end namespace Catch diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.cpp similarity index 98% rename from include/reporters/catch_reporter_junit.hpp rename to include/reporters/catch_reporter_junit.cpp index cebdf3c7..787de016 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -5,14 +5,13 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED #include "catch_reporter_bases.hpp" #include "../internal/catch_tostring.h" #include "../internal/catch_reporter_registrars.hpp" #include "../internal/catch_xmlwriter.hpp" +#include "../internal/catch_timer.h" #include @@ -247,8 +246,7 @@ namespace Catch { bool m_okToFail = false; }; + JunitReporter::~JunitReporter() {} INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.cpp similarity index 95% rename from include/reporters/catch_reporter_multi.hpp rename to include/reporters/catch_reporter_multi.cpp index 589c34e0..d16b9ba3 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED #include "../internal/catch_interfaces_reporter.h" @@ -124,5 +122,3 @@ void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.cpp similarity index 97% rename from include/reporters/catch_reporter_xml.hpp rename to include/reporters/catch_reporter_xml.cpp index b99ec11f..18e2af7c 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.cpp @@ -5,8 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED #include "catch_reporter_bases.hpp" @@ -221,8 +219,7 @@ namespace Catch { int m_sectionDepth = 0; }; - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + XmlReporter::~XmlReporter() {} + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED From 1d3bfa035344299f3fa1404ed0d138cf97d59fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 10 Jul 2017 14:25:38 +0200 Subject: [PATCH 107/398] More include and impl refactoring --- CMakeLists.txt | 7 +- include/catch_session.hpp | 3 +- include/internal/catch_commandline.cpp | 163 ++++++++++++++++++ include/internal/catch_commandline.hpp | 149 +--------------- include/internal/catch_console_colour.cpp | 4 + include/internal/catch_console_colour.hpp | 2 +- .../catch_exception_translator_registry.cpp | 63 +++++++ .../catch_exception_translator_registry.h | 29 ++++ .../catch_exception_translator_registry.hpp | 74 -------- .../{catch_list.hpp => catch_list.cpp} | 49 +++--- include/internal/catch_list.h | 36 ++++ include/internal/catch_registry_hub.cpp | 2 +- include/reporters/catch_reporter_console.cpp | 5 +- 13 files changed, 329 insertions(+), 257 deletions(-) create mode 100644 include/internal/catch_commandline.cpp create mode 100644 include/internal/catch_exception_translator_registry.cpp create mode 100644 include/internal/catch_exception_translator_registry.h delete mode 100644 include/internal/catch_exception_translator_registry.hpp rename include/internal/{catch_list.hpp => catch_list.cpp} (87%) create mode 100644 include/internal/catch_list.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 599a874b..137aeb8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,7 +135,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_default_main.hpp ${HEADER_DIR}/internal/catch_errno_guard.h ${HEADER_DIR}/internal/catch_evaluate.hpp - ${HEADER_DIR}/internal/catch_exception_translator_registry.hpp + ${HEADER_DIR}/internal/catch_exception_translator_registry.h ${HEADER_DIR}/internal/catch_expression_lhs.hpp ${HEADER_DIR}/internal/catch_fatal_condition.h ${HEADER_DIR}/internal/catch_impl.hpp @@ -147,7 +147,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_interfaces_runner.h ${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h ${HEADER_DIR}/internal/catch_interfaces_testcase.h - ${HEADER_DIR}/internal/catch_list.hpp + ${HEADER_DIR}/internal/catch_list.h ${HEADER_DIR}/internal/catch_matchers.hpp ${HEADER_DIR}/internal/catch_matchers_string.h ${HEADER_DIR}/internal/catch_matchers_vector.h @@ -193,12 +193,15 @@ set(INTERNAL_HEADERS ) set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_assertionresult.cpp + ${HEADER_DIR}/internal/catch_commandline.cpp ${HEADER_DIR}/internal/catch_common.cpp ${HEADER_DIR}/internal/catch_console_colour.cpp ${HEADER_DIR}/internal/catch_context.cpp ${HEADER_DIR}/internal/catch_debugger.cpp ${HEADER_DIR}/internal/catch_errno_guard.cpp + ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp ${HEADER_DIR}/internal/catch_fatal_condition.cpp + ${HEADER_DIR}/internal/catch_list.cpp ${HEADER_DIR}/internal/catch_matchers_string.cpp ${HEADER_DIR}/internal/catch_message.cpp ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 42080cd1..7acf80a6 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -9,7 +9,8 @@ #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED #include "internal/catch_commandline.hpp" -#include "internal/catch_list.hpp" +#include "internal/catch_console_colour.hpp" +#include "internal/catch_list.h" #include "internal/catch_run_context.hpp" #include "internal/catch_test_spec.hpp" #include "internal/catch_version.h" diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp new file mode 100644 index 00000000..d5f2ab4e --- /dev/null +++ b/include/internal/catch_commandline.cpp @@ -0,0 +1,163 @@ +/* + * Created by Phil on 02/11/2010. + * Copyright 2010 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) + */ + +#include "catch_commandline.hpp" + +#include "catch_common.h" + +#include +#include + +namespace Catch { + + clara::Parser makeCommandLineParser( ConfigData& config ) { + + using namespace clara; + + auto const setWarning = [&]( std::string const& warning ) { + if( warning != "NoAssertions" ) + return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const loadTestNamesFromFile = [&]( std::string const& filename ) { + std::ifstream f( filename.c_str() ); + if( !f.is_open() ) + return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, '#' ) ) { + if( !startsWith( line, '"' ) ) + line = '"' + line + '"'; + config.testsOrTags.push_back( line + ',' ); + } + } + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setTestOrder = [&]( std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setRngSeed = [&]( std::string const& seed ) { + if( seed != "time" ) + return clara::detail::convertInto( seed, config.rngSeed ); + config.rngSeed = static_cast( std::time(0) ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setColourUsage = [&]( std::string const& useColour ) { + auto mode = toLower( useColour ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setVerbosity = [&]( std::string const& verbosity ) { + auto lcVerbosity = toLower( verbosity ); + if( lcVerbosity == "quiet" ) + config.verbosity = Verbosity::Quiet; + else if( lcVerbosity == "normal" ) + config.verbosity = Verbosity::Normal; + else if( lcVerbosity == "high" ) + config.verbosity = Verbosity::High; + else + return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + + auto cli + = ExeName( config.processName ) + + Help( config.showHelp ) + + Opt( config.listTests ) + ["-l"]["--list-tests"] + ( "list all/matching test cases" ) + + Opt( config.listTags ) + ["-t"]["--list-tags"] + ( "list all/matching tags" ) + + Opt( config.showSuccessfulTests ) + ["-s"]["--success"] + ( "include successful tests in output" ) + + Opt( config.shouldDebugBreak ) + ["-b"]["--break"] + ( "break into debugger on failure" ) + + Opt( config.noThrow ) + ["-e"]["--nothrow"] + ( "skip exception tests" ) + + Opt( config.showInvisibles ) + ["-i"]["--invisibles"] + ( "show invisibles (tabs, newlines)" ) + + Opt( config.outputFilename, "filename" ) + ["-o"]["--out"] + ( "output filename" ) + + Opt( config.reporterNames, "name" ) + ["-r"]["--reporter"] + ( "reporter to use (defaults to console)" ) + + Opt( config.name, "name" ) + ["-n"]["--name"] + ( "suite name" ) + + Opt( [&]( bool ){ config.abortAfter = 1; } ) + ["-a"]["--abort"] + ( "abort at first failure" ) + + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + ["-x"]["--abortx"] + ( "abort after x failures" ) + + Opt( setWarning, "warning name" ) + ["-w"]["--warn"] + ( "enable warnings" ) + + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) + ["-d"]["--durations"] + ( "show test durations" ) + + Opt( loadTestNamesFromFile, "filename" ) + ["-f"]["--input-file"] + ( "load test names to run from a file" ) + + Opt( config.filenamesAsTags ) + ["-#"]["--filenames-as-tags"] + ( "adds a tag for the filename" ) + + Opt( config.sectionsToRun, "section name" ) + ["-c"]["--section"] + ( "specify section to run" ) + + Opt( setVerbosity, "quiet|normal|high" ) + ["-v"]["--verbosity"] + ( "set output verbosity" ) + + Opt( config.listTestNamesOnly ) + ["--list-test-names-only"] + ( "list all/matching test cases names only" ) + + Opt( config.listReporters ) + ["--list-reporters"] + ( "list all reporters" ) + + Opt( setTestOrder, "decl|lex|rand" ) + ["--order"] + ( "test case order (defaults to decl)" ) + + Opt( setRngSeed, "'time'|number" ) + ["--rng-seed"] + ( "set a specific seed for random numbers" ) + + Opt( setColourUsage, "yes|no" ) + ["--use-colour"] + ( "should output be colourised" ) + + + Arg( config.testsOrTags, "test name|pattern|tags" ) + ( "which test or tests to use" ); + + return cli; + } + +} // end namespace Catch diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index b81e9931..b73cfa2d 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -9,158 +9,11 @@ #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED #include "catch_config.hpp" -#include "catch_common.h" #include "catch_clara.h" -#include -#include - namespace Catch { - inline clara::Parser makeCommandLineParser( ConfigData& config ) { - - using namespace clara; - - auto const setWarning = [&]( std::string const& warning ) { - if( warning != "NoAssertions" ) - return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); - config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const loadTestNamesFromFile = [&]( std::string const& filename ) { - std::ifstream f( filename.c_str() ); - if( !f.is_open() ) - return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); - - std::string line; - while( std::getline( f, line ) ) { - line = trim(line); - if( !line.empty() && !startsWith( line, '#' ) ) { - if( !startsWith( line, '"' ) ) - line = '"' + line + '"'; - config.testsOrTags.push_back( line + ',' ); - } - } - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setTestOrder = [&]( std::string const& order ) { - if( startsWith( "declared", order ) ) - config.runOrder = RunTests::InDeclarationOrder; - else if( startsWith( "lexical", order ) ) - config.runOrder = RunTests::InLexicographicalOrder; - else if( startsWith( "random", order ) ) - config.runOrder = RunTests::InRandomOrder; - else - return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setRngSeed = [&]( std::string const& seed ) { - if( seed != "time" ) - return clara::detail::convertInto( seed, config.rngSeed ); - config.rngSeed = static_cast( std::time(0) ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setColourUsage = [&]( std::string const& useColour ) { - auto mode = toLower( useColour ); - - if( mode == "yes" ) - config.useColour = UseColour::Yes; - else if( mode == "no" ) - config.useColour = UseColour::No; - else if( mode == "auto" ) - config.useColour = UseColour::Auto; - else - return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - auto const setVerbosity = [&]( std::string const& verbosity ) { - auto lcVerbosity = toLower( verbosity ); - if( lcVerbosity == "quiet" ) - config.verbosity = Verbosity::Quiet; - else if( lcVerbosity == "normal" ) - config.verbosity = Verbosity::Normal; - else if( lcVerbosity == "high" ) - config.verbosity = Verbosity::High; - else - return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); - return ParserResult::ok( ParseResultType::Matched ); - }; - - auto cli - = ExeName( config.processName ) - + Help( config.showHelp ) - + Opt( config.listTests ) - ["-l"]["--list-tests"] - ( "list all/matching test cases" ) - + Opt( config.listTags ) - ["-t"]["--list-tags"] - ( "list all/matching tags" ) - + Opt( config.showSuccessfulTests ) - ["-s"]["--success"] - ( "include successful tests in output" ) - + Opt( config.shouldDebugBreak ) - ["-b"]["--break"] - ( "break into debugger on failure" ) - + Opt( config.noThrow ) - ["-e"]["--nothrow"] - ( "skip exception tests" ) - + Opt( config.showInvisibles ) - ["-i"]["--invisibles"] - ( "show invisibles (tabs, newlines)" ) - + Opt( config.outputFilename, "filename" ) - ["-o"]["--out"] - ( "output filename" ) - + Opt( config.reporterNames, "name" ) - ["-r"]["--reporter"] - ( "reporter to use (defaults to console)" ) - + Opt( config.name, "name" ) - ["-n"]["--name"] - ( "suite name" ) - + Opt( [&]( bool ){ config.abortAfter = 1; } ) - ["-a"]["--abort"] - ( "abort at first failure" ) - + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) - ["-x"]["--abortx"] - ( "abort after x failures" ) - + Opt( setWarning, "warning name" ) - ["-w"]["--warn"] - ( "enable warnings" ) - + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) - ["-d"]["--durations"] - ( "show test durations" ) - + Opt( loadTestNamesFromFile, "filename" ) - ["-f"]["--input-file"] - ( "load test names to run from a file" ) - + Opt( config.filenamesAsTags ) - ["-#"]["--filenames-as-tags"] - ( "adds a tag for the filename" ) - + Opt( config.sectionsToRun, "section name" ) - ["-c"]["--section"] - ( "specify section to run" ) - + Opt( setVerbosity, "quiet|normal|high" ) - ["-v"]["--verbosity"] - ( "set output verbosity" ) - + Opt( config.listTestNamesOnly ) - ["--list-test-names-only"] - ( "list all/matching test cases names only" ) - + Opt( config.listReporters ) - ["--list-reporters"] - ( "list all reporters" ) - + Opt( setTestOrder, "decl|lex|rand" ) - ["--order"] - ( "test case order (defaults to decl)" ) - + Opt( setRngSeed, "'time'|number" ) - ["--rng-seed"] - ( "set a specific seed for random numbers" ) - + Opt( setColourUsage, "yes|no" ) - ["--use-colour"] - ( "should output be colourised" ) - - + Arg( config.testsOrTags, "test name|pattern|tags" ) - ( "which test or tests to use" ); - - return cli; - } + clara::Parser makeCommandLineParser( ConfigData& config ); } // end namespace Catch diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index 5670b8bf..6ffe7ba5 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -187,4 +187,8 @@ namespace Catch { impl->use( _colourCode ); } + std::ostream& operator << ( std::ostream& os, Colour const& ) { + return os; + } + } // end namespace Catch diff --git a/include/internal/catch_console_colour.hpp b/include/internal/catch_console_colour.hpp index f0a8a697..7122decc 100644 --- a/include/internal/catch_console_colour.hpp +++ b/include/internal/catch_console_colour.hpp @@ -60,7 +60,7 @@ namespace Catch { bool m_moved; }; - inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + std::ostream& operator << ( std::ostream& os, Colour const& ); } // end namespace Catch diff --git a/include/internal/catch_exception_translator_registry.cpp b/include/internal/catch_exception_translator_registry.cpp new file mode 100644 index 00000000..18e7c0b6 --- /dev/null +++ b/include/internal/catch_exception_translator_registry.cpp @@ -0,0 +1,63 @@ +/* + * Created by Phil on 20/04/2011. + * Copyright 2011 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) + */ + +#include "catch_exception_translator_registry.h" +#include "catch_result_builder.h" + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + std::string ExceptionTranslatorRegistry::translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string ExceptionTranslatorRegistry::tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } +} diff --git a/include/internal/catch_exception_translator_registry.h b/include/internal/catch_exception_translator_registry.h new file mode 100644 index 00000000..dc5d8159 --- /dev/null +++ b/include/internal/catch_exception_translator_registry.h @@ -0,0 +1,29 @@ +/* + * Created by Phil on 20/04/2011. + * Copyright 2011 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) + */ +#ifndef TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#include "catch_interfaces_exception.h" +#include +#include + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry(); + virtual void registerTranslator( const IExceptionTranslator* translator ); + virtual std::string translateActiveException() const; + std::string tryTranslators() const; + + private: + std::vector m_translators; + }; +} + +#endif // TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_exception_translator_registry.hpp b/include/internal/catch_exception_translator_registry.hpp deleted file mode 100644 index 07d83f21..00000000 --- a/include/internal/catch_exception_translator_registry.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Created by Phil on 20/04/2011. - * Copyright 2011 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) - */ -#ifndef TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED - -#include "catch_interfaces_exception.h" -#include "catch_tostring.h" -#include "catch_result_builder.h" - -#ifdef __OBJC__ -#import "Foundation/Foundation.h" -#endif - -namespace Catch { - - class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { - public: - ~ExceptionTranslatorRegistry() { - deleteAll( m_translators ); - } - - virtual void registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( translator ); - } - - virtual std::string translateActiveException() const { - try { -#ifdef __OBJC__ - // In Objective-C try objective-c exceptions first - @try { - return tryTranslators(); - } - @catch (NSException *exception) { - return Catch::toString( [exception description] ); - } -#else - return tryTranslators(); -#endif - } - catch( TestFailureException& ) { - throw; - } - catch( std::exception& ex ) { - return ex.what(); - } - catch( std::string& msg ) { - return msg; - } - catch( const char* msg ) { - return msg; - } - catch(...) { - return "Unknown exception"; - } - } - - std::string tryTranslators() const { - if( m_translators.empty() ) - throw; - else - return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); - } - - private: - std::vector m_translators; - }; -} - -#endif // TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.cpp similarity index 87% rename from include/internal/catch_list.hpp rename to include/internal/catch_list.cpp index 5d9d8ed4..8f13be8d 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.cpp @@ -5,22 +5,24 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED -#include "catch_commandline.hpp" +#include "catch_list.h" + +#include "catch_interfaces_registry_hub.h" +#include "catch_interfaces_reporter.h" +#include "catch_interfaces_testcase.h" + #include "catch_text.h" #include "catch_console_colour.hpp" -#include "catch_interfaces_reporter.h" #include "catch_test_spec_parser.hpp" #include #include +#include namespace Catch { - inline std::size_t listTests( Config const& config ) { - + std::size_t listTests( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) Catch::cout() << "Matching test cases:\n"; @@ -62,7 +64,7 @@ namespace Catch { return matchedTests; } - inline std::size_t listTestsNamesOnly( Config const& config ) { + std::size_t listTestsNamesOnly( Config const& config ) { TestSpec testSpec = config.testSpec(); if( !config.testSpec().hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); @@ -81,22 +83,19 @@ namespace Catch { return matchedTests; } - struct TagInfo { - void add( std::string const& spelling ) { - ++count; - spellings.insert( spelling ); - } - std::string all() const { - std::string out; - for( auto const& spelling : spellings ) - out += "[" + spelling + "]"; - return out; - } - std::set spellings; - std::size_t count = 0; - }; + void TagInfo::add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } - inline std::size_t listTags( Config const& config ) { + std::string TagInfo::all() const { + std::string out; + for( auto const& spelling : spellings ) + out += "[" + spelling + "]"; + return out; + } + + std::size_t listTags( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) Catch::cout() << "Tags for matching test cases:\n"; @@ -131,7 +130,7 @@ namespace Catch { return tagCounts.size(); } - inline std::size_t listReporters( Config const& /*config*/ ) { + std::size_t listReporters( Config const& /*config*/ ) { Catch::cout() << "Available reporters:\n"; IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); std::size_t maxNameLen = 0; @@ -153,7 +152,7 @@ namespace Catch { return factories.size(); } - inline Option list( Config const& config ) { + Option list( Config const& config ) { Option listedCount; if( config.listTests() ) listedCount = listedCount.valueOr(0) + listTests( config ); @@ -167,5 +166,3 @@ namespace Catch { } } // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED diff --git a/include/internal/catch_list.h b/include/internal/catch_list.h new file mode 100644 index 00000000..daf158d0 --- /dev/null +++ b/include/internal/catch_list.h @@ -0,0 +1,36 @@ +/* + * Created by Phil on 5/11/2010. + * Copyright 2010 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) + */ +#ifndef TWOBLUECUBES_CATCH_LIST_H_INCLUDED +#define TWOBLUECUBES_CATCH_LIST_H_INCLUDED + +#include "catch_option.hpp" +#include "catch_config.hpp" + +namespace Catch { + + std::size_t listTests( Config const& config ); + + std::size_t listTestsNamesOnly( Config const& config ); + + struct TagInfo { + void add( std::string const& spelling ); + std::string all() const; + + std::set spellings; + std::size_t count = 0; + }; + + std::size_t listTags( Config const& config ); + + std::size_t listReporters( Config const& /*config*/ ); + + Option list( Config const& config ); + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_LIST_H_INCLUDED diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 9f901085..71967f58 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -10,7 +10,7 @@ #include "catch_test_case_registry_impl.hpp" #include "catch_reporter_registry.hpp" -#include "catch_exception_translator_registry.hpp" +#include "catch_exception_translator_registry.h" #include "catch_tag_alias_registry.h" #include "catch_startup_exception_registry.h" diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 25ad3668..9c18e6c5 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -11,16 +11,13 @@ #include "../internal/catch_reporter_registrars.hpp" #include "../internal/catch_console_colour.hpp" #include "../internal/catch_version.h" -#include "../external/tbc_text_format.h" +#include "../internal/catch_text.h" #include #include namespace Catch { - using Tbc::Text; - using Tbc::TextAttributes; - struct ConsoleReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; From 9c318af98728778d84e05d2f9f93c4f6943bbb15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 14:46:49 +0200 Subject: [PATCH 108/398] Remove obsolete GENERATE macro --- include/catch.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index ccf695c6..ccbfd28e 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -142,8 +142,6 @@ LeakDetector leakDetector; #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - // "BDD-style" convenience wrappers #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) @@ -210,8 +208,6 @@ LeakDetector leakDetector; #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) -#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) - #endif #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) From 4332b84c9bcf2b1e70a6e6e9c4ce27ade9f8365c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 14:47:36 +0200 Subject: [PATCH 109/398] Moved leak detector to its own file --- CMakeLists.txt | 2 ++ include/catch.hpp | 23 ----------------- include/internal/catch_impl.hpp | 4 +++ include/internal/catch_leak_detector.cpp | 33 ++++++++++++++++++++++++ include/internal/catch_leak_detector.h | 17 ++++++++++++ 5 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 include/internal/catch_leak_detector.cpp create mode 100644 include/internal/catch_leak_detector.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 137aeb8e..0c680adc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,6 +147,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_interfaces_runner.h ${HEADER_DIR}/internal/catch_interfaces_tag_alias_registry.h ${HEADER_DIR}/internal/catch_interfaces_testcase.h + ${HEADER_DIR}/internal/catch_leak_detector.h ${HEADER_DIR}/internal/catch_list.h ${HEADER_DIR}/internal/catch_matchers.hpp ${HEADER_DIR}/internal/catch_matchers_string.h @@ -202,6 +203,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp ${HEADER_DIR}/internal/catch_fatal_condition.cpp ${HEADER_DIR}/internal/catch_list.cpp + ${HEADER_DIR}/internal/catch_leak_detector.cpp ${HEADER_DIR}/internal/catch_matchers_string.cpp ${HEADER_DIR}/internal/catch_message.cpp ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp diff --git a/include/catch.hpp b/include/catch.hpp index ccbfd28e..40ee9da1 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -50,29 +50,6 @@ #endif #ifdef CATCH_IMPL - -// !TBD: Move the leak detector code into a separate header -#ifdef CATCH_CONFIG_WINDOWS_CRTDBG -#include -class LeakDetector { -public: - LeakDetector() { - int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flag |= _CRTDBG_LEAK_CHECK_DF; - flag |= _CRTDBG_ALLOC_MEM_DF; - _CrtSetDbgFlag(flag); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); - // Change this to leaking allocation's number to break there - _CrtSetBreakAlloc(-1); - } -}; -#else -class LeakDetector {}; -#endif - -LeakDetector leakDetector; - #include "internal/catch_impl.hpp" #endif diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index b6249593..637df27b 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -21,6 +21,8 @@ #include "catch_reporter_registrars.hpp" // +#include "internal/catch_leak_detector.h" + #include "../catch_session.hpp" #include "catch_stream.hpp" @@ -31,6 +33,8 @@ // ~*~* CATCH_CPP_STITCH_PLACE *~*~ namespace Catch { + LeakDetector leakDetector; + // These are all here to avoid warnings about not having any out of line // virtual methods NonCopyable::~NonCopyable() {} diff --git a/include/internal/catch_leak_detector.cpp b/include/internal/catch_leak_detector.cpp new file mode 100644 index 00000000..32109310 --- /dev/null +++ b/include/internal/catch_leak_detector.cpp @@ -0,0 +1,33 @@ +/* + * Created by Martin on 12/07/2017. + * + * 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) + */ + + #include "catch_leak_detector.h" + + +namespace Catch { + +#ifdef CATCH_CONFIG_WINDOWS_CRTDBG +#include + + LeakDetector::LeakDetector() { + int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flag |= _CRTDBG_LEAK_CHECK_DF; + flag |= _CRTDBG_ALLOC_MEM_DF; + _CrtSetDbgFlag(flag); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + // Change this to leaking allocation's number to break there + _CrtSetBreakAlloc(-1); + } + +#else + + LeakDetector::LeakDetector(){} + +#endif + +} diff --git a/include/internal/catch_leak_detector.h b/include/internal/catch_leak_detector.h new file mode 100644 index 00000000..bfb0b429 --- /dev/null +++ b/include/internal/catch_leak_detector.h @@ -0,0 +1,17 @@ +/* + * Created by Martin on 12/07/2017. + * + * 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) + */ +#ifndef TWOBLUECUBES_CATCH_LEAK_DETECTOR_H_INCLUDED +#define TWOBLUECUBES_CATCH_LEAK_DETECTOR_H_INCLUDED + +namespace Catch { + + struct LeakDetector { + LeakDetector(); + }; + +} +#endif // TWOBLUECUBES_CATCH_LEAK_DETECTOR_H_INCLUDED From 91c155607868d5c771bfaf59763ae4aa46547fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 15:05:01 +0200 Subject: [PATCH 110/398] Moved Catch NotImplementedException out of the common include path We could probably toss it away completely, currently it is used only by TeamCity reporter. --- docs/reporters.md | 2 +- include/catch.hpp | 1 - include/internal/catch_impl.hpp | 4 ++++ projects/SelfTest/ExceptionTests.cpp | 9 --------- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/docs/reporters.md b/docs/reporters.md index 703234b1..92710622 100644 --- a/docs/reporters.md +++ b/docs/reporters.md @@ -22,7 +22,7 @@ Because of the way the junit format is structured the run must complete before a * `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively. There are a few additional reporters, for specific build systems, in the Catch repository (in `include\reporters`) which you can `#include` in your project if you would like to make use of them. -Do this in one source file - typically the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`. +Do this in one source file - the same one you have `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`. * `teamcity` writes the native, streaming, format that [TeamCity](https://www.jetbrains.com/teamcity/) understands. Use this when building as part of a TeamCity build to see results as they happen. diff --git a/include/catch.hpp b/include/catch.hpp index 40ee9da1..2d3edb58 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -28,7 +28,6 @@ # endif #endif -#include "internal/catch_notimplemented_exception.h" #include "internal/catch_context.h" #include "internal/catch_test_registry.hpp" #include "internal/catch_capture.hpp" diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 637df27b..a62ce3c0 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -16,6 +16,10 @@ #pragma clang diagnostic ignored "-Wweak-vtables" #endif + +#include "internal/catch_notimplemented_exception.h" + + // Temporary hack to fix separately provided reporters #include "../reporters/catch_reporter_bases.hpp" #include "catch_reporter_registrars.hpp" diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 50822ded..14828d47 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -181,15 +181,6 @@ TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]" ) throw double( 3.14 ); } -inline int thisFunctionNotImplemented( int ) { - CATCH_NOT_IMPLEMENTED; -} - -TEST_CASE( "NotImplemented exception", "[!throws]" ) -{ - REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ); -} - TEST_CASE( "Exception messages can be tested for", "[!throws]" ) { using namespace Catch::Matchers; SECTION( "exact match" ) From 0bb9f52a99579bd748f7a25420f88012d39c4b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 15:10:55 +0200 Subject: [PATCH 111/398] Removed declared-but-undefined function --- include/internal/catch_context.cpp | 1 - include/internal/catch_context.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/include/internal/catch_context.cpp b/include/internal/catch_context.cpp index 44d8a99e..48b4f4a9 100644 --- a/include/internal/catch_context.cpp +++ b/include/internal/catch_context.cpp @@ -8,7 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED -#include "catch_stream.h" #include "catch_context.h" #include "catch_common.h" diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 086b75fd..7815be22 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -40,8 +40,6 @@ namespace Catch { IContext& getCurrentContext(); IMutableContext& getCurrentMutableContext(); void cleanUpContext(); - Stream createStream( std::string const& streamName ); - } #endif // TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED From 3f6c078173301280a6dd1728912abe3d4b6b08a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 15:11:23 +0200 Subject: [PATCH 112/398] Use = delete instead of private, unimplemented copy operations --- include/internal/catch_test_registry.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index 5be6f6d7..1f269ee9 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -71,9 +71,8 @@ struct AutoReg { ~AutoReg(); -private: - AutoReg( AutoReg const& ); - void operator= ( AutoReg const& ); + AutoReg( AutoReg const& ) = delete; + AutoReg& operator = (AutoReg const& ) = delete; }; void registerTestCaseFunction From 8d8f481597cea543d72b8ac35bd47745fdca647c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 16:07:10 +0200 Subject: [PATCH 113/398] Moved couple function's bodies out of common-include path --- CMakeLists.txt | 1 + include/internal/catch_result_type.cpp | 28 ++++++++++++++++++++++++++ include/internal/catch_result_type.h | 18 ++++++----------- 3 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 include/internal/catch_result_type.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c680adc..3aed65bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,6 +209,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp ${HEADER_DIR}/internal/catch_registry_hub.cpp ${HEADER_DIR}/internal/catch_result_builder.cpp + ${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_section.cpp ${HEADER_DIR}/internal/catch_section_info.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp diff --git a/include/internal/catch_result_type.cpp b/include/internal/catch_result_type.cpp new file mode 100644 index 00000000..6e048865 --- /dev/null +++ b/include/internal/catch_result_type.cpp @@ -0,0 +1,28 @@ +/* + * Created by Phil on 07/01/2011. + * Copyright 2011 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) + */ + +#include "catch_result_type.h" + +namespace Catch { + + bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch diff --git a/include/internal/catch_result_type.h b/include/internal/catch_result_type.h index 4c3d77dc..6934fc11 100644 --- a/include/internal/catch_result_type.h +++ b/include/internal/catch_result_type.h @@ -31,12 +31,8 @@ namespace Catch { }; }; - inline bool isOk( ResultWas::OfType resultType ) { - return ( resultType & ResultWas::FailureBit ) == 0; - } - inline bool isJustInfo( int flags ) { - return flags == ResultWas::Info; - } + bool isOk( ResultWas::OfType resultType ); + bool isJustInfo( int flags ); // ResultDisposition::Flags enum @@ -48,13 +44,11 @@ namespace Catch { SuppressFail = 0x08 // Failures are reported but do not fail the test }; }; - inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { - return static_cast( static_cast( lhs ) | static_cast( rhs ) ); - } + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); - inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } - inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } - inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + bool shouldContinueOnFailure( int flags ); + bool isFalseTest( int flags ); + bool shouldSuppressFailure( int flags ); } // end namespace Catch From d8df83ee2f3d68e07df9cc34f511a9cbeccd89a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 16:07:52 +0200 Subject: [PATCH 114/398] Don't rely on transitive include --- include/internal/catch_matchers_string.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index e3772cbf..2192ee8f 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -10,6 +10,8 @@ #include "catch_matchers.hpp" +#include + namespace Catch { namespace Matchers { From 878bd140e6fd94654fe24edfd2a721b6062c3806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 16:16:55 +0200 Subject: [PATCH 115/398] Removed superfluous inline keywords --- include/internal/catch_common.cpp | 5 +++++ include/internal/catch_common.h | 10 +++++----- include/internal/catch_debugger.cpp | 2 +- include/internal/catch_registry_hub.cpp | 2 +- include/internal/catch_test_case_info.cpp | 6 +++--- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp index 12968515..6cd1b46d 100644 --- a/include/internal/catch_common.cpp +++ b/include/internal/catch_common.cpp @@ -106,4 +106,9 @@ namespace Catch { #endif return os; } + + bool isTrue( bool value ){ return value; } + bool alwaysTrue() { return true; } + bool alwaysFalse() { return false; } + } diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 87b7020f..f86af403 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -46,12 +46,12 @@ namespace Catch { }; template - inline void deleteAll( ContainerT& container ) { + void deleteAll( ContainerT& container ) { for( auto p : container ) delete p; } template - inline void deleteAllValues( AssociativeContainerT& container ) { + void deleteAllValues( AssociativeContainerT& container ) { for( auto const& kvp : container ) delete kvp.second; } @@ -96,9 +96,9 @@ namespace Catch { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); // This is just here to avoid compiler warnings with macro constants and boolean literals - inline bool isTrue( bool value ){ return value; } - inline bool alwaysTrue() { return true; } - inline bool alwaysFalse() { return false; } + bool isTrue( bool value ); + bool alwaysTrue(); + bool alwaysFalse(); void seedRng( IConfig const& config ); unsigned int rngSeed(); diff --git a/include/internal/catch_debugger.cpp b/include/internal/catch_debugger.cpp index e857717d..c7d66375 100644 --- a/include/internal/catch_debugger.cpp +++ b/include/internal/catch_debugger.cpp @@ -105,7 +105,7 @@ } #else namespace Catch { - inline bool isDebuggerActive() { return false; } + bool isDebuggerActive() { return false; } } #endif // Platform diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 71967f58..4d34311c 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -69,7 +69,7 @@ namespace Catch { }; // Single, global, instance - inline RegistryHub*& getTheRegistryHub() { + RegistryHub*& getTheRegistryHub() { static RegistryHub* theRegistryHub = nullptr; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 5ef88593..04bebecd 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -16,7 +16,7 @@ namespace Catch { - inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { if( startsWith( tag, '.' ) || tag == "hide" || tag == "!hide" ) @@ -32,10 +32,10 @@ namespace Catch { else return TestCaseInfo::None; } - inline bool isReservedTag( std::string const& tag ) { + bool isReservedTag( std::string const& tag ) { return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); } - inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { CATCH_ENFORCE( !isReservedTag(tag), "Tag name: [" << tag << "] is not allowed.\n" << "Tag names starting with non alpha-numeric characters are reserved\n" From e3e6453229705ad9ac122c3a165538f4616d1571 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 12 Jul 2017 14:52:36 +0100 Subject: [PATCH 116/398] Removed spurious "inline" (was causing linker errors) and fixed broken macOS detection --- include/internal/catch_debugger.cpp | 1 + include/internal/catch_platform.h | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_debugger.cpp b/include/internal/catch_debugger.cpp index c7d66375..4d05c85a 100644 --- a/include/internal/catch_debugger.cpp +++ b/include/internal/catch_debugger.cpp @@ -10,6 +10,7 @@ #include "catch_debugger.h" #include "catch_errno_guard.h" #include "catch_stream.h" +#include "catch_platform.h" #ifdef CATCH_PLATFORM_MAC diff --git a/include/internal/catch_platform.h b/include/internal/catch_platform.h index 09b91bfb..87250c60 100644 --- a/include/internal/catch_platform.h +++ b/include/internal/catch_platform.h @@ -9,12 +9,17 @@ #ifndef TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED -#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#ifdef __APPLE__ +# include +# if TARGET_OS_MAC == 1 # define CATCH_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# elif TARGET_OS_IPHONE == 1 # define CATCH_PLATFORM_IPHONE +# endif + #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX + #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) # define CATCH_PLATFORM_WINDOWS # if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) From bc73189c527323c1086a5b49b15cbbef17d3700d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 12 Jul 2017 16:24:58 +0200 Subject: [PATCH 117/398] Rebase baselines to take into account the removed test --- .../SelfTest/Baselines/console.std.approved.txt | 4 ++-- .../SelfTest/Baselines/console.sw.approved.txt | 14 ++------------ projects/SelfTest/Baselines/junit.sw.approved.txt | 3 +-- projects/SelfTest/Baselines/xml.sw.approved.txt | 15 ++------------- 4 files changed, 7 insertions(+), 29 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 4a061ae7..7a4c8321 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1002,6 +1002,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 174 | 124 passed | 46 failed | 4 failed as expected -assertions: 908 | 793 passed | 94 failed | 21 failed as expected +test cases: 173 | 123 passed | 46 failed | 4 failed as expected +assertions: 907 | 792 passed | 94 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index c27c1098..17f5fc6a 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3380,16 +3380,6 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: custom exception -------------------------------------------------------------------------------- -NotImplemented exception -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ) - ------------------------------------------------------------------------------- Objects that evaluated in boolean contexts can be checked ------------------------------------------------------------------------------- @@ -8894,6 +8884,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 174 | 123 passed | 47 failed | 4 failed as expected -assertions: 910 | 793 passed | 96 failed | 21 failed as expected +test cases: 173 | 122 passed | 47 failed | 4 failed as expected +assertions: 909 | 792 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 91e2307a..df8d91eb 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -336,7 +336,6 @@ custom exception ExceptionTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 4e65d8ce..1f7e73f0 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -3702,17 +3702,6 @@ re>" - - - - thisFunctionNotImplemented( 7 ) - - - thisFunctionNotImplemented( 7 ) - - - - @@ -9780,7 +9769,7 @@ spanner
- + - + From 10c36aa74c0de81ba1cb6fd26a4dd898c10cbb6f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 12 Jul 2017 17:59:46 +0100 Subject: [PATCH 118/398] added override keyword to overrides in compact reporter --- include/reporters/catch_reporter_compact.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp index 1ce307d0..23f043c9 100644 --- a/include/reporters/catch_reporter_compact.cpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -23,19 +23,19 @@ namespace Catch { return "Reports test results on a single line, suitable for IDEs"; } - virtual ReporterPreferences getPreferences() const { + ReporterPreferences getPreferences() const override { ReporterPreferences prefs; prefs.shouldRedirectStdOut = false; return prefs; } - virtual void noMatchingTestCases( std::string const& spec ) { + void noMatchingTestCases( std::string const& spec ) override { stream << "No test cases matched '" << spec << '\'' << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) {} + void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + bool assertionEnded( AssertionStats const& _assertionStats ) override { AssertionResult const& result = _assertionStats.assertionResult; bool printInfoMessages = true; @@ -60,7 +60,7 @@ namespace Catch { } } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { + void testRunEnded( TestRunStats const& _testRunStats ) override { printTotals( _testRunStats.totals ); stream << '\n' << std::endl; StreamingReporterBase::testRunEnded( _testRunStats ); From 79627cdcdb457d21c04b762ed5c128397dd3d807 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 12 Jul 2017 18:01:54 +0100 Subject: [PATCH 119/398] Changed some names in test case registry - in preparation for a bigger refactoring --- include/internal/catch_impl.hpp | 2 +- include/internal/catch_interfaces_testcase.h | 6 ++--- include/internal/catch_objc.hpp | 2 +- include/internal/catch_test_case_info.cpp | 4 ++-- include/internal/catch_test_case_info.h | 8 +++---- .../catch_test_case_registry_impl.hpp | 22 ++++++------------- include/internal/catch_test_registry.hpp | 19 ++++++---------- 7 files changed, 25 insertions(+), 38 deletions(-) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index a62ce3c0..96b7a452 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -49,7 +49,7 @@ namespace Catch { StreamBufBase::~StreamBufBase() noexcept {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} - ITestCase::~ITestCase() {} + ITestInvoker::~ITestInvoker() {} ITestCaseRegistry::~ITestCaseRegistry() {} IRegistryHub::~IRegistryHub() {} IMutableRegistryHub::~IMutableRegistryHub() {} diff --git a/include/internal/catch_interfaces_testcase.h b/include/internal/catch_interfaces_testcase.h index c9ab3238..9e02b14f 100644 --- a/include/internal/catch_interfaces_testcase.h +++ b/include/internal/catch_interfaces_testcase.h @@ -15,12 +15,12 @@ namespace Catch { class TestSpec; - struct ITestCase { + struct ITestInvoker { virtual void invoke () const = 0; - virtual ~ITestCase(); + virtual ~ITestInvoker(); }; - using ITestCasePtr = std::shared_ptr; + using ITestCasePtr = std::shared_ptr; class TestCase; struct IConfig; diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 30237ac4..300d796f 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -33,7 +33,7 @@ namespace Catch { - class OcMethod : public SharedImpl { + class OcMethod : public SharedImpl { public: OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 04bebecd..f75f5a3c 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -42,7 +42,7 @@ namespace Catch { << _lineInfo ); } - TestCase makeTestCase( ITestCase* _testCase, + TestCase makeTestCase( ITestInvoker* _testCase, std::string const& _className, std::string const& _name, std::string const& _descOrTags, @@ -130,7 +130,7 @@ namespace Catch { } - TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} TestCase TestCase::withName( std::string const& _newName ) const { diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index 1ff0c819..7f6d5a85 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -21,7 +21,7 @@ namespace Catch { - struct ITestCase; + struct ITestInvoker; struct TestCaseInfo { enum SpecialProperties{ @@ -59,7 +59,7 @@ namespace Catch { class TestCase : public TestCaseInfo { public: - TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( ITestInvoker* testCase, TestCaseInfo const& info ); TestCase withName( std::string const& _newName ) const; @@ -71,10 +71,10 @@ namespace Catch { bool operator < ( TestCase const& other ) const; private: - std::shared_ptr test; + std::shared_ptr test; }; - TestCase makeTestCase( ITestCase* testCase, + TestCase makeTestCase( ITestInvoker* testCase, std::string const& className, std::string const& name, std::string const& description, diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index d50b3b28..cbe755e3 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -125,24 +125,16 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// - class FreeFunctionTestCase : public ITestCase { + class TestInvokerAsFunction : public ITestInvoker { + void(*m_testAsFunction)(); public: + TestInvokerAsFunction( void(*testAsFunction)() ) : m_testAsFunction( testAsFunction ) {} - FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} - - virtual void invoke() const { - m_fun(); + void invoke() const override { + m_testAsFunction(); } - - private: - virtual ~FreeFunctionTestCase(); - - TestFunction m_fun; }; - FreeFunctionTestCase::~FreeFunctionTestCase() {} - - inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { std::string className = classOrQualifiedMethodName; if( startsWith( className, '&' ) ) @@ -157,7 +149,7 @@ namespace Catch { } void registerTestCase - ( ITestCase* testCase, + ( ITestInvoker* testCase, char const* classOrQualifiedMethodName, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ) { @@ -178,7 +170,7 @@ namespace Catch { ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ) { - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + registerTestCase( new TestInvokerAsFunction( function ), "", nameAndDesc, lineInfo ); } /////////////////////////////////////////////////////////////////////////// diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index 1f269ee9..374b9228 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -15,20 +15,15 @@ namespace Catch { template -class MethodTestCase : public ITestCase { - +class TestInvokerAsMethod : public ITestInvoker { + void (C::*m_testAsMethod)(); public: - MethodTestCase( void (C::*method)() ) : m_method( method ) {} + TestInvokerAsMethod( void (C::*testAsMethod)() ) : m_testAsMethod( testAsMethod ) {} - virtual void invoke() const { + void invoke() const override { C obj; - (obj.*m_method)(); + (obj.*m_testAsMethod)(); } - -private: - virtual ~MethodTestCase() {} - - void (C::*m_method)(); }; typedef void(*TestFunction)(); @@ -43,7 +38,7 @@ struct NameAndDesc { }; void registerTestCase - ( ITestCase* testCase, + ( ITestInvoker* testCase, char const* className, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ); @@ -63,7 +58,7 @@ struct AutoReg { SourceLineInfo const& lineInfo ) { registerTestCase - ( new MethodTestCase( method ), + ( new TestInvokerAsMethod( method ), className, nameAndDesc, lineInfo ); From 720fdf1d02dd5d5566a1f82bda87a2a43cec213d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 12 Jul 2017 22:39:31 +0100 Subject: [PATCH 120/398] Simplified test case registration and started using StringRefs --- include/internal/catch_stringref.cpp | 14 ++-- include/internal/catch_stringref.h | 2 - .../catch_test_case_registry_impl.hpp | 44 +++++-------- include/internal/catch_test_registry.hpp | 64 ++++++------------- 4 files changed, 44 insertions(+), 80 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 4ee4f7dd..3c4e292d 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -12,13 +12,17 @@ #include #include +#include namespace Catch { - - StringRef StringRef::s_emptyStringRef = ""; + + auto getEmptyStringRef() -> StringRef { + static StringRef s_emptyStringRef(""); + return s_emptyStringRef; + } StringRef::StringRef() noexcept - : StringRef( s_emptyStringRef ) + : StringRef( getEmptyStringRef() ) {} StringRef::StringRef( StringRef const& other ) noexcept @@ -41,7 +45,9 @@ namespace Catch { StringRef::StringRef( char const* rawChars ) noexcept : m_start( rawChars ), m_size( static_cast( std::strlen( rawChars ) ) ) - {} + { + assert( rawChars != nullptr ); + } StringRef::StringRef( char const* rawChars, size_type size ) noexcept : m_start( rawChars ), diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index 1cf5670f..dd223beb 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -31,8 +31,6 @@ namespace Catch { StringData const* m_data = nullptr; - static StringRef s_emptyStringRef; - void takeOwnership(); public: // construction/ assignment diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index cbe755e3..6874107c 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -134,6 +134,10 @@ namespace Catch { m_testAsFunction(); } }; + auto makeTestInvoker( void(*testAsFunction)() ) -> ITestInvoker* { + return new TestInvokerAsFunction( testAsFunction ); + } + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { std::string className = classOrQualifiedMethodName; @@ -148,40 +152,24 @@ namespace Catch { return className; } - void registerTestCase - ( ITestInvoker* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) + { try { - getMutableRegistryHub().registerTest - (makeTestCase - (testCase, - extractClassName(classOrQualifiedMethodName), - nameAndDesc.name, - nameAndDesc.description, - lineInfo)); + getMutableRegistryHub() + .registerTest( + makeTestCase( + invoker, + extractClassName( classOrMethod.c_str() ), + nameAndTags.name.c_str(), + nameAndTags.tags.c_str(), + lineInfo)); } catch (...) { // Do not throw when constructing global objects, instead register the exception to be processed later getMutableRegistryHub().registerStartupException( std::current_exception() ); } } - void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCase( new TestInvokerAsFunction( function ), "", nameAndDesc, lineInfo ); - } - - /////////////////////////////////////////////////////////////////////////// - - AutoReg::AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCaseFunction( function, lineInfo, nameAndDesc ); - } - AutoReg::~AutoReg() {} } // end namespace Catch diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index 374b9228..da0fbc2e 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -11,6 +11,7 @@ #include "catch_common.h" #include "catch_interfaces_testcase.h" #include "catch_compiler_capabilities.h" +#include "catch_stringref.h" namespace Catch { @@ -26,62 +27,33 @@ public: } }; -typedef void(*TestFunction)(); +auto makeTestInvoker( void(*testAsFunction)() ) -> ITestInvoker*; -struct NameAndDesc { - NameAndDesc( const char* _name = "", const char* _description= "" ) - : name( _name ), description( _description ) - {} +template +auto makeTestInvoker( void (C::*testAsMethod)() ) -> ITestInvoker* { + return new TestInvokerAsMethod( testAsMethod ); +} - const char* name; - const char* description; +struct NameAndTags { + + NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) : name( name_ ), tags( tags_ ) {} + + StringRef name; + StringRef tags; }; -void registerTestCase - ( ITestInvoker* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); - -struct AutoReg { - - AutoReg - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - - template - AutoReg - ( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - registerTestCase - ( new TestInvokerAsMethod( method ), - className, - nameAndDesc, - lineInfo ); - } - +struct AutoReg : NonCopyable { + AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ); ~AutoReg(); - - AutoReg( AutoReg const& ) = delete; - AutoReg& operator = (AutoReg const& ) = delete; }; -void registerTestCaseFunction - ( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); - } // end namespace Catch /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ @@ -90,7 +62,7 @@ void registerTestCaseFunction /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// @@ -100,7 +72,7 @@ void registerTestCaseFunction struct TestName : ClassName{ \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); \ } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestName::test() @@ -110,7 +82,7 @@ void registerTestCaseFunction /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \ + Catch::AutoReg( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS From 989222eceb34f749cd547d4d419ec2f7ac948a70 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 12 Jul 2017 23:26:13 +0100 Subject: [PATCH 121/398] Fixed up OcMethod base --- include/internal/catch_objc.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 300d796f..8b11d83e 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -33,7 +33,7 @@ namespace Catch { - class OcMethod : public SharedImpl { + class OcMethod : public ITestInvoker { public: OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} From e01ed48a70925a6b18f70882f0065a42a560782b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 13 Jul 2017 08:25:47 +0100 Subject: [PATCH 122/398] Made everything used in test case registration noexcept - this prevents warnings about startup-time exceptions --- include/internal/catch_common.cpp | 10 +++++----- include/internal/catch_common.h | 10 +++++----- include/internal/catch_interfaces_registry_hub.h | 2 +- include/internal/catch_registry_hub.cpp | 2 +- .../internal/catch_startup_exception_registry.cpp | 12 +++++++++--- .../internal/catch_startup_exception_registry.h | 4 ++-- include/internal/catch_test_case_registry_impl.hpp | 14 ++++++-------- include/internal/catch_test_registry.hpp | 12 ++++++------ 8 files changed, 35 insertions(+), 31 deletions(-) diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp index 6cd1b46d..a35ef93a 100644 --- a/include/internal/catch_common.cpp +++ b/include/internal/catch_common.cpp @@ -75,18 +75,18 @@ namespace Catch { return os; } - SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} - SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + SourceLineInfo::SourceLineInfo() noexcept : file(""), line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept : file( _file ), line( _line ) {} - bool SourceLineInfo::empty() const { + bool SourceLineInfo::empty() const noexcept { return file[0] == '\0'; } - bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); } - bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); } diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index f86af403..6f037c71 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -77,17 +77,17 @@ namespace Catch { struct SourceLineInfo { - SourceLineInfo(); - SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo() noexcept; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept; SourceLineInfo(SourceLineInfo const& other) = default; SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; - bool empty() const; - bool operator == ( SourceLineInfo const& other ) const; - bool operator < ( SourceLineInfo const& other ) const; + 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; diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index 8934d008..f71178be 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -46,7 +46,7 @@ namespace Catch { virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; - virtual void registerStartupException( std::exception_ptr const& exception ) = 0; + virtual void registerStartupException( std::exception_ptr const& exception ) noexcept = 0; }; IRegistryHub& getRegistryHub(); diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 4d34311c..12af6e38 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -56,7 +56,7 @@ namespace Catch { virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { m_tagAliasRegistry.add( alias, tag, lineInfo ); } - virtual void registerStartupException( std::exception_ptr const& exception ) override { + virtual void registerStartupException( std::exception_ptr const& exception ) noexcept override { m_exceptionRegistry.add(exception); } diff --git a/include/internal/catch_startup_exception_registry.cpp b/include/internal/catch_startup_exception_registry.cpp index 088b6446..d58d18a5 100644 --- a/include/internal/catch_startup_exception_registry.cpp +++ b/include/internal/catch_startup_exception_registry.cpp @@ -9,11 +9,17 @@ #include "catch_startup_exception_registry.h" namespace Catch { - void StartupExceptionRegistry::add( std::exception_ptr const& exception ) { - m_exceptions.push_back(exception); + void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { + try { + m_exceptions.push_back(exception); + } + catch(...) { + // If we run out of memory during start-up there's really not a lot more we can do about it + std::terminate(); + } } - std::vector const& StartupExceptionRegistry::getExceptions() const { + std::vector const& StartupExceptionRegistry::getExceptions() const noexcept { return m_exceptions; } diff --git a/include/internal/catch_startup_exception_registry.h b/include/internal/catch_startup_exception_registry.h index ece5e6ca..feb56601 100644 --- a/include/internal/catch_startup_exception_registry.h +++ b/include/internal/catch_startup_exception_registry.h @@ -16,8 +16,8 @@ namespace Catch { class StartupExceptionRegistry { public: - void add(std::exception_ptr const& exception); - std::vector const& getExceptions() const; + void add(std::exception_ptr const& exception) noexcept; + std::vector const& getExceptions() const noexcept; private: std::vector m_exceptions; }; diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 6874107c..5bb32f5e 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -46,10 +46,8 @@ namespace Catch { std::sort( sorted.begin(), sorted.end() ); break; case RunTests::InRandomOrder: - { - seedRng( config ); - RandomNumberGenerator::shuffle( sorted ); - } + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); break; case RunTests::InDeclarationOrder: // already in declaration order @@ -128,14 +126,14 @@ namespace Catch { class TestInvokerAsFunction : public ITestInvoker { void(*m_testAsFunction)(); public: - TestInvokerAsFunction( void(*testAsFunction)() ) : m_testAsFunction( testAsFunction ) {} + TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} void invoke() const override { m_testAsFunction(); } }; - auto makeTestInvoker( void(*testAsFunction)() ) -> ITestInvoker* { - return new TestInvokerAsFunction( testAsFunction ); + auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); } @@ -154,7 +152,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// - AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) + AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept { try { getMutableRegistryHub() diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index da0fbc2e..c8538a2c 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -19,7 +19,7 @@ template class TestInvokerAsMethod : public ITestInvoker { void (C::*m_testAsMethod)(); public: - TestInvokerAsMethod( void (C::*testAsMethod)() ) : m_testAsMethod( testAsMethod ) {} + TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} void invoke() const override { C obj; @@ -27,23 +27,23 @@ public: } }; -auto makeTestInvoker( void(*testAsFunction)() ) -> ITestInvoker*; +auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; template -auto makeTestInvoker( void (C::*testAsMethod)() ) -> ITestInvoker* { - return new TestInvokerAsMethod( testAsMethod ); +auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsMethod( testAsMethod ); } struct NameAndTags { - NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) : name( name_ ), tags( tags_ ) {} + NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept : name( name_ ), tags( tags_ ) {} StringRef name; StringRef tags; }; struct AutoReg : NonCopyable { - AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ); + AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; ~AutoReg(); }; From d2d591047995b80bb9e55d104397c229a586d644 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 13 Jul 2017 08:26:08 +0100 Subject: [PATCH 123/398] Suppress clang-tidy warnings about inline asm --- include/internal/catch_debugger.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_debugger.h b/include/internal/catch_debugger.h index ddb37097..279bec06 100644 --- a/include/internal/catch_debugger.h +++ b/include/internal/catch_debugger.h @@ -21,14 +21,14 @@ namespace Catch{ #ifdef CATCH_PLATFORM_MAC - #define CATCH_TRAP() __asm__("int $3\n" : : ) + #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break // directly at the location of the failing check instead of breaking inside // raise() called from it, i.e. one stack frame below. #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) - #define CATCH_TRAP() asm volatile ("int $3") + #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ #else // Fall back to the generic way. #include From e4456aa243c82e39db5fabf1f9b7fff2ebd900df Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 13 Jul 2017 08:29:12 +0100 Subject: [PATCH 124/398] Some clean-ups --- projects/SelfTest/ConditionTests.cpp | 36 +++++++++++----------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index ff66854d..565d9815 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -15,17 +15,10 @@ #include struct TestData { - TestData() - : int_seven( 7 ), - str_hello( "hello" ), - float_nine_point_one( 9.1f ), - double_pi( 3.1415926535 ) - {} - - int int_seven; - std::string str_hello; - float float_nine_point_one; - double double_pi; + int int_seven = 7; + std::string str_hello = "hello"; + float float_nine_point_one = 9.1f; + double double_pi = 3.1415926535; }; @@ -36,14 +29,13 @@ struct TestDef { TestDef& operator[]( const std::string& ) { return *this; } - }; // The "failing" tests all use the CHECK macro, which continues if the specific test fails. // This allows us to see all results, even if an earlier check fails // Equality tests -TEST_CASE( "Equality checks that should succeed", "" ) +TEST_CASE( "Equality checks that should succeed" ) { TestDef td; @@ -83,7 +75,7 @@ TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" ) CHECK( x == Approx( 1.301 ) ); } -TEST_CASE( "Inequality checks that should succeed", "" ) +TEST_CASE( "Inequality checks that should succeed" ) { TestData data; @@ -112,7 +104,7 @@ TEST_CASE( "Inequality checks that should fail", "[.][failing][!shouldfail]" ) } // Ordering comparison tests -TEST_CASE( "Ordering comparison checks that should succeed", "" ) +TEST_CASE( "Ordering comparison checks that should succeed" ) { TestData data; @@ -169,7 +161,7 @@ TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" ) } // Comparisons with int literals -TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned", "" ) +TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned" ) { int i = 1; unsigned int ui = 2; @@ -207,7 +199,7 @@ TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigne #pragma warning(disable:4389) // '==' : signed/unsigned mismatch #endif -TEST_CASE( "comparisons between int variables", "" ) +TEST_CASE( "comparisons between int variables" ) { long long_var = 1L; unsigned char unsigned_char_var = 1; @@ -221,7 +213,7 @@ TEST_CASE( "comparisons between int variables", "" ) REQUIRE( long_var == unsigned_long_var ); } -TEST_CASE( "comparisons between const int variables", "" ) +TEST_CASE( "comparisons between const int variables" ) { const unsigned char unsigned_char_var = 1; const unsigned short unsigned_short_var = 1; @@ -234,7 +226,7 @@ TEST_CASE( "comparisons between const int variables", "" ) REQUIRE( unsigned_long_var == 1 ); } -TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ standard behaviour", "" ) +TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" ) { CHECK( ( -1 > 2u ) ); CHECK( -1 > 2u ); @@ -247,7 +239,7 @@ TEST_CASE( "Comparisons between unsigned ints and negative signed ints match c++ CHECK( minInt > 2u ); } -TEST_CASE( "Comparisons between ints where one side is computed", "" ) +TEST_CASE( "Comparisons between ints where one side is computed" ) { CHECK( 54 == 6*9 ); } @@ -259,7 +251,7 @@ TEST_CASE( "Comparisons between ints where one side is computed", "" ) inline const char* returnsConstNull(){ return nullptr; } inline char* returnsNull(){ return nullptr; } -TEST_CASE( "Pointers can be compared to null", "" ) +TEST_CASE( "Pointers can be compared to null" ) { TestData* p = nullptr; TestData* pNULL = nullptr; @@ -291,7 +283,7 @@ TEST_CASE( "Pointers can be compared to null", "" ) // is detected and a warning issued. // An alternative form of the macros (CHECK_FALSE and REQUIRE_FALSE) can be used instead to capture // the operand value. -TEST_CASE( "'Not' checks that should succeed", "" ) +TEST_CASE( "'Not' checks that should succeed" ) { bool falseValue = false; From c874a99c6c7cb938769119c0d3a423868e7050d7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 13 Jul 2017 08:52:51 +0100 Subject: [PATCH 125/398] Enabled c++11 tests in approvals --- projects/SelfTest/ApproxTests.cpp | 6 +- .../Baselines/console.std.approved.txt | 22 +- .../Baselines/console.sw.approved.txt | 284 +++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 22 +- .../SelfTest/Baselines/xml.sw.approved.txt | 311 +++++++++++++++++- projects/SelfTest/EnumToString.cpp | 4 +- projects/SelfTest/MiscTests.cpp | 2 +- projects/SelfTest/ToStringTuple.cpp | 12 +- projects/SelfTest/ToStringVector.cpp | 4 +- projects/SelfTest/TrickyTests.cpp | 2 +- scripts/approvalTests.py | 10 +- 11 files changed, 649 insertions(+), 30 deletions(-) diff --git a/projects/SelfTest/ApproxTests.cpp b/projects/SelfTest/ApproxTests.cpp index e4bc6ecd..bb6abffe 100644 --- a/projects/SelfTest/ApproxTests.cpp +++ b/projects/SelfTest/ApproxTests.cpp @@ -166,11 +166,7 @@ inline std::ostream& operator<<( std::ostream& os, StrongDoubleTypedef td ) { return os << "StrongDoubleTypedef(" << static_cast(td) << ")"; } -TEST_CASE -( - "Comparison with explicitly convertible types", - "[Approx][c++11]" -) +TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" ) { StrongDoubleTypedef td(10.0); diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 7a4c8321..2b41e42a 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1001,7 +1001,23 @@ TrickyTests.cpp:: FAILED: with expansion: "first" == "second" -=============================================================================== -test cases: 173 | 123 passed | 46 failed | 4 failed as expected -assertions: 907 | 792 passed | 94 failed | 21 failed as expected +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e0) == "0" ) +with expansion: + "{?}" == "0" + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e1) == "1" ) +with expansion: + "{?}" == "1" + +=============================================================================== +test cases: 186 | 135 passed | 47 failed | 4 failed as expected +assertions: 939 | 822 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 17f5fc6a..0857fc24 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -923,6 +923,84 @@ with expansion: == 0x +------------------------------------------------------------------------------- +Comparison with explicitly convertible types +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( td == Approx(10.0) ) +with expansion: + StrongDoubleTypedef(10) == Approx( 10.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(10.0) == td ) +with expansion: + Approx( 10.0 ) == StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td != Approx(11.0) ) +with expansion: + StrongDoubleTypedef(10) != Approx( 11.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(11.0) != td ) +with expansion: + Approx( 11.0 ) != StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td <= Approx(10.0) ) +with expansion: + StrongDoubleTypedef(10) <= Approx( 10.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td <= Approx(11.0) ) +with expansion: + StrongDoubleTypedef(10) <= Approx( 11.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(10.0) <= td ) +with expansion: + Approx( 10.0 ) <= StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(9.0) <= td ) +with expansion: + Approx( 9.0 ) <= StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td >= Approx(9.0) ) +with expansion: + StrongDoubleTypedef(10) >= Approx( 9.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td >= Approx(10.0) ) +with expansion: + StrongDoubleTypedef(10) >= Approx( 10.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(10.0) >= td ) +with expansion: + Approx( 10.0 ) >= StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(11.0) >= td ) +with expansion: + Approx( 11.0 ) >= StrongDoubleTypedef(10) + ------------------------------------------------------------------------------- Comparisons between ints where one side is computed ------------------------------------------------------------------------------- @@ -8059,6 +8137,20 @@ MessageTests.cpp:: FAILED: explicitly with message: Previous info should not be seen +------------------------------------------------------------------------------- +long long +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( l == std::numeric_limits::max() ) +with expansion: + 9223372036854775807 (0x) + == + 9223372036854775807 (0x) + ------------------------------------------------------------------------------- looped SECTION tests s1 @@ -8248,6 +8340,18 @@ PASSED: with expansion: {null string} == {null string} +------------------------------------------------------------------------------- +null_ptr +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( ptr.get() == 0 ) +with expansion: + 0 == 0 + ------------------------------------------------------------------------------- pair > -> toString ------------------------------------------------------------------------------- @@ -8615,6 +8719,48 @@ with expansion: == "{ StringMaker }" +------------------------------------------------------------------------------- +toString(enum class w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" ) +with expansion: + "E2/V0" == "E2/V0" + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" ) +with expansion: + "E2/V1" == "E2/V1" + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" ) +with expansion: + "Unknown enum value 10" + == + "Unknown enum value 10" + +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e0) == "0" ) +with expansion: + "{?}" == "0" + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e1) == "1" ) +with expansion: + "{?}" == "1" + ------------------------------------------------------------------------------- toString(enum w/operator<<) ------------------------------------------------------------------------------- @@ -8651,6 +8797,140 @@ PASSED: with expansion: "1" == "1" +------------------------------------------------------------------------------- +tuple<> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ }" == ::Catch::Detail::stringify(type{}) ) +with expansion: + "{ }" == "{ }" + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ }" == ::Catch::Detail::stringify(value) ) +with expansion: + "{ }" == "{ }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) ) +with expansion: + "1.2f" == "1.2f" + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) ) +with expansion: + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) ) +with expansion: + "{ 0 }" == "{ 0 }" + +------------------------------------------------------------------------------- +tuple<0,int,const char *> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) ) +with expansion: + "{ 0, 42, "Catch me" }" + == + "{ 0, 42, "Catch me" }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) ) +with expansion: + "{ "hello", "world" }" + == + "{ "hello", "world" }" + +------------------------------------------------------------------------------- +tuple,tuple<>,float> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) ) +with expansion: + "{ { 42 }, { }, 1.2f }" + == + "{ { 42 }, { }, 1.2f }" + +------------------------------------------------------------------------------- +vec> -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(v) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" ) +with expansion: + "{ { "hello" }, { "world" } }" + == + "{ { "hello" }, { "world" } }" + +------------------------------------------------------------------------------- +vector -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ) +with expansion: + "{ 42 }" == "{ 42 }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ) +with expansion: + "{ 42, 250 }" == "{ 42, 250 }" + ------------------------------------------------------------------------------- vector -> toString ------------------------------------------------------------------------------- @@ -8884,6 +9164,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 173 | 122 passed | 47 failed | 4 failed as expected -assertions: 909 | 792 passed | 96 failed | 21 failed as expected +test cases: 186 | 134 passed | 48 failed | 4 failed as expected +assertions: 941 | 822 passed | 98 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index df8d91eb..6f09f338 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -112,6 +112,7 @@ ExceptionTests.cpp: + @@ -692,6 +693,7 @@ Previous info should not be seen MessageTests.cpp: + MiscTests.cpp: @@ -735,6 +737,7 @@ MiscTests.cpp: + @@ -775,8 +778,25 @@ TrickyTests.cpp: + + + +EnumToString.cpp: + + +EnumToString.cpp: + + + + + + + + + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 1f7e73f0..adbdba86 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1029,6 +1029,105 @@ + + + + td == Approx(10.0) + + + StrongDoubleTypedef(10) == Approx( 10.0 ) + + + + + Approx(10.0) == td + + + Approx( 10.0 ) == StrongDoubleTypedef(10) + + + + + td != Approx(11.0) + + + StrongDoubleTypedef(10) != Approx( 11.0 ) + + + + + Approx(11.0) != td + + + Approx( 11.0 ) != StrongDoubleTypedef(10) + + + + + td <= Approx(10.0) + + + StrongDoubleTypedef(10) <= Approx( 10.0 ) + + + + + td <= Approx(11.0) + + + StrongDoubleTypedef(10) <= Approx( 11.0 ) + + + + + Approx(10.0) <= td + + + Approx( 10.0 ) <= StrongDoubleTypedef(10) + + + + + Approx(9.0) <= td + + + Approx( 9.0 ) <= StrongDoubleTypedef(10) + + + + + td >= Approx(9.0) + + + StrongDoubleTypedef(10) >= Approx( 9.0 ) + + + + + td >= Approx(10.0) + + + StrongDoubleTypedef(10) >= Approx( 10.0 ) + + + + + Approx(10.0) >= td + + + Approx( 10.0 ) >= StrongDoubleTypedef(10) + + + + + Approx(11.0) >= td + + + Approx( 11.0 ) >= StrongDoubleTypedef(10) + + + + @@ -8927,6 +9026,19 @@ spanner + + + + l == std::numeric_limits<long long>::max() + + + 9223372036854775807 (0x) +== +9223372036854775807 (0x) + + + +
@@ -9143,6 +9255,17 @@ spanner + + + + ptr.get() == 0 + + + 0 == 0 + + + + @@ -9512,6 +9635,54 @@ spanner + + + + ::Catch::Detail::stringify(e0) == "E2/V0" + + + "E2/V0" == "E2/V0" + + + + + ::Catch::Detail::stringify(e1) == "E2/V1" + + + "E2/V1" == "E2/V1" + + + + + ::Catch::Detail::stringify(e3) == "Unknown enum value 10" + + + "Unknown enum value 10" +== +"Unknown enum value 10" + + + + + + + + ::Catch::Detail::stringify(e0) == "0" + + + "{?}" == "0" + + + + + ::Catch::Detail::stringify(e1) == "1" + + + "{?}" == "1" + + + + @@ -9550,6 +9721,142 @@ spanner + + + + "{ }" == ::Catch::Detail::stringify(type{}) + + + "{ }" == "{ }" + + + + + "{ }" == ::Catch::Detail::stringify(value) + + + "{ }" == "{ }" + + + + + + + + "1.2f" == ::Catch::Detail::stringify(float(1.2)) + + + "1.2f" == "1.2f" + + + + + "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) + + + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + + + + + + + + "{ 0 }" == ::Catch::Detail::stringify(type{0}) + + + "{ 0 }" == "{ 0 }" + + + + + + + + "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) + + + "{ 0, 42, "Catch me" }" +== +"{ 0, 42, "Catch me" }" + + + + + + + + "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) + + + "{ "hello", "world" }" +== +"{ "hello", "world" }" + + + + + + + + "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) + + + "{ { 42 }, { }, 1.2f }" +== +"{ { 42 }, { }, 1.2f }" + + + + + + + + ::Catch::Detail::stringify(v) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" + + + "{ { "hello" }, { "world" } }" +== +"{ { "hello" }, { "world" } }" + + + + + + + + ::Catch::Detail::stringify(vv) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42 }" + + + "{ 42 }" == "{ 42 }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42, 250 }" + + + "{ 42, 250 }" == "{ 42, 250 }" + + + + @@ -9769,7 +10076,7 @@ spanner
- + - + diff --git a/projects/SelfTest/EnumToString.cpp b/projects/SelfTest/EnumToString.cpp index eb80c747..7d18a292 100644 --- a/projects/SelfTest/EnumToString.cpp +++ b/projects/SelfTest/EnumToString.cpp @@ -28,7 +28,7 @@ TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) { // Enum class without user-provided stream operator enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 }; -TEST_CASE( "toString(enum class)", "[toString][enum][enumClass][c++11][.]" ) { +TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) { EnumClass1 e0 = EnumClass1::EnumClass1Value0; CHECK( ::Catch::Detail::stringify(e0) == "0" ); EnumClass1 e1 = EnumClass1::EnumClass1Value1; @@ -49,7 +49,7 @@ std::ostream& operator<<( std::ostream& os, EnumClass2 e2 ) { } } -TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass][c++11][.]" ) { +TEST_CASE( "toString(enum class w/operator<<)", "[toString][enum][enumClass]" ) { EnumClass2 e0 = EnumClass2::EnumClass2Value0; CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" ); EnumClass2 e1 = EnumClass2::EnumClass2Value1; diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 9d837822..87381b08 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -372,7 +372,7 @@ TEST_CASE( "XmlEncode" ) { } } -TEST_CASE( "long long", "[c++11][.]" ) { +TEST_CASE( "long long" ) { long long l = std::numeric_limits::max(); REQUIRE( l == std::numeric_limits::max() ); diff --git a/projects/SelfTest/ToStringTuple.cpp b/projects/SelfTest/ToStringTuple.cpp index dcd1d803..330e427e 100644 --- a/projects/SelfTest/ToStringTuple.cpp +++ b/projects/SelfTest/ToStringTuple.cpp @@ -2,7 +2,7 @@ #include -TEST_CASE( "tuple<>", "[toString][tuple][c++11][.]" ) +TEST_CASE( "tuple<>", "[toString][tuple]" ) { typedef std::tuple<> type; CHECK( "{ }" == ::Catch::Detail::stringify(type{}) ); @@ -10,34 +10,34 @@ TEST_CASE( "tuple<>", "[toString][tuple][c++11][.]" ) CHECK( "{ }" == ::Catch::Detail::stringify(value) ); } -TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) +TEST_CASE( "tuple", "[toString][tuple]" ) { typedef std::tuple type; CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) ); } -TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) +TEST_CASE( "tuple", "[toString][tuple]" ) { typedef std::tuple type; CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) ); CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) ); } -TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) +TEST_CASE( "tuple", "[toString][tuple]" ) { typedef std::tuple type; CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) ); } -TEST_CASE( "tuple,tuple<>,float>", "[toString][tuple][c++11][.]" ) +TEST_CASE( "tuple,tuple<>,float>", "[toString][tuple]" ) { typedef std::tuple,std::tuple<>,float> type; type value { std::tuple{42}, {}, 1.2f }; CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) ); } -TEST_CASE( "tuple", "[toString][tuple][c++11][.]" ) +TEST_CASE( "tuple", "[toString][tuple]" ) { typedef std::tuple type; type value { nullptr, 42, "Catch me" }; diff --git a/projects/SelfTest/ToStringVector.cpp b/projects/SelfTest/ToStringVector.cpp index c70872c8..df9c55ab 100644 --- a/projects/SelfTest/ToStringVector.cpp +++ b/projects/SelfTest/ToStringVector.cpp @@ -48,7 +48,7 @@ namespace { }; } -TEST_CASE( "vector -> toString", "[toString][vector,allocator][c++11][.]" ) { +TEST_CASE( "vector -> toString", "[toString][vector,allocator]" ) { std::vector > vv; REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ); vv.push_back( 42 ); @@ -57,7 +57,7 @@ TEST_CASE( "vector -> toString", "[toString][vector,allocator][c+ REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ); } -TEST_CASE( "vec> -> toString", "[toString][vector,allocator][c++11][.]" ) { +TEST_CASE( "vec> -> toString", "[toString][vector,allocator]" ) { using inner = std::vector>; using vector = std::vector; vector v; diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index ca8c4518..4ebb0f29 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -383,7 +383,7 @@ TEST_CASE( "pointer to class", "[Tricky]" ) #include -TEST_CASE( "null_ptr", "[Tricky][c++11][.]" ) +TEST_CASE( "null_ptr", "[Tricky]" ) { std::unique_ptr ptr; REQUIRE(ptr.get() == nullptr); diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py index 3b71be3e..016997cc 100755 --- a/scripts/approvalTests.py +++ b/scripts/approvalTests.py @@ -145,15 +145,15 @@ print("Running approvals against executable:") print(" " + cmdPath) # Standard console reporter -approve("console.std", ["~[c++11]~[!nonportable]", "--order", "lex"]) +approve("console.std", ["~[!nonportable]", "--order", "lex"]) # console reporter, include passes, warn about No Assertions -approve("console.sw", ["~[c++11]~[!nonportable]", "-s", "-w", "NoAssertions", "--order", "lex"]) +approve("console.sw", ["~[!nonportable]", "-s", "-w", "NoAssertions", "--order", "lex"]) # console reporter, include passes, warn about No Assertions, limit failures to first 4 -approve("console.swa4", ["~[c++11]~[!nonportable]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"]) +approve("console.swa4", ["~[!nonportable]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"]) # junit reporter, include passes, warn about No Assertions -approve("junit.sw", ["~[c++11]~[!nonportable]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"]) +approve("junit.sw", ["~[!nonportable]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"]) # xml reporter, include passes, warn about No Assertions -approve("xml.sw", ["~[c++11]~[!nonportable]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"]) +approve("xml.sw", ["~[!nonportable]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"]) if overallResult != 0: print("If these differences are expected, run approve.py to approve new baselines.") From c89bdf842e7fad283d9749373a267e89ed7d994c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 13 Jul 2017 09:18:40 +0100 Subject: [PATCH 126/398] Removed failing enum test from test run --- projects/SelfTest/Baselines/xml.sw.approved.txt | 2 +- projects/SelfTest/EnumToString.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index adbdba86..c18f5c94 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -9664,7 +9664,7 @@ spanner
- + ::Catch::Detail::stringify(e0) == "0" diff --git a/projects/SelfTest/EnumToString.cpp b/projects/SelfTest/EnumToString.cpp index 7d18a292..be0da03a 100644 --- a/projects/SelfTest/EnumToString.cpp +++ b/projects/SelfTest/EnumToString.cpp @@ -28,7 +28,9 @@ TEST_CASE( "toString(enum w/operator<<)", "[toString][enum]" ) { // Enum class without user-provided stream operator enum class EnumClass1 { EnumClass1Value0, EnumClass1Value1 }; -TEST_CASE( "toString(enum class)", "[toString][enum][enumClass]" ) { +// This fails, but has been hidden for a while - not sure if it's a regression or if it never worked +// - need to investigate +TEST_CASE( "toString(enum class)", "[toString][enum][enumClass][.]" ) { EnumClass1 e0 = EnumClass1::EnumClass1Value0; CHECK( ::Catch::Detail::stringify(e0) == "0" ); EnumClass1 e1 = EnumClass1::EnumClass1Value1; From f193698fb3ff9d2471e43f672695a9d00ac04608 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 13 Jul 2017 09:20:37 +0100 Subject: [PATCH 127/398] Removed all (that I could find) redundant second macro args to TEST_CASE and SECTION - now we can rely on variadic macros --- include/catch.hpp | 24 ++--- projects/SelfTest/CmdLineTests.cpp | 68 ++++++------ projects/SelfTest/ExceptionTests.cpp | 2 +- projects/SelfTest/MessageTests.cpp | 62 ++++------- projects/SelfTest/MiscTests.cpp | 144 +++++++++---------------- projects/SelfTest/PartTrackerTests.cpp | 28 ++--- projects/SelfTest/TagAliasTests.cpp | 6 +- projects/SelfTest/TestMain.cpp | 2 +- projects/SelfTest/TrickyTests.cpp | 8 +- 9 files changed, 140 insertions(+), 204 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 2d3edb58..920e17b0 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -114,18 +114,18 @@ #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) // "BDD-style" convenience wrappers #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else @@ -180,7 +180,7 @@ #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) @@ -192,11 +192,11 @@ #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) -#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) -#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) -#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) -#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) -#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc ) using Catch::Detail::Approx; diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp index ec14cb8b..50d4e9d5 100644 --- a/projects/SelfTest/CmdLineTests.cpp +++ b/projects/SelfTest/CmdLineTests.cpp @@ -15,52 +15,52 @@ inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( nullptr, "", name, desc, CATCH_INTERNAL_LINEINFO ); } -TEST_CASE( "Parse test names and tags", "" ) { +TEST_CASE( "Parse test names and tags" ) { using Catch::parseTestSpec; using Catch::TestSpec; - Catch::TestCase tcA = fakeTestCase( "a", "" ); + Catch::TestCase tcA = fakeTestCase( "a" ); Catch::TestCase tcB = fakeTestCase( "b", "[one][x]" ); Catch::TestCase tcC = fakeTestCase( "longer name with spaces", "[two][three][.][x]" ); - Catch::TestCase tcD = fakeTestCase( "zlonger name with spacesz", "" ); + Catch::TestCase tcD = fakeTestCase( "zlonger name with spacesz" ); - SECTION( "Empty test spec should have no filters", "" ) { + SECTION( "Empty test spec should have no filters" ) { TestSpec spec; CHECK( spec.hasFilters() == false ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == false ); } - SECTION( "Test spec from empty string should have no filters", "" ) { + SECTION( "Test spec from empty string should have no filters" ) { TestSpec spec = parseTestSpec( "" ); CHECK( spec.hasFilters() == false ); CHECK( spec.matches(tcA ) == false ); CHECK( spec.matches( tcB ) == false ); } - SECTION( "Test spec from just a comma should have no filters", "" ) { + SECTION( "Test spec from just a comma should have no filters" ) { TestSpec spec = parseTestSpec( "," ); CHECK( spec.hasFilters() == false ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == false ); } - SECTION( "Test spec from name should have one filter", "" ) { + SECTION( "Test spec from name should have one filter" ) { TestSpec spec = parseTestSpec( "b" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == true ); } - SECTION( "Test spec from quoted name should have one filter", "" ) { + SECTION( "Test spec from quoted name should have one filter" ) { TestSpec spec = parseTestSpec( "\"b\"" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == true ); } - SECTION( "Test spec from name should have one filter", "" ) { + SECTION( "Test spec from name should have one filter" ) { TestSpec spec = parseTestSpec( "b" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -68,7 +68,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == false ); } - SECTION( "Wildcard at the start", "" ) { + SECTION( "Wildcard at the start" ) { TestSpec spec = parseTestSpec( "*spaces" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -77,7 +77,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcD ) == false ); CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ); } - SECTION( "Wildcard at the end", "" ) { + SECTION( "Wildcard at the end" ) { TestSpec spec = parseTestSpec( "long*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -86,7 +86,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcD ) == false ); CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ); } - SECTION( "Wildcard at both ends", "" ) { + SECTION( "Wildcard at both ends" ) { TestSpec spec = parseTestSpec( "*name*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -95,25 +95,25 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcD ) == true ); CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ); } - SECTION( "Redundant wildcard at the start", "" ) { + SECTION( "Redundant wildcard at the start" ) { TestSpec spec = parseTestSpec( "*a" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); CHECK( spec.matches( tcB ) == false ); } - SECTION( "Redundant wildcard at the end", "" ) { + SECTION( "Redundant wildcard at the end" ) { TestSpec spec = parseTestSpec( "a*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); CHECK( spec.matches( tcB ) == false ); } - SECTION( "Redundant wildcard at both ends", "" ) { + SECTION( "Redundant wildcard at both ends" ) { TestSpec spec = parseTestSpec( "*a*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); CHECK( spec.matches( tcB ) == false ); } - SECTION( "Wildcard at both ends, redundant at start", "" ) { + SECTION( "Wildcard at both ends, redundant at start" ) { TestSpec spec = parseTestSpec( "*longer*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -121,7 +121,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == true ); CHECK( spec.matches( tcD ) == true ); } - SECTION( "Just wildcard", "" ) { + SECTION( "Just wildcard" ) { TestSpec spec = parseTestSpec( "*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); @@ -130,35 +130,35 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcD ) == true ); } - SECTION( "Single tag", "" ) { + SECTION( "Single tag" ) { TestSpec spec = parseTestSpec( "[one]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == true ); CHECK( spec.matches( tcC ) == false ); } - SECTION( "Single tag, two matches", "" ) { + SECTION( "Single tag, two matches" ) { TestSpec spec = parseTestSpec( "[x]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == true ); CHECK( spec.matches( tcC ) == true ); } - SECTION( "Two tags", "" ) { + SECTION( "Two tags" ) { TestSpec spec = parseTestSpec( "[two][x]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == false ); CHECK( spec.matches( tcC ) == true ); } - SECTION( "Two tags, spare separated", "" ) { + SECTION( "Two tags, spare separated" ) { TestSpec spec = parseTestSpec( "[two] [x]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == false ); CHECK( spec.matches( tcC ) == true ); } - SECTION( "Wildcarded name and tag", "" ) { + SECTION( "Wildcarded name and tag" ) { TestSpec spec = parseTestSpec( "*name*[x]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -166,21 +166,21 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == true ); CHECK( spec.matches( tcD ) == false ); } - SECTION( "Single tag exclusion", "" ) { + SECTION( "Single tag exclusion" ) { TestSpec spec = parseTestSpec( "~[one]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); CHECK( spec.matches( tcB ) == false ); CHECK( spec.matches( tcC ) == true ); } - SECTION( "One tag exclusion and one tag inclusion", "" ) { + SECTION( "One tag exclusion and one tag inclusion" ) { TestSpec spec = parseTestSpec( "~[two][x]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); CHECK( spec.matches( tcB ) == true ); CHECK( spec.matches( tcC ) == false ); } - SECTION( "One tag exclusion and one wldcarded name inclusion", "" ) { + SECTION( "One tag exclusion and one wldcarded name inclusion" ) { TestSpec spec = parseTestSpec( "~[two]*name*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -188,7 +188,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == false ); CHECK( spec.matches( tcD ) == true ); } - SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion", "" ) { + SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion" ) { TestSpec spec = parseTestSpec( "exclude:[two]*name*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -196,7 +196,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == false ); CHECK( spec.matches( tcD ) == true ); } - SECTION( "name exclusion", "" ) { + SECTION( "name exclusion" ) { TestSpec spec = parseTestSpec( "~b" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); @@ -204,7 +204,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == true ); CHECK( spec.matches( tcD ) == true ); } - SECTION( "wildcarded name exclusion", "" ) { + SECTION( "wildcarded name exclusion" ) { TestSpec spec = parseTestSpec( "~*name*" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); @@ -212,7 +212,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == false ); CHECK( spec.matches( tcD ) == false ); } - SECTION( "wildcarded name exclusion with tag inclusion", "" ) { + SECTION( "wildcarded name exclusion with tag inclusion" ) { TestSpec spec = parseTestSpec( "~*name*,[three]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); @@ -220,7 +220,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == true ); CHECK( spec.matches( tcD ) == false ); } - SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion", "" ) { + SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion" ) { TestSpec spec = parseTestSpec( "exclude:*name*,[three]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == true ); @@ -228,7 +228,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == true ); CHECK( spec.matches( tcD ) == false ); } - SECTION( "two wildcarded names", "" ) { + SECTION( "two wildcarded names" ) { TestSpec spec = parseTestSpec( "\"longer*\"\"*spaces\"" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); @@ -236,7 +236,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == true ); CHECK( spec.matches( tcD ) == false ); } - SECTION( "empty tag", "" ) { + SECTION( "empty tag" ) { TestSpec spec = parseTestSpec( "[]" ); CHECK( spec.hasFilters() == false ); CHECK( spec.matches( tcA ) == false ); @@ -244,7 +244,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == false ); CHECK( spec.matches( tcD ) == false ); } - SECTION( "empty quoted name", "" ) { + SECTION( "empty quoted name" ) { TestSpec spec = parseTestSpec( "\"\"" ); CHECK( spec.hasFilters() == false ); CHECK( spec.matches( tcA ) == false ); @@ -252,7 +252,7 @@ TEST_CASE( "Parse test names and tags", "" ) { CHECK( spec.matches( tcC ) == false ); CHECK( spec.matches( tcD ) == false ); } - SECTION( "quoted string followed by tag exclusion", "" ) { + SECTION( "quoted string followed by tag exclusion" ) { TestSpec spec = parseTestSpec( "\"*name*\"~[.]" ); CHECK( spec.hasFilters() == true ); CHECK( spec.matches( tcA ) == false ); diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 14828d47..2ec64c71 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -59,7 +59,7 @@ TEST_CASE( "An unchecked exception reports the line of the last assertion", "[.] TEST_CASE( "When unchecked exceptions are thrown from sections they are always failures", "[.][failing][!throws]" ) { - SECTION( "section name", "" ) + SECTION( "section name" ) { if( Catch::alwaysTrue() ) throw std::domain_error( "unexpected exception" ); diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp index e0970886..21802ccd 100644 --- a/projects/SelfTest/MessageTests.cpp +++ b/projects/SelfTest/MessageTests.cpp @@ -13,26 +13,23 @@ #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #endif -TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) -{ +TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) { INFO( "this is a " << "message" ); // This should output the message if a failure occurs WARN( "this is a " << "warning" ); // This should always output the message but then continue } -TEST_CASE( "SUCCEED counts as a test pass", "[messages]" ) -{ + +TEST_CASE( "SUCCEED counts as a test pass", "[messages]" ) { SUCCEED( "this is a " << "success" ); } -TEST_CASE( "INFO gets logged on failure", "[failing][messages][.]" ) -{ +TEST_CASE( "INFO gets logged on failure", "[failing][messages][.]" ) { INFO( "this message should be logged" ); INFO( "so should this" ); int a = 2; REQUIRE( a == 1 ); } -TEST_CASE( "INFO gets logged on failure, even if captured before successful assertions", "[failing][messages][.]" ) -{ +TEST_CASE( "INFO gets logged on failure, even if captured before successful assertions", "[failing][messages][.]" ) { INFO( "this message may be logged later" ); int a = 2; CHECK( a == 2 ); @@ -50,55 +47,45 @@ TEST_CASE( "INFO gets logged on failure, even if captured before successful asse CHECK( a == 2 ); } -TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" ) -{ +TEST_CASE( "FAIL aborts the test", "[failing][messages][.]" ) { FAIL( "This is a " << "failure" ); // This should output the message and abort WARN( "We should never see this"); } -TEST_CASE( "FAIL_CHECK does not abort the test", "[failing][messages][.]" ) -{ +TEST_CASE( "FAIL_CHECK does not abort the test", "[failing][messages][.]" ) { FAIL_CHECK( "This is a " << "failure" ); // This should output the message then continue WARN( "This message appears in the output"); } -TEST_CASE( "FAIL does not require an argument", "[failing][messages][.]" ) -{ +TEST_CASE( "FAIL does not require an argument", "[failing][messages][.]" ) { FAIL(); } -TEST_CASE( "SUCCESS does not require an argument", "[messages][.]" ) -{ + +TEST_CASE( "SUCCESS does not require an argument", "[messages][.]" ) { SUCCEED(); } -TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) -{ - SECTION( "one", "" ) - { +TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) { + SECTION( "one" ) { FAIL( "Message from section one" ); } - SECTION( "two", "" ) - { + SECTION( "two" ) { FAIL( "Message from section two" ); } } -TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) -{ - SECTION( "one", "" ) - { +TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) { + SECTION( "one" ) { std::cout << "Message from section one" << std::endl; } - SECTION( "two", "" ) - { + SECTION( "two" ) { std::cout << "Message from section two" << std::endl; } } -TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" ) -{ +TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" ) { for( int i=0; i<100; i++ ) { SCOPED_INFO( "current counter " << i ); @@ -107,31 +94,26 @@ TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" ) } } -TEST_CASE( "The NO_FAIL macro reports a failure but does not fail the test", "[messages]" ) -{ +TEST_CASE( "The NO_FAIL macro reports a failure but does not fail the test", "[messages]" ) { CHECK_NOFAIL( 1 == 2 ); } -TEST_CASE( "just info", "[info][isolated info][messages]" ) -{ +TEST_CASE( "just info", "[info][isolated info][messages]" ) { INFO( "this should never be seen" ); } -TEST_CASE( "just failure", "[fail][isolated info][.][messages]" ) -{ +TEST_CASE( "just failure", "[fail][isolated info][.][messages]" ) { FAIL( "Previous info should not be seen" ); } -TEST_CASE( "sends information to INFO", "[.][failing]" ) -{ +TEST_CASE( "sends information to INFO", "[.][failing]" ) { INFO( "hi" ); int i = 7; CAPTURE( i ); REQUIRE( false ); } -TEST_CASE( "Pointers can be converted to strings", "[messages][.]" ) -{ +TEST_CASE( "Pointers can be converted to strings", "[messages][.]" ) { int p; WARN( "actual address of p: " << &p ); WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) ); diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 87381b08..5b3e9ed7 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -18,185 +18,150 @@ #include #include -TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) -{ +TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) { int a = 1; int b = 2; - SECTION( "s1", "doesn't equal" ) - { + SECTION( "s1", "doesn't equal" ) { REQUIRE( a != b ); REQUIRE( b != a ); } - SECTION( "s2", "not equal" ) - { + SECTION( "s2", "not equal" ) { REQUIRE( a != b); } } -TEST_CASE( "nested SECTION tests", "[.][sections][failing]" ) -{ +TEST_CASE( "nested SECTION tests", "[.][sections][failing]" ) { int a = 1; int b = 2; - SECTION( "s1", "doesn't equal" ) - { + SECTION( "s1", "doesn't equal" ) { REQUIRE( a != b ); REQUIRE( b != a ); - SECTION( "s2", "not equal" ) - { + SECTION( "s2", "not equal" ) { REQUIRE( a != b); } } } -TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" ) -{ +TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" ) { int a = 1; int b = 2; - SECTION( "s1", "doesn't equal" ) - { - SECTION( "s2", "equal" ) - { + SECTION( "s1", "doesn't equal" ) { + SECTION( "s2", "equal" ) { REQUIRE( a == b ); } - SECTION( "s3", "not equal" ) - { + SECTION( "s3", "not equal" ) { REQUIRE( a != b ); } - SECTION( "s4", "less than" ) - { + SECTION( "s4", "less than" ) { REQUIRE( a < b ); } } } -TEST_CASE( "even more nested SECTION tests", "[sections]" ) -{ - SECTION( "c", "" ) - { - SECTION( "d (leaf)", "" ) - { +TEST_CASE( "even more nested SECTION tests", "[sections]" ) { + SECTION( "c" ) { + SECTION( "d (leaf)" ) { SUCCEED(""); // avoid failing due to no tests } - SECTION( "e (leaf)", "" ) - { + SECTION( "e (leaf)" ) { SUCCEED(""); // avoid failing due to no tests } } - SECTION( "f (leaf)", "" ) - { + SECTION( "f (leaf)" ) { SUCCEED(""); // avoid failing due to no tests } } -TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) -{ +TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) { int a = 1; - for( int b = 0; b < 10; ++b ) - { + for( int b = 0; b < 10; ++b ) { std::ostringstream oss; oss << "b is currently: " << b; - SECTION( "s1", oss.str() ) - { + SECTION( "s1", oss.str() ) { CHECK( b > a ); } } } -TEST_CASE( "looped tests", "[.][failing]" ) -{ +TEST_CASE( "looped tests", "[.][failing]" ) { static const int fib[] = { 1, 1, 2, 3, 5, 8, 13, 21 }; - for( size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) - { + for( size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) { INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" ); CHECK( ( fib[i] % 2 ) == 0 ); } } -TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) -{ +TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) { std::cout << "A string sent directly to stdout" << std::endl; std::cerr << "A string sent directly to stderr" << std::endl; } -inline const char* makeString( bool makeNull ) -{ +inline const char* makeString( bool makeNull ) { return makeNull ? nullptr : "valid string"; } -TEST_CASE( "null strings", "" ) -{ +TEST_CASE( "null strings" ) { REQUIRE( makeString( false ) != static_cast(nullptr)); REQUIRE( makeString( true ) == static_cast(nullptr)); } -inline bool testCheckedIf( bool flag ) -{ +inline bool testCheckedIf( bool flag ) { CHECKED_IF( flag ) return true; else return false; } -TEST_CASE( "checkedIf", "" ) -{ +TEST_CASE( "checkedIf" ) { REQUIRE( testCheckedIf( true ) ); } -TEST_CASE( "checkedIf, failing", "[failing][.]" ) -{ +TEST_CASE( "checkedIf, failing", "[failing][.]" ) { REQUIRE( testCheckedIf( false ) ); } -inline bool testCheckedElse( bool flag ) -{ +inline bool testCheckedElse( bool flag ) { CHECKED_ELSE( flag ) return false; return true; } -TEST_CASE( "checkedElse", "" ) -{ +TEST_CASE( "checkedElse" ) { REQUIRE( testCheckedElse( true ) ); } -TEST_CASE( "checkedElse, failing", "[failing][.]" ) -{ +TEST_CASE( "checkedElse, failing", "[failing][.]" ) { REQUIRE( testCheckedElse( false ) ); } -TEST_CASE( "xmlentitycheck", "" ) -{ - SECTION( "embedded xml", "it should be possible to embed xml characters, such as <, \" or &, or even whole documents within an attribute" ) - { +TEST_CASE( "xmlentitycheck" ) { + SECTION( "embedded xml", "it should be possible to embed xml characters, such as <, \" or &, or even whole documents within an attribute" ) { SUCCEED(""); // We need this here to stop it failing due to no tests } - SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) - { + SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) { SUCCEED(""); // We need this here to stop it failing due to no tests } } -TEST_CASE( "send a single char to INFO", "[failing][.]" ) -{ +TEST_CASE( "send a single char to INFO", "[failing][.]" ) { INFO(3); REQUIRE(false); } -TEST_CASE( "atomic if", "[failing][0]") -{ +TEST_CASE( "atomic if", "[failing][0]") { size_t x = 0; if( x ) @@ -205,9 +170,7 @@ TEST_CASE( "atomic if", "[failing][0]") REQUIRE(x == 0); } -inline unsigned int Factorial( unsigned int number ) -{ -// return number <= 1 ? number : Factorial(number-1)*number; +inline unsigned int Factorial( unsigned int number ) { return number > 1 ? Factorial(number-1)*number : 1; } @@ -219,20 +182,14 @@ TEST_CASE( "Factorials are computed", "[factorial]" ) { REQUIRE( Factorial(10) == 3628800 ); } -TEST_CASE( "An empty test with no assertions", "[empty]" ) -{ -} +TEST_CASE( "An empty test with no assertions", "[empty]" ) {} -TEST_CASE( "Nice descriptive name", "[tag1][tag2][tag3][.]" ) -{ +TEST_CASE( "Nice descriptive name", "[tag1][tag2][tag3][.]" ) { WARN( "This one ran" ); } -TEST_CASE( "first tag", "[tag1]" ) -{ -} -TEST_CASE( "second tag", "[tag2]" ) -{ -} +TEST_CASE( "first tag", "[tag1]" ) {} +TEST_CASE( "second tag", "[tag2]" ) {} + // //TEST_CASE( "spawn a new process", "[.]" ) //{ @@ -250,32 +207,32 @@ TEST_CASE( "vectors can be sized and resized", "[vector]" ) { REQUIRE( v.size() == 5 ); REQUIRE( v.capacity() >= 5 ); - SECTION( "resizing bigger changes size and capacity", "" ) { + SECTION( "resizing bigger changes size and capacity" ) { v.resize( 10 ); REQUIRE( v.size() == 10 ); REQUIRE( v.capacity() >= 10 ); } - SECTION( "resizing smaller changes size but not capacity", "" ) { + SECTION( "resizing smaller changes size but not capacity" ) { v.resize( 0 ); REQUIRE( v.size() == 0 ); REQUIRE( v.capacity() >= 5 ); - SECTION( "We can use the 'swap trick' to reset the capacity", "" ) { + SECTION( "We can use the 'swap trick' to reset the capacity" ) { std::vector empty; empty.swap( v ); REQUIRE( v.capacity() == 0 ); } } - SECTION( "reserving bigger changes capacity but not size", "" ) { + SECTION( "reserving bigger changes capacity but not size" ) { v.reserve( 10 ); REQUIRE( v.size() == 5 ); REQUIRE( v.capacity() >= 10 ); } - SECTION( "reserving smaller does not change size or capacity", "" ) { + SECTION( "reserving smaller does not change size or capacity" ) { v.reserve( 0 ); REQUIRE( v.size() == 5 ); @@ -284,8 +241,7 @@ TEST_CASE( "vectors can be sized and resized", "[vector]" ) { } // https://github.com/philsquared/Catch/issues/166 -TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") -{ +TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") { SECTION("Outer", "") SECTION("Inner", "") SUCCEED("that's not flying - that's failing in style"); @@ -293,8 +249,7 @@ TEST_CASE("A couple of nested sections followed by a failure", "[failing][.]") FAIL("to infinity and beyond"); } -TEST_CASE("not allowed", "[!throws]") -{ +TEST_CASE("not allowed", "[!throws]") { // This test case should not be included if you run with -e on the command line SUCCEED( "" ); } @@ -384,8 +339,7 @@ TEST_CASE( "long long" ) { // CHECK( x == 0 ); //} -TEST_CASE( "This test 'should' fail but doesn't", "[.][failing][!shouldfail]" ) -{ +TEST_CASE( "This test 'should' fail but doesn't", "[.][failing][!shouldfail]" ) { SUCCEED( "oops!" ); } diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 45f4cf1c..ff21e74d 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -40,7 +40,7 @@ Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) { return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo() ); } -TEST_CASE( "Tracker", "" ) { +TEST_CASE( "Tracker" ) { TrackerContext ctx; ctx.startRun(); @@ -53,7 +53,7 @@ TEST_CASE( "Tracker", "" ) { ITracker& s1 = SectionTracker::acquire( ctx, makeNAL( "S1" ) ); REQUIRE( s1.isOpen() ); - SECTION( "successfully close one section", "" ) { + SECTION( "successfully close one section" ) { s1.close(); REQUIRE( s1.isSuccessfullyCompleted() ); REQUIRE( testCase.isComplete() == false ); @@ -63,7 +63,7 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( testCase.isSuccessfullyCompleted() ); } - SECTION( "fail one section", "" ) { + SECTION( "fail one section" ) { s1.fail(); REQUIRE( s1.isComplete() ); REQUIRE( s1.isSuccessfullyCompleted() == false ); @@ -73,7 +73,7 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( ctx.completedCycle() ); REQUIRE( testCase.isSuccessfullyCompleted() == false ); - SECTION( "re-enter after failed section", "" ) { + SECTION( "re-enter after failed section" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) ); REQUIRE( testCase2.isOpen() ); @@ -86,7 +86,7 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( testCase.isComplete() ); REQUIRE( testCase.isSuccessfullyCompleted() ); } - SECTION( "re-enter after failed section and find next section", "" ) { + SECTION( "re-enter after failed section and find next section" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) ); REQUIRE( testCase2.isOpen() ); @@ -106,7 +106,7 @@ TEST_CASE( "Tracker", "" ) { } } - SECTION( "successfully close one section, then find another", "" ) { + SECTION( "successfully close one section, then find another" ) { s1.close(); ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) ); @@ -115,7 +115,7 @@ TEST_CASE( "Tracker", "" ) { testCase.close(); REQUIRE( testCase.isComplete() == false ); - SECTION( "Re-enter - skips S1 and enters S2", "" ) { + SECTION( "Re-enter - skips S1 and enters S2" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) ); REQUIRE( testCase2.isOpen() ); @@ -165,7 +165,7 @@ TEST_CASE( "Tracker", "" ) { } } - SECTION( "open a nested section", "" ) { + SECTION( "open a nested section" ) { ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) ); REQUIRE( s2.isOpen() ); @@ -181,7 +181,7 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( testCase.isComplete() ); } - SECTION( "start a generator", "" ) { + SECTION( "start a generator" ) { IndexTracker& g1 = IndexTracker::acquire( ctx, makeNAL( "G1" ), 2 ); REQUIRE( g1.isOpen() ); REQUIRE( g1.index() == 0 ); @@ -196,7 +196,7 @@ TEST_CASE( "Tracker", "" ) { testCase.close(); REQUIRE( testCase.isSuccessfullyCompleted() == false ); - SECTION( "Re-enter for second generation", "" ) { + SECTION( "Re-enter for second generation" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) ); REQUIRE( testCase2.isOpen() ); @@ -218,7 +218,7 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( testCase2.isComplete() ); } } - SECTION( "Start a new inner section", "" ) { + SECTION( "Start a new inner section" ) { ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) ); REQUIRE( s2.isOpen() ); @@ -231,7 +231,7 @@ TEST_CASE( "Tracker", "" ) { testCase.close(); REQUIRE( testCase.isComplete() == false ); - SECTION( "Re-enter for second generation", "" ) { + SECTION( "Re-enter for second generation" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) ); REQUIRE( testCase2.isOpen() ); @@ -260,7 +260,7 @@ TEST_CASE( "Tracker", "" ) { } } - SECTION( "Fail an inner section", "" ) { + SECTION( "Fail an inner section" ) { ITracker& s2 = SectionTracker::acquire( ctx, makeNAL( "S2" ) ); REQUIRE( s2.isOpen() ); @@ -274,7 +274,7 @@ TEST_CASE( "Tracker", "" ) { testCase.close(); REQUIRE( testCase.isComplete() == false ); - SECTION( "Re-enter for second generation", "" ) { + SECTION( "Re-enter for second generation" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, makeNAL( "Testcase" ) ); REQUIRE( testCase2.isOpen() ); diff --git a/projects/SelfTest/TagAliasTests.cpp b/projects/SelfTest/TagAliasTests.cpp index 002a93c0..840601e7 100644 --- a/projects/SelfTest/TagAliasTests.cpp +++ b/projects/SelfTest/TagAliasTests.cpp @@ -9,7 +9,7 @@ #include "catch.hpp" #include "internal/catch_tag_alias_registry.h" -TEST_CASE( "Tag alias can be registered against tag patterns", "" ) { +TEST_CASE( "Tag alias can be registered against tag patterns" ) { using namespace Catch::Matchers; @@ -17,7 +17,7 @@ TEST_CASE( "Tag alias can be registered against tag patterns", "" ) { registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) ); - SECTION( "The same tag alias can only be registered once", "" ) { + SECTION( "The same tag alias can only be registered once" ) { try { registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 10 ) ); @@ -32,7 +32,7 @@ TEST_CASE( "Tag alias can be registered against tag patterns", "" ) { } } - SECTION( "Tag aliases must be of the form [@name]", "" ) { + SECTION( "Tag aliases must be of the form [@name]" ) { CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) ); CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) ); CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) ); diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 980d302c..4a01441c 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -481,7 +481,7 @@ inline void manuallyRegisteredTestFunction() { } struct AutoTestReg { AutoTestReg() { - REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered", "" ); + REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered" ); } }; AutoTestReg autoTestReg; diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 4ebb0f29..0fe377ce 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -318,15 +318,15 @@ TEST_CASE( "Assertions then sections", "[Tricky]" ) REQUIRE( Catch::alwaysTrue() ); - SECTION( "A section", "" ) + SECTION( "A section" ) { REQUIRE( Catch::alwaysTrue() ); - SECTION( "Another section", "" ) + SECTION( "Another section" ) { REQUIRE( Catch::alwaysTrue() ); } - SECTION( "Another other section", "" ) + SECTION( "Another other section" ) { REQUIRE( Catch::alwaysTrue() ); } @@ -394,7 +394,7 @@ TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); } TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); } TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); } -TEST_CASE( "has printf", "" ) { +TEST_CASE( "has printf" ) { // This can cause problems as, currently, stdout itself is not redirect - only the cout (and cerr) buffer printf( "spanner" ); From cf6f9e32535285448cdb668e95a5ea10bc0f3a4b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 13 Jul 2017 10:10:39 +0100 Subject: [PATCH 128/398] Initialise unexpectedExceptions in JUnitReporter --- include/reporters/catch_reporter_junit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp index 787de016..49d913bf 100644 --- a/include/reporters/catch_reporter_junit.cpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -242,7 +242,7 @@ namespace Catch { Timer suiteTimer; std::ostringstream stdOutForSuite; std::ostringstream stdErrForSuite; - unsigned int unexpectedExceptions; + unsigned int unexpectedExceptions = 0; bool m_okToFail = false; }; From 7ccf11da2995a47c0595eb3a3be4df30a4ad098f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 15 Jul 2017 16:48:21 +0200 Subject: [PATCH 129/398] Split out catch_run_context into cpp and hpp file --- CMakeLists.txt | 1 + include/internal/catch_run_context.cpp | 295 ++++++++++++++++++++++++ include/internal/catch_run_context.hpp | 305 +++---------------------- 3 files changed, 325 insertions(+), 276 deletions(-) create mode 100644 include/internal/catch_run_context.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3aed65bd..2936a114 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,6 +210,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_registry_hub.cpp ${HEADER_DIR}/internal/catch_result_builder.cpp ${HEADER_DIR}/internal/catch_result_type.cpp + ${HEADER_DIR}/internal/catch_run_context.cpp ${HEADER_DIR}/internal/catch_section.cpp ${HEADER_DIR}/internal/catch_section_info.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp new file mode 100644 index 00000000..a44e6a64 --- /dev/null +++ b/include/internal/catch_run_context.cpp @@ -0,0 +1,295 @@ +#include "catch_run_context.hpp" + +namespace Catch { + + StreamRedirect::StreamRedirect(std::ostream& stream, std::string& targetString) + : m_stream(stream), + m_prevBuf(stream.rdbuf()), + m_targetString(targetString) { + stream.rdbuf(m_oss.rdbuf()); + } + + StreamRedirect::~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf(m_prevBuf); + } + + RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) + : m_runInfo(_config->name()), + m_context(getCurrentMutableContext()), + m_config(_config), + m_reporter(std::move(reporter)) { + m_context.setRunner(this); + m_context.setConfig(m_config); + m_context.setResultCapture(this); + m_reporter->testRunStarting(m_runInfo); + } + + RunContext::~RunContext() { + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); + } + + void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { + m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); + } + + void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { + m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); + } + + Totals RunContext::runTest(TestCase const& testCase) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting(testInfo); + + m_activeTestCase = &testCase; + + + ITracker& rootTracker = m_trackerContext.startRun(); + assert(rootTracker.isSectionTracker()); + static_cast(rootTracker).addInitialFilters(m_config->getSectionsToRun()); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); + runCurrentTest(redirectedCout, redirectedCerr); + } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); + + Totals deltaTotals = m_totals.delta(prevTotals); + if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting())); + + m_activeTestCase = nullptr; + m_testCaseTracker = nullptr; + + return deltaTotals; + } + + IConfigPtr RunContext::config() const { + return m_config; + } + + IStreamingReporter& RunContext::reporter() const { + return *m_reporter; + } + + void RunContext::assertionEnded(AssertionResult const & result) { + if (result.getResultType() == ResultWas::Ok) { + m_totals.assertions.passed++; + } else if (!result.isOk()) { + m_totals.assertions.failed++; + } + + // We have no use for the return value (whether messages should be cleared), because messages were made scoped + // and should be let to clear themselves out. + static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); + + // Reset working state + m_lastAssertionInfo = AssertionInfo("", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition); + m_lastResult = result; + } + + bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { + ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); + if (!sectionTracker.isOpen()) + return false; + m_activeSections.push_back(§ionTracker); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting(sectionInfo); + + assertions = m_totals.assertions; + + return true; + } + + bool RunContext::testForMissingAssertions(Counts& assertions) { + if (assertions.total() != 0) + return false; + if (!m_config->warnAboutMissingAssertions()) + return false; + if (m_trackerContext.currentTracker().hasChildren()) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + void RunContext::sectionEnded(SectionEndInfo const & endInfo) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + if (!m_activeSections.empty()) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); + m_messages.clear(); + } + + void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { + if (m_unfinishedSections.empty()) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back(endInfo); + } + + void RunContext::pushScopedMessage(MessageInfo const & message) { + m_messages.push_back(message); + } + + void RunContext::popScopedMessage(MessageInfo const & message) { + m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); + } + + std::string RunContext::getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : std::string(); + } + + const AssertionResult * RunContext::getLastResult() const { + return &m_lastResult; + } + + void RunContext::exceptionEarlyReported() { + m_shouldReportUnexpected = false; + } + + void RunContext::handleFatalErrorCondition(std::string const & message) { + // Don't rebuild the result -- the stringification itself can cause more fatal errors + // Instead, fake a result data. + AssertionResultData tempResult; + tempResult.resultType = ResultWas::FatalErrorCondition; + tempResult.message = message; + AssertionResult result(m_lastAssertionInfo, tempResult); + + getResultCapture().assertionEnded(result); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); + m_reporter->sectionEnded(testCaseSectionStats); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + std::string(), + std::string(), + false)); + m_totals.testCases.failed++; + testGroupEnded(std::string(), m_totals, 1, 1); + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); + } + + bool RunContext::aborting() const { + return m_totals.assertions.failed == static_cast(m_config->abortAfter()); + } + + void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); + m_reporter->sectionStarting(testCaseSection); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + m_shouldReportUnexpected = true; + try { + m_lastAssertionInfo = AssertionInfo("TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal); + + seedRng(*m_config); + + Timer timer; + timer.start(); + if (m_reporter->getPreferences().shouldRedirectStdOut) { + StreamRedirect coutRedir(cout(), redirectedCout); + StreamRedirect cerrRedir(cerr(), redirectedCerr); + invokeActiveTestCase(); + } else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } catch (TestFailureException&) { + // This just means the test was aborted due to failure + } catch (...) { + // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions + // are reported without translation at the point of origin. + if (m_shouldReportUnexpected) { + makeUnexpectedResultBuilder().useActiveException(); + } + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + if (testCaseInfo.okToFail()) { + std::swap(assertions.failedButOk, assertions.failed); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); + m_reporter->sectionEnded(testCaseSectionStats); + } + + void RunContext::invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + ResultBuilder RunContext::makeUnexpectedResultBuilder() const { + return ResultBuilder(m_lastAssertionInfo.macroName, + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression, + m_lastAssertionInfo.resultDisposition); + } + + void RunContext::handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for (std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it) + sectionEnded(*it); + m_unfinishedSections.clear(); + } + + IResultCapture& getResultCapture() { + if (IResultCapture* capture = getCurrentContext().getResultCapture()) + return *capture; + else + CATCH_INTERNAL_ERROR("No result capture instance"); + } + +} \ No newline at end of file diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 574969c8..74eacdcc 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -30,18 +30,9 @@ namespace Catch { class StreamRedirect { public: - StreamRedirect( std::ostream& stream, std::string& targetString ) - : m_stream( stream ), - m_prevBuf( stream.rdbuf() ), - m_targetString( targetString ) - { - stream.rdbuf( m_oss.rdbuf() ); - } + StreamRedirect(std::ostream& stream, std::string& targetString); - ~StreamRedirect() { - m_targetString += m_oss.str(); - m_stream.rdbuf( m_prevBuf ); - } + ~StreamRedirect(); private: std::ostream& m_stream; @@ -54,297 +45,64 @@ namespace Catch { class RunContext : public IResultCapture, public IRunner { - RunContext( RunContext const& ); - void operator =( RunContext const& ); - public: + RunContext( RunContext const& ) = delete; + RunContext& operator =( RunContext const& ) = delete; - explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ) - : m_runInfo( _config->name() ), - m_context( getCurrentMutableContext() ), - m_config( _config ), - m_reporter( std::move( reporter ) ) - { - m_context.setRunner( this ); - m_context.setConfig( m_config ); - m_context.setResultCapture( this ); - m_reporter->testRunStarting( m_runInfo ); - } + explicit RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter); - virtual ~RunContext() { - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - } + virtual ~RunContext(); - void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); - } - void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { - m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); - } + void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount); + void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount); - Totals runTest( TestCase const& testCase ) { - Totals prevTotals = m_totals; + Totals runTest(TestCase const& testCase); - std::string redirectedCout; - std::string redirectedCerr; - - TestCaseInfo testInfo = testCase.getTestCaseInfo(); - - m_reporter->testCaseStarting( testInfo ); - - m_activeTestCase = &testCase; - - - ITracker& rootTracker = m_trackerContext.startRun(); - assert( rootTracker.isSectionTracker() ); - static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); - do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); - runCurrentTest( redirectedCout, redirectedCerr ); - } - while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); - - Totals deltaTotals = m_totals.delta( prevTotals ); - if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { - deltaTotals.assertions.failed++; - deltaTotals.testCases.passed--; - deltaTotals.testCases.failed++; - } - m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - redirectedCout, - redirectedCerr, - aborting() ) ); - - m_activeTestCase = nullptr; - m_testCaseTracker = nullptr; - - return deltaTotals; - } - - IConfigPtr config() const { - return m_config; - } - IStreamingReporter& reporter() const { - return *m_reporter; - } + IConfigPtr config() const; + IStreamingReporter& reporter() const; private: // IResultCapture - virtual void assertionEnded( AssertionResult const& result ) { - if( result.getResultType() == ResultWas::Ok ) { - m_totals.assertions.passed++; - } - else if( !result.isOk() ) { - m_totals.assertions.failed++; - } + virtual void assertionEnded(AssertionResult const& result); - // We have no use for the return value (whether messages should be cleared), because messages were made scoped - // and should be let to clear themselves out. - static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); - - // Reset working state - m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); - m_lastResult = result; - } - - virtual bool sectionStarted ( + virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions - ) - { - ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); - if( !sectionTracker.isOpen() ) - return false; - m_activeSections.push_back( §ionTracker ); + ); + bool testForMissingAssertions(Counts& assertions); - m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + virtual void sectionEnded(SectionEndInfo const& endInfo); - m_reporter->sectionStarting( sectionInfo ); + virtual void sectionEndedEarly(SectionEndInfo const& endInfo); - assertions = m_totals.assertions; + virtual void pushScopedMessage(MessageInfo const& message); - return true; - } - bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 ) - return false; - if( !m_config->warnAboutMissingAssertions() ) - return false; - if( m_trackerContext.currentTracker().hasChildren() ) - return false; - m_totals.assertions.failed++; - assertions.failed++; - return true; - } + virtual void popScopedMessage(MessageInfo const& message); - virtual void sectionEnded( SectionEndInfo const& endInfo ) { - Counts assertions = m_totals.assertions - endInfo.prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); + virtual std::string getCurrentTestName() const; - if( !m_activeSections.empty() ) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); - } + virtual const AssertionResult* getLastResult() const; - m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); - m_messages.clear(); - } + virtual void exceptionEarlyReported(); - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { - if( m_unfinishedSections.empty() ) - m_activeSections.back()->fail(); - else - m_activeSections.back()->close(); - m_activeSections.pop_back(); - - m_unfinishedSections.push_back( endInfo ); - } - - virtual void pushScopedMessage( MessageInfo const& message ) { - m_messages.push_back( message ); - } - - virtual void popScopedMessage( MessageInfo const& message ) { - m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); - } - - virtual std::string getCurrentTestName() const { - return m_activeTestCase - ? m_activeTestCase->getTestCaseInfo().name - : std::string(); - } - - virtual const AssertionResult* getLastResult() const { - return &m_lastResult; - } - - virtual void exceptionEarlyReported() { - m_shouldReportUnexpected = false; - } - - virtual void handleFatalErrorCondition( std::string const& message ) { - // Don't rebuild the result -- the stringification itself can cause more fatal errors - // Instead, fake a result data. - AssertionResultData tempResult; - tempResult.resultType = ResultWas::FatalErrorCondition; - tempResult.message = message; - AssertionResult result(m_lastAssertionInfo, tempResult); - - getResultCapture().assertionEnded(result); - - handleUnfinishedSections(); - - // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - - Counts assertions; - assertions.failed = 1; - SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); - m_reporter->sectionEnded( testCaseSectionStats ); - - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); - - Totals deltaTotals; - deltaTotals.testCases.failed = 1; - m_reporter->testCaseEnded( TestCaseStats( testInfo, - deltaTotals, - std::string(), - std::string(), - false ) ); - m_totals.testCases.failed++; - testGroupEnded( std::string(), m_totals, 1, 1 ); - m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); - } + virtual void handleFatalErrorCondition(std::string const& message); public: // !TBD We need to do this another way! - bool aborting() const { - return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); - } + bool aborting() const; private: - void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); - SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); - m_reporter->sectionStarting( testCaseSection ); - Counts prevAssertions = m_totals.assertions; - double duration = 0; - m_shouldReportUnexpected = true; - try { - m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); - seedRng( *m_config ); - - Timer timer; - timer.start(); - if( m_reporter->getPreferences().shouldRedirectStdOut ) { - StreamRedirect coutRedir( Catch::cout(), redirectedCout ); - StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); - invokeActiveTestCase(); - } - else { - invokeActiveTestCase(); - } - duration = timer.getElapsedSeconds(); - } - catch( TestFailureException& ) { - // This just means the test was aborted due to failure - } - catch(...) { - // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions - // are reported without translation at the point of origin. - if (m_shouldReportUnexpected) { - makeUnexpectedResultBuilder().useActiveException(); - } - } - m_testCaseTracker->close(); - handleUnfinishedSections(); - m_messages.clear(); - - Counts assertions = m_totals.assertions - prevAssertions; - bool missingAssertions = testForMissingAssertions( assertions ); - - if( testCaseInfo.okToFail() ) { - std::swap( assertions.failedButOk, assertions.failed ); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - - SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); - m_reporter->sectionEnded( testCaseSectionStats ); - } - - void invokeActiveTestCase() { - FatalConditionHandler fatalConditionHandler; // Handle signals - m_activeTestCase->invoke(); - fatalConditionHandler.reset(); - } + void invokeActiveTestCase(); private: - ResultBuilder makeUnexpectedResultBuilder() const { - return ResultBuilder( m_lastAssertionInfo.macroName, - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression, - m_lastAssertionInfo.resultDisposition ); - } + ResultBuilder makeUnexpectedResultBuilder() const; - void handleUnfinishedSections() { - // If sections ended prematurely due to an exception we stored their - // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); - it != itEnd; - ++it ) - sectionEnded( *it ); - m_unfinishedSections.clear(); - } + void handleUnfinishedSections(); TestRunInfo m_runInfo; IMutableContext& m_context; @@ -364,12 +122,7 @@ namespace Catch { bool m_shouldReportUnexpected = true; }; - IResultCapture& getResultCapture() { - if( IResultCapture* capture = getCurrentContext().getResultCapture() ) - return *capture; - else - CATCH_INTERNAL_ERROR( "No result capture instance" ); - } + IResultCapture& getResultCapture(); } // end namespace Catch From 01a21f67f79d8bec7d767a735023751d6ebfc23a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 18 Jul 2017 08:08:17 +0100 Subject: [PATCH 130/398] Converted a load of spelt out iterators to auto --- include/internal/catch_run_context.cpp | 2 +- include/internal/catch_tag_alias_registry.cpp | 2 +- include/internal/catch_test_case_tracker.hpp | 2 +- include/reporters/catch_reporter_bases.cpp | 2 +- include/reporters/catch_reporter_compact.cpp | 2 +- include/reporters/catch_reporter_console.cpp | 2 +- include/reporters/catch_reporter_tap.hpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index a44e6a64..a8d36122 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -277,7 +277,7 @@ namespace Catch { void RunContext::handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. - for (std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + for (auto it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it) diff --git a/include/internal/catch_tag_alias_registry.cpp b/include/internal/catch_tag_alias_registry.cpp index f8c25a10..d0ee2f7c 100644 --- a/include/internal/catch_tag_alias_registry.cpp +++ b/include/internal/catch_tag_alias_registry.cpp @@ -16,7 +16,7 @@ namespace Catch { TagAliasRegistry::~TagAliasRegistry() {} Option TagAliasRegistry::find( std::string const& alias ) const { - std::map::const_iterator it = m_registry.find( alias ); + auto it = m_registry.find( alias ); if( it != m_registry.end() ) return it->second; else diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index d03fc936..a7b754c2 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -167,7 +167,7 @@ namespace TestCaseTracking { } virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override { - Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); + auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); return( it != m_children.end() ) ? *it : nullptr; diff --git a/include/reporters/catch_reporter_bases.cpp b/include/reporters/catch_reporter_bases.cpp index b041e526..4e50d6e6 100644 --- a/include/reporters/catch_reporter_bases.cpp +++ b/include/reporters/catch_reporter_bases.cpp @@ -120,7 +120,7 @@ namespace Catch { node = m_rootSection; } else { SectionNode& parentNode = *m_sectionStack.back(); - SectionNode::ChildSections::const_iterator it = + auto it = std::find_if(parentNode.childSections.begin(), parentNode.childSections.end(), BySectionInfo(sectionInfo)); diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp index 23f043c9..e5b2f5a4 100644 --- a/include/reporters/catch_reporter_compact.cpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -217,7 +217,7 @@ namespace Catch { if ( itMessage == messages.end() ) return; - // using messages.end() directly yields compilation error: + // using messages.end() directly yields (or auto) compilation error: std::vector::const_iterator itEnd = messages.end(); const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 9c18e6c5..bbfc151e 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -274,7 +274,7 @@ namespace Catch { if( m_sectionStack.size() > 1 ) { Colour colourGuard( Colour::Headers ); - std::vector::const_iterator + auto it = m_sectionStack.begin()+1, // Skip first section (test case) itEnd = m_sectionStack.end(); for( ; it != itEnd; ++it ) diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index b34acac3..0101fdab 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -205,7 +205,7 @@ namespace Catch { return; } - // using messages.end() directly yields compilation error: + // using messages.end() directly (or auto) yields compilation error: std::vector::const_iterator itEnd = messages.end(); const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); From c7931f6f18d6797eb1d2d00bb00793ae8d571bd6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 18 Jul 2017 08:35:41 +0100 Subject: [PATCH 131/398] Reuse ostringstream in XML reporter --- include/internal/catch_xmlwriter.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 35ae1648..2cd0b1c4 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -165,9 +165,10 @@ namespace Catch { template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::ostringstream oss; - oss << attribute; - return writeAttribute( name, oss.str() ); + m_oss.clear(); + m_oss.str(std::string()); + m_oss << attribute; + return writeAttribute( name, m_oss.str() ); } XmlWriter& writeText( std::string const& text, bool indent = true ) { @@ -226,6 +227,7 @@ namespace Catch { std::vector m_tags; std::string m_indent; std::ostream& m_os; + std::ostringstream m_oss; }; } From d43024ff6bc3179576d899aecfc1c1d5bc884c25 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 18 Jul 2017 18:03:57 +0100 Subject: [PATCH 132/398] Removed intermediate IConfig ptr --- include/catch_session.hpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 7acf80a6..8ebe88ca 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -50,12 +50,10 @@ namespace Catch { Totals runTests( std::shared_ptr const& config ) { - IConfigPtr iconfig = config; - IStreamingReporterPtr reporter = makeReporter( config ); - addListeners( reporter, iconfig ); + addListeners( reporter, config ); - RunContext context( iconfig, std::move( reporter ) ); + RunContext context( config, std::move( reporter ) ); Totals totals; @@ -65,15 +63,15 @@ namespace Catch { if( !testSpec.hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); + std::vector const& allTestCases = getAllTestCasesSorted( *config ); for( auto const& testCase : allTestCases ) { - if( !context.aborting() && matchTest( testCase, testSpec, *iconfig ) ) + if( !context.aborting() && matchTest( testCase, testSpec, *config ) ) totals += context.runTest( testCase ); else context.reporter().skipTest( testCase ); } - context.testGroupEnded( iconfig->name(), totals, 1, 1 ); + context.testGroupEnded( config->name(), totals, 1, 1 ); return totals; } @@ -96,6 +94,7 @@ namespace Catch { } } + class Session : NonCopyable { static const int MaxExitCode; public: @@ -112,10 +111,10 @@ namespace Catch { } void showHelp() { - Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; - - Catch::cout() << m_cli << std::endl; - Catch::cout() << "For more detailed usage please see the project docs\n" << std::endl; + Catch::cout() + << "\nCatch v" << libraryVersion() << "\n" + << m_cli << std::endl + << "For more detailed usage please see the project docs\n" << std::endl; } int applyCommandLine( int argc, char* argv[] ) { @@ -138,8 +137,8 @@ namespace Catch { return 0; } - void useConfigData( ConfigData const& _configData ) { - m_configData = _configData; + void useConfigData( ConfigData const& configData ) { + m_configData = configData; m_config.reset(); } From b0e3f45a22d47dfa73710574a505c191baa2fb27 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 18 Jul 2017 20:27:42 +0100 Subject: [PATCH 133/398] Replaced some uses of tbc_text_format with TextFlow (from Clara) --- include/catch_session.hpp | 16 +++--- include/internal/catch_clara.h | 2 +- include/internal/catch_list.cpp | 54 +++++++++---------- include/reporters/catch_reporter_teamcity.hpp | 8 +-- projects/SelfTest/TestMain.cpp | 1 + 5 files changed, 41 insertions(+), 40 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 8ebe88ca..05ebff47 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -14,7 +14,6 @@ #include "internal/catch_run_context.hpp" #include "internal/catch_test_spec.hpp" #include "internal/catch_version.h" -#include "internal/catch_text.h" #include "internal/catch_interfaces_reporter.h" #include "internal/catch_startup_exception_registry.h" @@ -24,6 +23,8 @@ namespace Catch { + using namespace clara::TextFlow; + IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); @@ -120,13 +121,12 @@ namespace Catch { int applyCommandLine( int argc, char* argv[] ) { auto result = m_cli.parse( clara::Args( argc, argv ) ); if( !result ) { - { - Colour colourGuard( Colour::Red ); - Catch::cerr() - << "\nError(s) in input:\n" - << Text( result.errorMessage(), TextAttributes().setIndent(2) ) - << "\n\n"; - } + Catch::cerr() + << Colour( Colour::Red ) + << "\nError(s) in input:\n" + << Column( result.errorMessage() ).indent( 2 ) + << "\n\n"; + Catch::cerr() << m_cli << std::endl; return MaxExitCode; } diff --git a/include/internal/catch_clara.h b/include/internal/catch_clara.h index 1aeb4658..abe7626b 100644 --- a/include/internal/catch_clara.h +++ b/include/internal/catch_clara.h @@ -14,7 +14,7 @@ #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH #endif -#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 #include "../external/clara.hpp" diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index 8f13be8d..b8c4cc2f 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -12,7 +12,8 @@ #include "catch_interfaces_reporter.h" #include "catch_interfaces_testcase.h" -#include "catch_text.h" +#include "catch_clara.h" // For TextFlow + #include "catch_console_colour.hpp" #include "catch_test_spec_parser.hpp" @@ -22,6 +23,8 @@ namespace Catch { + using namespace clara::TextFlow; + std::size_t listTests( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) @@ -31,37 +34,31 @@ namespace Catch { testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } - std::size_t matchedTests = 0; - TextAttributes nameAttr, descAttr, tagsAttr; - nameAttr.setInitialIndent( 2 ).setIndent( 4 ); - descAttr.setIndent( 4 ); - tagsAttr.setIndent( 6 ); - - std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( auto const& testCaseInfo : matchedTestCases ) { - matchedTests++; Colour::Code colour = testCaseInfo.isHidden() ? Colour::SecondaryText : Colour::None; Colour colourGuard( colour ); - Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; + Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; if( config.verbosity() >= Verbosity::High ) { - Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; - std::string description = testCaseInfo.description; - if( description == "" ) - description = "(NO DESCRIPTION)"; - Catch::cout() << Text( description, descAttr ) << std::endl; + std::string description = testCaseInfo.description.empty() + ? std::string( "(NO DESCRIPTION)" ) + : testCaseInfo.description; + Catch::cout() + << " " << testCaseInfo.lineInfo << "\n" + << Column( description ).indent( 4 ) << "\n"; } if( !testCaseInfo.tags.empty() ) - Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + Catch::cout() << Column( testCaseInfo.tagsAsString ).indent( 6 ) << "\n"; } if( !config.testSpec().hasFilters() ) - Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; + Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; else - Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; - return matchedTests; + Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; + return matchedTestCases.size(); } std::size_t listTestsNamesOnly( Config const& config ) { @@ -120,10 +117,10 @@ namespace Catch { for( auto const& tagCount : tagCounts ) { std::ostringstream oss; oss << " " << std::setw(2) << tagCount.second.count << " "; - Text wrapper( tagCount.second.all(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( oss.str().size() ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + auto wrapper = Column( tagCount.second.all() ) + .initialIndent( 0 ) + .indent( oss.str().size() ) + .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); Catch::cout() << oss.str() << wrapper << '\n'; } Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; @@ -138,11 +135,12 @@ namespace Catch { maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); for( auto const& factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) { - Text wrapper( factoryKvp.second->getDescription(), TextAttributes() - .setInitialIndent( 0 ) - .setIndent( 7+maxNameLen ) - .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); - Catch::cout() << " " + auto wrapper = Column( factoryKvp.second->getDescription() ) + .initialIndent( 0 ) + .indent( 7+maxNameLen ) + .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ); + Catch::cout() + << " " << factoryKvp.first << ':' << std::string( maxNameLen - factoryKvp.first.size() + 2, ' ' ) diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 623ae6a3..82e18660 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -23,6 +23,8 @@ namespace Catch { + using namespace clara::TextFlow; + struct TeamCityReporter : StreamingReporterBase { TeamCityReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ) @@ -194,9 +196,9 @@ namespace Catch { i+=2; else i = 0; - os << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << "\n"; + os << Column( _string ) + .indent( indent+i) + .initialIndent( indent ) << "\n"; } private: bool m_headerPrintedForThisSection = false; diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 4a01441c..10a2ae4d 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -8,6 +8,7 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" +#include "internal/catch_text.h" // temporarily #include "../include/reporters/catch_reporter_teamcity.hpp" #include "../include/reporters/catch_reporter_tap.hpp" #include "../include/reporters/catch_reporter_automake.hpp" From cd6f6c021afbd8b45de825164259fe6ce110df7d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 19 Jul 2017 08:16:55 +0100 Subject: [PATCH 134/398] Minor clean-ups in string conversion code --- include/internal/catch_tostring.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 2828be1a..23bfa0f2 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -35,6 +35,9 @@ namespace Catch { using ::operator<<; namespace Detail { + + extern const std::string unprintableString; + std::string rawMemoryToString( const void *object, std::size_t size ); template @@ -64,7 +67,7 @@ namespace Catch { static typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type convert(const Fake& t) { - std::stringstream sstr; + std::ostringstream sstr; sstr << t; return sstr.str(); } @@ -73,14 +76,12 @@ namespace Catch { static typename std::enable_if::value, std::string>::type convert(const Fake&) { - return "{?}"; + return Detail::unprintableString; } }; namespace Detail { - extern const std::string unprintableString; - // This function dispatches all stringification requests inside of Catch. // Should be preferably called fully qualified, like ::Catch::Detail::stringify template From 4833932ab25a54743d12d46b5a8f71b82b60649e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 19 Jul 2017 08:17:41 +0100 Subject: [PATCH 135/398] Removed redundant member --- include/internal/catch_run_context.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 74eacdcc..44b648a9 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -95,7 +95,6 @@ namespace Catch { private: void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); - void invokeActiveTestCase(); private: @@ -108,7 +107,6 @@ namespace Catch { IMutableContext& m_context; TestCase const* m_activeTestCase = nullptr; ITracker* m_testCaseTracker; - ITracker* m_currentSectionTracker; AssertionResult m_lastResult; IConfigPtr m_config; From 0a614ee5ba469120b9fb61c4f34b2763ae59d65a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 19 Jul 2017 08:31:10 +0100 Subject: [PATCH 136/398] re/moved some headers in catch_tostring --- include/internal/catch_tostring.cpp | 2 ++ include/internal/catch_tostring.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_tostring.cpp b/include/internal/catch_tostring.cpp index 7599c053..f3b9267c 100644 --- a/include/internal/catch_tostring.cpp +++ b/include/internal/catch_tostring.cpp @@ -10,6 +10,8 @@ #include "catch_interfaces_config.h" #include "catch_context.h" +#include + namespace Catch { namespace Detail { diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 23bfa0f2..e4cded72 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -11,8 +11,6 @@ #include "catch_common.h" #include -#include -#include #include #include From edbe12276143fb27a7f98c1af0e6f25c8787aae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 19 Jul 2017 10:01:06 +0200 Subject: [PATCH 137/398] Split out non-templated Approx methods into cpp file --- CMakeLists.txt | 1 + include/internal/catch_approx.cpp | 39 +++++++++++++++++++++++++++++++ include/internal/catch_approx.hpp | 24 ++++--------------- 3 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 include/internal/catch_approx.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2936a114..ff300ca7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,6 +193,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_xmlwriter.hpp ) set(IMPL_SOURCES + ${HEADER_DIR}/internal/catch_approx.cpp ${HEADER_DIR}/internal/catch_assertionresult.cpp ${HEADER_DIR}/internal/catch_commandline.cpp ${HEADER_DIR}/internal/catch_common.cpp diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp new file mode 100644 index 00000000..98fc7bce --- /dev/null +++ b/include/internal/catch_approx.cpp @@ -0,0 +1,39 @@ +/* + * Created by Martin on 19/07/2017. + * Copyright 2017 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) + */ + +#include "catch_approx.hpp" + +#include + +namespace Catch { +namespace Detail { + + Approx::Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_margin( 0.0 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx Approx::custom() { + return Approx( 0 ); + } + + std::string Approx::toString() const { + std::ostringstream oss; + oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; + return oss.str(); + } + +} // end namespace Detail + +std::string StringMaker::convert(Catch::Detail::Approx const& value) { + return value.toString(); +} + +} // end namespace Catch diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index 4235d0bc..bb930a4b 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -20,18 +20,9 @@ namespace Detail { class Approx { public: - explicit Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_margin( 0.0 ), - m_scale( 1.0 ), - m_value( value ) - {} + explicit Approx ( double value ); - Approx( Approx const& other ) = default; - - static Approx custom() { - return Approx( 0 ); - } + static Approx custom(); template ::value>::type> Approx operator()( T value ) { @@ -111,12 +102,7 @@ namespace Detail { return *this; } - - std::string toString() const { - std::ostringstream oss; - oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; - return oss.str(); - } + std::string toString() const; private: double m_epsilon; @@ -128,9 +114,7 @@ namespace Detail { template<> struct StringMaker { - static std::string convert(Catch::Detail::Approx const& value) { - return value.toString(); - } + static std::string convert(Catch::Detail::Approx const& value); }; } // end namespace Catch From d7ff62430a009cca04dcdb10a320dd6162f2a3d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 19 Jul 2017 10:11:10 +0200 Subject: [PATCH 138/398] Removed superfluous inline specifications --- include/internal/catch_evaluate.hpp | 2 +- include/internal/catch_matchers.hpp | 10 +++++----- include/internal/catch_result_builder.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index e1d2505f..31be0dcf 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -37,7 +37,7 @@ namespace Internal { template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; template - inline T& opCast(T const& t) { return const_cast(t); } + T& opCast(T const& t) { return const_cast(t); } // nullptr_t support based on pull request #154 from Konstantin Baumann inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index ef039aa9..8131b225 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -155,23 +155,23 @@ namespace Matchers { // This allows the types to be inferred // - deprecated: prefer ||, && and ! template - inline Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { + Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { return Impl::MatchNotOf( underlyingMatcher ); } template - inline Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { + Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { return Impl::MatchAllOf() && m1 && m2; } template - inline Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { + Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { return Impl::MatchAllOf() && m1 && m2 && m3; } template - inline Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { + Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { return Impl::MatchAnyOf() || m1 || m2; } template - inline Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { + Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { return Impl::MatchAnyOf() || m1 || m2 || m3; } diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index e8de6735..1d822361 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -99,7 +99,7 @@ namespace Catch { namespace Catch { template - inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { + ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { return ExpressionLhs( *this, operand ); } @@ -108,7 +108,7 @@ namespace Catch { } template - inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, + void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ) { MatchExpression expr( arg, matcher, matcherString ); setResultType( matcher.match( arg ) ); From 4a1e898eaeab7910a872e3d1d1e26932bfaadcce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 19 Jul 2017 10:13:47 +0200 Subject: [PATCH 139/398] More method bodies moved out of line --- CMakeLists.txt | 9 + include/internal/catch_assertionresult.cpp | 28 ++ include/internal/catch_assertionresult.h | 44 +-- include/internal/catch_config.cpp | 71 +++++ include/internal/catch_config.hpp | 81 ++--- include/internal/catch_impl.hpp | 20 -- .../internal/catch_interfaces_reporter.cpp | 120 ++++++++ include/internal/catch_interfaces_reporter.h | 106 ++----- include/internal/catch_result_builder.cpp | 10 + include/internal/catch_result_builder.h | 11 +- include/internal/catch_run_context.cpp | 2 + include/internal/catch_run_context.hpp | 1 - include/internal/catch_test_case_tracker.cpp | 277 ++++++++++++++++++ include/internal/catch_test_case_tracker.hpp | 271 +++-------------- include/internal/catch_test_spec.cpp | 50 ++++ include/internal/catch_test_spec.hpp | 47 +-- include/internal/catch_test_spec_parser.cpp | 87 ++++++ include/internal/catch_test_spec_parser.hpp | 82 +----- include/internal/catch_totals.cpp | 61 ++++ include/internal/catch_totals.hpp | 51 +--- include/internal/catch_wildcard_pattern.cpp | 46 +++ include/internal/catch_wildcard_pattern.hpp | 36 +-- include/internal/catch_xmlwriter.cpp | 181 ++++++++++++ include/internal/catch_xmlwriter.hpp | 176 ++--------- include/reporters/catch_reporter_junit.cpp | 2 + include/reporters/catch_reporter_multi.cpp | 67 ++--- include/reporters/catch_reporter_multi.h | 57 ++++ 27 files changed, 1199 insertions(+), 795 deletions(-) create mode 100644 include/internal/catch_config.cpp create mode 100644 include/internal/catch_interfaces_reporter.cpp create mode 100644 include/internal/catch_test_case_tracker.cpp create mode 100644 include/internal/catch_test_spec.cpp create mode 100644 include/internal/catch_test_spec_parser.cpp create mode 100644 include/internal/catch_totals.cpp create mode 100644 include/internal/catch_wildcard_pattern.cpp create mode 100644 include/internal/catch_xmlwriter.cpp create mode 100644 include/reporters/catch_reporter_multi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ff300ca7..f427977c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_assertionresult.cpp ${HEADER_DIR}/internal/catch_commandline.cpp ${HEADER_DIR}/internal/catch_common.cpp + ${HEADER_DIR}/internal/catch_config.cpp ${HEADER_DIR}/internal/catch_console_colour.cpp ${HEADER_DIR}/internal/catch_context.cpp ${HEADER_DIR}/internal/catch_debugger.cpp @@ -209,6 +210,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_message.cpp ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp ${HEADER_DIR}/internal/catch_registry_hub.cpp + ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp ${HEADER_DIR}/internal/catch_result_builder.cpp ${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_run_context.cpp @@ -221,9 +223,15 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp ${HEADER_DIR}/internal/catch_test_case_info.cpp + ${HEADER_DIR}/internal/catch_test_case_tracker.cpp + ${HEADER_DIR}/internal/catch_test_spec.cpp + ${HEADER_DIR}/internal/catch_test_spec_parser.cpp ${HEADER_DIR}/internal/catch_timer.cpp ${HEADER_DIR}/internal/catch_tostring.cpp + ${HEADER_DIR}/internal/catch_totals.cpp ${HEADER_DIR}/internal/catch_version.cpp + ${HEADER_DIR}/internal/catch_wildcard_pattern.cpp + ${HEADER_DIR}/internal/catch_xmlwriter.cpp ) set(INTERNAL_FILES ${IMPL_SOURCES} ${INTERNAL_HEADERS}) CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal) @@ -232,6 +240,7 @@ CheckFileList(INTERNAL_FILES ${HEADER_DIR}/internal) set(REPORTER_HEADERS ${HEADER_DIR}/reporters/catch_reporter_automake.hpp ${HEADER_DIR}/reporters/catch_reporter_bases.hpp + ${HEADER_DIR}/reporters/catch_reporter_multi.h ${HEADER_DIR}/reporters/catch_reporter_tap.hpp ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp ) diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 77c69281..9a4b0c65 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -11,6 +11,10 @@ namespace Catch { + bool DecomposedExpression::isBinaryExpression() const { + return false; + } + AssertionInfo::AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, char const * _capturedExpression, @@ -21,6 +25,30 @@ namespace Catch { resultDisposition( _resultDisposition ) {} + void AssertionResultData::negate( bool parenthesize ) { + negated = !negated; + parenthesized = parenthesize; + if( resultType == ResultWas::Ok ) + resultType = ResultWas::ExpressionFailed; + else if( resultType == ResultWas::ExpressionFailed ) + resultType = ResultWas::Ok; + } + + std::string const& AssertionResultData::reconstructExpression() const { + if( decomposedExpression != nullptr ) { + decomposedExpression->reconstructExpression( reconstructedExpression ); + if( parenthesized ) { + reconstructedExpression.insert( 0, 1, '(' ); + reconstructedExpression.append( 1, ')' ); + } + if( negated ) { + reconstructedExpression.insert( 0, 1, '!' ); + } + decomposedExpression = nullptr; + } + return reconstructedExpression; + } + AssertionResult::AssertionResult() {} AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 26546d38..c9a08b9a 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -18,10 +18,12 @@ namespace Catch { struct DecomposedExpression { - virtual ~DecomposedExpression() {} - virtual bool isBinaryExpression() const { - return false; - } + DecomposedExpression() = default; + DecomposedExpression( DecomposedExpression const& ) = default; + DecomposedExpression& operator = ( DecomposedExpression const& ) = delete; + + virtual ~DecomposedExpression() = default; + virtual bool isBinaryExpression() const; virtual void reconstructExpression( std::string& dest ) const = 0; // Only simple binary comparisons can be decomposed. @@ -33,50 +35,26 @@ namespace Catch { template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); - - private: - DecomposedExpression& operator = (DecomposedExpression const&); }; struct AssertionInfo { - AssertionInfo() {} + AssertionInfo() = default; AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, char const * _capturedExpression, ResultDisposition::Flags _resultDisposition); - char const * macroName; + char const * macroName = nullptr; SourceLineInfo lineInfo; - char const * capturedExpression; + char const * capturedExpression = nullptr; ResultDisposition::Flags resultDisposition; }; struct AssertionResultData { - void negate( bool parenthesize ) { - negated = !negated; - parenthesized = parenthesize; - if( resultType == ResultWas::Ok ) - resultType = ResultWas::ExpressionFailed; - else if( resultType == ResultWas::ExpressionFailed ) - resultType = ResultWas::Ok; - } - - std::string const& reconstructExpression() const { - if( decomposedExpression != nullptr ) { - decomposedExpression->reconstructExpression( reconstructedExpression ); - if( parenthesized ) { - reconstructedExpression.insert( 0, 1, '(' ); - reconstructedExpression.append( 1, ')' ); - } - if( negated ) { - reconstructedExpression.insert( 0, 1, '!' ); - } - decomposedExpression = nullptr; - } - return reconstructedExpression; - } + void negate( bool parenthesize ); + std::string const& reconstructExpression() const; mutable DecomposedExpression const* decomposedExpression = nullptr; mutable std::string reconstructedExpression; diff --git a/include/internal/catch_config.cpp b/include/internal/catch_config.cpp new file mode 100644 index 00000000..cf7c0c6e --- /dev/null +++ b/include/internal/catch_config.cpp @@ -0,0 +1,71 @@ +/* + * Created by Martin on 19/07/2017. + * + * 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) + */ + +#include "catch_config.hpp" + +namespace Catch { + + Config::Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( auto const& testOrTags : data.testsOrTags ) + parser.parse( testOrTags ); + m_testSpec = parser.testSpec(); + } + } + + std::string const& Config::getFilename() const { + return m_data.outputFilename ; + } + + bool Config::listTests() const { return m_data.listTests; } + bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool Config::listTags() const { return m_data.listTags; } + bool Config::listReporters() const { return m_data.listReporters; } + + Verbosity Config::verbosity() const { return m_data.verbosity; } + + std::string Config::getProcessName() const { return m_data.processName; } + + std::vector const& Config::getReporterNames() const { return m_data.reporterNames; } + std::vector const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } + + TestSpec const& Config::testSpec() const { return m_testSpec; } + + bool Config::showHelp() const { return m_data.showHelp; } + + // IConfig interface + bool Config::allowThrows() const { return !m_data.noThrow; } + std::ostream& Config::stream() const { return m_stream->stream(); } + std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } + RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } + unsigned int Config::rngSeed() const { return m_data.rngSeed; } + UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } + bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } + int Config::abortAfter() const { return m_data.abortAfter; } + bool Config::showInvisibles() const { return m_data.showInvisibles; } + + IStream const* Config::openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" ); + } + else + return new FileStream( m_data.outputFilename ); + } + +} // end namespace Catch diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index bc1f5b26..add50100 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -16,7 +16,6 @@ #include #include #include -#include #ifndef CATCH_CONFIG_CONSOLE_WIDTH #define CATCH_CONFIG_CONSOLE_WIDTH 80 @@ -60,71 +59,45 @@ namespace Catch { virtual void dummy(); public: - Config() - {} + Config() = default; + Config( ConfigData const& data ); + virtual ~Config() = default; - Config( ConfigData const& data ) - : m_data( data ), - m_stream( openStream() ) - { - if( !data.testsOrTags.empty() ) { - TestSpecParser parser( ITagAliasRegistry::get() ); - for( auto const& testOrTags : data.testsOrTags ) - parser.parse( testOrTags ); - m_testSpec = parser.testSpec(); - } - } + std::string const& getFilename() const; - virtual ~Config() {} + bool listTests() const; + bool listTestNamesOnly() const; + bool listTags() const; + bool listReporters() const; - std::string const& getFilename() const { - return m_data.outputFilename ; - } + Verbosity verbosity() const; - bool listTests() const { return m_data.listTests; } - bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } - bool listTags() const { return m_data.listTags; } - bool listReporters() const { return m_data.listReporters; } + std::string getProcessName() const; - Verbosity verbosity() const { return m_data.verbosity; } + std::vector const& getReporterNames() const; + std::vector const& getSectionsToRun() const override; - std::string getProcessName() const { return m_data.processName; } + virtual TestSpec const& testSpec() const override; - std::vector const& getReporterNames() const { return m_data.reporterNames; } - std::vector const& getSectionsToRun() const override { return m_data.sectionsToRun; } - - virtual TestSpec const& testSpec() const override { return m_testSpec; } - - bool showHelp() const { return m_data.showHelp; } + bool showHelp() const; // IConfig interface - virtual bool allowThrows() const override { return !m_data.noThrow; } - virtual std::ostream& stream() const override { return m_stream->stream(); } - virtual std::string name() const override { return m_data.name.empty() ? m_data.processName : m_data.name; } - virtual bool includeSuccessfulResults() const override { return m_data.showSuccessfulTests; } - virtual bool warnAboutMissingAssertions() const override { return m_data.warnings & WarnAbout::NoAssertions; } - virtual ShowDurations::OrNot showDurations() const override { return m_data.showDurations; } - virtual RunTests::InWhatOrder runOrder() const override { return m_data.runOrder; } - virtual unsigned int rngSeed() const override { return m_data.rngSeed; } - virtual UseColour::YesOrNo useColour() const override { return m_data.useColour; } - virtual bool shouldDebugBreak() const override { return m_data.shouldDebugBreak; } - virtual int abortAfter() const override { return m_data.abortAfter; } - virtual bool showInvisibles() const override { return m_data.showInvisibles; } + virtual bool allowThrows() const override; + virtual std::ostream& stream() const override; + virtual std::string name() const override; + virtual bool includeSuccessfulResults() const override; + virtual bool warnAboutMissingAssertions() const override; + virtual ShowDurations::OrNot showDurations() const override; + virtual RunTests::InWhatOrder runOrder() const override; + virtual unsigned int rngSeed() const override; + virtual UseColour::YesOrNo useColour() const override; + virtual bool shouldDebugBreak() const override; + virtual int abortAfter() const override; + virtual bool showInvisibles() const override; private: - IStream const* openStream() { - if( m_data.outputFilename.empty() ) - return new CoutStream(); - else if( m_data.outputFilename[0] == '%' ) { - if( m_data.outputFilename == "%debug" ) - return new DebugOutStream(); - else - CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" ); - } - else - return new FileStream( m_data.outputFilename ); - } + IStream const* openStream(); ConfigData m_data; std::unique_ptr m_stream; diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 96b7a452..94696662 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -55,33 +55,13 @@ namespace Catch { IMutableRegistryHub::~IMutableRegistryHub() {} IExceptionTranslator::~IExceptionTranslator() {} IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IReporterFactory::~IReporterFactory() {} - IReporterRegistry::~IReporterRegistry() {} - IStreamingReporter::~IStreamingReporter() {} - AssertionStats::~AssertionStats() {} - SectionStats::~SectionStats() {} - TestCaseStats::~TestCaseStats() {} - TestGroupStats::~TestGroupStats() {} - TestRunStats::~TestRunStats() {} IRunner::~IRunner() {} IMutableContext::~IMutableContext() {} IConfig::~IConfig() {} - WildcardPattern::~WildcardPattern() {} - TestSpec::Pattern::~Pattern() {} - TestSpec::NamePattern::~NamePattern() {} - TestSpec::TagPattern::~TagPattern() {} - TestSpec::ExcludedPattern::~ExcludedPattern() {} Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} void Config::dummy() {} - - namespace TestCaseTracking { - ITracker::~ITracker() {} - TrackerBase::~TrackerBase() {} - SectionTracker::~SectionTracker() {} - IndexTracker::~IndexTracker() {} - } } #ifdef __clang__ diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp new file mode 100644 index 00000000..8ad16248 --- /dev/null +++ b/include/internal/catch_interfaces_reporter.cpp @@ -0,0 +1,120 @@ +/* + * Created by Martin on 19/07/2017. + * + * 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) + */ + +#include "catch_interfaces_reporter.h" +#include "../reporters/catch_reporter_multi.h" + +namespace Catch { + + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& ReporterConfig::stream() const { return *m_stream; } + IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } + + + TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} + + GroupInfo::GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + AssertionStats::AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + + SectionStats::SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + + + TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + + TestRunStats::TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + + bool IStreamingReporter::isMulti() const { return false; } + + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { + + if( !existingReporter ) { + existingReporter = std::move( additionalReporter ); + return; + } + + MultipleReporters* multi = nullptr; + + if( existingReporter->isMulti() ) { + multi = static_cast( existingReporter.get() ); + } + else { + auto newMulti = std::unique_ptr( new MultipleReporters ); + newMulti->add( std::move( existingReporter ) ); + multi = newMulti.get(); + existingReporter = std::move( newMulti ); + } + multi->add( std::move( additionalReporter ) ); + } + +} // end namespace Catch diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 7a42f097..eb419a20 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -10,29 +10,29 @@ #include "catch_section_info.h" #include "catch_common.h" -#include "catch_totals.hpp" #include "catch_config.hpp" +#include "catch_context.h" +#include "catch_totals.hpp" #include "catch_test_case_info.h" #include "catch_assertionresult.h" #include "catch_message.h" #include "catch_option.hpp" + #include -#include +#include #include #include -namespace Catch -{ +namespace Catch { + struct ReporterConfig { - explicit ReporterConfig( IConfigPtr const& _fullConfig ) - : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + explicit ReporterConfig( IConfigPtr const& _fullConfig ); - ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) - : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); - std::ostream& stream() const { return *m_stream; } - IConfigPtr fullConfig() const { return m_fullConfig; } + std::ostream& stream() const; + IConfigPtr fullConfig() const; private: std::ostream* m_stream; @@ -40,16 +40,11 @@ namespace Catch }; struct ReporterPreferences { - ReporterPreferences() - : shouldRedirectStdOut( false ) - {} - - bool shouldRedirectStdOut; + bool shouldRedirectStdOut = false; }; template struct LazyStat : Option { - LazyStat() : used( false ) {} LazyStat& operator=( T const& _value ) { Option::operator=( _value ); used = false; @@ -59,21 +54,17 @@ namespace Catch Option::reset(); used = false; } - bool used; + bool used = false; }; struct TestRunInfo { - TestRunInfo( std::string const& _name ) : name( _name ) {} + TestRunInfo( std::string const& _name ); std::string name; }; struct GroupInfo { GroupInfo( std::string const& _name, std::size_t _groupIndex, - std::size_t _groupsCount ) - : name( _name ), - groupIndex( _groupIndex ), - groupsCounts( _groupsCount ) - {} + std::size_t _groupsCount ); std::string name; std::size_t groupIndex; @@ -83,27 +74,13 @@ namespace Catch struct AssertionStats { AssertionStats( AssertionResult const& _assertionResult, std::vector const& _infoMessages, - Totals const& _totals ) - : assertionResult( _assertionResult ), - infoMessages( _infoMessages ), - totals( _totals ) - { - if( assertionResult.hasMessage() ) { - // Copy message into messages list. - // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); - builder << assertionResult.getMessage(); - builder.m_info.message = builder.m_stream.str(); - - infoMessages.push_back( builder.m_info ); - } - } - virtual ~AssertionStats(); + Totals const& _totals ); AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats && ) = default; + virtual ~AssertionStats() = default; AssertionResult assertionResult; std::vector infoMessages; @@ -114,17 +91,12 @@ namespace Catch SectionStats( SectionInfo const& _sectionInfo, Counts const& _assertions, double _durationInSeconds, - bool _missingAssertions ) - : sectionInfo( _sectionInfo ), - assertions( _assertions ), - durationInSeconds( _durationInSeconds ), - missingAssertions( _missingAssertions ) - {} - virtual ~SectionStats(); + bool _missingAssertions ); SectionStats( SectionStats const& ) = default; SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats && ) = default; + virtual ~SectionStats() = default; SectionInfo sectionInfo; Counts assertions; @@ -137,19 +109,13 @@ namespace Catch Totals const& _totals, std::string const& _stdOut, std::string const& _stdErr, - bool _aborting ) - : testInfo( _testInfo ), - totals( _totals ), - stdOut( _stdOut ), - stdErr( _stdErr ), - aborting( _aborting ) - {} - virtual ~TestCaseStats(); + bool _aborting ); TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats && ) = default; + virtual ~TestCaseStats() = default; TestCaseInfo testInfo; Totals totals; @@ -161,21 +127,14 @@ namespace Catch struct TestGroupStats { TestGroupStats( GroupInfo const& _groupInfo, Totals const& _totals, - bool _aborting ) - : groupInfo( _groupInfo ), - totals( _totals ), - aborting( _aborting ) - {} - TestGroupStats( GroupInfo const& _groupInfo ) - : groupInfo( _groupInfo ), - aborting( false ) - {} - virtual ~TestGroupStats(); + bool _aborting ); + TestGroupStats( GroupInfo const& _groupInfo ); TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats && ) = default; + virtual ~TestGroupStats() = default; GroupInfo groupInfo; Totals totals; @@ -185,17 +144,13 @@ namespace Catch struct TestRunStats { TestRunStats( TestRunInfo const& _runInfo, Totals const& _totals, - bool _aborting ) - : runInfo( _runInfo ), - totals( _totals ), - aborting( _aborting ) - {} - virtual ~TestRunStats(); + bool _aborting ); TestRunStats( TestRunStats const& ) = default; TestRunStats( TestRunStats && ) = default; TestRunStats& operator = ( TestRunStats const& ) = default; TestRunStats& operator = ( TestRunStats && ) = default; + virtual ~TestRunStats() = default; TestRunInfo runInfo; Totals totals; @@ -205,7 +160,7 @@ namespace Catch class MultipleReporters; struct IStreamingReporter { - virtual ~IStreamingReporter(); + virtual ~IStreamingReporter() = default; // Implementing class must also provide the following static method: // static std::string getDescription(); @@ -232,12 +187,12 @@ namespace Catch virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - virtual bool isMulti() const { return false; } + virtual bool isMulti() const; }; using IStreamingReporterPtr = std::unique_ptr; struct IReporterFactory { - virtual ~IReporterFactory(); + virtual ~IReporterFactory() = default; virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; @@ -247,13 +202,14 @@ namespace Catch using FactoryMap = std::map; using Listeners = std::vector; - virtual ~IReporterRegistry(); + virtual ~IReporterRegistry() = default; virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; }; void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); -} + +} // end namespace Catch #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index 727b42e7..09a2f53e 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -19,6 +19,16 @@ namespace Catch { + CopyableStream::CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& CopyableStream::operator=( CopyableStream const& other ) { + oss.str(std::string()); + oss << other.oss.str(); + return *this; + } + + ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 1d822361..d442ce40 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -21,14 +21,9 @@ namespace Catch { struct CopyableStream { CopyableStream() = default; - CopyableStream( CopyableStream const& other ) { - oss << other.oss.str(); - } - CopyableStream& operator=( CopyableStream const& other ) { - oss.str(std::string()); - oss << other.oss.str(); - return *this; - } + CopyableStream( CopyableStream const& other ); + CopyableStream& operator=( CopyableStream const& other ); + std::ostringstream oss; }; diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index a8d36122..7ed79950 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -1,5 +1,7 @@ #include "catch_run_context.hpp" +#include + namespace Catch { StreamRedirect::StreamRedirect(std::ostream& stream, std::string& targetString) diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 44b648a9..abe8c1fe 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -22,7 +22,6 @@ #include "catch_result_builder.h" #include "catch_fatal_condition.h" -#include #include namespace Catch { diff --git a/include/internal/catch_test_case_tracker.cpp b/include/internal/catch_test_case_tracker.cpp new file mode 100644 index 00000000..7efb470c --- /dev/null +++ b/include/internal/catch_test_case_tracker.cpp @@ -0,0 +1,277 @@ +/* + * Created by Martin on 19/07/2017 + * + * 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) + */ + +#include "catch_test_case_tracker.hpp" + +#include +#include +#include +#include + +CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS + +namespace Catch { +namespace TestCaseTracking { + + NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) + : name( _name ), + location( _location ) + {} + + + + TrackerContext& TrackerContext::instance() { + static TrackerContext s_instance; + return s_instance; + } + + ITracker& TrackerContext::startRun() { + m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); + m_currentTracker = nullptr; + m_runState = Executing; + return *m_rootTracker; + } + + void TrackerContext::endRun() { + m_rootTracker.reset(); + m_currentTracker = nullptr; + m_runState = NotStarted; + } + + void TrackerContext::startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void TrackerContext::completeCycle() { + m_runState = CompletedCycle; + } + + bool TrackerContext::completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& TrackerContext::currentTracker() { + return *m_currentTracker; + } + void TrackerContext::setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + + + + TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} + bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) { + return + tracker->nameAndLocation().name == m_nameAndLocation.name && + tracker->nameAndLocation().location == m_nameAndLocation.location; + } + + TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : m_nameAndLocation( nameAndLocation ), + m_ctx( ctx ), + m_parent( parent ) + {} + + NameAndLocation const& TrackerBase::nameAndLocation() const { + return m_nameAndLocation; + } + bool TrackerBase::isComplete() const { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + bool TrackerBase::isSuccessfullyCompleted() const { + return m_runState == CompletedSuccessfully; + } + bool TrackerBase::isOpen() const { + return m_runState != NotStarted && !isComplete(); + } + bool TrackerBase::hasChildren() const { + return !m_children.empty(); + } + + + void TrackerBase::addChild( ITrackerPtr const& child ) { + m_children.push_back( child ); + } + + ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { + auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); + return( it != m_children.end() ) + ? *it + : nullptr; + } + ITracker& TrackerBase::parent() { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + void TrackerBase::openChild() { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + bool TrackerBase::isSectionTracker() const { return false; } + bool TrackerBase::isIndexTracker() const { return false; } + + void TrackerBase::open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + void TrackerBase::close() { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + case NotStarted: + case CompletedSuccessfully: + case Failed: + CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); + + default: + CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); + } + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::fail() { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::markAsNeedingAnotherRun() { + m_runState = NeedsAnotherRun; + } + + void TrackerBase::moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void TrackerBase::moveToThis() { + m_ctx.setCurrentTracker( this ); + } + + SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( nameAndLocation, ctx, parent ) + { + if( parent ) { + while( !parent->isSectionTracker() ) + parent = &parent->parent(); + + SectionTracker& parentSection = static_cast( *parent ); + addNextFilters( parentSection.m_filters ); + } + } + + bool SectionTracker::isSectionTracker() const { return true; } + + SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { + std::shared_ptr section; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = std::static_pointer_cast( childTracker ); + } + else { + section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() ) + section->tryOpen(); + return *section; + } + + void SectionTracker::tryOpen() { + if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) + open(); + } + + void SectionTracker::addInitialFilters( std::vector const& filters ) { + if( !filters.empty() ) { + m_filters.push_back(""); // Root - should never be consulted + m_filters.push_back(""); // Test Case - not a section filter + m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); + } + } + void SectionTracker::addNextFilters( std::vector const& filters ) { + if( filters.size() > 1 ) + m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); + } + + IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_size( size ) + {} + + bool IndexTracker::isIndexTracker() const { return true; } + + IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { + std::shared_ptr tracker; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = std::static_pointer_cast( childTracker ); + } + else { + tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int IndexTracker::index() const { return m_index; } + + void IndexTracker::moveNext() { + m_index++; + m_children.clear(); + } + + void IndexTracker::close() { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index a7b754c2..964b45f9 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -11,11 +11,8 @@ #include "catch_compiler_capabilities.h" #include "catch_common.h" -#include #include -#include #include -#include #include CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS @@ -27,10 +24,7 @@ namespace TestCaseTracking { std::string name; SourceLineInfo location; - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) - : name( _name ), - location( _location ) - {} + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); }; struct ITracker; @@ -38,7 +32,7 @@ namespace TestCaseTracking { using ITrackerPtr = std::shared_ptr; struct ITracker { - virtual ~ITracker(); + virtual ~ITracker() = default; // static queries virtual NameAndLocation const& nameAndLocation() const = 0; @@ -79,36 +73,17 @@ namespace TestCaseTracking { public: - static TrackerContext& instance() { - static TrackerContext s_instance; - return s_instance; - } + static TrackerContext& instance(); ITracker& startRun(); + void endRun(); - void endRun() { - m_rootTracker.reset(); - m_currentTracker = nullptr; - m_runState = NotStarted; - } + void startCycle(); + void completeCycle(); - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void completeCycle() { - m_runState = CompletedCycle; - } - - bool completedCycle() const { - return m_runState == CompletedCycle; - } - ITracker& currentTracker() { - return *m_currentTracker; - } - void setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } + bool completedCycle() const; + ITracker& currentTracker(); + void setCurrentTracker( ITracker* tracker ); }; class TrackerBase : public ITracker { @@ -121,239 +96,87 @@ namespace TestCaseTracking { CompletedSuccessfully, Failed }; + class TrackerHasName { NameAndLocation m_nameAndLocation; public: - TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} - bool operator ()( ITrackerPtr const& tracker ) { - return - tracker->nameAndLocation().name == m_nameAndLocation.name && - tracker->nameAndLocation().location == m_nameAndLocation.location; - } + TrackerHasName( NameAndLocation const& nameAndLocation ); + bool operator ()( ITrackerPtr const& tracker ); }; + typedef std::vector Children; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; Children m_children; CycleState m_runState = NotStarted; + public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : m_nameAndLocation( nameAndLocation ), - m_ctx( ctx ), - m_parent( parent ) - {} - virtual ~TrackerBase(); + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + virtual ~TrackerBase() = default; - virtual NameAndLocation const& nameAndLocation() const override { - return m_nameAndLocation; - } - virtual bool isComplete() const override { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - virtual bool isSuccessfullyCompleted() const override { - return m_runState == CompletedSuccessfully; - } - virtual bool isOpen() const override { - return m_runState != NotStarted && !isComplete(); - } - virtual bool hasChildren() const override { - return !m_children.empty(); - } + virtual NameAndLocation const& nameAndLocation() const override; + virtual bool isComplete() const override; + virtual bool isSuccessfullyCompleted() const override; + virtual bool isOpen() const override; + virtual bool hasChildren() const override; - virtual void addChild( ITrackerPtr const& child ) override { - m_children.push_back( child ); - } + virtual void addChild( ITrackerPtr const& child ) override; - virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override { - auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); - return( it != m_children.end() ) - ? *it - : nullptr; - } - virtual ITracker& parent() override { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } + virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; + virtual ITracker& parent() override; - virtual void openChild() override { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } + virtual void openChild() override; - virtual bool isSectionTracker() const override { return false; } - virtual bool isIndexTracker() const override { return false; } + virtual bool isSectionTracker() const override; + virtual bool isIndexTracker() const override; - void open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } + void open(); - virtual void close() override { + virtual void close() override; + virtual void fail() override; + virtual void markAsNeedingAnotherRun() override; - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case NeedsAnotherRun: - break;; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - case NotStarted: - case CompletedSuccessfully: - case Failed: - CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); - - default: - CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); - } - moveToParent(); - m_ctx.completeCycle(); - } - virtual void fail() override { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - virtual void markAsNeedingAnotherRun() override { - m_runState = NeedsAnotherRun; - } private: - void moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void moveToThis() { - m_ctx.setCurrentTracker( this ); - } + void moveToParent(); + void moveToThis(); }; class SectionTracker : public TrackerBase { std::vector m_filters; public: - SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( nameAndLocation, ctx, parent ) - { - if( parent ) { - while( !parent->isSectionTracker() ) - parent = &parent->parent(); + SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + virtual ~SectionTracker() = default; - SectionTracker& parentSection = static_cast( *parent ); - addNextFilters( parentSection.m_filters ); - } - } - virtual ~SectionTracker(); + virtual bool isSectionTracker() const override; - virtual bool isSectionTracker() const override { return true; } + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { - std::shared_ptr section; + void tryOpen(); - ITracker& currentTracker = ctx.currentTracker(); - if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isSectionTracker() ); - section = std::static_pointer_cast( childTracker ); - } - else { - section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() ) - section->tryOpen(); - return *section; - } - - void tryOpen() { - if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) - open(); - } - - void addInitialFilters( std::vector const& filters ) { - if( !filters.empty() ) { - m_filters.push_back(""); // Root - should never be consulted - m_filters.push_back(""); // Test Case - not a section filter - m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); - } - } - void addNextFilters( std::vector const& filters ) { - if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); - } + void addInitialFilters( std::vector const& filters ); + void addNextFilters( std::vector const& filters ); }; class IndexTracker : public TrackerBase { int m_size; int m_index = -1; public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( nameAndLocation, ctx, parent ), - m_size( size ) - {} - virtual ~IndexTracker(); + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); + virtual ~IndexTracker() = default; - virtual bool isIndexTracker() const override { return true; } + virtual bool isIndexTracker() const override; - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { - std::shared_ptr tracker; + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); - ITracker& currentTracker = ctx.currentTracker(); - if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { - assert( childTracker ); - assert( childTracker->isIndexTracker() ); - tracker = std::static_pointer_cast( childTracker ); - } - else { - tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } + int index() const; - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } + void moveNext(); - return *tracker; - } - - int index() const { return m_index; } - - void moveNext() { - m_index++; - m_children.clear(); - } - - virtual void close() override { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) - m_runState = Executing; - } + virtual void close() override; }; - inline ITracker& TrackerContext::startRun() { - m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); - m_currentTracker = nullptr; - m_runState = Executing; - return *m_rootTracker; - } - } // namespace TestCaseTracking using TestCaseTracking::ITracker; diff --git a/include/internal/catch_test_spec.cpp b/include/internal/catch_test_spec.cpp new file mode 100644 index 00000000..878d8424 --- /dev/null +++ b/include/internal/catch_test_spec.cpp @@ -0,0 +1,50 @@ +/* + * Created by Martin on 19/07/2017. + * + * 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) + */ + +#include "catch_test_spec.hpp" + +#include +#include +#include + +namespace Catch { + + TestSpec::NamePattern::NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + + TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + + TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + + bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( auto const& pattern : m_patterns ) { + if( !pattern->matches( testCase ) ) + return false; + } + return true; + } + + bool TestSpec::hasFilters() const { + return !m_filters.empty(); + } + bool TestSpec::matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( auto const& filter : m_filters ) + if( filter.matches( testCase ) ) + return true; + return false; + } +} diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index 6571fdd5..48788fd7 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -24,40 +24,34 @@ namespace Catch { class TestSpec { struct Pattern { - virtual ~Pattern(); + virtual ~Pattern() = default; virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; using PatternPtr = std::shared_ptr; class NamePattern : public Pattern { public: - NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), CaseSensitive::No ) - {} - virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return m_wildcardPattern.matches( toLower( testCase.name ) ); - } + NamePattern( std::string const& name ); + virtual ~NamePattern() = default; + virtual bool matches( TestCaseInfo const& testCase ) const; private: WildcardPattern m_wildcardPattern; }; class TagPattern : public Pattern { public: - TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} - virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { - return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); - } + TagPattern( std::string const& tag ); + virtual ~TagPattern() = default; + virtual bool matches( TestCaseInfo const& testCase ) const; private: std::string m_tag; }; class ExcludedPattern : public Pattern { public: - ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} - virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + ExcludedPattern( PatternPtr const& underlyingPattern ); + virtual ~ExcludedPattern() = default; + virtual bool matches( TestCaseInfo const& testCase ) const; private: PatternPtr m_underlyingPattern; }; @@ -65,27 +59,12 @@ namespace Catch { struct Filter { std::vector m_patterns; - bool matches( TestCaseInfo const& testCase ) const { - // All patterns in a filter must match for the filter to be a match - for( auto const& pattern : m_patterns ) { - if( !pattern->matches( testCase ) ) - return false; - } - return true; - } + bool matches( TestCaseInfo const& testCase ) const; }; public: - bool hasFilters() const { - return !m_filters.empty(); - } - bool matches( TestCaseInfo const& testCase ) const { - // A TestSpec matches if any filter matches - for( auto const& filter : m_filters ) - if( filter.matches( testCase ) ) - return true; - return false; - } + bool hasFilters() const; + bool matches( TestCaseInfo const& testCase ) const; private: std::vector m_filters; diff --git a/include/internal/catch_test_spec_parser.cpp b/include/internal/catch_test_spec_parser.cpp new file mode 100644 index 00000000..fcfc44c9 --- /dev/null +++ b/include/internal/catch_test_spec_parser.cpp @@ -0,0 +1,87 @@ +/* + * Created by Martin on 19/07/2017. + * + * 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) + */ + +#include "catch_test_spec_parser.hpp" + +namespace Catch { + + TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& TestSpecParser::parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + m_escapeChars.clear(); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec TestSpecParser::testSpec() { + addFilter(); + return m_testSpec; + } + + void TestSpecParser::visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + case '\\': return escape(); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + else if( c == '\\' ) + escape(); + } + else if( m_mode == EscapedName ) + m_mode = Name; + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + void TestSpecParser::escape() { + if( m_mode == None ) + m_start = m_pos; + m_mode = EscapedName; + m_escapeChars.push_back( m_pos ); + } + std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + + void TestSpecParser::addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + + TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch diff --git a/include/internal/catch_test_spec_parser.hpp b/include/internal/catch_test_spec_parser.hpp index c2c797ce..2cc44f09 100644 --- a/include/internal/catch_test_spec_parser.hpp +++ b/include/internal/catch_test_spec_parser.hpp @@ -30,69 +30,17 @@ namespace Catch { ITagAliasRegistry const* m_tagAliases; public: - TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + TestSpecParser( ITagAliasRegistry const& tagAliases ); + + TestSpecParser& parse( std::string const& arg ); + TestSpec testSpec(); - TestSpecParser& parse( std::string const& arg ) { - m_mode = None; - m_exclusion = false; - m_start = std::string::npos; - m_arg = m_tagAliases->expandAliases( arg ); - m_escapeChars.clear(); - for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) - visitChar( m_arg[m_pos] ); - if( m_mode == Name ) - addPattern(); - return *this; - } - TestSpec testSpec() { - addFilter(); - return m_testSpec; - } private: - void visitChar( char c ) { - if( m_mode == None ) { - switch( c ) { - case ' ': return; - case '~': m_exclusion = true; return; - case '[': return startNewMode( Tag, ++m_pos ); - case '"': return startNewMode( QuotedName, ++m_pos ); - case '\\': return escape(); - default: startNewMode( Name, m_pos ); break; - } - } - if( m_mode == Name ) { - if( c == ',' ) { - addPattern(); - addFilter(); - } - else if( c == '[' ) { - if( subString() == "exclude:" ) - m_exclusion = true; - else - addPattern(); - startNewMode( Tag, ++m_pos ); - } - else if( c == '\\' ) - escape(); - } - else if( m_mode == EscapedName ) - m_mode = Name; - else if( m_mode == QuotedName && c == '"' ) - addPattern(); - else if( m_mode == Tag && c == ']' ) - addPattern(); - } - void startNewMode( Mode mode, std::size_t start ) { - m_mode = mode; - m_start = start; - } - void escape() { - if( m_mode == None ) - m_start = m_pos; - m_mode = EscapedName; - m_escapeChars.push_back( m_pos ); - } - std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + void visitChar( char c ); + void startNewMode( Mode mode, std::size_t start ); + void escape(); + std::string subString() const; + template void addPattern() { std::string token = subString(); @@ -112,16 +60,10 @@ namespace Catch { m_exclusion = false; m_mode = None; } - void addFilter() { - if( !m_currentFilter.m_patterns.empty() ) { - m_testSpec.m_filters.push_back( m_currentFilter ); - m_currentFilter = TestSpec::Filter(); - } - } + + void addFilter(); }; - inline TestSpec parseTestSpec( std::string const& arg ) { - return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); - } + TestSpec parseTestSpec( std::string const& arg ); } // namespace Catch diff --git a/include/internal/catch_totals.cpp b/include/internal/catch_totals.cpp new file mode 100644 index 00000000..3ddc6bab --- /dev/null +++ b/include/internal/catch_totals.cpp @@ -0,0 +1,61 @@ +/* + * Created by Martin on 19/07/2017. + * + * 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) + */ + +#include "catch_totals.hpp" + +namespace Catch { + + Counts Counts::operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + + Counts& Counts::operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t Counts::total() const { + return passed + failed + failedButOk; + } + bool Counts::allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool Counts::allOk() const { + return failed == 0; + } + + Totals Totals::operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals& Totals::operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Totals Totals::delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + +} diff --git a/include/internal/catch_totals.hpp b/include/internal/catch_totals.hpp index 8c26263c..9507582d 100644 --- a/include/internal/catch_totals.hpp +++ b/include/internal/catch_totals.hpp @@ -13,29 +13,12 @@ namespace Catch { struct Counts { - Counts operator - ( Counts const& other ) const { - Counts diff; - diff.passed = passed - other.passed; - diff.failed = failed - other.failed; - diff.failedButOk = failedButOk - other.failedButOk; - return diff; - } - Counts& operator += ( Counts const& other ) { - passed += other.passed; - failed += other.failed; - failedButOk += other.failedButOk; - return *this; - } + Counts operator - ( Counts const& other ) const; + Counts& operator += ( Counts const& other ); - std::size_t total() const { - return passed + failed + failedButOk; - } - bool allPassed() const { - return failed == 0 && failedButOk == 0; - } - bool allOk() const { - return failed == 0; - } + std::size_t total() const; + bool allPassed() const; + bool allOk() const; std::size_t passed = 0; std::size_t failed = 0; @@ -44,29 +27,11 @@ namespace Catch { struct Totals { - Totals operator - ( Totals const& other ) const { - Totals diff; - diff.assertions = assertions - other.assertions; - diff.testCases = testCases - other.testCases; - return diff; - } + Totals operator - ( Totals const& other ) const; + Totals& operator += ( Totals const& other ); - Totals delta( Totals const& prevTotals ) const { - Totals diff = *this - prevTotals; - if( diff.assertions.failed > 0 ) - ++diff.testCases.failed; - else if( diff.assertions.failedButOk > 0 ) - ++diff.testCases.failedButOk; - else - ++diff.testCases.passed; - return diff; - } + Totals delta( Totals const& prevTotals ) const; - Totals& operator += ( Totals const& other ) { - assertions += other.assertions; - testCases += other.testCases; - return *this; - } Counts assertions; Counts testCases; diff --git a/include/internal/catch_wildcard_pattern.cpp b/include/internal/catch_wildcard_pattern.cpp new file mode 100644 index 00000000..e99ff5f2 --- /dev/null +++ b/include/internal/catch_wildcard_pattern.cpp @@ -0,0 +1,46 @@ +/* + * Created by Martin on 19/07/2017. + * + * 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) + */ + +#include "catch_wildcard_pattern.hpp" + + +namespace Catch { + + WildcardPattern::WildcardPattern( std::string const& pattern, + CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + + bool WildcardPattern::matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + default: + CATCH_INTERNAL_ERROR( "Unknown enum" ); + } + } + + std::string WildcardPattern::adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } +} diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp index 04d70f12..e163650c 100644 --- a/include/internal/catch_wildcard_pattern.hpp +++ b/include/internal/catch_wildcard_pattern.hpp @@ -25,38 +25,12 @@ namespace Catch public: - WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) - : m_caseSensitivity( caseSensitivity ), - m_pattern( adjustCase( pattern ) ) - { - if( startsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_pattern, '*' ) ) { - m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } - virtual ~WildcardPattern(); - virtual bool matches( std::string const& str ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_pattern == adjustCase( str ); - case WildcardAtStart: - return endsWith( adjustCase( str ), m_pattern ); - case WildcardAtEnd: - return startsWith( adjustCase( str ), m_pattern ); - case WildcardAtBothEnds: - return contains( adjustCase( str ), m_pattern ); - default: - CATCH_INTERNAL_ERROR( "Unknown enum" ); - } - } + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); + virtual ~WildcardPattern() = default; + virtual bool matches( std::string const& str ) const; + private: - std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - } + std::string adjustCase( std::string const& str ) const; CaseSensitive::Choice m_caseSensitivity; WildcardPosition m_wildcard = NoWildcard; std::string m_pattern; diff --git a/include/internal/catch_xmlwriter.cpp b/include/internal/catch_xmlwriter.cpp new file mode 100644 index 00000000..2ecb768c --- /dev/null +++ b/include/internal/catch_xmlwriter.cpp @@ -0,0 +1,181 @@ +/* + * Created by Phil on 19/07/2017. + * + * 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) + */ + +#include "catch_xmlwriter.hpp" + +#include + +namespace Catch { + + XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void XmlEncode::encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 and + // by @mrpi PR #588 + if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { + // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast( c ); + } + else + os << c; + } + } + } + + std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + XmlWriter::ScopedElement::ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = nullptr; + } + + XmlWriter::ScopedElement::~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { + m_writer->writeText( text, indent ); + return *this; + } + + XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) + { + writeDeclaration(); + } + + XmlWriter::~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& XmlWriter::startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { + m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& XmlWriter::writeComment( std::string const& text ) { + ensureTagClosed(); + m_os << m_indent << ""; + m_needsNewline = true; + return *this; + } + + void XmlWriter::writeStylesheetRef( std::string const& url ) { + m_os << "\n"; + } + + XmlWriter& XmlWriter::writeBlankLine() { + ensureTagClosed(); + m_os << '\n'; + return *this; + } + + void XmlWriter::ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + void XmlWriter::writeDeclaration() { + m_os << "\n"; + } + + void XmlWriter::newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } +} diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 2cd0b1c4..2d7e0fdc 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -12,9 +12,7 @@ #include "catch_compiler_capabilities.h" #include -#include #include -#include namespace Catch { @@ -22,55 +20,11 @@ namespace Catch { public: enum ForWhat { ForTextNodes, ForAttributes }; - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) - : m_str( str ), - m_forWhat( forWhat ) - {} + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); - void encodeTo( std::ostream& os ) const { + void encodeTo( std::ostream& os ) const; - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: http://www.w3.org/TR/xml/#syntax) - - for( std::size_t i = 0; i < m_str.size(); ++ i ) { - char c = m_str[i]; - switch( c ) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: http://www.w3.org/TR/xml/#syntax - if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) - os << ">"; - else - os << c; - break; - - case '\"': - if( m_forWhat == ForAttributes ) - os << """; - else - os << c; - break; - - default: - // Escape control chars - based on contribution by @espenalb in PR #465 and - // by @mrpi PR #588 - if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { - // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast( c ); - } - else - os << c; - } - } - } - - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); private: std::string m_str; @@ -82,24 +36,13 @@ namespace Catch { class ScopedElement { public: - ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} + ScopedElement( XmlWriter* writer ); - ScopedElement( ScopedElement const& other ) - : m_writer( other.m_writer ){ - other.m_writer = nullptr; - } + ScopedElement( ScopedElement const& other ); - ~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } + ~ScopedElement(); - ScopedElement& writeText( std::string const& text, bool indent = true ) { - m_writer->writeText( text, indent ); - return *this; - } + ScopedElement& writeText( std::string const& text, bool indent = true ); template ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { @@ -111,57 +54,21 @@ namespace Catch { mutable XmlWriter* m_writer; }; - XmlWriter( std::ostream& os = Catch::cout() ) : m_os( os ) - { - writeDeclaration(); - } + XmlWriter( std::ostream& os = Catch::cout() ); + ~XmlWriter(); + + XmlWriter( XmlWriter const& ) = delete; + XmlWriter& operator=( XmlWriter const& ) = delete; - ~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } + XmlWriter& startElement( std::string const& name ); - XmlWriter& startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } + ScopedElement scopedElement( std::string const& name ); - ScopedElement scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } + XmlWriter& endElement(); - XmlWriter& endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } + XmlWriter& writeAttribute( std::string const& name, bool attribute ); template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { @@ -171,56 +78,21 @@ namespace Catch { return writeAttribute( name, m_oss.str() ); } - XmlWriter& writeText( std::string const& text, bool indent = true ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } + XmlWriter& writeText( std::string const& text, bool indent = true ); - XmlWriter& writeComment( std::string const& text ) { - ensureTagClosed(); - m_os << m_indent << ""; - m_needsNewline = true; - return *this; - } + XmlWriter& writeComment( std::string const& text ); - void writeStylesheetRef( std::string const& url ) { - m_os << "\n"; - } + void writeStylesheetRef( std::string const& url ); - XmlWriter& writeBlankLine() { - ensureTagClosed(); - m_os << '\n'; - return *this; - } + XmlWriter& writeBlankLine(); - void ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } + void ensureTagClosed(); private: - XmlWriter( XmlWriter const& ); - void operator=( XmlWriter const& ); - void writeDeclaration() { - m_os << "\n"; - } + void writeDeclaration(); - void newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } + void newlineIfNecessary(); bool m_tagIsOpen = false; bool m_needsNewline = false; diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp index 49d913bf..c993c468 100644 --- a/include/reporters/catch_reporter_junit.cpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -15,6 +15,8 @@ #include +#include + namespace Catch { namespace { diff --git a/include/reporters/catch_reporter_multi.cpp b/include/reporters/catch_reporter_multi.cpp index d16b9ba3..d2650bea 100644 --- a/include/reporters/catch_reporter_multi.cpp +++ b/include/reporters/catch_reporter_multi.cpp @@ -6,119 +6,86 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "../internal/catch_interfaces_reporter.h" - + #include "catch_reporter_multi.h" + namespace Catch { -class MultipleReporters : public IStreamingReporter { - typedef std::vector Reporters; - Reporters m_reporters; - -public: - void add( IStreamingReporterPtr&& reporter ) { + void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { m_reporters.push_back( std::move( reporter ) ); } -public: // IStreamingReporter - - virtual ReporterPreferences getPreferences() const override { + ReporterPreferences MultipleReporters::getPreferences() const { return m_reporters[0]->getPreferences(); } - virtual void noMatchingTestCases( std::string const& spec ) override { + void MultipleReporters::noMatchingTestCases( std::string const& spec ) { for( auto const& reporter : m_reporters ) reporter->noMatchingTestCases( spec ); } - virtual void testRunStarting( TestRunInfo const& testRunInfo ) override { + void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { for( auto const& reporter : m_reporters ) reporter->testRunStarting( testRunInfo ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) override { + void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) { for( auto const& reporter : m_reporters ) reporter->testGroupStarting( groupInfo ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) override { + void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) { for( auto const& reporter : m_reporters ) reporter->testCaseStarting( testInfo ); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) override { + void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) { for( auto const& reporter : m_reporters ) reporter->sectionStarting( sectionInfo ); } - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) override { + void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) { for( auto const& reporter : m_reporters ) reporter->assertionStarting( assertionInfo ); } - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) override { + bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) { bool clearBuffer = false; for( auto const& reporter : m_reporters ) clearBuffer |= reporter->assertionEnded( assertionStats ); return clearBuffer; } - virtual void sectionEnded( SectionStats const& sectionStats ) override { + void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) { for( auto const& reporter : m_reporters ) reporter->sectionEnded( sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { + void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) { for( auto const& reporter : m_reporters ) reporter->testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { + void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) { for( auto const& reporter : m_reporters ) reporter->testGroupEnded( testGroupStats ); } - virtual void testRunEnded( TestRunStats const& testRunStats ) override { + void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) { for( auto const& reporter : m_reporters ) reporter->testRunEnded( testRunStats ); } - virtual void skipTest( TestCaseInfo const& testInfo ) override { + void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) { for( auto const& reporter : m_reporters ) reporter->skipTest( testInfo ); } - virtual bool isMulti() const override { + bool MultipleReporters::isMulti() const { return true; } -}; - -void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { - - if( !existingReporter ) { - existingReporter = std::move( additionalReporter ); - return; - } - - MultipleReporters* multi = nullptr; - - if( existingReporter->isMulti() ) { - multi = static_cast( existingReporter.get() ); - } - else { - auto newMulti = std::unique_ptr( new MultipleReporters ); - newMulti->add( std::move( existingReporter ) ); - multi = newMulti.get(); - existingReporter = std::move( newMulti ); - } - multi->add( std::move( additionalReporter ) ); -} - - } // end namespace Catch diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_multi.h new file mode 100644 index 00000000..047bb110 --- /dev/null +++ b/include/reporters/catch_reporter_multi.h @@ -0,0 +1,57 @@ +/* + * Created by Martin on 19/07/2017. + * + * 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) + */ + +#include "../internal/catch_interfaces_reporter.h" + +namespace Catch { + + class MultipleReporters : public IStreamingReporter { + typedef std::vector Reporters; + Reporters m_reporters; + + public: + void add( IStreamingReporterPtr&& reporter ); + + public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const override; + + virtual void noMatchingTestCases( std::string const& spec ) override; + + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) override; + + virtual void testGroupStarting( GroupInfo const& groupInfo ) override; + + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) override; + + virtual void sectionStarting( SectionInfo const& sectionInfo ) override; + + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) override; + + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) override; + + virtual void sectionEnded( SectionStats const& sectionStats ) override; + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override; + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override; + + virtual void testRunEnded( TestRunStats const& testRunStats ) override; + + + virtual void skipTest( TestCaseInfo const& testInfo ) override; + + virtual bool isMulti() const override; + + }; + +} // end namespace Catch From efd79aa0bdeb7d02be2d9b3db01685c7f0467568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 19 Jul 2017 21:30:00 +0200 Subject: [PATCH 140/398] Extend exception type in _THROWS_ with const& unconditionally Potentially breaking change, but most people apparently were using it wrong and thus it won't be breaking for them. Closes #955 --- include/internal/catch_capture.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 9a7714cc..1c862505 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -130,7 +130,7 @@ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ - catch( exceptionType ) { \ + catch( exceptionType const& ) { \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ @@ -194,7 +194,7 @@ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ - catch( exceptionType ex ) { \ + catch( exceptionType const& ex ) { \ __catchResult.captureMatch( ex, matcher, #matcher ); \ } \ catch( ... ) { \ From a14bd08b2766f7c32a7d8de06e51650da5fe5451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 19 Jul 2017 21:34:06 +0200 Subject: [PATCH 141/398] Update documentation to reflect the last change --- docs/assertions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/assertions.md b/docs/assertions.md index 8c8bd198..6f390448 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -95,7 +95,7 @@ Expects that an exception (of any type) is be thrown during evaluation of the ex * **REQUIRE_THROWS_AS(** _expression_, _exception type_ **)** and * **CHECK_THROWS_AS(** _expression_, _exception type_ **)** -Expects that an exception of the _specified type_ is thrown during evaluation of the expression. Note that the _exception type_ is used verbatim and you should include (const) reference (`const&`). +Expects that an exception of the _specified type_ is thrown during evaluation of the expression. Note that the _exception type_ is extended with `const&` and you should not include it yourself. * **REQUIRE_THROWS_WITH(** _expression_, _string or string matcher_ **)** and * **CHECK_THROWS_WITH(** _expression_, _string or string matcher_ **)** From d7f754dc4934efb898e6d70e66d19302cf9a5a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 19 Jul 2017 22:21:25 +0200 Subject: [PATCH 142/398] Fix SelfTest compilation after _THROWS_ assertion change That is, changes made in efd79aa0bdeb7d02be2d9b3db01685c7f0467568 --- projects/SelfTest/CompilationTests.cpp | 2 +- projects/SelfTest/MatchersTests.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/projects/SelfTest/CompilationTests.cpp b/projects/SelfTest/CompilationTests.cpp index 3298c79e..e6c31f65 100644 --- a/projects/SelfTest/CompilationTests.cpp +++ b/projects/SelfTest/CompilationTests.cpp @@ -41,7 +41,7 @@ bool templated_tests(T t) { REQUIRE(a == t); CHECK(a == t); REQUIRE_THROWS(throws_int(true)); - CHECK_THROWS_AS(throws_int(true), const int&); + CHECK_THROWS_AS(throws_int(true), int); REQUIRE_NOTHROW(throws_int(false)); REQUIRE_THAT("aaa", Catch::EndsWith("aaa")); return true; diff --git a/projects/SelfTest/MatchersTests.cpp b/projects/SelfTest/MatchersTests.cpp index 5984eb3a..a4f8a45f 100644 --- a/projects/SelfTest/MatchersTests.cpp +++ b/projects/SelfTest/MatchersTests.cpp @@ -205,21 +205,21 @@ public: TEST_CASE( "Exception matchers that succeed", "[matchers][exceptions][!throws]" ) { - CHECK_THROWS_MATCHES(throws(1), SpecialException const&, ExceptionMatcher{ 1 }); - REQUIRE_THROWS_MATCHES(throws(2), SpecialException const&, ExceptionMatcher{ 2 }); + CHECK_THROWS_MATCHES(throws(1), SpecialException, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(throws(2), SpecialException, ExceptionMatcher{ 2 }); } TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") { SECTION("No exception") { - CHECK_THROWS_MATCHES(doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 }); - REQUIRE_THROWS_MATCHES(doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 }); + CHECK_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{ 1 }); } SECTION("Type mismatch") { - CHECK_THROWS_MATCHES(throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 }); - REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 }); + CHECK_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 }); } SECTION("Contents are wrong") { - CHECK_THROWS_MATCHES(throws(3), SpecialException const&, ExceptionMatcher{ 1 }); - REQUIRE_THROWS_MATCHES(throws(4), SpecialException const&, ExceptionMatcher{ 1 }); + CHECK_THROWS_MATCHES(throws(3), SpecialException, ExceptionMatcher{ 1 }); + REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{ 1 }); } } From 2a586437e83885e2f60f4c0f71fee4eaf07f3436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 19 Jul 2017 23:20:30 +0200 Subject: [PATCH 143/398] Fix merge mishap (duplicated catch_reporter_multi header) --- include/reporters/catch_reporter_multi.cpp | 2 +- include/reporters/catch_reporter_multi.h | 1 + include/reporters/catch_reporter_multi.hpp | 64 ---------------------- 3 files changed, 2 insertions(+), 65 deletions(-) delete mode 100644 include/reporters/catch_reporter_multi.hpp diff --git a/include/reporters/catch_reporter_multi.cpp b/include/reporters/catch_reporter_multi.cpp index f66b5eee..b21672c3 100644 --- a/include/reporters/catch_reporter_multi.cpp +++ b/include/reporters/catch_reporter_multi.cpp @@ -18,7 +18,7 @@ namespace Catch { return m_reporters[0]->getPreferences(); } - std::set getSupportedVerbosities() { + std::set MultipleReporters::getSupportedVerbosities() { return { }; } diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_multi.h index 047bb110..ab6d5077 100644 --- a/include/reporters/catch_reporter_multi.h +++ b/include/reporters/catch_reporter_multi.h @@ -22,6 +22,7 @@ namespace Catch { virtual void noMatchingTestCases( std::string const& spec ) override; + static std::set getSupportedVerbosities(); virtual void testRunStarting( TestRunInfo const& testRunInfo ) override; diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp deleted file mode 100644 index 59359240..00000000 --- a/include/reporters/catch_reporter_multi.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Created by Phil on 5/08/2015. - * Copyright 2015 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) - */ -#ifndef TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED - -#include "../internal/catch_interfaces_reporter.h" - -namespace Catch { - -class MultipleReporters : public IStreamingReporter { - typedef std::vector Reporters; - Reporters m_reporters; - -public: - void add( IStreamingReporterPtr&& reporter ); - -public: // IStreamingReporter - - virtual ReporterPreferences getPreferences() const override; - - static std::set getSupportedVerbosities(); - - virtual void noMatchingTestCases( std::string const& spec ) override; - - - virtual void testRunStarting( TestRunInfo const& testRunInfo ) override; - - virtual void testGroupStarting( GroupInfo const& groupInfo ) override; - - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) override; - - virtual void sectionStarting( SectionInfo const& sectionInfo ) override; - - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) override; - - - // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) override; - - virtual void sectionEnded( SectionStats const& sectionStats ) override; - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override; - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override; - - virtual void testRunEnded( TestRunStats const& testRunStats ) override; - - - virtual void skipTest( TestCaseInfo const& testInfo ) override; - - virtual bool isMulti() const override; - -}; - -} // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED From 87a66b84792a6f884a224053804c8786b546c977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 20 Jul 2017 00:27:28 +0200 Subject: [PATCH 144/398] Address results of PVS-Studio static analysis Couple are left un-addressed, see #958 for details. --- CMakeLists.txt | 1 + include/internal/catch_assertionresult.h | 2 +- include/internal/catch_console_colour.cpp | 12 +- include/internal/catch_console_colour.hpp | 5 +- include/internal/catch_expression_lhs.hpp | 6 +- include/internal/catch_impl.hpp | 1 - include/internal/catch_matchers.cpp | 26 + include/internal/catch_matchers.hpp | 13 +- include/internal/catch_message.cpp | 3 - include/internal/catch_message.h | 1 - .../internal/catch_notimplemented_exception.h | 3 +- include/internal/catch_test_spec_parser.hpp | 8 +- include/internal/catch_version.cpp | 2 +- include/internal/catch_version.h | 7 +- include/internal/catch_xmlwriter.cpp | 11 +- include/internal/catch_xmlwriter.hpp | 5 +- include/reporters/catch_reporter_compact.cpp | 3 +- include/reporters/catch_reporter_console.cpp | 3 +- include/reporters/catch_reporter_tap.hpp | 3 +- .../Baselines/console.std.unapproved.txt | 1023 ++ .../Baselines/console.sw.unapproved.txt | 9169 ++++++++++++++ .../Baselines/console.swa4.unapproved.txt | 163 + .../Baselines/junit.sw.unapproved.txt | 821 ++ .../SelfTest/Baselines/xml.sw.unapproved.txt | 10082 ++++++++++++++++ 24 files changed, 21335 insertions(+), 38 deletions(-) create mode 100644 include/internal/catch_matchers.cpp create mode 100644 projects/SelfTest/Baselines/console.std.unapproved.txt create mode 100644 projects/SelfTest/Baselines/console.sw.unapproved.txt create mode 100644 projects/SelfTest/Baselines/console.swa4.unapproved.txt create mode 100644 projects/SelfTest/Baselines/junit.sw.unapproved.txt create mode 100644 projects/SelfTest/Baselines/xml.sw.unapproved.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index f427977c..32992a3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_fatal_condition.cpp ${HEADER_DIR}/internal/catch_list.cpp ${HEADER_DIR}/internal/catch_leak_detector.cpp + ${HEADER_DIR}/internal/catch_matchers.cpp ${HEADER_DIR}/internal/catch_matchers_string.cpp ${HEADER_DIR}/internal/catch_message.cpp ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index c9a08b9a..89a96298 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -48,7 +48,7 @@ namespace Catch { char const * macroName = nullptr; SourceLineInfo lineInfo; char const * capturedExpression = nullptr; - ResultDisposition::Flags resultDisposition; + ResultDisposition::Flags resultDisposition = ResultDisposition::Normal; }; struct AssertionResultData diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index 6ffe7ba5..fc6c76f2 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -17,7 +17,7 @@ namespace Catch { namespace { struct IColourImpl { - virtual ~IColourImpl() {} + virtual ~IColourImpl() = default; virtual void use( Colour::Code _colourCode ) = 0; }; @@ -178,8 +178,14 @@ namespace Catch { namespace Catch { - Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } - Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::Colour( Code _colourCode ) { use( _colourCode ); } + Colour::Colour( Colour&& _other ) { const_cast( _other ).m_moved = true; } + Colour& Colour::operator=( Colour&& _other ) { + m_moved = false; + const_cast( _other ).m_moved = true; + return *this; + } + Colour::~Colour(){ if( !m_moved ) use( None ); } void Colour::use( Code _colourCode ) { diff --git a/include/internal/catch_console_colour.hpp b/include/internal/catch_console_colour.hpp index 7122decc..6b5b8fa6 100644 --- a/include/internal/catch_console_colour.hpp +++ b/include/internal/catch_console_colour.hpp @@ -50,14 +50,15 @@ namespace Catch { // Use constructed object for RAII guard Colour( Code _colourCode ); - Colour( Colour const& other ); + Colour( Colour&& other ); + Colour& operator=( Colour&& other ); ~Colour(); // Use static method for one-shot changes static void use( Code _colourCode ); private: - bool m_moved; + bool m_moved = false; }; std::ostream& operator << ( std::ostream& os, Colour const& ); diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 6173401b..dc32fff7 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -27,7 +27,8 @@ class ExpressionLhs : public DecomposedExpression { public: ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} - ExpressionLhs& operator = ( const ExpressionLhs& ); + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs& operator = ( const ExpressionLhs& ) = delete; template BinaryExpression @@ -107,7 +108,8 @@ public: BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} - BinaryExpression& operator = ( BinaryExpression& ); + BinaryExpression( BinaryExpression const& ) = default; + BinaryExpression& operator = ( BinaryExpression const& ) = delete; void endExpression() const { m_rb diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index aa196c2d..03fa6e46 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -58,7 +58,6 @@ namespace Catch { IRunner::~IRunner() {} IMutableContext::~IMutableContext() {} IConfig::~IConfig() {} - Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} void Config::dummy() {} } diff --git a/include/internal/catch_matchers.cpp b/include/internal/catch_matchers.cpp new file mode 100644 index 00000000..38ae8c77 --- /dev/null +++ b/include/internal/catch_matchers.cpp @@ -0,0 +1,26 @@ +/* + * Created by Phil Nash on 19/07/2017. + * + * 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) + */ + +#include "catch_matchers.hpp" + +namespace Catch { +namespace Matchers { + namespace Impl { + + std::string MatcherUntypedBase::toString() const { + if( m_cachedToString.empty() ) + m_cachedToString = describe(); + return m_cachedToString; + } + + } // namespace Impl +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 8131b225..2083db73 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -22,18 +22,15 @@ namespace Matchers { class MatcherUntypedBase { public: - std::string toString() const { - if( m_cachedToString.empty() ) - m_cachedToString = describe(); - return m_cachedToString; - } + MatcherUntypedBase() = default; + MatcherUntypedBase ( MatcherUntypedBase const& ) = default; + MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; + std::string toString() const; protected: - virtual ~MatcherUntypedBase(); + virtual ~MatcherUntypedBase() = default; virtual std::string describe() const = 0; mutable std::string m_cachedToString; - private: - MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); }; template diff --git a/include/internal/catch_message.cpp b/include/internal/catch_message.cpp index 2f474a90..a66c5271 100644 --- a/include/internal/catch_message.cpp +++ b/include/internal/catch_message.cpp @@ -48,9 +48,6 @@ namespace Catch { m_info.message = builder.m_stream.str(); getResultCapture().pushScopedMessage( m_info ); } - ScopedMessage::ScopedMessage( ScopedMessage const& other ) - : m_info( other.m_info ) - {} ScopedMessage::~ScopedMessage() { if ( !std::uncaught_exception() ){ diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h index 25d7c259..e2cc65aa 100644 --- a/include/internal/catch_message.h +++ b/include/internal/catch_message.h @@ -49,7 +49,6 @@ namespace Catch { class ScopedMessage { public: ScopedMessage( MessageBuilder const& builder ); - ScopedMessage( ScopedMessage const& other ); ~ScopedMessage(); MessageInfo m_info; diff --git a/include/internal/catch_notimplemented_exception.h b/include/internal/catch_notimplemented_exception.h index 30a60cad..e728c363 100644 --- a/include/internal/catch_notimplemented_exception.h +++ b/include/internal/catch_notimplemented_exception.h @@ -16,9 +16,8 @@ namespace Catch { { public: NotImplementedException( SourceLineInfo const& lineInfo ); - NotImplementedException( NotImplementedException const& ) {} - virtual ~NotImplementedException() noexcept {} + virtual ~NotImplementedException() noexcept = default; virtual const char* what() const noexcept; diff --git a/include/internal/catch_test_spec_parser.hpp b/include/internal/catch_test_spec_parser.hpp index 2cc44f09..3e003685 100644 --- a/include/internal/catch_test_spec_parser.hpp +++ b/include/internal/catch_test_spec_parser.hpp @@ -20,14 +20,14 @@ namespace Catch { class TestSpecParser { enum Mode{ None, Name, QuotedName, Tag, EscapedName }; - Mode m_mode; - bool m_exclusion; - std::size_t m_start, m_pos; + Mode m_mode = None; + bool m_exclusion = false; + std::size_t m_start = std::string::npos, m_pos = 0; std::string m_arg; std::vector m_escapeChars; TestSpec::Filter m_currentFilter; TestSpec m_testSpec; - ITagAliasRegistry const* m_tagAliases; + ITagAliasRegistry const* m_tagAliases = nullptr; public: TestSpecParser( ITagAliasRegistry const& tagAliases ); diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index d2f234ea..6f13d8a5 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -36,7 +36,7 @@ namespace Catch { return os; } - Version libraryVersion() { + Version const& libraryVersion() { static Version version( 2, 0, 0, "develop", 1 ); return version; } diff --git a/include/internal/catch_version.h b/include/internal/catch_version.h index 567ac253..018397f4 100644 --- a/include/internal/catch_version.h +++ b/include/internal/catch_version.h @@ -14,6 +14,8 @@ namespace Catch { // Versioning information struct Version { + Version( Version const& ) = delete; + Version& operator=( Version const& ) = delete; Version( unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber, @@ -29,12 +31,9 @@ namespace Catch { unsigned int const buildNumber; friend std::ostream& operator << ( std::ostream& os, Version const& version ); - - private: - void operator=( Version const& ); }; - Version libraryVersion(); + Version const& libraryVersion(); } #endif // TWOBLUECUBES_CATCH_VERSION_H_INCLUDED diff --git a/include/internal/catch_xmlwriter.cpp b/include/internal/catch_xmlwriter.cpp index 2ecb768c..edc1be2a 100644 --- a/include/internal/catch_xmlwriter.cpp +++ b/include/internal/catch_xmlwriter.cpp @@ -65,10 +65,19 @@ namespace Catch { : m_writer( writer ) {} - XmlWriter::ScopedElement::ScopedElement( ScopedElement const& other ) + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) : m_writer( other.m_writer ){ other.m_writer = nullptr; } + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) { + if ( m_writer ) { + m_writer->endElement(); + } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; + } + XmlWriter::ScopedElement::~ScopedElement() { if( m_writer ) diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 2d7e0fdc..4c9f5ca8 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -38,7 +38,8 @@ namespace Catch { public: ScopedElement( XmlWriter* writer ); - ScopedElement( ScopedElement const& other ); + ScopedElement( ScopedElement&& other ); + ScopedElement& operator=( ScopedElement&& other ); ~ScopedElement(); @@ -51,7 +52,7 @@ namespace Catch { } private: - mutable XmlWriter* m_writer; + mutable XmlWriter* m_writer = nullptr; }; XmlWriter( std::ostream& os = Catch::cout() ); diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp index 1b84969b..7ad9d6b0 100644 --- a/include/reporters/catch_reporter_compact.cpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -68,8 +68,9 @@ namespace Catch { private: class AssertionPrinter { - void operator= ( AssertionPrinter const& ); public: + AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; + AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ) , stats( _stats ) diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 2a176189..228abc3f 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -97,8 +97,9 @@ namespace Catch { private: class AssertionPrinter { - void operator= ( AssertionPrinter const& ); public: + AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; + AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ), stats( _stats ), diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index 0bbcd7c4..00bd017d 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -61,8 +61,9 @@ namespace Catch { private: size_t counter = 0; class AssertionPrinter { - void operator= ( AssertionPrinter const& ); public: + AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; + AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, size_t counter ) : stream( _stream ) , stats( _stats ) diff --git a/projects/SelfTest/Baselines/console.std.unapproved.txt b/projects/SelfTest/Baselines/console.std.unapproved.txt new file mode 100644 index 00000000..58571bb2 --- /dev/null +++ b/projects/SelfTest/Baselines/console.std.unapproved.txt @@ -0,0 +1,1023 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + is a host application. +Run with -? for options + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + outside assertions +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with messages: + answer := 42 + expected exception + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + inside REQUIRE_NOTHROW +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_NOTHROW( thisThrows() ) +due to unexpected exception with messages: + answer := 42 + expected exception + +------------------------------------------------------------------------------- +#835 -- errno should not be touched by Catch +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( f() == 0 ) +with expansion: + 1 == 0 + +------------------------------------------------------------------------------- +'Not' checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( false != false ) + +ConditionTests.cpp:: FAILED: + CHECK( true != true ) + +ConditionTests.cpp:: FAILED: + CHECK( !true ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( true ) + +ConditionTests.cpp:: FAILED: + CHECK( !trueValue ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( trueValue ) +with expansion: + !true + +ConditionTests.cpp:: FAILED: + CHECK( !(1 == 1) ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( 1 == 1 ) +with expansion: + !(1 == 1) + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: +explicitly with message: + to infinity and beyond + +------------------------------------------------------------------------------- +A failing expression with a non streamable type is still captured +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + CHECK( &o1 == &o2 ) +with expansion: + 0x == 0x + +TrickyTests.cpp:: FAILED: + CHECK( o1 == o2 ) +with expansion: + {?} == {?} + +------------------------------------------------------------------------------- +An unchecked exception reports the line of the last assertion +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + {Unknown expression after the reported line} +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +Contains string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "not there" + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for nothrow +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_NOTHROW( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for throwing as something else +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_AS( throwCustom(), std::exception ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + +------------------------------------------------------------------------------- +EndsWith string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "this" + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 0 ) +with expansion: + 7 == 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.11f ) ) +with expansion: + 9.1f == Approx( 9.1099996567 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.0f ) ) +with expansion: + 9.1f == Approx( 9.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 1 ) ) +with expansion: + 9.1f == Approx( 1.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 0 ) ) +with expansion: + 9.1f == Approx( 0.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi == Approx( 3.1415 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "goodbye" ) +with expansion: + "hello" == "goodbye" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hell" ) +with expansion: + "hello" == "hell" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hello1" ) +with expansion: + "hello" == "hello1" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() == 6 ) +with expansion: + 5 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( x == Approx( 1.301 ) ) +with expansion: + 1.3 == Approx( 1.301 ) + +------------------------------------------------------------------------------- +Equals string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "something else" + +------------------------------------------------------------------------------- +Exception matchers that fail + No exception +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +------------------------------------------------------------------------------- +Exception matchers that fail + Type mismatch +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +------------------------------------------------------------------------------- +Exception matchers that fail + Contents are wrong +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +------------------------------------------------------------------------------- +Expected exceptions that don't throw or unexpected exceptions fail the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisThrows(), std::string ) +due to unexpected exception with message: + expected exception + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error ) +because no exception was thrown where one was expected: + +ExceptionTests.cpp:: FAILED: + CHECK_NOTHROW( thisThrows() ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +FAIL aborts the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + This is a failure + +------------------------------------------------------------------------------- +FAIL does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + +------------------------------------------------------------------------------- +FAIL_CHECK does not abort the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + This is a failure + +MessageTests.cpp:: +warning: + This message appears in the output + +------------------------------------------------------------------------------- +INFO and WARN do not abort tests +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + this is a warning + +------------------------------------------------------------------------------- +INFO gets logged on failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message should be logged + so should this + +------------------------------------------------------------------------------- +INFO gets logged on failure, even if captured before successful assertions +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + CHECK( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message may be logged later + this message should be logged + +MessageTests.cpp:: FAILED: + CHECK( a == 0 ) +with expansion: + 2 == 0 +with messages: + this message may be logged later + this message should be logged + and this, but later + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi != Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415926535 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello != "hello" ) +with expansion: + "hello" != "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() != 5 ) +with expansion: + 5 != 5 + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || - failing +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + +------------------------------------------------------------------------------- +Nice descriptive name +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +warning: + This one ran + +------------------------------------------------------------------------------- +Non-std exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom exception + +------------------------------------------------------------------------------- +Ordering comparison checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 7 ) +with expansion: + 7 > 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 7 ) +with expansion: + 7 < 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 8 ) +with expansion: + 7 > 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 6 ) +with expansion: + 7 < 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 0 ) +with expansion: + 7 < 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < -1 ) +with expansion: + 7 < -1 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven >= 8 ) +with expansion: + 7 >= 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven <= 6 ) +with expansion: + 7 <= 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one < 9 ) +with expansion: + 9.1f < 9 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 10 ) +with expansion: + 9.1f > 10 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 9.2 ) +with expansion: + 9.1f > 9.2 + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hello" ) +with expansion: + "hello" > "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hello" ) +with expansion: + "hello" < "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hellp" ) +with expansion: + "hello" > "hellp" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "z" ) +with expansion: + "hello" > "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hellm" ) +with expansion: + "hello" < "hellm" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "a" ) +with expansion: + "hello" < "a" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello >= "z" ) +with expansion: + "hello" >= "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello <= "a" ) +with expansion: + "hello" <= "a" + +------------------------------------------------------------------------------- +Output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section one + +------------------------------------------------------------------------------- +Output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section two + +------------------------------------------------------------------------------- +Pointers can be converted to strings +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + actual address of p: 0x + +MessageTests.cpp:: +warning: + toString(p): 0x + +------------------------------------------------------------------------------- +Reconstruction should be based on stringification: #914 +------------------------------------------------------------------------------- +DecompositionTests.cpp: +............................................................................... + +DecompositionTests.cpp:: FAILED: + CHECK( truthy(false) ) +with expansion: + Hey, its truthy! + +------------------------------------------------------------------------------- +SCOPED_INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + +A string sent directly to stdout +A string sent directly to stderr +Message from section one +Message from section two +------------------------------------------------------------------------------- +StartsWith string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "string" + +hello +hello +------------------------------------------------------------------------------- +Tabs and newlines show in output +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( s1 == s2 ) +with expansion: + "if ($b == 10) { + $a = 20; + }" + == + "if ($b == 10) { + $a = 20; + } + " + +------------------------------------------------------------------------------- +Unexpected exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + 3.14 + +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (element) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, VectorContains( -1 ) ) +with expansion: + { 1, 2, 3 } Contains: -1 + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, VectorContains( 1 ) ) +with expansion: + { } Contains: 1 + +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (vector) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Contains( v) ) +with expansion: + { } Contains: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2, 4 } + +------------------------------------------------------------------------------- +Vector matchers that fail + Equals +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( v2 ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v2, Equals( v ) ) +with expansion: + { 1, 2 } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Equals( v ) ) +with expansion: + { } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( empty ) ) +with expansion: + { 1, 2, 3 } Equals: { } + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown directly they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a CHECK the test should continue +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a REQUIRE the test should abort +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from functions they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from sections they are always failures + section name +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +Where the LHS is not a simple value +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +Where there is more to the expression after the RHS +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +checkedElse, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_ELSE( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedElse( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +checkedIf, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_IF( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedIf( false ) ) +with expansion: + false + +spanner------------------------------------------------------------------------------- +just failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Previous info should not be seen + +------------------------------------------------------------------------------- +looped SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( b > a ) +with expansion: + 0 > 1 + +------------------------------------------------------------------------------- +looped tests +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[0] (1) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[1] (1) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[3] (3) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[4] (5) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[6] (13) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[7] (21) is even + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( a == b ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +send a single char to INFO +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( false ) +with message: + 3 + +------------------------------------------------------------------------------- +sends information to INFO +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( false ) +with messages: + hi + i := 7 + +------------------------------------------------------------------------------- +string literals of different sizes can be compared +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + REQUIRE( std::string( "first" ) == "second" ) +with expansion: + "first" == "second" + +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e0) == "0" ) +with expansion: + "{?}" == "0" + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e1) == "1" ) +with expansion: + "{?}" == "1" + +=============================================================================== +test cases: 186 | 135 passed | 47 failed | 4 failed as expected +assertions: 939 | 822 passed | 96 failed | 21 failed as expected + diff --git a/projects/SelfTest/Baselines/console.sw.unapproved.txt b/projects/SelfTest/Baselines/console.sw.unapproved.txt new file mode 100644 index 00000000..61e865c6 --- /dev/null +++ b/projects/SelfTest/Baselines/console.sw.unapproved.txt @@ -0,0 +1,9169 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + is a host application. +Run with -? for options + +------------------------------------------------------------------------------- +# A test name that starts with a # +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + yay + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + outside assertions +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with messages: + answer := 42 + expected exception + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + inside REQUIRE_NOTHROW +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_NOTHROW( thisThrows() ) +due to unexpected exception with messages: + answer := 42 + expected exception + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + inside REQUIRE_THROWS +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS( thisThrows() ) +with message: + answer := 42 + +------------------------------------------------------------------------------- +#809 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( 42 == f ) +with expansion: + 42 == {?} + +------------------------------------------------------------------------------- +#833 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( a == t ) +with expansion: + 3 == 3 + +CompilationTests.cpp:: +PASSED: + CHECK( a == t ) +with expansion: + 3 == 3 + +CompilationTests.cpp:: +PASSED: + REQUIRE_THROWS( throws_int(true) ) + +CompilationTests.cpp:: +PASSED: + CHECK_THROWS_AS( throws_int(true), int ) + +CompilationTests.cpp:: +PASSED: + REQUIRE_NOTHROW( throws_int(false) ) + +CompilationTests.cpp:: +PASSED: + REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") ) +with expansion: + "aaa" ends with: "aaa" + +CompilationTests.cpp:: +PASSED: + REQUIRE( templated_tests(3) ) +with expansion: + true + +------------------------------------------------------------------------------- +#835 -- errno should not be touched by Catch +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( f() == 0 ) +with expansion: + 1 == 0 + +MiscTests.cpp:: +PASSED: + REQUIRE( errno == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +#872 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( x == 4 ) +with expansion: + {?} == 4 +with message: + dummy := 0 + +------------------------------------------------------------------------------- +'Not' checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( false != false ) + +ConditionTests.cpp:: FAILED: + CHECK( true != true ) + +ConditionTests.cpp:: FAILED: + CHECK( !true ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( true ) + +ConditionTests.cpp:: FAILED: + CHECK( !trueValue ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( trueValue ) +with expansion: + !true + +ConditionTests.cpp:: FAILED: + CHECK( !(1 == 1) ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( 1 == 1 ) +with expansion: + !(1 == 1) + +------------------------------------------------------------------------------- +'Not' checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( false == false ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( true == true ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( !false ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + REQUIRE_FALSE( false ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( !falseValue ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + REQUIRE_FALSE( falseValue ) +with expansion: + !false + +ConditionTests.cpp:: +PASSED: + REQUIRE( !(1 == 2) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + REQUIRE_FALSE( 1 == 2 ) +with expansion: + !(1 == 2) + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + compare to true +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( is_true::value == true ) +with expansion: + true == true + +TrickyTests.cpp:: +PASSED: + REQUIRE( true == is_true::value ) +with expansion: + true == true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + compare to false +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( is_true::value == false ) +with expansion: + false == false + +TrickyTests.cpp:: +PASSED: + REQUIRE( false == is_true::value ) +with expansion: + false == false + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + negation +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( !is_true::value ) +with expansion: + true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + double negation +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( !!is_true::value ) +with expansion: + true + +------------------------------------------------------------------------------- +(unimplemented) static bools can be evaluated + direct +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( is_true::value ) +with expansion: + true + +TrickyTests.cpp:: +PASSED: + REQUIRE_FALSE( is_true::value ) +with expansion: + !false + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( s == "world" ) +with expansion: + "hello" == "world" + +------------------------------------------------------------------------------- +A METHOD_AS_TEST_CASE based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: +PASSED: + REQUIRE( s == "hello" ) +with expansion: + "hello" == "hello" + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that fails +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: FAILED: + REQUIRE( m_a == 2 ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +A TEST_CASE_METHOD based test run that succeeds +------------------------------------------------------------------------------- +ClassTests.cpp: +............................................................................... + +ClassTests.cpp:: +PASSED: + REQUIRE( m_a == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure + Outer + Inner +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + that's not flying - that's failing in style + +------------------------------------------------------------------------------- +A couple of nested sections followed by a failure +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: +explicitly with message: + to infinity and beyond + +------------------------------------------------------------------------------- +A failing expression with a non streamable type is still captured +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + CHECK( &o1 == &o2 ) +with expansion: + 0x == 0x + +TrickyTests.cpp:: FAILED: + CHECK( o1 == o2 ) +with expansion: + {?} == {?} + +------------------------------------------------------------------------------- +Absolute margin +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 104.0 != Approx(100.0) ) +with expansion: + 104.0 != Approx( 100.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 104.0 == Approx(100.0).margin(5) ) +with expansion: + 104.0 == Approx( 100.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 104.0 != Approx(100.0).margin(3) ) +with expansion: + 104.0 != Approx( 100.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 100.3 != Approx(100.0) ) +with expansion: + 100.3 != Approx( 100.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 100.3 == Approx(100.0).margin(0.5) ) +with expansion: + 100.3 == Approx( 100.0 ) + +------------------------------------------------------------------------------- +AllOf matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" and + contains: "abc" ) + +------------------------------------------------------------------------------- +An expression with side-effects should only be evaluated once +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( i++ == 7 ) +with expansion: + 7 == 7 + +TrickyTests.cpp:: +PASSED: + REQUIRE( i++ == 8 ) +with expansion: + 8 == 8 + +------------------------------------------------------------------------------- +An unchecked exception reports the line of the last assertion +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + CHECK( 1 == 1 ) + +ExceptionTests.cpp:: FAILED: + {Unknown expression after the reported line} +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +Anonymous test case 1 +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp: +............................................................................... + +VariadicMacrosTests.cpp:: +PASSED: +with message: + anonymous test case + +------------------------------------------------------------------------------- +AnyOf matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" or contains: + "not there" ) + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "not there" or + contains: "string" ) + +------------------------------------------------------------------------------- +Approximate PI +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ) +with expansion: + 3.1428571429 == Approx( 3.141 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ) +with expansion: + 3.1428571429 != Approx( 3.141 ) + +------------------------------------------------------------------------------- +Approximate comparisons with different epsilons +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.231 ) ) +with expansion: + 1.23 != Approx( 1.231 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ) +with expansion: + 1.23 == Approx( 1.231 ) + +------------------------------------------------------------------------------- +Approximate comparisons with floats +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.23f == Approx( 1.23f ) ) +with expansion: + 1.23f == Approx( 1.2300000191 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0.0f == Approx( 0.0f ) ) +with expansion: + 0.0f == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with ints +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1 == Approx( 1 ) ) +with expansion: + 1 == Approx( 1.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( 0 ) ) +with expansion: + 0 == Approx( 0.0 ) + +------------------------------------------------------------------------------- +Approximate comparisons with mixed numeric types +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.0f == Approx( 1 ) ) +with expansion: + 1.0f == Approx( 1.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( dZero) ) +with expansion: + 0 == Approx( 0.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ) +with expansion: + 0 == Approx( 0.00001 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( 1.234f == Approx( dMedium ) ) +with expansion: + 1.234f == Approx( 1.234 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( dMedium == Approx( 1.234f ) ) +with expansion: + 1.234 == Approx( 1.2339999676 ) + +------------------------------------------------------------------------------- +Assertions then sections +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section + Another section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Assertions then sections + A section + Another other section +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( Catch::alwaysTrue() ) +with expansion: + true + +------------------------------------------------------------------------------- +Capture and info messages + Capture should stringify like assertions +------------------------------------------------------------------------------- +ToStringGeneralTests.cpp: +............................................................................... + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( true ) +with message: + i := 2 + +------------------------------------------------------------------------------- +Capture and info messages + Info should NOT stringify the way assertions do +------------------------------------------------------------------------------- +ToStringGeneralTests.cpp: +............................................................................... + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( true ) +with message: + 3 + +------------------------------------------------------------------------------- +Character pretty printing + Specifically escaped +------------------------------------------------------------------------------- +ToStringGeneralTests.cpp: +............................................................................... + +ToStringGeneralTests.cpp:: +PASSED: + CHECK( tab == '\t' ) +with expansion: + '\t' == '\t' + +ToStringGeneralTests.cpp:: +PASSED: + CHECK( newline == '\n' ) +with expansion: + '\n' == '\n' + +ToStringGeneralTests.cpp:: +PASSED: + CHECK( carr_return == '\r' ) +with expansion: + '\r' == '\r' + +ToStringGeneralTests.cpp:: +PASSED: + CHECK( form_feed == '\f' ) +with expansion: + '\f' == '\f' + +------------------------------------------------------------------------------- +Character pretty printing + General chars +------------------------------------------------------------------------------- +ToStringGeneralTests.cpp: +............................................................................... + +ToStringGeneralTests.cpp:: +PASSED: + CHECK( space == ' ' ) +with expansion: + ' ' == ' ' + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == chars[i] ) +with expansion: + 'a' == 'a' + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == chars[i] ) +with expansion: + 'z' == 'z' + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == chars[i] ) +with expansion: + 'A' == 'A' + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == chars[i] ) +with expansion: + 'Z' == 'Z' + +------------------------------------------------------------------------------- +Character pretty printing + Low ASCII +------------------------------------------------------------------------------- +ToStringGeneralTests.cpp: +............................................................................... + +ToStringGeneralTests.cpp:: +PASSED: + CHECK( null_terminator == '\0' ) +with expansion: + 0 == 0 + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == i ) +with expansion: + 2 == 2 + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == i ) +with expansion: + 3 == 3 + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == i ) +with expansion: + 4 == 4 + +ToStringGeneralTests.cpp:: +PASSED: + REQUIRE( c == i ) +with expansion: + 5 == 5 + +------------------------------------------------------------------------------- +Commas in various macros are allowed +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ) + +TrickyTests.cpp:: +PASSED: + CHECK_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ) + +TrickyTests.cpp:: +PASSED: + REQUIRE_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ) + +TrickyTests.cpp:: +PASSED: + CHECK_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ) + +TrickyTests.cpp:: +PASSED: + REQUIRE( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + CHECK( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + REQUIRE_FALSE( std::vector{1, 2} == std::vector{1, 2, 3} ) +with expansion: + !({ 1, 2 } == { 1, 2, 3 }) + +TrickyTests.cpp:: +PASSED: + CHECK_FALSE( std::vector{1, 2} == std::vector{1, 2, 3} ) +with expansion: + !({ 1, 2 } == { 1, 2, 3 }) + +TrickyTests.cpp:: +PASSED: + CHECK_NOFAIL( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + CHECKED_IF( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +TrickyTests.cpp:: +PASSED: + REQUIRE( true ) + +TrickyTests.cpp:: +PASSED: + CHECKED_ELSE( std::vector{1, 2} == std::vector{1, 2} ) +with expansion: + { 1, 2 } == { 1, 2 } + +------------------------------------------------------------------------------- +Comparing function pointers +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( a ) +with expansion: + 0x + +TrickyTests.cpp:: +PASSED: + REQUIRE( a == &foo ) +with expansion: + 0x == 0x + +------------------------------------------------------------------------------- +Comparing member function pointers +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + CHECK( m == &S::f ) +with expansion: + 0x + == + 0x + +------------------------------------------------------------------------------- +Comparison with explicitly convertible types +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( td == Approx(10.0) ) +with expansion: + StrongDoubleTypedef(10) == Approx( 10.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(10.0) == td ) +with expansion: + Approx( 10.0 ) == StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td != Approx(11.0) ) +with expansion: + StrongDoubleTypedef(10) != Approx( 11.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(11.0) != td ) +with expansion: + Approx( 11.0 ) != StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td <= Approx(10.0) ) +with expansion: + StrongDoubleTypedef(10) <= Approx( 10.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td <= Approx(11.0) ) +with expansion: + StrongDoubleTypedef(10) <= Approx( 11.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(10.0) <= td ) +with expansion: + Approx( 10.0 ) <= StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(9.0) <= td ) +with expansion: + Approx( 9.0 ) <= StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td >= Approx(9.0) ) +with expansion: + StrongDoubleTypedef(10) >= Approx( 9.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( td >= Approx(10.0) ) +with expansion: + StrongDoubleTypedef(10) >= Approx( 10.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(10.0) >= td ) +with expansion: + Approx( 10.0 ) >= StrongDoubleTypedef(10) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx(11.0) >= td ) +with expansion: + Approx( 11.0 ) >= StrongDoubleTypedef(10) + +------------------------------------------------------------------------------- +Comparisons between ints where one side is computed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + CHECK( 54 == 6*9 ) +with expansion: + 54 == 54 + +------------------------------------------------------------------------------- +Comparisons between unsigned ints and negative signed ints match c++ standard +behaviour +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + CHECK( ( -1 > 2u ) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + CHECK( -1 > 2u ) +with expansion: + -1 > 2 + +ConditionTests.cpp:: +PASSED: + CHECK( ( 2u < -1 ) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + CHECK( 2u < -1 ) +with expansion: + 2 < -1 + +ConditionTests.cpp:: +PASSED: + CHECK( ( minInt > 2u ) ) +with expansion: + true + +ConditionTests.cpp:: +PASSED: + CHECK( minInt > 2u ) +with expansion: + -2147483648 > 2 + +------------------------------------------------------------------------------- +Comparisons with int literals don't warn when mixing signed/ unsigned +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( i == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( ui == 2 ) +with expansion: + 2 == 2 + +ConditionTests.cpp:: +PASSED: + REQUIRE( l == 3 ) +with expansion: + 3 == 3 + +ConditionTests.cpp:: +PASSED: + REQUIRE( ul == 4 ) +with expansion: + 4 == 4 + +ConditionTests.cpp:: +PASSED: + REQUIRE( c == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:: +PASSED: + REQUIRE( uc == 6 ) +with expansion: + 6 == 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 1 == i ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 2 == ui ) +with expansion: + 2 == 2 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 3 == l ) +with expansion: + 3 == 3 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 4 == ul ) +with expansion: + 4 == 4 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 5 == c ) +with expansion: + 5 == 5 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 6 == uc ) +with expansion: + 6 == 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( (std::numeric_limits::max)() > ul ) +with expansion: + 18446744073709551615 (0x) + > + 4 + +------------------------------------------------------------------------------- +Contains string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "not there" + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for nothrow +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_NOTHROW( throwCustom() ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom exceptions can be translated when testing for throwing as something else +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_AS( throwCustom(), std::exception ) +due to unexpected exception with message: + custom exception - not std + +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + +------------------------------------------------------------------------------- +Demonstrate that a non-const == is not used +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( t == 1u ) +with expansion: + {?} == 1 + +------------------------------------------------------------------------------- +EndsWith string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "this" + +------------------------------------------------------------------------------- +Equality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 6 ) +with expansion: + 7 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 8 ) +with expansion: + 7 == 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven == 0 ) +with expansion: + 7 == 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.11f ) ) +with expansion: + 9.1f == Approx( 9.1099996567 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 9.0f ) ) +with expansion: + 9.1f == Approx( 9.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 1 ) ) +with expansion: + 9.1f == Approx( 1.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one == Approx( 0 ) ) +with expansion: + 9.1f == Approx( 0.0 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi == Approx( 3.1415 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "goodbye" ) +with expansion: + "hello" == "goodbye" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hell" ) +with expansion: + "hello" == "hell" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello == "hello1" ) +with expansion: + "hello" == "hello1" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() == 6 ) +with expansion: + 5 == 6 + +ConditionTests.cpp:: FAILED: + CHECK( x == Approx( 1.301 ) ) +with expansion: + 1.3 == Approx( 1.301 ) + +------------------------------------------------------------------------------- +Equality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven == 7 ) +with expansion: + 7 == 7 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ) +with expansion: + 9.1f == Approx( 9.1000003815 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.double_pi == Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 == Approx( 3.1415926535 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello == "hello" ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( "hello" == data.str_hello ) +with expansion: + "hello" == "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello.size() == 5 ) +with expansion: + 5 == 5 + +ConditionTests.cpp:: +PASSED: + REQUIRE( x == Approx( 1.3 ) ) +with expansion: + 1.3 == Approx( 1.3 ) + +------------------------------------------------------------------------------- +Equals +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "this string contains + 'abc' as a substring" + +------------------------------------------------------------------------------- +Equals string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) +with expansion: + "this string contains 'abc' as a substring" equals: "something else" + +------------------------------------------------------------------------------- +Exception matchers that fail + No exception +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) +because no exception was thrown where one was expected: + +------------------------------------------------------------------------------- +Exception matchers that fail + Type mismatch +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) +due to unexpected exception with message: + Unknown exception + +------------------------------------------------------------------------------- +Exception matchers that fail + Contents are wrong +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +MatchersTests.cpp:: FAILED: + REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +------------------------------------------------------------------------------- +Exception matchers that succeed +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THROWS_MATCHES( throws(1), SpecialException, ExceptionMatcher{ 1 } ) +with expansion: + {?} special exception has value of 1 + +MatchersTests.cpp:: +PASSED: + REQUIRE_THROWS_MATCHES( throws(2), SpecialException, ExceptionMatcher{ 2 } ) +with expansion: + {?} special exception has value of 2 + +------------------------------------------------------------------------------- +Exception messages can be tested for + exact match +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + different case +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + wildcarded +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) + +------------------------------------------------------------------------------- +Expected exceptions that don't throw or unexpected exceptions fail the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisThrows(), std::string ) +due to unexpected exception with message: + expected exception + +ExceptionTests.cpp:: FAILED: + CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error ) +because no exception was thrown where one was expected: + +ExceptionTests.cpp:: FAILED: + CHECK_NOTHROW( thisThrows() ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +FAIL aborts the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + This is a failure + +------------------------------------------------------------------------------- +FAIL does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + +------------------------------------------------------------------------------- +FAIL_CHECK does not abort the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + This is a failure + +MessageTests.cpp:: +warning: + This message appears in the output + +------------------------------------------------------------------------------- +Factorials are computed +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(0) == 1 ) +with expansion: + 1 == 1 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(1) == 1 ) +with expansion: + 1 == 1 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(2) == 2 ) +with expansion: + 2 == 2 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(3) == 6 ) +with expansion: + 6 == 6 + +MiscTests.cpp:: +PASSED: + REQUIRE( Factorial(10) == 3628800 ) +with expansion: + 3628800 (0x) == 3628800 (0x) + +------------------------------------------------------------------------------- +Greater-than inequalities with different epsilons +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d >= Approx( 1.22 ) ) +with expansion: + 1.23 >= Approx( 1.22 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d >= Approx( 1.23 ) ) +with expansion: + 1.23 >= Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE_FALSE( d >= Approx( 1.24 ) ) +with expansion: + !(1.23 >= Approx( 1.24 )) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) ) +with expansion: + 1.23 >= Approx( 1.24 ) + +------------------------------------------------------------------------------- +INFO and WARN do not abort tests +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + this is a message + this is a warning + +------------------------------------------------------------------------------- +INFO gets logged on failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message should be logged + so should this + +------------------------------------------------------------------------------- +INFO gets logged on failure, even if captured before successful assertions +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: + CHECK( a == 2 ) +with expansion: + 2 == 2 +with message: + this message may be logged later + +MessageTests.cpp:: FAILED: + CHECK( a == 1 ) +with expansion: + 2 == 1 +with messages: + this message may be logged later + this message should be logged + +MessageTests.cpp:: FAILED: + CHECK( a == 0 ) +with expansion: + 2 == 0 +with messages: + this message may be logged later + this message should be logged + and this, but later + +MessageTests.cpp:: +PASSED: + CHECK( a == 2 ) +with expansion: + 2 == 2 +with messages: + this message may be logged later + this message should be logged + and this, but later + but not this + +------------------------------------------------------------------------------- +Inequality checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven != 7 ) +with expansion: + 7 != 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one != Approx( 9.1f ) ) +with expansion: + 9.1f != Approx( 9.1000003815 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.double_pi != Approx( 3.1415926535 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415926535 ) + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello != "hello" ) +with expansion: + "hello" != "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello.size() != 5 ) +with expansion: + 5 != 5 + +------------------------------------------------------------------------------- +Inequality checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven != 6 ) +with expansion: + 7 != 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven != 8 ) +with expansion: + 7 != 8 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ) +with expansion: + 9.1f != Approx( 9.1099996567 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ) +with expansion: + 9.1f != Approx( 9.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 1 ) ) +with expansion: + 9.1f != Approx( 1.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one != Approx( 0 ) ) +with expansion: + 9.1f != Approx( 0.0 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.double_pi != Approx( 3.1415 ) ) +with expansion: + 3.1415926535 != Approx( 3.1415 ) + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "goodbye" ) +with expansion: + "hello" != "goodbye" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "hell" ) +with expansion: + "hello" != "hell" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello != "hello1" ) +with expansion: + "hello" != "hello1" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello.size() != 6 ) +with expansion: + 5 != 6 + +------------------------------------------------------------------------------- +Less-than inequalities with different epsilons +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d <= Approx( 1.24 ) ) +with expansion: + 1.23 <= Approx( 1.24 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d <= Approx( 1.23 ) ) +with expansion: + 1.23 <= Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE_FALSE( d <= Approx( 1.22 ) ) +with expansion: + !(1.23 <= Approx( 1.22 )) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) ) +with expansion: + 1.23 <= Approx( 1.22 ) + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + No wrapping +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) +with expansion: + "one two three four" + == + "one two three four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) +with expansion: + "one two three four" + == + "one two three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped once +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ) +with expansion: + "one two three + four" + == + "one two three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ) +with expansion: + "one two + three four" + == + "one two + three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped twice +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Wrapped three times +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Short wrap +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ) +with expansion: + "abc- + def" + == + "abc- + def" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ) +with expansion: + "abc- + defg" + == + "abc- + defg" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ) +with expansion: + "abc- + def- + gh" + == + "abc- + def- + gh" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ) +with expansion: + "one + two + thr- + ee + four" + == + "one + two + thr- + ee + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ) +with expansion: + "one + two + th- + ree + fo- + ur" + == + "one + two + th- + ree + fo- + ur" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + As container +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + REQUIRE( text.size() == 4 ) +with expansion: + 4 == 4 + +TestMain.cpp:: +PASSED: + CHECK( text[0] == "one" ) +with expansion: + "one" == "one" + +TestMain.cpp:: +PASSED: + CHECK( text[1] == "two" ) +with expansion: + "two" == "two" + +TestMain.cpp:: +PASSED: + CHECK( text[2] == "three" ) +with expansion: + "three" == "three" + +TestMain.cpp:: +PASSED: + CHECK( text[3] == "four" ) +with expansion: + "four" == "four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + plain string + Indent first line differently +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( text.toString() == " one two\n three\n four" ) +with expansion: + " one two + three + four" + == + " one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + No wrapping +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ) +with expansion: + "one two + three four" + == + "one two + three four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Trailing newline +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" ) +with expansion: + "abcdef" == "abcdef" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) +with expansion: + "abcdef" == "abcdef" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) +with expansion: + "abcdef" == "abcdef" + +TestMain.cpp:: +PASSED: + CHECK( Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" ) +with expansion: + "abcd- + ef" + == + "abcd- + ef" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Wrapped once +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) +with expansion: + "one two + three + four" + == + "one two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With newlines + Wrapped twice +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) +with expansion: + "one + two + three + four" + == + "one + two + three + four" + +------------------------------------------------------------------------------- +Long strings can be wrapped + With wrap-before/ after characters + No wrapping +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) +with expansion: + "one,two(three) " + == + "one,two(three) " + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString ) +with expansion: + "one,two(three) " + == + "one,two(three) " + +------------------------------------------------------------------------------- +Long strings can be wrapped + With wrap-before/ after characters + Wrap before +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n" ) +with expansion: + "one,two + (three) + " + == + "one,two + (three) + " + +------------------------------------------------------------------------------- +Long strings can be wrapped + With wrap-before/ after characters + Wrap after +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n" ) +with expansion: + "one, + two + (thre- + e) + " + == + "one, + two + (thre- + e) + " + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n" ) +with expansion: + "one, + two + (thr- + ee) + " + == + "one, + two + (thr- + ee) + " + +TestMain.cpp:: +PASSED: + CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n" ) +with expansion: + "one, + two + (th- + ree) + " + == + "one, + two + (th- + ree) + " + +------------------------------------------------------------------------------- +Long text is truncated +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ) +with expansion: + "***************************************************************************- + ***- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ + ****************************************************************************- + **- + ****************************************************************************- + **- + ************************ +... message truncated due to excessive size + +------------------------------------------------------------------------------- +ManuallyRegistered +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: +with message: + was called + +------------------------------------------------------------------------------- +Matchers can be (AllOf) composed with the && operator +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" and + contains: "abc" and contains: "substring" and contains: "contains" ) + +------------------------------------------------------------------------------- +Matchers can be (AnyOf) composed with the || operator +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" or contains: + "different" or contains: "random" ) + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "some completely different text that contains one common word" ( contains: + "string" or contains: "different" or contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "substring" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both && and || - failing +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), !Contains( "different" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "different" + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + +------------------------------------------------------------------------------- +Nice descriptive name +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +warning: + This one ran + +------------------------------------------------------------------------------- +Non-std exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom exception + +------------------------------------------------------------------------------- +Objects that evaluated in boolean contexts can be checked +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + CHECK( True ) +with expansion: + {?} + +TrickyTests.cpp:: +PASSED: + CHECK( !False ) +with expansion: + true + +TrickyTests.cpp:: +PASSED: + CHECK_FALSE( False ) +with expansion: + !{?} + +------------------------------------------------------------------------------- +Operators at different namespace levels not hijacked by Koenig lookup +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( 0x == o ) +with expansion: + 3221225472 (0x) == {?} + +------------------------------------------------------------------------------- +Ordering comparison checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 7 ) +with expansion: + 7 > 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 7 ) +with expansion: + 7 < 7 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven > 8 ) +with expansion: + 7 > 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 6 ) +with expansion: + 7 < 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < 0 ) +with expansion: + 7 < 0 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven < -1 ) +with expansion: + 7 < -1 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven >= 8 ) +with expansion: + 7 >= 8 + +ConditionTests.cpp:: FAILED: + CHECK( data.int_seven <= 6 ) +with expansion: + 7 <= 6 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one < 9 ) +with expansion: + 9.1f < 9 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 10 ) +with expansion: + 9.1f > 10 + +ConditionTests.cpp:: FAILED: + CHECK( data.float_nine_point_one > 9.2 ) +with expansion: + 9.1f > 9.2 + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hello" ) +with expansion: + "hello" > "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hello" ) +with expansion: + "hello" < "hello" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "hellp" ) +with expansion: + "hello" > "hellp" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello > "z" ) +with expansion: + "hello" > "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "hellm" ) +with expansion: + "hello" < "hellm" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello < "a" ) +with expansion: + "hello" < "a" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello >= "z" ) +with expansion: + "hello" >= "z" + +ConditionTests.cpp:: FAILED: + CHECK( data.str_hello <= "a" ) +with expansion: + "hello" <= "a" + +------------------------------------------------------------------------------- +Ordering comparison checks that should succeed +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven < 8 ) +with expansion: + 7 < 8 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven > 6 ) +with expansion: + 7 > 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven > 0 ) +with expansion: + 7 > 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven > -1 ) +with expansion: + 7 > -1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven >= 7 ) +with expansion: + 7 >= 7 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven >= 6 ) +with expansion: + 7 >= 6 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven <= 7 ) +with expansion: + 7 <= 7 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.int_seven <= 8 ) +with expansion: + 7 <= 8 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one > 9 ) +with expansion: + 9.1f > 9 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one < 10 ) +with expansion: + 9.1f < 10 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.float_nine_point_one < 9.2 ) +with expansion: + 9.1f < 9.2 + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello <= "hello" ) +with expansion: + "hello" <= "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello >= "hello" ) +with expansion: + "hello" >= "hello" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello < "hellp" ) +with expansion: + "hello" < "hellp" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello < "zebra" ) +with expansion: + "hello" < "zebra" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello > "hellm" ) +with expansion: + "hello" > "hellm" + +ConditionTests.cpp:: +PASSED: + REQUIRE( data.str_hello > "a" ) +with expansion: + "hello" > "a" + +------------------------------------------------------------------------------- +Output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section one + +------------------------------------------------------------------------------- +Output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Message from section two + +------------------------------------------------------------------------------- +Parse test names and tags + Empty test spec should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from empty string should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches(tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from just a comma should have no filters +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from quoted name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Test spec from name should have one filter +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at the start +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at the end +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at both ends +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at the start +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at the end +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Redundant wildcard at both ends +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcard at both ends, redundant at start +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Just wildcard +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag, two matches +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Two tags +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Two tags, spare separated +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + Wildcarded name and tag +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + Single tag exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion and one tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion and one wldcarded name inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + One tag exclusion, using exclude:, and one wldcarded name inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + name exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion with tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + wildcarded name exclusion, using exclude:, with tag inclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + two wildcarded names +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + empty tag +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + empty quoted name +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Parse test names and tags + quoted string followed by tag exclusion +------------------------------------------------------------------------------- +CmdLineTests.cpp: +............................................................................... + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.hasFilters() == true ) +with expansion: + true == true + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcA ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcB ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcC ) == false ) +with expansion: + false == false + +CmdLineTests.cpp:: +PASSED: + CHECK( spec.matches( tcD ) == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Parsing a std::pair +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( (std::pair( 1, 2 )) == aNicePair ) +with expansion: + { 1, 2 } == { 1, 2 } + +------------------------------------------------------------------------------- +Pointers can be compared to null +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( p == 0 ) +with expansion: + 0 == 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( p == pNULL ) +with expansion: + 0 == 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( p != 0 ) +with expansion: + 0x != 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( cp != 0 ) +with expansion: + 0x != 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( cpc != 0 ) +with expansion: + 0x != 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( returnsNull() == 0 ) +with expansion: + {null string} == 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( returnsConstNull() == 0 ) +with expansion: + {null string} == 0 + +ConditionTests.cpp:: +PASSED: + REQUIRE( 0 != p ) +with expansion: + 0 != 0x + +------------------------------------------------------------------------------- +Pointers can be converted to strings +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +warning: + actual address of p: 0x + +MessageTests.cpp:: +warning: + toString(p): 0x + +------------------------------------------------------------------------------- +Process can be configured on command line + empty args don't cause a crash +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( result ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + CHECK( config.processName == "" ) +with expansion: + "" == "" + +------------------------------------------------------------------------------- +Process can be configured on command line + default - no arguments +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( result ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + CHECK( config.processName == "test" ) +with expansion: + "test" == "test" + +TestMain.cpp:: +PASSED: + CHECK( config.shouldDebugBreak == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + CHECK( config.abortAfter == -1 ) +with expansion: + -1 == -1 + +TestMain.cpp:: +PASSED: + CHECK( config.noThrow == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + CHECK( config.reporterNames.empty() ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + 1 test +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( result ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches(fakeTestCase("notIncluded")) == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + Specify one test case exclusion using exclude: +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( result ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + test lists + Specify one test case exclusion using ~ +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( result ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false ) +with expansion: + false == false + +TestMain.cpp:: +PASSED: + REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r/console +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-r", "console"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "console" ) +with expansion: + "console" == "console" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r/xml +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-r", "xml"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "xml" ) +with expansion: + "xml" == "xml" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r xml and junit +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-r", "xml", "-r", "junit"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames.size() == 2 ) +with expansion: + 2 == 2 + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "xml" ) +with expansion: + "xml" == "xml" + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[1] == "junit" ) +with expansion: + "junit" == "junit" + +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + --reporter/junit +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "--reporter", "junit"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "junit" ) +with expansion: + "junit" == "junit" + +------------------------------------------------------------------------------- +Process can be configured on command line + debugger + -b +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-b"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.shouldDebugBreak == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + debugger + --break +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "--break"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.shouldDebugBreak ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -a aborts after first failure +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-a"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.abortAfter == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x 2 aborts after two failures +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-x", "2"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.abortAfter == 2 ) +with expansion: + 2 == 2 + +------------------------------------------------------------------------------- +Process can be configured on command line + abort + -x must be numeric +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( !result ) +with expansion: + true + +TestMain.cpp:: +PASSED: + REQUIRE_THAT( result.errorMessage(), Contains("convert") && Contains("oops") ) +with expansion: + "Unable to convert 'oops' to destination type" ( contains: "convert" and + contains: "oops" ) + +------------------------------------------------------------------------------- +Process can be configured on command line + nothrow + -e +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-e"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.noThrow ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + nothrow + --nothrow +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "--nothrow"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.noThrow ) +with expansion: + true + +------------------------------------------------------------------------------- +Process can be configured on command line + output filename + -o filename +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-o", "filename.ext"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.outputFilename == "filename.ext" ) +with expansion: + "filename.ext" == "filename.ext" + +------------------------------------------------------------------------------- +Process can be configured on command line + output filename + --out +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "--out", "filename.ext"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.outputFilename == "filename.ext" ) +with expansion: + "filename.ext" == "filename.ext" + +------------------------------------------------------------------------------- +Process can be configured on command line + combinations + Single character flags can be combined +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "-abe"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + CHECK( config.abortAfter == 1 ) +with expansion: + 1 == 1 + +TestMain.cpp:: +PASSED: + CHECK( config.shouldDebugBreak ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( config.noThrow == true ) +with expansion: + true == true + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + without option +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.useColour == UseColour::Auto ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + auto +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "--use-colour", "auto"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.useColour == UseColour::Auto ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + yes +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "--use-colour", "yes"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.useColour == UseColour::Yes ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + no +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( cli.parse({"test", "--use-colour", "no"}) ) +with expansion: + {?} + +TestMain.cpp:: +PASSED: + REQUIRE( config.useColour == UseColour::No ) +with expansion: + 2 == 2 + +------------------------------------------------------------------------------- +Process can be configured on command line + use-colour + error +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( !result ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) ) +with expansion: + "colour mode must be one of: auto, yes or no. 'wrong' not recognised" + contains: "colour mode must be one of" + +------------------------------------------------------------------------------- +Reconstruction should be based on stringification: #914 +------------------------------------------------------------------------------- +DecompositionTests.cpp: +............................................................................... + +DecompositionTests.cpp:: FAILED: + CHECK( truthy(false) ) +with expansion: + Hey, its truthy! + +------------------------------------------------------------------------------- +SCOPED_INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 0 < 10 +with messages: + current counter 0 + i := 0 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 1 < 10 +with messages: + current counter 1 + i := 1 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 2 < 10 +with messages: + current counter 2 + i := 2 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 3 < 10 +with messages: + current counter 3 + i := 3 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 4 < 10 +with messages: + current counter 4 + i := 4 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 5 < 10 +with messages: + current counter 5 + i := 5 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 6 < 10 +with messages: + current counter 6 + i := 6 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 7 < 10 +with messages: + current counter 7 + i := 7 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 8 < 10 +with messages: + current counter 8 + i := 8 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 9 < 10 +with messages: + current counter 9 + i := 9 + +MessageTests.cpp:: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + +------------------------------------------------------------------------------- +SUCCEED counts as a test pass +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: +with message: + this is a success + +------------------------------------------------------------------------------- +SUCCESS does not require an argument +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or + methods + Given: No operations precede me +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( before == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or + methods + Given: No operations precede me + When: We get the count + Then: Subsequently values are higher +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( after > before ) +with expansion: + 1 > 0 + +------------------------------------------------------------------------------- +Scenario: Do that thing with the thing + Given: This stuff exists + When: I do this + Then: it should do this +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( itDoesThis() ) +with expansion: + true + +------------------------------------------------------------------------------- +Scenario: Do that thing with the thing + Given: This stuff exists + When: I do this + Then: it should do this + And: do that +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( itDoesThat() ) +with expansion: + true + +------------------------------------------------------------------------------- +Scenario: This is a really long scenario name to see how the list command deals + with wrapping + Given: A section name that is so long that it cannot fit in a single + console width + When: The test headers are printed as part of the normal running of the + scenario + Then: The, deliberately very long and overly verbose (you see what I did + there?) section names must wrap, along with an indent +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: +with message: + boo! + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: it is made larger + Then: the size and capacity go up +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 10 ) +with expansion: + 10 == 10 + +BDDTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: it is made larger + Then: the size and capacity go up + And when: it is made smaller again + Then: the size goes down but the capacity stays the same +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +BDDTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +Scenario: Vector resizing affects size and capacity + Given: an empty vector + When: we reserve more space + Then: The capacity is increased but the size remains the same +------------------------------------------------------------------------------- +BDDTests.cpp: +............................................................................... + +BDDTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +BDDTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +A string sent directly to stdout +A string sent directly to stderr +------------------------------------------------------------------------------- +Some simple comparisons between doubles +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == Approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.22 ) ) +with expansion: + 1.23 != Approx( 1.22 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != Approx( 1.24 ) ) +with expansion: + 1.23 != Approx( 1.24 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) != 1.22 ) +with expansion: + Approx( 1.23 ) != 1.22 + +ApproxTests.cpp:: +PASSED: + REQUIRE( Approx( d ) != 1.24 ) +with expansion: + Approx( 1.23 ) != 1.24 + +Message from section one +------------------------------------------------------------------------------- +Standard output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'one' + +Message from section two +------------------------------------------------------------------------------- +Standard output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'two' + +------------------------------------------------------------------------------- +StartsWith string matcher +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "string" + +------------------------------------------------------------------------------- +String + empty string +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + +String.tests.cpp:: +PASSED: + REQUIRE( empty.empty() ) +with expansion: + true + +String.tests.cpp:: +PASSED: + REQUIRE( empty.size() == 0 ) +with expansion: + 0 == 0 + +String.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +String + from literal +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + +String.tests.cpp:: +PASSED: + REQUIRE( s.empty() == false ) +with expansion: + false == false + +String.tests.cpp:: +PASSED: + REQUIRE( s.size() == 5 ) +with expansion: + 5 == 5 + +------------------------------------------------------------------------------- +String matchers +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "string" + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), Contains( "abc" ) ) +with expansion: + "this string contains 'abc' as a substring" contains: "abc" + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ) +with expansion: + "this string contains 'abc' as a substring" starts with: "this" + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" ends with: "substring" + +------------------------------------------------------------------------------- +StringBuilder + basic +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.capacity() == 0 ) +with expansion: + 0 == 0 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.size() == 0 ) +with expansion: + 0 == 0 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.capacity() == 32 ) +with expansion: + 32 == 32 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.size() == 0 ) +with expansion: + 0 == 0 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.capacity() == 32 ) +with expansion: + 32 == 32 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb.size() == 5 ) +with expansion: + 5 == 5 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello" ) +with expansion: + {?} == "hello" + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s.size() == 5 ) +with expansion: + 5 == 5 + +------------------------------------------------------------------------------- +StringBuilder + concatenation +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello world" ) +with expansion: + {?} == "hello world" + +------------------------------------------------------------------------------- +StringBuilder + concat & move +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello world" ) +with expansion: + {?} == "hello world" + +------------------------------------------------------------------------------- +StringBuilder + reserved +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb16.capacity() == 16 ) +with expansion: + 16 == 16 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( sb16.capacity() == 16 ) +with expansion: + 16 == 16 + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s == "hello world" ) +with expansion: + {?} == "hello world" + +------------------------------------------------------------------------------- +StringBuilder + from String + copy +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2 == s ) +with expansion: + {?} == {?} + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2.c_str() != s.c_str() ) +with expansion: + "hello" != "hello" + +------------------------------------------------------------------------------- +StringBuilder + from String + move from uniquely owned string +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2 == "hello" ) +with expansion: + {?} == "hello" + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2.c_str() == originalPointer ) +with expansion: + "hello" == "hello" + +------------------------------------------------------------------------------- +StringBuilder + from String + move from shared string (copies) +------------------------------------------------------------------------------- +StringBuilder.tests.cpp: +............................................................................... + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2 == "hello" ) +with expansion: + {?} == "hello" + +StringBuilder.tests.cpp:: +PASSED: + REQUIRE( s2.c_str() != originalPointer ) +with expansion: + "hello" != "hello" + +------------------------------------------------------------------------------- +StringRef + Empty string +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( empty.empty() ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( empty.size() == 0 ) +with expansion: + 0 == 0 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +StringRef + From string literal +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.empty() == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.size() == 5 ) +with expansion: + 5 == 5 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( s ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( rawChars, "hello" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +StringRef + From string literal + c_str() does not cause copy +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( s ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.c_str() == rawChars ) +with expansion: + "hello" == "hello" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( s ) == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +StringRef + From sub-string +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( original == "original" ) +with expansion: + {?} == "original" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( original ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( original ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( original ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( original ) ) +with expansion: + true + +------------------------------------------------------------------------------- +StringRef + Substrings + zero-based substring +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.empty() == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.size() == 5 ) +with expansion: + 5 == 5 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( ss.c_str(), "hello" ) == 0 ) +with expansion: + 0 == 0 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss == "hello" ) +with expansion: + {?} == "hello" + +------------------------------------------------------------------------------- +StringRef + Substrings + c_str() causes copy +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( ss ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( ss ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( rawChars == data( s ) ) +with expansion: + "hello world!" == "hello world!" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.c_str() != rawChars ) +with expansion: + "hello" != "hello world!" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isSubstring( ss ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( ss ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( data( ss ) != data( s ) ) +with expansion: + "hello" != "hello world!" + +------------------------------------------------------------------------------- +StringRef + Substrings + non-zero-based substring +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( ss.size() == 6 ) +with expansion: + 6 == 6 + +StringRef.tests.cpp:: +PASSED: + REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +StringRef + Substrings + Pointer values of full refs should match +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.c_str() == s2.c_str() ) +with expansion: + "hello world!" == "hello world!" + +------------------------------------------------------------------------------- +StringRef + Substrings + Pointer values of substring refs should not match +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( s.c_str() != ss.c_str() ) +with expansion: + "hello world!" != "hello" + +------------------------------------------------------------------------------- +StringRef + Comparisons +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( StringRef("hello") == StringRef("hello") ) +with expansion: + {?} == {?} + +StringRef.tests.cpp:: +PASSED: + REQUIRE( StringRef("hello") != StringRef("cello") ) +with expansion: + {?} != {?} + +------------------------------------------------------------------------------- +StringRef + From string + Copied +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( copied == "hot potato" ) +with expansion: + {?} == "hot potato" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( str == "hot potato" ) +with expansion: + {?} == "hot potato" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( copied ) == false ) +with expansion: + false == false + +StringRef.tests.cpp:: +PASSED: + REQUIRE( data( copied ) == originalPointer ) +with expansion: + "hot potato" == "hot potato" + +------------------------------------------------------------------------------- +StringRef + From string + Moved +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( copied == "hot potato" ) +with expansion: + {?} == "hot potato" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( isOwned( copied ) ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( str.empty() ) +with expansion: + true + +StringRef.tests.cpp:: +PASSED: + REQUIRE( data( copied ) == originalPointer ) +with expansion: + "hot potato" == "hot potato" + +hello +hello +------------------------------------------------------------------------------- +Tabs and newlines show in output +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( s1 == s2 ) +with expansion: + "if ($b == 10) { + $a = 20; + }" + == + "if ($b == 10) { + $a = 20; + } + " + +------------------------------------------------------------------------------- +Tag alias can be registered against tag patterns + The same tag alias can only be registered once +------------------------------------------------------------------------------- +TagAliasTests.cpp: +............................................................................... + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "[@zzz]" ) ) +with expansion: + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "[@zzz]" + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "file" ) ) +with expansion: + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "file" + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "2" ) ) +with expansion: + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "2" + +TagAliasTests.cpp:: +PASSED: + CHECK_THAT( what, Contains( "10" ) ) +with expansion: + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "10" + +------------------------------------------------------------------------------- +Tag alias can be registered against tag patterns + Tag aliases must be of the form [@name] +------------------------------------------------------------------------------- +TagAliasTests.cpp: +............................................................................... + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +TagAliasTests.cpp:: +PASSED: + CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) ) + +------------------------------------------------------------------------------- +Test case with one argument +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp: +............................................................................... + +VariadicMacrosTests.cpp:: +PASSED: +with message: + no assertions + +------------------------------------------------------------------------------- +Test enum bit values +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( 0x == bit30and31 ) +with expansion: + 3221225472 (0x) == 3221225472 + +------------------------------------------------------------------------------- +Text can be formatted using the Text class +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( Text( "hi there" ).toString() == "hi there" ) +with expansion: + "hi there" == "hi there" + +TestMain.cpp:: +PASSED: + CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ) +with expansion: + "hi + there" + == + "hi + there" + +------------------------------------------------------------------------------- +The NO_FAIL macro reports a failure but does not fail the test +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +FAILED - but was ok: + CHECK_NOFAIL( 1 == 2 ) + +------------------------------------------------------------------------------- +This test 'should' fail but doesn't +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + oops! + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section and find next section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + Successfully close S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + fail S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + open a nested section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Unexpected exceptions can be translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + 3.14 + +------------------------------------------------------------------------------- +Use a custom approx +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.23 ) ) +with expansion: + 1.23 == Approx( 1.23 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.22 ) ) +with expansion: + 1.23 == Approx( 1.22 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d == approx( 1.24 ) ) +with expansion: + 1.23 == Approx( 1.24 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( d != approx( 1.25 ) ) +with expansion: + 1.23 != Approx( 1.25 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.23 ) +with expansion: + Approx( 1.23 ) == 1.23 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.22 ) +with expansion: + Approx( 1.23 ) == 1.22 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) == 1.24 ) +with expansion: + Approx( 1.23 ) == 1.24 + +ApproxTests.cpp:: +PASSED: + REQUIRE( approx( d ) != 1.25 ) +with expansion: + Approx( 1.23 ) != 1.25 + +------------------------------------------------------------------------------- +Variadic macros + Section with one argument +------------------------------------------------------------------------------- +VariadicMacrosTests.cpp: +............................................................................... + +VariadicMacrosTests.cpp:: +PASSED: +with message: + no assertions + +------------------------------------------------------------------------------- +Vector matchers + Contains (element) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, VectorContains( 1 ) ) +with expansion: + { 1, 2, 3 } Contains: 1 + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, VectorContains( 2 ) ) +with expansion: + { 1, 2, 3 } Contains: 2 + +------------------------------------------------------------------------------- +Vector matchers + Contains (vector) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2 } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2, 3 } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Contains( empty) ) +with expansion: + { 1, 2, 3 } Contains: { } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( empty, Contains( empty) ) +with expansion: + { } Contains: { } + +------------------------------------------------------------------------------- +Vector matchers + Equals +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Equals( v ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( empty, Equals( empty ) ) +with expansion: + { } Equals: { } + +MatchersTests.cpp:: +PASSED: + CHECK_THAT( v, Equals( v2 ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2, 3 } + +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (element) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, VectorContains( -1 ) ) +with expansion: + { 1, 2, 3 } Contains: -1 + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, VectorContains( 1 ) ) +with expansion: + { } Contains: 1 + +------------------------------------------------------------------------------- +Vector matchers that fail + Contains (vector) +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Contains( v) ) +with expansion: + { } Contains: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Contains( v2 ) ) +with expansion: + { 1, 2, 3 } Contains: { 1, 2, 4 } + +------------------------------------------------------------------------------- +Vector matchers that fail + Equals +------------------------------------------------------------------------------- +MatchersTests.cpp: +............................................................................... + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( v2 ) ) +with expansion: + { 1, 2, 3 } Equals: { 1, 2 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v2, Equals( v ) ) +with expansion: + { 1, 2 } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( empty, Equals( v ) ) +with expansion: + { } Equals: { 1, 2, 3 } + +MatchersTests.cpp:: FAILED: + CHECK_THAT( v, Equals( empty ) ) +with expansion: + { 1, 2, 3 } Equals: { } + +------------------------------------------------------------------------------- +When checked exceptions are thrown they can be expected or unexpected +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_AS( thisThrows(), std::domain_error ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_NOTHROW( thisDoesntThrow() ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS( thisThrows() ) + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown directly they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a CHECK the test should continue +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown during a REQUIRE the test should abort +fail +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from functions they are always failures +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + CHECK( thisThrows() == 0 ) +due to unexpected exception with message: + expected exception + +------------------------------------------------------------------------------- +When unchecked exceptions are thrown from sections they are always failures + section name +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + unexpected exception + +------------------------------------------------------------------------------- +Where the LHS is not a simple value +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +Where there is more to the expression after the RHS +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +warning: + Uncomment the code in this test to check that it gives a sensible compiler + error + +------------------------------------------------------------------------------- +X/level/0/a +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +X/level/0/b +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +X/level/1/a +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +X/level/1/b +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +XmlEncode + normal string +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "normal string" ) == "normal string" ) +with expansion: + "normal string" == "normal string" + +------------------------------------------------------------------------------- +XmlEncode + empty string +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "" ) == "" ) +with expansion: + "" == "" + +------------------------------------------------------------------------------- +XmlEncode + string with ampersand +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith & jones" ) == "smith & jones" ) +with expansion: + "smith & jones" == "smith & jones" + +------------------------------------------------------------------------------- +XmlEncode + string with less-than +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith < jones" ) == "smith < jones" ) +with expansion: + "smith < jones" == "smith < jones" + +------------------------------------------------------------------------------- +XmlEncode + string with greater-than +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith > jones" ) == "smith > jones" ) +with expansion: + "smith > jones" == "smith > jones" + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ) +with expansion: + "smith ]]> jones" + == + "smith ]]> jones" + +------------------------------------------------------------------------------- +XmlEncode + string with quotes +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (1) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "[\x01]" ) == "[\\x01]" ) +with expansion: + "[\x01]" == "[\x01]" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (x7F) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" ) +with expansion: + "[\x7F]" == "[\x7F]" + +------------------------------------------------------------------------------- +atomic if +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( x == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +boolean member +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( obj.prop != 0 ) +with expansion: + 0x != 0 + +------------------------------------------------------------------------------- +checkedElse +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECKED_ELSE( flag ) +with expansion: + true + +MiscTests.cpp:: +PASSED: + REQUIRE( testCheckedElse( true ) ) +with expansion: + true + +------------------------------------------------------------------------------- +checkedElse, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_ELSE( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedElse( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +checkedIf +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECKED_IF( flag ) +with expansion: + true + +MiscTests.cpp:: +PASSED: + REQUIRE( testCheckedIf( true ) ) +with expansion: + true + +------------------------------------------------------------------------------- +checkedIf, failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECKED_IF( flag ) +with expansion: + false + +MiscTests.cpp:: FAILED: + REQUIRE( testCheckedIf( false ) ) +with expansion: + false + +------------------------------------------------------------------------------- +comparisons between const int variables +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_char_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_short_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_int_var == 1 ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( unsigned_long_var == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +comparisons between int variables +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_char_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_short_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_int_var ) +with expansion: + 1 == 1 + +ConditionTests.cpp:: +PASSED: + REQUIRE( long_var == unsigned_long_var ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + d (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + e (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + f (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +spanner------------------------------------------------------------------------------- +just failure +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: +explicitly with message: + Previous info should not be seen + +------------------------------------------------------------------------------- +long long +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( l == std::numeric_limits::max() ) +with expansion: + 9223372036854775807 (0x) + == + 9223372036854775807 (0x) + +------------------------------------------------------------------------------- +looped SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( b > a ) +with expansion: + 0 > 1 + +------------------------------------------------------------------------------- +looped tests +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[0] (1) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[1] (1) is even + +MiscTests.cpp:: +PASSED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 0 == 0 +with message: + Testing if fib[2] (2) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[3] (3) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[4] (5) is even + +MiscTests.cpp:: +PASSED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 0 == 0 +with message: + Testing if fib[5] (8) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[6] (13) is even + +MiscTests.cpp:: FAILED: + CHECK( ( fib[i] % 2 ) == 0 ) +with expansion: + 1 == 0 +with message: + Testing if fib[7] (21) is even + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( a == b ) +with expansion: + 1 == 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s3 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s4 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a < b ) +with expansion: + 1 < 2 + +------------------------------------------------------------------------------- +nested SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +MiscTests.cpp:: +PASSED: + REQUIRE( b != a ) +with expansion: + 2 != 1 + +------------------------------------------------------------------------------- +nested SECTION tests + s1 + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +non streamable - with conv. op +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( s == "7" ) +with expansion: + "7" == "7" + +------------------------------------------------------------------------------- +not allowed +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +null strings +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( makeString( false ) != static_cast(0) ) +with expansion: + "valid string" != {null string} + +MiscTests.cpp:: +PASSED: + REQUIRE( makeString( true ) == static_cast(0) ) +with expansion: + {null string} == {null string} + +------------------------------------------------------------------------------- +null_ptr +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( ptr.get() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +pair > -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ) +with expansion: + "{ { 42, "Arthur" }, { "Ford", 24 } }" + == + "{ { 42, "Arthur" }, { "Ford", 24 } }" + +------------------------------------------------------------------------------- +pointer to class +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( p == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +random SECTION tests + s1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +MiscTests.cpp:: +PASSED: + REQUIRE( b != a ) +with expansion: + 2 != 1 + +------------------------------------------------------------------------------- +random SECTION tests + s2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +replaceInPlace + replace single char +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "b", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "azcdefcg" ) +with expansion: + "azcdefcg" == "azcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + replace two chars +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "c", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "abzdefzg" ) +with expansion: + "abzdefzg" == "abzdefzg" + +------------------------------------------------------------------------------- +replaceInPlace + replace first char +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "a", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "zbcdefcg" ) +with expansion: + "zbcdefcg" == "zbcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + replace last char +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, "g", "z" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "abcdefcz" ) +with expansion: + "abcdefcz" == "abcdefcz" + +------------------------------------------------------------------------------- +replaceInPlace + replace all chars +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( letters, letters, "replaced" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( letters == "replaced" ) +with expansion: + "replaced" == "replaced" + +------------------------------------------------------------------------------- +replaceInPlace + replace no chars +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ) +with expansion: + !false + +TestMain.cpp:: +PASSED: + CHECK( letters == letters ) +with expansion: + "abcdefcg" == "abcdefcg" + +------------------------------------------------------------------------------- +replaceInPlace + escape ' +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK( replaceInPlace( s, "'", "|'" ) ) +with expansion: + true + +TestMain.cpp:: +PASSED: + CHECK( s == "didn|'t" ) +with expansion: + "didn|'t" == "didn|'t" + +------------------------------------------------------------------------------- +send a single char to INFO +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + REQUIRE( false ) +with message: + 3 + +------------------------------------------------------------------------------- +sends information to INFO +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( false ) +with messages: + hi + i := 7 + +------------------------------------------------------------------------------- +std::pair -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" ) +with expansion: + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + +------------------------------------------------------------------------------- +std::pair -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" ) +with expansion: + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + +------------------------------------------------------------------------------- +std::vector > -> toString +------------------------------------------------------------------------------- +ToStringPair.cpp: +............................................................................... + +ToStringPair.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" ) +with expansion: + "{ { "green", 55 } }" + == + "{ { "green", 55 } }" + +------------------------------------------------------------------------------- +string literals of different sizes can be compared +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: FAILED: + REQUIRE( std::string( "first" ) == "second" ) +with expansion: + "first" == "second" + +------------------------------------------------------------------------------- +stringify( has_maker ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ) +with expansion: + "StringMaker" + == + "StringMaker" + +------------------------------------------------------------------------------- +stringify( has_maker_and_toString ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ) +with expansion: + "StringMaker" + == + "StringMaker" + +------------------------------------------------------------------------------- +stringify( has_operator ) +------------------------------------------------------------------------------- +ToStringWhich.cpp: +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" ) +with expansion: + "operator<<( has_operator )" + == + "operator<<( has_operator )" + +------------------------------------------------------------------------------- +toString on const wchar_t const pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on const wchar_t pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on wchar_t const pointer returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString on wchar_t returns the string contents +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK( result == "\"wide load\"" ) +with expansion: + ""wide load"" == ""wide load"" + +------------------------------------------------------------------------------- +toString( vectors +............................................................................... + +ToStringWhich.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker }" ) +with expansion: + "{ StringMaker }" + == + "{ StringMaker }" + +------------------------------------------------------------------------------- +toString(enum class w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" ) +with expansion: + "E2/V0" == "E2/V0" + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" ) +with expansion: + "E2/V1" == "E2/V1" + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" ) +with expansion: + "Unknown enum value 10" + == + "Unknown enum value 10" + +------------------------------------------------------------------------------- +toString(enum class) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e0) == "0" ) +with expansion: + "{?}" == "0" + +EnumToString.cpp:: FAILED: + CHECK( ::Catch::Detail::stringify(e1) == "1" ) +with expansion: + "{?}" == "1" + +------------------------------------------------------------------------------- +toString(enum w/operator<<) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" ) +with expansion: + "E2{0}" == "E2{0}" + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" ) +with expansion: + "E2{1}" == "E2{1}" + +------------------------------------------------------------------------------- +toString(enum) +------------------------------------------------------------------------------- +EnumToString.cpp: +............................................................................... + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e0) == "0" ) +with expansion: + "0" == "0" + +EnumToString.cpp:: +PASSED: + CHECK( ::Catch::Detail::stringify(e1) == "1" ) +with expansion: + "1" == "1" + +------------------------------------------------------------------------------- +tuple<> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ }" == ::Catch::Detail::stringify(type{}) ) +with expansion: + "{ }" == "{ }" + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ }" == ::Catch::Detail::stringify(value) ) +with expansion: + "{ }" == "{ }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) ) +with expansion: + "1.2f" == "1.2f" + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) ) +with expansion: + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) ) +with expansion: + "{ 0 }" == "{ 0 }" + +------------------------------------------------------------------------------- +tuple<0,int,const char *> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) ) +with expansion: + "{ 0, 42, "Catch me" }" + == + "{ 0, 42, "Catch me" }" + +------------------------------------------------------------------------------- +tuple +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) ) +with expansion: + "{ "hello", "world" }" + == + "{ "hello", "world" }" + +------------------------------------------------------------------------------- +tuple,tuple<>,float> +------------------------------------------------------------------------------- +ToStringTuple.cpp: +............................................................................... + +ToStringTuple.cpp:: +PASSED: + CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) ) +with expansion: + "{ { 42 }, { }, 1.2f }" + == + "{ { 42 }, { }, 1.2f }" + +------------------------------------------------------------------------------- +vec> -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(v) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" ) +with expansion: + "{ { "hello" }, { "world" } }" + == + "{ { "hello" }, { "world" } }" + +------------------------------------------------------------------------------- +vector -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ) +with expansion: + "{ 42 }" == "{ 42 }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ) +with expansion: + "{ 42, 250 }" == "{ 42, 250 }" + +------------------------------------------------------------------------------- +vector -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ) +with expansion: + "{ 42 }" == "{ 42 }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ) +with expansion: + "{ 42, 250 }" == "{ 42, 250 }" + +------------------------------------------------------------------------------- +vector -> toString +------------------------------------------------------------------------------- +ToStringVector.cpp: +............................................................................... + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) +with expansion: + "{ }" == "{ }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" ) +with expansion: + "{ "hello" }" == "{ "hello" }" + +ToStringVector.cpp:: +PASSED: + REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" ) +with expansion: + "{ "hello", "world" }" + == + "{ "hello", "world" }" + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing bigger changes size and capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 10 ) +with expansion: + 10 == 10 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing smaller changes size but not capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 0 ) +with expansion: + 0 == 0 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + resizing smaller changes size but not capacity + We can use the 'swap trick' to reset the capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() == 0 ) +with expansion: + 0 == 0 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + reserving bigger changes capacity but not size +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 10 ) +with expansion: + 10 >= 10 + +------------------------------------------------------------------------------- +vectors can be sized and resized +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +vectors can be sized and resized + reserving smaller does not change size or capacity +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( v.size() == 5 ) +with expansion: + 5 == 5 + +MiscTests.cpp:: +PASSED: + REQUIRE( v.capacity() >= 5 ) +with expansion: + 5 >= 5 + +------------------------------------------------------------------------------- +xmlentitycheck + embedded xml +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +xmlentitycheck + encoded chars +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +=============================================================================== +test cases: 186 | 134 passed | 48 failed | 4 failed as expected +assertions: 941 | 822 passed | 98 failed | 21 failed as expected + diff --git a/projects/SelfTest/Baselines/console.swa4.unapproved.txt b/projects/SelfTest/Baselines/console.swa4.unapproved.txt new file mode 100644 index 00000000..fe22e2b3 --- /dev/null +++ b/projects/SelfTest/Baselines/console.swa4.unapproved.txt @@ -0,0 +1,163 @@ + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + is a host application. +Run with -? for options + +------------------------------------------------------------------------------- +# A test name that starts with a # +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + yay + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + outside assertions +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with messages: + answer := 42 + expected exception + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + inside REQUIRE_NOTHROW +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_NOTHROW( thisThrows() ) +due to unexpected exception with messages: + answer := 42 + expected exception + +------------------------------------------------------------------------------- +#748 - captures with unexpected exceptions + inside REQUIRE_THROWS +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS( thisThrows() ) +with message: + answer := 42 + +------------------------------------------------------------------------------- +#809 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( 42 == f ) +with expansion: + 42 == {?} + +------------------------------------------------------------------------------- +#833 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( a == t ) +with expansion: + 3 == 3 + +CompilationTests.cpp:: +PASSED: + CHECK( a == t ) +with expansion: + 3 == 3 + +CompilationTests.cpp:: +PASSED: + REQUIRE_THROWS( throws_int(true) ) + +CompilationTests.cpp:: +PASSED: + CHECK_THROWS_AS( throws_int(true), int ) + +CompilationTests.cpp:: +PASSED: + REQUIRE_NOTHROW( throws_int(false) ) + +CompilationTests.cpp:: +PASSED: + REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") ) +with expansion: + "aaa" ends with: "aaa" + +CompilationTests.cpp:: +PASSED: + REQUIRE( templated_tests(3) ) +with expansion: + true + +------------------------------------------------------------------------------- +#835 -- errno should not be touched by Catch +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK( f() == 0 ) +with expansion: + 1 == 0 + +MiscTests.cpp:: +PASSED: + REQUIRE( errno == 1 ) +with expansion: + 1 == 1 + +------------------------------------------------------------------------------- +#872 +------------------------------------------------------------------------------- +CompilationTests.cpp: +............................................................................... + +CompilationTests.cpp:: +PASSED: + REQUIRE( x == 4 ) +with expansion: + {?} == 4 +with message: + dummy := 0 + +------------------------------------------------------------------------------- +'Not' checks that should fail +------------------------------------------------------------------------------- +ConditionTests.cpp: +............................................................................... + +ConditionTests.cpp:: FAILED: + CHECK( false != false ) + +ConditionTests.cpp:: FAILED: + CHECK( true != true ) + +ConditionTests.cpp:: FAILED: + CHECK( !true ) +with expansion: + false + +ConditionTests.cpp:: FAILED: + CHECK_FALSE( true ) + +=============================================================================== +test cases: 7 | 4 passed | 1 failed | 2 failed as expected +assertions: 19 | 12 passed | 4 failed | 3 failed as expected + diff --git a/projects/SelfTest/Baselines/junit.sw.unapproved.txt b/projects/SelfTest/Baselines/junit.sw.unapproved.txt new file mode 100644 index 00000000..bd931044 --- /dev/null +++ b/projects/SelfTest/Baselines/junit.sw.unapproved.txt @@ -0,0 +1,821 @@ + + + + + + +expected exception +answer := 42 +ExceptionTests.cpp: + + + + +expected exception +answer := 42 +ExceptionTests.cpp: + + + + + + + +MiscTests.cpp: + + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + + + + + + +ClassTests.cpp: + + + + + +ClassTests.cpp: + + + + + +to infinity and beyond +MiscTests.cpp: + + + + + +TrickyTests.cpp: + + +TrickyTests.cpp: + + + + + + + +unexpected exception +ExceptionTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + + + + + +MatchersTests.cpp: + + + + +custom exception - not std +ExceptionTests.cpp: + + + + +custom exception - not std +ExceptionTests.cpp: + + + + +custom std exception +ExceptionTests.cpp: + + + + + +MatchersTests.cpp: + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + + +MatchersTests.cpp: + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + +Unknown exception +MatchersTests.cpp: + + +Unknown exception +MatchersTests.cpp: + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + + + + + +expected exception +ExceptionTests.cpp: + + +ExceptionTests.cpp: + + +expected exception +ExceptionTests.cpp: + + + + +This is a failure +MessageTests.cpp: + + + + +MessageTests.cpp: + + + + +This is a failure +MessageTests.cpp: + + + + + + + +this message should be logged +so should this +MessageTests.cpp: + + + + +this message may be logged later +this message should be logged +MessageTests.cpp: + + +this message may be logged later +this message should be logged +and this, but later +MessageTests.cpp: + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + + + +MatchersTests.cpp: + + + + + +MatchersTests.cpp: + + + + +ExceptionTests.cpp: + + + + + +custom exception +ExceptionTests.cpp: + + + + + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + +ConditionTests.cpp: + + + + + +Message from section one +MessageTests.cpp: + + + + +Message from section two +MessageTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +DecompositionTests.cpp: + + + + +current counter 10 +i := 10 +MessageTests.cpp: + + + + + + + + + + + + + + + +A string sent directly to stdout + + +A string sent directly to stderr + + + + + +Message from section one +Message from section two + + + + +MatchersTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + + + + +hello +hello + + + + +MiscTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +3.14 +ExceptionTests.cpp: + + + + + + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + +MatchersTests.cpp: + + + + + +unexpected exception +ExceptionTests.cpp: + + + + +expected exception +ExceptionTests.cpp: + + + + +expected exception +ExceptionTests.cpp: + + + + +expected exception +ExceptionTests.cpp: + + + + +unexpected exception +ExceptionTests.cpp: + + + + + + + + + + + + + + + + + + + + + +MiscTests.cpp: + + +MiscTests.cpp: + + + + + +MiscTests.cpp: + + +MiscTests.cpp: + + + + + + + + + +Previous info should not be seen +MessageTests.cpp: + + + + + +MiscTests.cpp: + + + + +Testing if fib[0] (1) is even +MiscTests.cpp: + + +Testing if fib[1] (1) is even +MiscTests.cpp: + + +Testing if fib[3] (3) is even +MiscTests.cpp: + + +Testing if fib[4] (5) is even +MiscTests.cpp: + + +Testing if fib[6] (13) is even +MiscTests.cpp: + + +Testing if fib[7] (21) is even +MiscTests.cpp: + + + + +MiscTests.cpp: + + + + + + + + + + + + + + + + + + + + + + + +3 +MiscTests.cpp: + + + + +hi +i := 7 +MessageTests.cpp: + + + + + + + +TrickyTests.cpp: + + + + + + + + + + + + + +EnumToString.cpp: + + +EnumToString.cpp: + + + + + + + + + + + + + + + + + + + + + + + +A string sent directly to stdout +Message from section one +Message from section two +hello +hello + + +A string sent directly to stderr + + + diff --git a/projects/SelfTest/Baselines/xml.sw.unapproved.txt b/projects/SelfTest/Baselines/xml.sw.unapproved.txt new file mode 100644 index 00000000..5b4ecb9e --- /dev/null +++ b/projects/SelfTest/Baselines/xml.sw.unapproved.txt @@ -0,0 +1,10082 @@ + + + + + + + +
+ + answer := 42 + + + expected exception + + +
+
+ + answer := 42 + + + + thisThrows() + + + thisThrows() + + + expected exception + + + +
+
+ + answer := 42 + + + + thisThrows() + + + thisThrows() + + + +
+ +
+ + + + 42 == f + + + 42 == {?} + + + + + + + + a == t + + + 3 == 3 + + + + + a == t + + + 3 == 3 + + + + + throws_int(true) + + + throws_int(true) + + + + + throws_int(true), int + + + throws_int(true), int + + + + + throws_int(false) + + + throws_int(false) + + + + + "aaa", Catch::EndsWith("aaa") + + + "aaa" ends with: "aaa" + + + + + templated_tests<int>(3) + + + true + + + + + + + + f() == 0 + + + 1 == 0 + + + + + errno == 1 + + + 1 == 1 + + + + + + + dummy := 0 + + + + x == 4 + + + {?} == 4 + + + + + + + + false != false + + + false != false + + + + + true != true + + + true != true + + + + + !true + + + false + + + + + !true + + + !true + + + + + !trueValue + + + false + + + + + !trueValue + + + !true + + + + + !(1 == 1) + + + false + + + + + !1 == 1 + + + !(1 == 1) + + + + + + + + false == false + + + false == false + + + + + true == true + + + true == true + + + + + !false + + + true + + + + + !false + + + !false + + + + + !falseValue + + + true + + + + + !falseValue + + + !false + + + + + !(1 == 2) + + + true + + + + + !1 == 2 + + + !(1 == 2) + + + + + +
+ + + is_true<true>::value == true + + + true == true + + + + + true == is_true<true>::value + + + true == true + + + +
+
+ + + is_true<false>::value == false + + + false == false + + + + + false == is_true<false>::value + + + false == false + + + +
+
+ + + !is_true<false>::value + + + true + + + +
+
+ + + !!is_true<true>::value + + + true + + + +
+
+ + + is_true<true>::value + + + true + + + + + !is_true<false>::value + + + !false + + + +
+ +
+ + + + s == "world" + + + "hello" == "world" + + + + + + + + s == "hello" + + + "hello" == "hello" + + + + + + + + m_a == 2 + + + 1 == 2 + + + + + + + + m_a == 1 + + + 1 == 1 + + + + + +
+
+ +
+ +
+ + to infinity and beyond + + +
+ + + + &o1 == &o2 + + + 0x == 0x + + + + + o1 == o2 + + + {?} == {?} + + + + + + + + 104.0 != Approx(100.0) + + + 104.0 != Approx( 100.0 ) + + + + + 104.0 == Approx(100.0).margin(5) + + + 104.0 == Approx( 100.0 ) + + + + + 104.0 != Approx(100.0).margin(3) + + + 104.0 != Approx( 100.0 ) + + + + + 100.3 != Approx(100.0) + + + 100.3 != Approx( 100.0 ) + + + + + 100.3 == Approx(100.0).margin(0.5) + + + 100.3 == Approx( 100.0 ) + + + + + + + + testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) + + + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) + + + + + + + + + + + i++ == 7 + + + 7 == 7 + + + + + i++ == 8 + + + 8 == 8 + + + + + + + + 1 == 1 + + + 1 == 1 + + + + + {Unknown expression after the reported line} + + + {Unknown expression after the reported line} + + + unexpected exception + + + + + + + + + + + testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) + + + "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) + + + + + testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) + + + "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) + + + + + + + + divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) + + + 3.1428571429 == Approx( 3.141 ) + + + + + divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) + + + 3.1428571429 != Approx( 3.141 ) + + + + + + + + d != Approx( 1.231 ) + + + 1.23 != Approx( 1.231 ) + + + + + d == Approx( 1.231 ).epsilon( 0.1 ) + + + 1.23 == Approx( 1.231 ) + + + + + + + + 1.23f == Approx( 1.23f ) + + + 1.23f == Approx( 1.2300000191 ) + + + + + 0.0f == Approx( 0.0f ) + + + 0.0f == Approx( 0.0 ) + + + + + + + + 1 == Approx( 1 ) + + + 1 == Approx( 1.0 ) + + + + + 0 == Approx( 0 ) + + + 0 == Approx( 0.0 ) + + + + + + + + 1.0f == Approx( 1 ) + + + 1.0f == Approx( 1.0 ) + + + + + 0 == Approx( dZero) + + + 0 == Approx( 0.0 ) + + + + + 0 == Approx( dSmall ).epsilon( 0.001 ) + + + 0 == Approx( 0.00001 ) + + + + + 1.234f == Approx( dMedium ) + + + 1.234f == Approx( 1.234 ) + + + + + dMedium == Approx( 1.234f ) + + + 1.234 == Approx( 1.2339999676 ) + + + + + + + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + + +
+ +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + + +
+ +
+ +
+ +
+ + i := 2 + + + + true + + + true + + + +
+
+ + 3 + + + + true + + + true + + + +
+ +
+ +
+ + + tab == '\t' + + + '\t' == '\t' + + + + + newline == '\n' + + + '\n' == '\n' + + + + + carr_return == '\r' + + + '\r' == '\r' + + + + + form_feed == '\f' + + + '\f' == '\f' + + + +
+
+ + + space == ' ' + + + ' ' == ' ' + + + + + c == chars[i] + + + 'a' == 'a' + + + + + c == chars[i] + + + 'z' == 'z' + + + + + c == chars[i] + + + 'A' == 'A' + + + + + c == chars[i] + + + 'Z' == 'Z' + + + +
+
+ + + null_terminator == '\0' + + + 0 == 0 + + + + + c == i + + + 2 == 2 + + + + + c == i + + + 3 == 3 + + + + + c == i + + + 4 == 4 + + + + + c == i + + + 5 == 5 + + + +
+ +
+ + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + + + !({ 1, 2 } == { 1, 2, 3 }) + + + + + !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + + + !({ 1, 2 } == { 1, 2, 3 }) + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + true + + + true + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + + + + a + + + 0x + + + + + a == &foo + + + 0x == 0x + + + + + + + + m == &S::f + + + 0x +== +0x + + + + + + + + td == Approx(10.0) + + + StrongDoubleTypedef(10) == Approx( 10.0 ) + + + + + Approx(10.0) == td + + + Approx( 10.0 ) == StrongDoubleTypedef(10) + + + + + td != Approx(11.0) + + + StrongDoubleTypedef(10) != Approx( 11.0 ) + + + + + Approx(11.0) != td + + + Approx( 11.0 ) != StrongDoubleTypedef(10) + + + + + td <= Approx(10.0) + + + StrongDoubleTypedef(10) <= Approx( 10.0 ) + + + + + td <= Approx(11.0) + + + StrongDoubleTypedef(10) <= Approx( 11.0 ) + + + + + Approx(10.0) <= td + + + Approx( 10.0 ) <= StrongDoubleTypedef(10) + + + + + Approx(9.0) <= td + + + Approx( 9.0 ) <= StrongDoubleTypedef(10) + + + + + td >= Approx(9.0) + + + StrongDoubleTypedef(10) >= Approx( 9.0 ) + + + + + td >= Approx(10.0) + + + StrongDoubleTypedef(10) >= Approx( 10.0 ) + + + + + Approx(10.0) >= td + + + Approx( 10.0 ) >= StrongDoubleTypedef(10) + + + + + Approx(11.0) >= td + + + Approx( 11.0 ) >= StrongDoubleTypedef(10) + + + + + + + + 54 == 6*9 + + + 54 == 54 + + + + + + + + ( -1 > 2u ) + + + true + + + + + -1 > 2u + + + -1 > 2 + + + + + ( 2u < -1 ) + + + true + + + + + 2u < -1 + + + 2 < -1 + + + + + ( minInt > 2u ) + + + true + + + + + minInt > 2u + + + -2147483648 > 2 + + + + + + + + i == 1 + + + 1 == 1 + + + + + ui == 2 + + + 2 == 2 + + + + + l == 3 + + + 3 == 3 + + + + + ul == 4 + + + 4 == 4 + + + + + c == 5 + + + 5 == 5 + + + + + uc == 6 + + + 6 == 6 + + + + + 1 == i + + + 1 == 1 + + + + + 2 == ui + + + 2 == 2 + + + + + 3 == l + + + 3 == 3 + + + + + 4 == ul + + + 4 == 4 + + + + + 5 == c + + + 5 == 5 + + + + + 6 == uc + + + 6 == 6 + + + + + (std::numeric_limits<unsigned long>::max)() > ul + + + 18446744073709551615 (0x) +> +4 + + + + + + + + testStringForMatching(), Contains( "not there" ) + + + "this string contains 'abc' as a substring" contains: "not there" + + + + + + + + throwCustom() + + + throwCustom() + + + custom exception - not std + + + + + + + + throwCustom(), std::exception + + + throwCustom(), std::exception + + + custom exception - not std + + + + + + + custom std exception + + + + + + + t == 1u + + + {?} == 1 + + + + + + + + testStringForMatching(), EndsWith( "this" ) + + + "this string contains 'abc' as a substring" ends with: "this" + + + + + + + + data.int_seven == 6 + + + 7 == 6 + + + + + data.int_seven == 8 + + + 7 == 8 + + + + + data.int_seven == 0 + + + 7 == 0 + + + + + data.float_nine_point_one == Approx( 9.11f ) + + + 9.1f == Approx( 9.1099996567 ) + + + + + data.float_nine_point_one == Approx( 9.0f ) + + + 9.1f == Approx( 9.0 ) + + + + + data.float_nine_point_one == Approx( 1 ) + + + 9.1f == Approx( 1.0 ) + + + + + data.float_nine_point_one == Approx( 0 ) + + + 9.1f == Approx( 0.0 ) + + + + + data.double_pi == Approx( 3.1415 ) + + + 3.1415926535 == Approx( 3.1415 ) + + + + + data.str_hello == "goodbye" + + + "hello" == "goodbye" + + + + + data.str_hello == "hell" + + + "hello" == "hell" + + + + + data.str_hello == "hello1" + + + "hello" == "hello1" + + + + + data.str_hello.size() == 6 + + + 5 == 6 + + + + + x == Approx( 1.301 ) + + + 1.3 == Approx( 1.301 ) + + + + + + + + data.int_seven == 7 + + + 7 == 7 + + + + + data.float_nine_point_one == Approx( 9.1f ) + + + 9.1f == Approx( 9.1000003815 ) + + + + + data.double_pi == Approx( 3.1415926535 ) + + + 3.1415926535 == Approx( 3.1415926535 ) + + + + + data.str_hello == "hello" + + + "hello" == "hello" + + + + + "hello" == data.str_hello + + + "hello" == "hello" + + + + + data.str_hello.size() == 5 + + + 5 == 5 + + + + + x == Approx( 1.3 ) + + + 1.3 == Approx( 1.3 ) + + + + + + + + testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) + + + "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" + + + + + + + + testStringForMatching(), Equals( "something else" ) + + + "this string contains 'abc' as a substring" equals: "something else" + + + + + +
+ + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + +
+
+ + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + Unknown exception + + + + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + Unknown exception + + + +
+
+ + + throws(3), SpecialException, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + + + throws(4), SpecialException, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + +
+ +
+ + + + throws(1), SpecialException, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + + + throws(2), SpecialException, ExceptionMatcher{ 2 } + + + {?} special exception has value of 2 + + + + + +
+ + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + + +
+
+ + + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + + + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + + + +
+
+ + + thisThrows(), StartsWith( "expected" ) + + + thisThrows(), StartsWith( "expected" ) + + + + + thisThrows(), EndsWith( "exception" ) + + + thisThrows(), EndsWith( "exception" ) + + + + + thisThrows(), Contains( "except" ) + + + thisThrows(), Contains( "except" ) + + + + + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + + + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + + + +
+ +
+ + + + thisThrows(), std::string + + + thisThrows(), std::string + + + expected exception + + + + + thisDoesntThrow(), std::domain_error + + + thisDoesntThrow(), std::domain_error + + + + + thisThrows() + + + thisThrows() + + + expected exception + + + + + + + This is a failure + + + + + + + + + + This is a failure + + + This message appears in the output + + + + + + + Factorial(0) == 1 + + + 1 == 1 + + + + + Factorial(1) == 1 + + + 1 == 1 + + + + + Factorial(2) == 2 + + + 2 == 2 + + + + + Factorial(3) == 6 + + + 6 == 6 + + + + + Factorial(10) == 3628800 + + + 3628800 (0x) == 3628800 (0x) + + + + + + + + d >= Approx( 1.22 ) + + + 1.23 >= Approx( 1.22 ) + + + + + d >= Approx( 1.23 ) + + + 1.23 >= Approx( 1.23 ) + + + + + !d >= Approx( 1.24 ) + + + !(1.23 >= Approx( 1.24 )) + + + + + d >= Approx( 1.24 ).epsilon(0.1) + + + 1.23 >= Approx( 1.24 ) + + + + + + + this is a message + + + this is a warning + + + + + + this message should be logged + + + so should this + + + + a == 1 + + + 2 == 1 + + + + + + + this message may be logged later + + + + a == 2 + + + 2 == 2 + + + + this message may be logged later + + + this message should be logged + + + + a == 1 + + + 2 == 1 + + + + this message may be logged later + + + this message should be logged + + + and this, but later + + + + a == 0 + + + 2 == 0 + + + + this message may be logged later + + + this message should be logged + + + and this, but later + + + but not this + + + + a == 2 + + + 2 == 2 + + + + + + + + data.int_seven != 7 + + + 7 != 7 + + + + + data.float_nine_point_one != Approx( 9.1f ) + + + 9.1f != Approx( 9.1000003815 ) + + + + + data.double_pi != Approx( 3.1415926535 ) + + + 3.1415926535 != Approx( 3.1415926535 ) + + + + + data.str_hello != "hello" + + + "hello" != "hello" + + + + + data.str_hello.size() != 5 + + + 5 != 5 + + + + + + + + data.int_seven != 6 + + + 7 != 6 + + + + + data.int_seven != 8 + + + 7 != 8 + + + + + data.float_nine_point_one != Approx( 9.11f ) + + + 9.1f != Approx( 9.1099996567 ) + + + + + data.float_nine_point_one != Approx( 9.0f ) + + + 9.1f != Approx( 9.0 ) + + + + + data.float_nine_point_one != Approx( 1 ) + + + 9.1f != Approx( 1.0 ) + + + + + data.float_nine_point_one != Approx( 0 ) + + + 9.1f != Approx( 0.0 ) + + + + + data.double_pi != Approx( 3.1415 ) + + + 3.1415926535 != Approx( 3.1415 ) + + + + + data.str_hello != "goodbye" + + + "hello" != "goodbye" + + + + + data.str_hello != "hell" + + + "hello" != "hell" + + + + + data.str_hello != "hello1" + + + "hello" != "hello1" + + + + + data.str_hello.size() != 6 + + + 5 != 6 + + + + + + + + d <= Approx( 1.24 ) + + + 1.23 <= Approx( 1.24 ) + + + + + d <= Approx( 1.23 ) + + + 1.23 <= Approx( 1.23 ) + + + + + !d <= Approx( 1.22 ) + + + !(1.23 <= Approx( 1.22 )) + + + + + d <= Approx( 1.22 ).epsilon(0.1) + + + 1.23 <= Approx( 1.22 ) + + + + + +
+
+ + + Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString + + + "one two three four" +== +"one two three four" + + + + + Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString + + + "one two three four" +== +"one two three four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" + + + "one two three +four" +== +"one two three +four" + + + + + Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" + + + "one two +three four" +== +"one two +three four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + + + "one +two +three +four" +== +"one +two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" + + + "one +two +three +four" +== +"one +two +three +four" + + + +
+ +
+
+
+ + + Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" + + + "abc- +def" +== +"abc- +def" + + + + + Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" + + + "abc- +defg" +== +"abc- +defg" + + + + + Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" + + + "abc- +def- +gh" +== +"abc- +def- +gh" + + + + + Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" + + + "one +two +thr- +ee +four" +== +"one +two +thr- +ee +four" + + + + + Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" + + + "one +two +th- +ree +fo- +ur" +== +"one +two +th- +ree +fo- +ur" + + + +
+ +
+
+
+ + + text.size() == 4 + + + 4 == 4 + + + + + text[0] == "one" + + + "one" == "one" + + + + + text[1] == "two" + + + "two" == "two" + + + + + text[2] == "three" + + + "three" == "three" + + + + + text[3] == "four" + + + "four" == "four" + + + +
+ +
+
+
+ + + text.toString() == " one two\n three\n four" + + + " one two + three + four" +== +" one two + three + four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString + + + "one two +three four" +== +"one two +three four" + + + + + Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString + + + "one two +three four" +== +"one two +three four" + + + + + Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString + + + "one two +three four" +== +"one two +three four" + + + +
+ +
+
+
+ + + Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" + + + "abcdef" == "abcdef" + + + + + Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" + + + "abcdef" == "abcdef" + + + + + Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" + + + "abcdef" == "abcdef" + + + + + Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" + + + "abcd- +ef" +== +"abcd- +ef" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + + + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + + + "one two +three +four" +== +"one two +three +four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + + + "one +two +three +four" +== +"one +two +three +four" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString + + + "one,two(three) <here>" +== +"one,two(three) <here>" + + + + + Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString + + + "one,two(three) <here>" +== +"one,two(three) <here>" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n<here>" + + + "one,two +(three) +<here>" +== +"one,two +(three) +<here>" + + + +
+ +
+
+
+ + + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n<here>" + + + "one, +two +(thre- +e) +<here>" +== +"one, +two +(thre- +e) +<here>" + + + + + Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n<her-\ne>" + + + "one, +two +(thr- +ee) +<her- +e>" +== +"one, +two +(thr- +ee) +<her- +e>" + + + + + Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n<he-\nre>" + + + "one, +two +(th- +ree) +<he- +re>" +== +"one, +two +(th- +ree) +<he- +re>" + + + +
+ +
+ +
+ + + + t.toString(), EndsWith( "... message truncated due to excessive size" ) + + + "******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +******************************************************************************- +************************ +******************************************************************************- +... message truncated due to excessive size" ends with: "... message truncated due to excessive size" + + + + + + + + + + + testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) + + + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" ) + + + + + + + + testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + + + + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" ) + + + + + + + + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) + + + + + + + + testStringForMatching(), !Contains( "different" ) + + + "this string contains 'abc' as a substring" not contains: "different" + + + + + + + + testStringForMatching(), !Contains( "substring" ) + + + "this string contains 'abc' as a substring" not contains: "substring" + + + + + + + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + + + + thisThrows(), "should fail" + + + expected exception + + + + + + + This one ran + + + + + + custom exception + + + + + + + True + + + {?} + + + + + !False + + + true + + + + + !False + + + !{?} + + + + + + + + 0x == o + + + 3221225472 (0x) == {?} + + + + + + + + data.int_seven > 7 + + + 7 > 7 + + + + + data.int_seven < 7 + + + 7 < 7 + + + + + data.int_seven > 8 + + + 7 > 8 + + + + + data.int_seven < 6 + + + 7 < 6 + + + + + data.int_seven < 0 + + + 7 < 0 + + + + + data.int_seven < -1 + + + 7 < -1 + + + + + data.int_seven >= 8 + + + 7 >= 8 + + + + + data.int_seven <= 6 + + + 7 <= 6 + + + + + data.float_nine_point_one < 9 + + + 9.1f < 9 + + + + + data.float_nine_point_one > 10 + + + 9.1f > 10 + + + + + data.float_nine_point_one > 9.2 + + + 9.1f > 9.2 + + + + + data.str_hello > "hello" + + + "hello" > "hello" + + + + + data.str_hello < "hello" + + + "hello" < "hello" + + + + + data.str_hello > "hellp" + + + "hello" > "hellp" + + + + + data.str_hello > "z" + + + "hello" > "z" + + + + + data.str_hello < "hellm" + + + "hello" < "hellm" + + + + + data.str_hello < "a" + + + "hello" < "a" + + + + + data.str_hello >= "z" + + + "hello" >= "z" + + + + + data.str_hello <= "a" + + + "hello" <= "a" + + + + + + + + data.int_seven < 8 + + + 7 < 8 + + + + + data.int_seven > 6 + + + 7 > 6 + + + + + data.int_seven > 0 + + + 7 > 0 + + + + + data.int_seven > -1 + + + 7 > -1 + + + + + data.int_seven >= 7 + + + 7 >= 7 + + + + + data.int_seven >= 6 + + + 7 >= 6 + + + + + data.int_seven <= 7 + + + 7 <= 7 + + + + + data.int_seven <= 8 + + + 7 <= 8 + + + + + data.float_nine_point_one > 9 + + + 9.1f > 9 + + + + + data.float_nine_point_one < 10 + + + 9.1f < 10 + + + + + data.float_nine_point_one < 9.2 + + + 9.1f < 9.2 + + + + + data.str_hello <= "hello" + + + "hello" <= "hello" + + + + + data.str_hello >= "hello" + + + "hello" >= "hello" + + + + + data.str_hello < "hellp" + + + "hello" < "hellp" + + + + + data.str_hello < "zebra" + + + "hello" < "zebra" + + + + + data.str_hello > "hellm" + + + "hello" > "hellm" + + + + + data.str_hello > "a" + + + "hello" > "a" + + + + + +
+ + Message from section one + + +
+
+ + Message from section two + + +
+ +
+ +
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches(tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + + + parseTestSpec( "*a" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + + + parseTestSpec( "a*" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + + + parseTestSpec( "*a*" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+ +
+ + + + (std::pair<int, int>( 1, 2 )) == aNicePair + + + { 1, 2 } == { 1, 2 } + + + + + + + + p == 0 + + + 0 == 0 + + + + + p == pNULL + + + 0 == 0 + + + + + p != 0 + + + 0x != 0 + + + + + cp != 0 + + + 0x != 0 + + + + + cpc != 0 + + + 0x != 0 + + + + + returnsNull() == 0 + + + {null string} == 0 + + + + + returnsConstNull() == 0 + + + {null string} == 0 + + + + + 0 != p + + + 0 != 0x + + + + + + + actual address of p: 0x + + + toString(p): 0x + + + + +
+ + + result + + + {?} + + + + + config.processName == "" + + + "" == "" + + + +
+
+ + + result + + + {?} + + + + + config.processName == "test" + + + "test" == "test" + + + + + config.shouldDebugBreak == false + + + false == false + + + + + config.abortAfter == -1 + + + -1 == -1 + + + + + config.noThrow == false + + + false == false + + + + + config.reporterNames.empty() + + + true + + + +
+
+
+ + + result + + + {?} + + + + + cfg.testSpec().matches(fakeTestCase("notIncluded")) == false + + + false == false + + + + + cfg.testSpec().matches(fakeTestCase("test1")) + + + true + + + +
+ +
+
+
+ + + result + + + {?} + + + + + cfg.testSpec().matches(fakeTestCase("test1")) == false + + + false == false + + + + + cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) + + + true + + + +
+ +
+
+
+ + + result + + + {?} + + + + + cfg.testSpec().matches(fakeTestCase("test1")) == false + + + false == false + + + + + cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "-r", "console"}) + + + {?} + + + + + config.reporterNames[0] == "console" + + + "console" == "console" + + + +
+ +
+
+
+ + + cli.parse({"test", "-r", "xml"}) + + + {?} + + + + + config.reporterNames[0] == "xml" + + + "xml" == "xml" + + + +
+ +
+
+
+ + + cli.parse({"test", "-r", "xml", "-r", "junit"}) + + + {?} + + + + + config.reporterNames.size() == 2 + + + 2 == 2 + + + + + config.reporterNames[0] == "xml" + + + "xml" == "xml" + + + + + config.reporterNames[1] == "junit" + + + "junit" == "junit" + + + +
+ +
+
+
+ + + cli.parse({"test", "--reporter", "junit"}) + + + {?} + + + + + config.reporterNames[0] == "junit" + + + "junit" == "junit" + + + +
+ +
+
+
+ + + cli.parse({"test", "-b"}) + + + {?} + + + + + config.shouldDebugBreak == true + + + true == true + + + +
+ +
+
+
+ + + cli.parse({"test", "--break"}) + + + {?} + + + + + config.shouldDebugBreak + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "-a"}) + + + {?} + + + + + config.abortAfter == 1 + + + 1 == 1 + + + +
+ +
+
+
+ + + cli.parse({"test", "-x", "2"}) + + + {?} + + + + + config.abortAfter == 2 + + + 2 == 2 + + + +
+ +
+
+
+ + + !result + + + true + + + + + result.errorMessage(), Contains("convert") && Contains("oops") + + + "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" ) + + + +
+ +
+
+
+ + + cli.parse({"test", "-e"}) + + + {?} + + + + + config.noThrow + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "--nothrow"}) + + + {?} + + + + + config.noThrow + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "-o", "filename.ext"}) + + + {?} + + + + + config.outputFilename == "filename.ext" + + + "filename.ext" == "filename.ext" + + + +
+ +
+
+
+ + + cli.parse({"test", "--out", "filename.ext"}) + + + {?} + + + + + config.outputFilename == "filename.ext" + + + "filename.ext" == "filename.ext" + + + +
+ +
+
+
+ + + cli.parse({"test", "-abe"}) + + + {?} + + + + + config.abortAfter == 1 + + + 1 == 1 + + + + + config.shouldDebugBreak + + + true + + + + + config.noThrow == true + + + true == true + + + +
+ +
+
+
+ + + cli.parse({"test"}) + + + {?} + + + + + config.useColour == UseColour::Auto + + + 0 == 0 + + + +
+ +
+
+
+ + + cli.parse({"test", "--use-colour", "auto"}) + + + {?} + + + + + config.useColour == UseColour::Auto + + + 0 == 0 + + + +
+ +
+
+
+ + + cli.parse({"test", "--use-colour", "yes"}) + + + {?} + + + + + config.useColour == UseColour::Yes + + + 1 == 1 + + + +
+ +
+
+
+ + + cli.parse({"test", "--use-colour", "no"}) + + + {?} + + + + + config.useColour == UseColour::No + + + 2 == 2 + + + +
+ +
+
+
+ + + !result + + + true + + + + + result.errorMessage(), Contains( "colour mode must be one of" ) + + + "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" + + + +
+ +
+ +
+ + + + truthy(false) + + + Hey, its truthy! + + + + + + + current counter 0 + + + i := 0 + + + + i < 10 + + + 0 < 10 + + + + current counter 1 + + + i := 1 + + + + i < 10 + + + 1 < 10 + + + + current counter 2 + + + i := 2 + + + + i < 10 + + + 2 < 10 + + + + current counter 3 + + + i := 3 + + + + i < 10 + + + 3 < 10 + + + + current counter 4 + + + i := 4 + + + + i < 10 + + + 4 < 10 + + + + current counter 5 + + + i := 5 + + + + i < 10 + + + 5 < 10 + + + + current counter 6 + + + i := 6 + + + + i < 10 + + + 6 < 10 + + + + current counter 7 + + + i := 7 + + + + i < 10 + + + 7 < 10 + + + + current counter 8 + + + i := 8 + + + + i < 10 + + + 8 < 10 + + + + current counter 9 + + + i := 9 + + + + i < 10 + + + 9 < 10 + + + + current counter 10 + + + i := 10 + + + + i < 10 + + + 10 < 10 + + + + + + + + + + + +
+ + + before == 0 + + + 0 == 0 + + +
+
+ + + after > before + + + 1 > 0 + + + +
+ +
+ +
+ +
+ +
+
+
+ + + itDoesThis() + + + true + + +
+ + + itDoesThat() + + + true + + + +
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+ +
+ +
+ + + v.size() == 0 + + + 0 == 0 + + +
+
+ + + v.size() == 10 + + + 10 == 10 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + +
+
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ +
+ +
+ +
+ +
+
+ + + v.size() == 0 + + + 0 == 0 + + +
+
+ + + v.capacity() >= 10 + + + 10 >= 10 + + + + + v.size() == 0 + + + 0 == 0 + + + +
+ +
+ +
+ +
+ + + +A string sent directly to stdout + + +A string sent directly to stderr + + + + + + + d == Approx( 1.23 ) + + + 1.23 == Approx( 1.23 ) + + + + + d != Approx( 1.22 ) + + + 1.23 != Approx( 1.22 ) + + + + + d != Approx( 1.24 ) + + + 1.23 != Approx( 1.24 ) + + + + + Approx( d ) == 1.23 + + + Approx( 1.23 ) == 1.23 + + + + + Approx( d ) != 1.22 + + + Approx( 1.23 ) != 1.22 + + + + + Approx( d ) != 1.24 + + + Approx( 1.23 ) != 1.24 + + + + + +
+ +
+
+ +
+ + +Message from section one +Message from section two + + +
+ + + + testStringForMatching(), StartsWith( "string" ) + + + "this string contains 'abc' as a substring" starts with: "string" + + + + + +
+ + + empty.empty() + + + true + + + + + empty.size() == 0 + + + 0 == 0 + + + + + std::strcmp( empty.c_str(), "" ) == 0 + + + 0 == 0 + + + +
+
+ + + s.empty() == false + + + false == false + + + + + s.size() == 5 + + + 5 == 5 + + + +
+ +
+ + + + testStringForMatching(), Contains( "string" ) + + + "this string contains 'abc' as a substring" contains: "string" + + + + + testStringForMatching(), Contains( "abc" ) + + + "this string contains 'abc' as a substring" contains: "abc" + + + + + testStringForMatching(), StartsWith( "this" ) + + + "this string contains 'abc' as a substring" starts with: "this" + + + + + testStringForMatching(), EndsWith( "substring" ) + + + "this string contains 'abc' as a substring" ends with: "substring" + + + + + +
+ + + sb.capacity() == 0 + + + 0 == 0 + + + + + sb.size() == 0 + + + 0 == 0 + + + + + sb.capacity() == 32 + + + 32 == 32 + + + + + sb.size() == 0 + + + 0 == 0 + + + + + sb.capacity() == 32 + + + 32 == 32 + + + + + sb.size() == 5 + + + 5 == 5 + + + + + s == "hello" + + + {?} == "hello" + + + + + s.size() == 5 + + + 5 == 5 + + + +
+
+ + + s == "hello world" + + + {?} == "hello world" + + + +
+
+ + + s == "hello world" + + + {?} == "hello world" + + + +
+
+ + + sb16.capacity() == 16 + + + 16 == 16 + + + + + sb16.capacity() == 16 + + + 16 == 16 + + + + + s == "hello world" + + + {?} == "hello world" + + + +
+
+
+ + + s2 == s + + + {?} == {?} + + + + + s2.c_str() != s.c_str() + + + "hello" != "hello" + + + +
+ +
+
+
+ + + s2 == "hello" + + + {?} == "hello" + + + + + s2.c_str() == originalPointer + + + "hello" == "hello" + + + +
+ +
+
+
+ + + s2 == "hello" + + + {?} == "hello" + + + + + s2.c_str() != originalPointer + + + "hello" != "hello" + + + +
+ +
+ +
+ +
+ + + empty.empty() + + + true + + + + + empty.size() == 0 + + + 0 == 0 + + + + + std::strcmp( empty.c_str(), "" ) == 0 + + + 0 == 0 + + + +
+
+ + + s.empty() == false + + + false == false + + + + + s.size() == 5 + + + 5 == 5 + + + + + isSubstring( s ) == false + + + false == false + + + + + std::strcmp( rawChars, "hello" ) == 0 + + + 0 == 0 + + +
+ + + isOwned( s ) == false + + + false == false + + + + + s.c_str() == rawChars + + + "hello" == "hello" + + + + + isOwned( s ) == false + + + false == false + + + +
+ +
+
+ + + original == "original" + + + {?} == "original" + + + + + isSubstring( original ) + + + true + + + + + isOwned( original ) == false + + + false == false + + + + + isSubstring( original ) == false + + + false == false + + + + + isOwned( original ) + + + true + + + +
+
+
+ + + ss.empty() == false + + + false == false + + + + + ss.size() == 5 + + + 5 == 5 + + + + + std::strcmp( ss.c_str(), "hello" ) == 0 + + + 0 == 0 + + + + + ss == "hello" + + + {?} == "hello" + + + +
+ +
+
+
+ + + isSubstring( ss ) + + + true + + + + + isOwned( ss ) == false + + + false == false + + + + + rawChars == data( s ) + + + "hello world!" == "hello world!" + + + + + ss.c_str() != rawChars + + + "hello" != "hello world!" + + + + + isSubstring( ss ) == false + + + false == false + + + + + isOwned( ss ) + + + true + + + + + data( ss ) != data( s ) + + + "hello" != "hello world!" + + + +
+ +
+
+
+ + + ss.size() == 6 + + + 6 == 6 + + + + + std::strcmp( ss.c_str(), "world!" ) == 0 + + + 0 == 0 + + + +
+ +
+
+
+ + + s.c_str() == s2.c_str() + + + "hello world!" == "hello world!" + + + +
+ +
+
+
+ + + s.c_str() != ss.c_str() + + + "hello world!" != "hello" + + + +
+ +
+
+ + + StringRef("hello") == StringRef("hello") + + + {?} == {?} + + + + + StringRef("hello") != StringRef("cello") + + + {?} != {?} + + + +
+
+
+ + + copied == "hot potato" + + + {?} == "hot potato" + + + + + str == "hot potato" + + + {?} == "hot potato" + + + + + isOwned( copied ) == false + + + false == false + + + + + data( copied ) == originalPointer + + + "hot potato" == "hot potato" + + + +
+ +
+
+
+ + + copied == "hot potato" + + + {?} == "hot potato" + + + + + isOwned( copied ) + + + true + + + + + str.empty() + + + true + + + + + data( copied ) == originalPointer + + + "hot potato" == "hot potato" + + + +
+ +
+ +
+ + + +hello +hello + + + + + + + s1 == s2 + + + "if ($b == 10) { + $a = 20; +}" +== +"if ($b == 10) { + $a = 20; +} +" + + + + + +
+ + + what, Contains( "[@zzz]" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "[@zzz]" + + + + + what, Contains( "file" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "file" + + + + + what, Contains( "2" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "2" + + + + + what, Contains( "10" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "10" + + + +
+
+ + + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + + + +
+ +
+ + + + + + + 0x == bit30and31 + + + 3221225472 (0x) == 3221225472 + + + + + + + + Text( "hi there" ).toString() == "hi there" + + + "hi there" == "hi there" + + + + + Text( "hi there", narrow ).toString() == "hi\nthere" + + + "hi +there" +== +"hi +there" + + + + + + + + 1 == 2 + + + 1 == 2 + + + + + + + + + + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isSuccessfullyCompleted() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2.isOpen() + + + true + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isSuccessfullyCompleted() + + + true + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isComplete() + + + true + + + + + s2b.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() == false + + + false == false + + + + + s2c.isOpen() == false + + + false == false + + + + + testCase3.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + s1.isComplete() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + testCase.isComplete() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s1.isComplete() == false + + + false == false + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s1.isComplete() == false + + + false == false + + + + + s1b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s2b.isOpen() + + + true + + + + + s2b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + s1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s2.isSuccessfullyCompleted() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 0 + + + 0 == 0 + + + + + s2b.isOpen() == false + + + false == false + + + + + g1b.isComplete() == false + + + false == false + + + + + s1b.isComplete() == false + + + false == false + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() + + + true + + + + + g1c.isOpen() + + + true + + + + + g1c.index() == 1 + + + 1 == 1 + + + + + s2c.isOpen() + + + true + + + + + s2c.isComplete() + + + true + + + + + g1c.isComplete() + + + true + + + + + s1c.isComplete() + + + true + + + + + testCase3.isComplete() + + + true + + + +
+ +
+ +
+ +
+ + + 3.14 + + + + + + + d == approx( 1.23 ) + + + 1.23 == Approx( 1.23 ) + + + + + d == approx( 1.22 ) + + + 1.23 == Approx( 1.22 ) + + + + + d == approx( 1.24 ) + + + 1.23 == Approx( 1.24 ) + + + + + d != approx( 1.25 ) + + + 1.23 != Approx( 1.25 ) + + + + + approx( d ) == 1.23 + + + Approx( 1.23 ) == 1.23 + + + + + approx( d ) == 1.22 + + + Approx( 1.23 ) == 1.22 + + + + + approx( d ) == 1.24 + + + Approx( 1.23 ) == 1.24 + + + + + approx( d ) != 1.25 + + + Approx( 1.23 ) != 1.25 + + + + + +
+ +
+ +
+ +
+ + + v, VectorContains( 1 ) + + + { 1, 2, 3 } Contains: 1 + + + + + v, VectorContains( 2 ) + + + { 1, 2, 3 } Contains: 2 + + + +
+
+ + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2 } + + + + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2, 3 } + + + + + v, Contains( empty) + + + { 1, 2, 3 } Contains: { } + + + + + empty, Contains( empty) + + + { } Contains: { } + + + +
+
+ + + v, Equals( v ) + + + { 1, 2, 3 } Equals: { 1, 2, 3 } + + + + + empty, Equals( empty ) + + + { } Equals: { } + + + + + v, Equals( v2 ) + + + { 1, 2, 3 } Equals: { 1, 2, 3 } + + + +
+ +
+ +
+ + + v, VectorContains( -1 ) + + + { 1, 2, 3 } Contains: -1 + + + + + empty, VectorContains( 1 ) + + + { } Contains: 1 + + + +
+
+ + + empty, Contains( v) + + + { } Contains: { 1, 2, 3 } + + + + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2, 4 } + + + +
+
+ + + v, Equals( v2 ) + + + { 1, 2, 3 } Equals: { 1, 2 } + + + + + v2, Equals( v ) + + + { 1, 2 } Equals: { 1, 2, 3 } + + + + + empty, Equals( v ) + + + { } Equals: { 1, 2, 3 } + + + + + v, Equals( empty ) + + + { 1, 2, 3 } Equals: { } + + + +
+ +
+ + + + thisThrows(), std::domain_error + + + thisThrows(), std::domain_error + + + + + thisDoesntThrow() + + + thisDoesntThrow() + + + + + thisThrows() + + + thisThrows() + + + + + + + unexpected exception + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + +
+ + unexpected exception + + +
+ +
+ + + + + + Uncomment the code in this test to check that it gives a sensible compiler error + + + + + + Uncomment the code in this test to check that it gives a sensible compiler error + + + + + + + + + + + + + + + + +
+ + + encode( "normal string" ) == "normal string" + + + "normal string" == "normal string" + + + +
+
+ + + encode( "" ) == "" + + + "" == "" + + + +
+
+ + + encode( "smith & jones" ) == "smith &amp; jones" + + + "smith &amp; jones" == "smith &amp; jones" + + + +
+
+ + + encode( "smith < jones" ) == "smith &lt; jones" + + + "smith &lt; jones" == "smith &lt; jones" + + + +
+
+ + + encode( "smith > jones" ) == "smith > jones" + + + "smith > jones" == "smith > jones" + + + + + encode( "smith ]]> jones" ) == "smith ]]&gt; jones" + + + "smith ]]&gt; jones" +== +"smith ]]&gt; jones" + + + +
+
+ + + encode( stringWithQuotes ) == stringWithQuotes + + + "don't "quote" me on that" +== +"don't "quote" me on that" + + + + + encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" + + + "don't &quot;quote&quot; me on that" +== +"don't &quot;quote&quot; me on that" + + + +
+
+ + + encode( "[\x01]" ) == "[\\x01]" + + + "[\x01]" == "[\x01]" + + + +
+
+ + + encode( "[\x7F]" ) == "[\\x7F]" + + + "[\x7F]" == "[\x7F]" + + + +
+ +
+ + + + + + + x == 0 + + + 0 == 0 + + + + + + + + obj.prop != 0 + + + 0x != 0 + + + + + + + + flag + + + true + + + + + testCheckedElse( true ) + + + true + + + + + + + + flag + + + false + + + + + testCheckedElse( false ) + + + false + + + + + + + + flag + + + true + + + + + testCheckedIf( true ) + + + true + + + + + + + + flag + + + false + + + + + testCheckedIf( false ) + + + false + + + + + + + + unsigned_char_var == 1 + + + 1 == 1 + + + + + unsigned_short_var == 1 + + + 1 == 1 + + + + + unsigned_int_var == 1 + + + 1 == 1 + + + + + unsigned_long_var == 1 + + + 1 == 1 + + + + + + + + long_var == unsigned_char_var + + + 1 == 1 + + + + + long_var == unsigned_short_var + + + 1 == 1 + + + + + long_var == unsigned_int_var + + + 1 == 1 + + + + + long_var == unsigned_long_var + + + 1 == 1 + + + + + +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ + + + +spanner + + + + Previous info should not be seen + + + + + + + + + + l == std::numeric_limits<long long>::max() + + + 9223372036854775807 (0x) +== +9223372036854775807 (0x) + + + + + +
+ + + b > a + + + 0 > 1 + + + +
+ +
+ + + Testing if fib[0] (1) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[1] (1) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[2] (2) is even + + + + ( fib[i] % 2 ) == 0 + + + 0 == 0 + + + + Testing if fib[3] (3) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[4] (5) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[5] (8) is even + + + + ( fib[i] % 2 ) == 0 + + + 0 == 0 + + + + Testing if fib[6] (13) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[7] (21) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + + +
+
+ + + a == b + + + 1 == 2 + + + +
+ +
+
+
+ + + a != b + + + 1 != 2 + + + +
+ +
+
+
+ + + a < b + + + 1 < 2 + + + +
+ +
+ +
+ +
+ + + a != b + + + 1 != 2 + + + + + b != a + + + 2 != 1 + + +
+ + + a != b + + + 1 != 2 + + + +
+ +
+ +
+ + + + s == "7" + + + "7" == "7" + + + + + + + + + + + makeString( false ) != static_cast<char*>(0) + + + "valid string" != {null string} + + + + + makeString( true ) == static_cast<char*>(0) + + + {null string} == {null string} + + + + + + + + ptr.get() == 0 + + + 0 == 0 + + + + + + + + ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" + + + "{ { 42, "Arthur" }, { "Ford", 24 } }" +== +"{ { 42, "Arthur" }, { "Ford", 24 } }" + + + + + + + + p == 0 + + + 0 == 0 + + + + + +
+ + + a != b + + + 1 != 2 + + + + + b != a + + + 2 != 1 + + + +
+
+ + + a != b + + + 1 != 2 + + + +
+ +
+ +
+ + + replaceInPlace( letters, "b", "z" ) + + + true + + + + + letters == "azcdefcg" + + + "azcdefcg" == "azcdefcg" + + + +
+
+ + + replaceInPlace( letters, "c", "z" ) + + + true + + + + + letters == "abzdefzg" + + + "abzdefzg" == "abzdefzg" + + + +
+
+ + + replaceInPlace( letters, "a", "z" ) + + + true + + + + + letters == "zbcdefcg" + + + "zbcdefcg" == "zbcdefcg" + + + +
+
+ + + replaceInPlace( letters, "g", "z" ) + + + true + + + + + letters == "abcdefcz" + + + "abcdefcz" == "abcdefcz" + + + +
+
+ + + replaceInPlace( letters, letters, "replaced" ) + + + true + + + + + letters == "replaced" + + + "replaced" == "replaced" + + + +
+
+ + + !replaceInPlace( letters, "x", "z" ) + + + !false + + + + + letters == letters + + + "abcdefcg" == "abcdefcg" + + + +
+
+ + + replaceInPlace( s, "'", "|'" ) + + + true + + + + + s == "didn|'t" + + + "didn|'t" == "didn|'t" + + + +
+ +
+ + + + + + 3 + + + + false + + + false + + + + + + + hi + + + i := 7 + + + + false + + + false + + + + + + + + ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" + + + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + + + + + + + + ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" + + + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + + + + + + + + ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" + + + "{ { "green", 55 } }" +== +"{ { "green", 55 } }" + + + + + + + + std::string( "first" ) == "second" + + + "first" == "second" + + + + + + + + ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" + + + "StringMaker<has_maker>" +== +"StringMaker<has_maker>" + + + + + + + + ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" + + + "StringMaker<has_maker_and_operator>" +== +"StringMaker<has_maker_and_operator>" + + + + + + + + ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" + + + "operator<<( has_operator )" +== +"operator<<( has_operator )" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" + + + "{ StringMaker<has_maker> }" +== +"{ StringMaker<has_maker> }" + + + + + + + + ::Catch::Detail::stringify(e0) == "E2/V0" + + + "E2/V0" == "E2/V0" + + + + + ::Catch::Detail::stringify(e1) == "E2/V1" + + + "E2/V1" == "E2/V1" + + + + + ::Catch::Detail::stringify(e3) == "Unknown enum value 10" + + + "Unknown enum value 10" +== +"Unknown enum value 10" + + + + + + + + ::Catch::Detail::stringify(e0) == "0" + + + "{?}" == "0" + + + + + ::Catch::Detail::stringify(e1) == "1" + + + "{?}" == "1" + + + + + + + + ::Catch::Detail::stringify(e0) == "E2{0}" + + + "E2{0}" == "E2{0}" + + + + + ::Catch::Detail::stringify(e1) == "E2{1}" + + + "E2{1}" == "E2{1}" + + + + + + + + ::Catch::Detail::stringify(e0) == "0" + + + "0" == "0" + + + + + ::Catch::Detail::stringify(e1) == "1" + + + "1" == "1" + + + + + + + + "{ }" == ::Catch::Detail::stringify(type{}) + + + "{ }" == "{ }" + + + + + "{ }" == ::Catch::Detail::stringify(value) + + + "{ }" == "{ }" + + + + + + + + "1.2f" == ::Catch::Detail::stringify(float(1.2)) + + + "1.2f" == "1.2f" + + + + + "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) + + + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + + + + + + + + "{ 0 }" == ::Catch::Detail::stringify(type{0}) + + + "{ 0 }" == "{ 0 }" + + + + + + + + "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) + + + "{ 0, 42, "Catch me" }" +== +"{ 0, 42, "Catch me" }" + + + + + + + + "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) + + + "{ "hello", "world" }" +== +"{ "hello", "world" }" + + + + + + + + "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) + + + "{ { 42 }, { }, 1.2f }" +== +"{ { 42 }, { }, 1.2f }" + + + + + + + + ::Catch::Detail::stringify(v) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" + + + "{ { "hello" }, { "world" } }" +== +"{ { "hello" }, { "world" } }" + + + + + + + + ::Catch::Detail::stringify(vv) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42 }" + + + "{ 42 }" == "{ 42 }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42, 250 }" + + + "{ 42, 250 }" == "{ 42, 250 }" + + + + + + + + ::Catch::Detail::stringify(vv) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42 }" + + + "{ 42 }" == "{ 42 }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42, 250 }" + + + "{ 42, 250 }" == "{ 42, 250 }" + + + + + + + + ::Catch::Detail::stringify(vv) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(vv) == "{ \"hello\" }" + + + "{ "hello" }" == "{ "hello" }" + + + + + ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" + + + "{ "hello", "world" }" +== +"{ "hello", "world" }" + + + + + + + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 10 + + + 10 == 10 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 0 + + + 0 == 0 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.capacity() == 0 + + + 0 == 0 + + + +
+ +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
From 74ab1cd94b90886dd54dbf2cc4333fc4ff805291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 20 Jul 2017 00:29:19 +0200 Subject: [PATCH 145/398] Update Baselines --- .../Baselines/console.std.approved.txt | 12 ++++---- .../Baselines/console.sw.approved.txt | 18 ++++++------ .../Baselines/console.swa4.approved.txt | 2 +- .../SelfTest/Baselines/junit.sw.approved.txt | 8 +++--- .../SelfTest/Baselines/xml.sw.approved.txt | 28 +++++++++---------- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 2b41e42a..58571bb2 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -282,11 +282,11 @@ MatchersTests.cpp: ............................................................................... MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) + CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) because no exception was thrown where one was expected: MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) + REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) because no exception was thrown where one was expected: ------------------------------------------------------------------------------- @@ -297,12 +297,12 @@ MatchersTests.cpp: ............................................................................... MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) + CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) due to unexpected exception with message: Unknown exception MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) + REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) due to unexpected exception with message: Unknown exception @@ -314,12 +314,12 @@ MatchersTests.cpp: ............................................................................... MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throws(3), SpecialException const&, ExceptionMatcher{ 1 } ) + CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{ 1 } ) with expansion: {?} special exception has value of 1 MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throws(4), SpecialException const&, ExceptionMatcher{ 1 } ) + REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{ 1 } ) with expansion: {?} special exception has value of 1 diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 0857fc24..61e865c6 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -88,7 +88,7 @@ PASSED: CompilationTests.cpp:: PASSED: - CHECK_THROWS_AS( throws_int(true), const int& ) + CHECK_THROWS_AS( throws_int(true), int ) CompilationTests.cpp:: PASSED: @@ -1359,11 +1359,11 @@ MatchersTests.cpp: ............................................................................... MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) + CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) because no exception was thrown where one was expected: MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } ) + REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) because no exception was thrown where one was expected: ------------------------------------------------------------------------------- @@ -1374,12 +1374,12 @@ MatchersTests.cpp: ............................................................................... MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) + CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) due to unexpected exception with message: Unknown exception MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } ) + REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) due to unexpected exception with message: Unknown exception @@ -1391,12 +1391,12 @@ MatchersTests.cpp: ............................................................................... MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throws(3), SpecialException const&, ExceptionMatcher{ 1 } ) + CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{ 1 } ) with expansion: {?} special exception has value of 1 MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throws(4), SpecialException const&, ExceptionMatcher{ 1 } ) + REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{ 1 } ) with expansion: {?} special exception has value of 1 @@ -1408,13 +1408,13 @@ MatchersTests.cpp: MatchersTests.cpp:: PASSED: - CHECK_THROWS_MATCHES( throws(1), SpecialException const&, ExceptionMatcher{ 1 } ) + CHECK_THROWS_MATCHES( throws(1), SpecialException, ExceptionMatcher{ 1 } ) with expansion: {?} special exception has value of 1 MatchersTests.cpp:: PASSED: - REQUIRE_THROWS_MATCHES( throws(2), SpecialException const&, ExceptionMatcher{ 2 } ) + REQUIRE_THROWS_MATCHES( throws(2), SpecialException, ExceptionMatcher{ 2 } ) with expansion: {?} special exception has value of 2 diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index b1cf14f3..fe22e2b3 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -88,7 +88,7 @@ PASSED: CompilationTests.cpp:: PASSED: - CHECK_THROWS_AS( throws_int(true), const int& ) + CHECK_THROWS_AS( throws_int(true), int ) CompilationTests.cpp:: PASSED: diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 6f09f338..bd931044 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -194,19 +194,19 @@ MatchersTests.cpp:
- + MatchersTests.cpp: - + MatchersTests.cpp: - + Unknown exception MatchersTests.cpp: - + Unknown exception MatchersTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index c18f5c94..5b4ecb9e 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -85,10 +85,10 @@ - throws_int(true), const int& + throws_int(true), int - throws_int(true), const int& + throws_int(true), int @@ -1558,18 +1558,18 @@
- doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - doesNotThrow(), SpecialException const&, ExceptionMatcher{ 1 } + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } @@ -1577,10 +1577,10 @@
- throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } Unknown exception @@ -1588,10 +1588,10 @@ - throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - throwsAsInt(1), SpecialException const&, ExceptionMatcher{ 1 } + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } Unknown exception @@ -1602,7 +1602,7 @@
- throws(3), SpecialException const&, ExceptionMatcher{ 1 } + throws(3), SpecialException, ExceptionMatcher{ 1 } {?} special exception has value of 1 @@ -1610,7 +1610,7 @@ - throws(4), SpecialException const&, ExceptionMatcher{ 1 } + throws(4), SpecialException, ExceptionMatcher{ 1 } {?} special exception has value of 1 @@ -1623,7 +1623,7 @@ - throws(1), SpecialException const&, ExceptionMatcher{ 1 } + throws(1), SpecialException, ExceptionMatcher{ 1 } {?} special exception has value of 1 @@ -1631,7 +1631,7 @@ - throws(2), SpecialException const&, ExceptionMatcher{ 2 } + throws(2), SpecialException, ExceptionMatcher{ 2 } {?} special exception has value of 2 From f0890dcdf89d305862d0ba3518752c4becb65773 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 15:57:17 +0100 Subject: [PATCH 146/398] removed redundant virtuals on override functions (and added a couple of overrides) --- include/internal/catch_config.hpp | 26 ++++----- include/internal/catch_expression_lhs.hpp | 10 ++-- include/internal/catch_matchers.hpp | 12 ++-- include/internal/catch_matchers_string.h | 10 ++-- include/internal/catch_matchers_vector.h | 6 +- include/internal/catch_objc.hpp | 18 +++--- include/internal/catch_registry_hub.cpp | 22 ++++---- include/internal/catch_reporter_registry.hpp | 8 +-- include/internal/catch_result_builder.h | 2 +- include/internal/catch_stream.h | 12 ++-- include/internal/catch_tag_alias_registry.h | 6 +- .../catch_test_case_registry_impl.hpp | 4 +- include/internal/catch_test_case_tracker.hpp | 40 ++++++------- include/reporters/catch_reporter_automake.hpp | 10 ++-- include/reporters/catch_reporter_bases.hpp | 56 +++++++++---------- include/reporters/catch_reporter_compact.cpp | 6 +- include/reporters/catch_reporter_console.cpp | 19 +++---- include/reporters/catch_reporter_junit.cpp | 18 +++--- include/reporters/catch_reporter_multi.h | 41 +++++--------- include/reporters/catch_reporter_tap.hpp | 14 ++--- include/reporters/catch_reporter_teamcity.hpp | 21 ++++--- include/reporters/catch_reporter_xml.cpp | 24 ++++---- projects/SelfTest/MatchersTests.cpp | 4 +- 23 files changed, 183 insertions(+), 206 deletions(-) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 36894bec..531543c2 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -80,19 +80,19 @@ namespace Catch { bool showHelp() const; // IConfig interface - virtual bool allowThrows() const override; - virtual std::ostream& stream() const override; - virtual std::string name() const override; - virtual bool includeSuccessfulResults() const override; - virtual bool warnAboutMissingAssertions() const override; - virtual ShowDurations::OrNot showDurations() const override; - virtual RunTests::InWhatOrder runOrder() const override; - virtual unsigned int rngSeed() const override; - virtual UseColour::YesOrNo useColour() const override; - virtual bool shouldDebugBreak() const override; - virtual int abortAfter() const override; - virtual bool showInvisibles() const override; - virtual Verbosity verbosity() const override; + bool allowThrows() const override; + std::ostream& stream() const override; + std::string name() const override; + bool includeSuccessfulResults() const override; + bool warnAboutMissingAssertions() const override; + ShowDurations::OrNot showDurations() const override; + RunTests::InWhatOrder runOrder() const override; + unsigned int rngSeed() const override; + UseColour::YesOrNo useColour() const override; + bool shouldDebugBreak() const override; + int abortAfter() const override; + bool showInvisibles() const override; + Verbosity verbosity() const override; private: diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index dc32fff7..67db9d65 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -81,7 +81,7 @@ public: .endExpression( *this ); } - virtual void reconstructExpression( std::string& dest ) const override { + void reconstructExpression( std::string& dest ) const override { dest = ::Catch::Detail::stringify( m_lhs ); } @@ -117,11 +117,11 @@ public: .endExpression( *this ); } - virtual bool isBinaryExpression() const override { + bool isBinaryExpression() const override { return true; } - virtual void reconstructExpression( std::string& dest ) const override { + void reconstructExpression( std::string& dest ) const override { std::string lhs = ::Catch::Detail::stringify( m_lhs ); std::string rhs = ::Catch::Detail::stringify( m_rhs ); char delim = lhs.size() + rhs.size() < 40 && @@ -151,11 +151,11 @@ public: MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} - virtual bool isBinaryExpression() const override { + bool isBinaryExpression() const override { return true; } - virtual void reconstructExpression( std::string& dest ) const override { + void reconstructExpression( std::string& dest ) const override { std::string matcherAsString = m_matcher.toString(); dest = ::Catch::Detail::stringify( m_arg ); dest += ' '; diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 2083db73..4f41cb01 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -53,14 +53,14 @@ namespace Matchers { template struct MatchAllOf : MatcherBase { - virtual bool match( ArgT const& arg ) const override { + bool match( ArgT const& arg ) const override { for( auto matcher : m_matchers ) { if (!matcher->match(arg)) return false; } return true; } - virtual std::string describe() const override { + std::string describe() const override { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; @@ -86,14 +86,14 @@ namespace Matchers { template struct MatchAnyOf : MatcherBase { - virtual bool match( ArgT const& arg ) const override { + bool match( ArgT const& arg ) const override { for( auto matcher : m_matchers ) { if (matcher->match(arg)) return true; } return false; } - virtual std::string describe() const override { + std::string describe() const override { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; @@ -122,11 +122,11 @@ namespace Matchers { MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} - virtual bool match( ArgT const& arg ) const override { + bool match( ArgT const& arg ) const override { return !m_underlyingMatcher.match( arg ); } - virtual std::string describe() const override { + std::string describe() const override { return "not " + m_underlyingMatcher.toString(); } MatcherBase const& m_underlyingMatcher; diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index 2192ee8f..eca35789 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -29,7 +29,7 @@ namespace Matchers { struct StringMatcherBase : MatcherBase { StringMatcherBase( std::string const& operation, CasedString const& comparator ); - virtual std::string describe() const override; + std::string describe() const override; CasedString m_comparator; std::string m_operation; @@ -37,19 +37,19 @@ namespace Matchers { struct EqualsMatcher : StringMatcherBase { EqualsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const override; + bool match( std::string const& source ) const override; }; struct ContainsMatcher : StringMatcherBase { ContainsMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const override; + bool match( std::string const& source ) const override; }; struct StartsWithMatcher : StringMatcherBase { StartsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const override; + bool match( std::string const& source ) const override; }; struct EndsWithMatcher : StringMatcherBase { EndsWithMatcher( CasedString const& comparator ); - virtual bool match( std::string const& source ) const override; + bool match( std::string const& source ) const override; }; } // namespace StdString diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index e80f7e12..1f9e0a61 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -24,7 +24,7 @@ namespace Matchers { return std::find(v.begin(), v.end(), m_comparator) != v.end(); } - virtual std::string describe() const override { + std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } @@ -45,7 +45,7 @@ namespace Matchers { return false; return true; } - virtual std::string describe() const override { + std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } @@ -69,7 +69,7 @@ namespace Matchers { return false; return true; } - virtual std::string describe() const override { + std::string describe() const override { return "Equals: " + ::Catch::Detail::stringify( m_comparator ); } std::vector const& m_comparator; diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 8b11d83e..350dc72c 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -112,7 +112,7 @@ namespace Catch { arcSafeRelease( m_substr ); } - virtual bool match( NSString* arg ) const override { + bool match( NSString* arg ) const override { return false; } @@ -122,12 +122,12 @@ namespace Catch { struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const override { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } - virtual std::string describe() const override { + std::string describe() const override { return "equals string: " + Catch::toString( m_substr ); } }; @@ -135,12 +135,12 @@ namespace Catch { struct Contains : StringHolder { Contains( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const { + bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location != NSNotFound; } - virtual std::string describe() const override { + std::string describe() const override { return "contains string: " + Catch::toString( m_substr ); } }; @@ -148,24 +148,24 @@ namespace Catch { struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } - virtual std::string describe() const override { + std::string describe() const override { return "starts with: " + Catch::toString( m_substr ); } }; struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} - virtual bool match( NSString* str ) const { + bool match( NSString* str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } - virtual std::string describe() const override { + std::string describe() const override { return "ends with: " + Catch::toString( m_substr ); } }; diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 12af6e38..01208e77 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -24,39 +24,39 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const override { + IReporterRegistry const& getReporterRegistry() const override { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const override { + ITestCaseRegistry const& getTestCaseRegistry() const override { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { + IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { return m_exceptionTranslatorRegistry; } - virtual ITagAliasRegistry const& getTagAliasRegistry() const override { + ITagAliasRegistry const& getTagAliasRegistry() const override { return m_tagAliasRegistry; } - virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const override { + StartupExceptionRegistry const& getStartupExceptionRegistry() const override { return m_exceptionRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerListener( IReporterFactoryPtr const& factory ) override { + void registerListener( IReporterFactoryPtr const& factory ) override { m_reporterRegistry.registerListener( factory ); } - virtual void registerTest( TestCase const& testInfo ) override { + void registerTest( TestCase const& testInfo ) override { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) override { + void registerTranslator( const IExceptionTranslator* translator ) override { m_exceptionTranslatorRegistry.registerTranslator( translator ); } - virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { + void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { m_tagAliasRegistry.add( alias, tag, lineInfo ); } - virtual void registerStartupException( std::exception_ptr const& exception ) noexcept override { + void registerStartupException( std::exception_ptr const& exception ) noexcept override { m_exceptionRegistry.add(exception); } diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index 9556fb31..0c015fb9 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -18,9 +18,9 @@ namespace Catch { public: - virtual ~ReporterRegistry() override {} + ~ReporterRegistry() override {} - virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { + IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return nullptr; @@ -34,10 +34,10 @@ namespace Catch { m_listeners.push_back( factory ); } - virtual FactoryMap const& getFactories() const override { + FactoryMap const& getFactories() const override { return m_factories; } - virtual Listeners const& getListeners() const override { + Listeners const& getListeners() const override { return m_listeners; } diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index d442ce40..4c5c5d80 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -50,7 +50,7 @@ namespace Catch { void endExpression( DecomposedExpression const& expr ); - virtual void reconstructExpression( std::string& dest ) const override; + void reconstructExpression( std::string& dest ) const override; AssertionResult build() const; AssertionResult build( DecomposedExpression const& expr ) const; diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index baa10c44..8f2fb5a6 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -31,9 +31,9 @@ namespace Catch { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); - virtual ~FileStream() noexcept; + ~FileStream() noexcept override; public: // IStream - virtual std::ostream& stream() const override; + std::ostream& stream() const override; }; @@ -41,10 +41,10 @@ namespace Catch { mutable std::ostream m_os; public: CoutStream(); - virtual ~CoutStream() noexcept; + ~CoutStream() noexcept override; public: // IStream - virtual std::ostream& stream() const override; + std::ostream& stream() const override; }; @@ -53,10 +53,10 @@ namespace Catch { mutable std::ostream m_os; public: DebugOutStream(); - virtual ~DebugOutStream() noexcept; + ~DebugOutStream() noexcept override; public: // IStream - virtual std::ostream& stream() const override; + std::ostream& stream() const override; }; } diff --git a/include/internal/catch_tag_alias_registry.h b/include/internal/catch_tag_alias_registry.h index aea41275..d05c7739 100644 --- a/include/internal/catch_tag_alias_registry.h +++ b/include/internal/catch_tag_alias_registry.h @@ -16,9 +16,9 @@ namespace Catch { class TagAliasRegistry : public ITagAliasRegistry { public: - virtual ~TagAliasRegistry(); - virtual Option find( std::string const& alias ) const; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + ~TagAliasRegistry() override; + Option find( std::string const& alias ) const override; + std::string expandAliases( std::string const& unexpandedTestSpec ) const override; void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); private: diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 5bb32f5e..068ffe58 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -96,10 +96,10 @@ namespace Catch { m_functions.push_back( testCase ); } - virtual std::vector const& getAllTests() const { + std::vector const& getAllTests() const override { return m_functions; } - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + std::vector const& getAllTestsSorted( IConfig const& config ) const override { if( m_sortedFunctions.empty() ) enforceNoDuplicateTestCases( m_functions ); diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 964b45f9..39509300 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -59,7 +59,7 @@ namespace TestCaseTracking { virtual bool isIndexTracker() const = 0; }; - class TrackerContext { + class TrackerContext { enum RunState { NotStarted, @@ -113,30 +113,29 @@ namespace TestCaseTracking { public: TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - virtual ~TrackerBase() = default; - virtual NameAndLocation const& nameAndLocation() const override; - virtual bool isComplete() const override; - virtual bool isSuccessfullyCompleted() const override; - virtual bool isOpen() const override; - virtual bool hasChildren() const override; + NameAndLocation const& nameAndLocation() const override; + bool isComplete() const override; + bool isSuccessfullyCompleted() const override; + bool isOpen() const override; + bool hasChildren() const override; - virtual void addChild( ITrackerPtr const& child ) override; + void addChild( ITrackerPtr const& child ) override; - virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; - virtual ITracker& parent() override; + ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; + ITracker& parent() override; - virtual void openChild() override; + void openChild() override; - virtual bool isSectionTracker() const override; - virtual bool isIndexTracker() const override; + bool isSectionTracker() const override; + bool isIndexTracker() const override; void open(); - virtual void close() override; - virtual void fail() override; - virtual void markAsNeedingAnotherRun() override; + void close() override; + void fail() override; + void markAsNeedingAnotherRun() override; private: void moveToParent(); @@ -147,9 +146,8 @@ namespace TestCaseTracking { std::vector m_filters; public: SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - virtual ~SectionTracker() = default; - virtual bool isSectionTracker() const override; + bool isSectionTracker() const override; static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); @@ -164,17 +162,15 @@ namespace TestCaseTracking { int m_index = -1; public: IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); - virtual ~IndexTracker() = default; - virtual bool isIndexTracker() const override; + bool isIndexTracker() const override; + void close() override; static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); int index() const; void moveNext(); - - virtual void close() override; }; } // namespace TestCaseTracking diff --git a/include/reporters/catch_reporter_automake.hpp b/include/reporters/catch_reporter_automake.hpp index 7a841a1a..86eb0325 100644 --- a/include/reporters/catch_reporter_automake.hpp +++ b/include/reporters/catch_reporter_automake.hpp @@ -21,17 +21,17 @@ namespace Catch { : StreamingReporterBase( _config ) {} - virtual ~AutomakeReporter(); + ~AutomakeReporter() override; static std::string getDescription() { return "Reports test results in the format of Automake .trs files"; } - virtual void assertionStarting( AssertionInfo const& ) override {} + void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& /*_assertionStats*/ ) override { return true; } + bool assertionEnded( AssertionStats const& /*_assertionStats*/ ) override { return true; } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) override { + void testCaseEnded( TestCaseStats const& _testCaseStats ) override { // Possible values to emit are PASS, XFAIL, SKIP, FAIL, XPASS and ERROR. stream << ":test-result: "; if (_testCaseStats.totals.assertions.allPassed()) { @@ -45,7 +45,7 @@ namespace Catch { StreamingReporterBase::testCaseEnded( _testCaseStats ); } - virtual void skipTest( TestCaseInfo const& testInfo ) override { + void skipTest( TestCaseInfo const& testInfo ) override { stream << ":test-result: SKIP " << testInfo.name << '\n'; } diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index ccb44f00..85adc18f 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -32,7 +32,7 @@ namespace Catch { CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); } - virtual ReporterPreferences getPreferences() const override { + ReporterPreferences getPreferences() const override { return m_reporterPrefs; } @@ -40,40 +40,40 @@ namespace Catch { return { Verbosity::Normal }; } - virtual ~StreamingReporterBase() override = default; + ~StreamingReporterBase() override = default; - virtual void noMatchingTestCases(std::string const&) override {} + void noMatchingTestCases(std::string const&) override {} - virtual void testRunStarting(TestRunInfo const& _testRunInfo) override { + void testRunStarting(TestRunInfo const& _testRunInfo) override { currentTestRunInfo = _testRunInfo; } - virtual void testGroupStarting(GroupInfo const& _groupInfo) override { + void testGroupStarting(GroupInfo const& _groupInfo) override { currentGroupInfo = _groupInfo; } - virtual void testCaseStarting(TestCaseInfo const& _testInfo) override { + void testCaseStarting(TestCaseInfo const& _testInfo) override { currentTestCaseInfo = _testInfo; } - virtual void sectionStarting(SectionInfo const& _sectionInfo) override { + void sectionStarting(SectionInfo const& _sectionInfo) override { m_sectionStack.push_back(_sectionInfo); } - virtual void sectionEnded(SectionStats const& /* _sectionStats */) override { + void sectionEnded(SectionStats const& /* _sectionStats */) override { m_sectionStack.pop_back(); } - virtual void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { + void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { currentTestCaseInfo.reset(); } - virtual void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { + void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { currentGroupInfo.reset(); } - virtual void testRunEnded(TestRunStats const& /* _testRunStats */) override { + void testRunEnded(TestRunStats const& /* _testRunStats */) override { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } - virtual void skipTest(TestCaseInfo const&) override { + void skipTest(TestCaseInfo const&) override { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } @@ -144,9 +144,9 @@ namespace Catch { m_reporterPrefs.shouldRedirectStdOut = false; CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); } - virtual ~CumulativeReporterBase() = default; + ~CumulativeReporterBase() override = default; - virtual ReporterPreferences getPreferences() const override { + ReporterPreferences getPreferences() const override { return m_reporterPrefs; } @@ -154,12 +154,12 @@ namespace Catch { return { Verbosity::Normal }; } - virtual void testRunStarting( TestRunInfo const& ) override {} - virtual void testGroupStarting( GroupInfo const& ) override {} + void testRunStarting( TestRunInfo const& ) override {} + void testGroupStarting( GroupInfo const& ) override {} - virtual void testCaseStarting( TestCaseInfo const& ) override {} + void testCaseStarting( TestCaseInfo const& ) override {} - virtual void sectionStarting( SectionInfo const& sectionInfo ) override { + void sectionStarting( SectionInfo const& sectionInfo ) override { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); std::shared_ptr node; if( m_sectionStack.empty() ) { @@ -184,9 +184,9 @@ namespace Catch { m_deepestSection = node; } - virtual void assertionStarting(AssertionInfo const&) override {} + void assertionStarting(AssertionInfo const&) override {} - virtual bool assertionEnded(AssertionStats const& assertionStats) override { + bool assertionEnded(AssertionStats const& assertionStats) override { assert(!m_sectionStack.empty()); SectionNode& sectionNode = *m_sectionStack.back(); sectionNode.assertions.push_back(assertionStats); @@ -198,13 +198,13 @@ namespace Catch { prepareExpandedExpression(sectionNode.assertions.back().assertionResult); return true; } - virtual void sectionEnded(SectionStats const& sectionStats) override { + void sectionEnded(SectionStats const& sectionStats) override { assert(!m_sectionStack.empty()); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } - virtual void testCaseEnded(TestCaseStats const& testCaseStats) override { + void testCaseEnded(TestCaseStats const& testCaseStats) override { auto node = std::make_shared(testCaseStats); assert(m_sectionStack.size() == 0); node->children.push_back(m_rootSection); @@ -215,12 +215,12 @@ namespace Catch { m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } - virtual void testGroupEnded(TestGroupStats const& testGroupStats) override { + void testGroupEnded(TestGroupStats const& testGroupStats) override { auto node = std::make_shared(testGroupStats); node->children.swap(m_testCases); m_testGroups.push_back(node); } - virtual void testRunEnded(TestRunStats const& testRunStats) override { + void testRunEnded(TestRunStats const& testRunStats) override { auto node = std::make_shared(testRunStats); node->children.swap(m_testGroups); m_testRuns.push_back(node); @@ -228,9 +228,9 @@ namespace Catch { } virtual void testRunEndedCumulative() = 0; - virtual void skipTest(TestCaseInfo const&) override {} + void skipTest(TestCaseInfo const&) override {} - virtual void prepareExpandedExpression(AssertionResult& result) const { + void prepareExpandedExpression(AssertionResult& result) const { if (result.isOk()) result.discardDecomposedExpression(); else @@ -266,8 +266,8 @@ namespace Catch { struct TestEventListenerBase : StreamingReporterBase { TestEventListenerBase( ReporterConfig const& _config ); - virtual void assertionStarting(AssertionInfo const&) override; - virtual bool assertionEnded(AssertionStats const&) override; + void assertionStarting(AssertionInfo const&) override; + bool assertionEnded(AssertionStats const&) override; }; } // end namespace Catch diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp index 7ad9d6b0..1c4b9d56 100644 --- a/include/reporters/catch_reporter_compact.cpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -17,7 +17,7 @@ namespace Catch { using StreamingReporterBase::StreamingReporterBase; - virtual ~CompactReporter(); + ~CompactReporter() override; static std::string getDescription() { return "Reports test results on a single line, suitable for IDEs"; @@ -54,7 +54,7 @@ namespace Catch { return true; } - virtual void sectionEnded(SectionStats const& _sectionStats) override { + void sectionEnded(SectionStats const& _sectionStats) override { if (m_config->showDurations() == ShowDurations::Always) { stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } @@ -73,7 +73,6 @@ namespace Catch { AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ) - , stats( _stats ) , result( _stats.assertionResult ) , messages( _stats.infoMessages ) , itMessage( _stats.infoMessages.begin() ) @@ -241,7 +240,6 @@ namespace Catch { private: std::ostream& stream; - AssertionStats const& stats; AssertionResult const& result; std::vector messages; std::vector::const_iterator itMessage; diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 228abc3f..3643c1df 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -22,19 +22,18 @@ namespace Catch { using StreamingReporterBase::StreamingReporterBase; - virtual ~ConsoleReporter() override; + ~ConsoleReporter() override; static std::string getDescription() { return "Reports test results as plain lines of text"; } - virtual void noMatchingTestCases( std::string const& spec ) override { + void noMatchingTestCases( std::string const& spec ) override { stream << "No test cases matched '" << spec << '\'' << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) override { - } + void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& _assertionStats ) override { + bool assertionEnded( AssertionStats const& _assertionStats ) override { AssertionResult const& result = _assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); @@ -51,11 +50,11 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) override { + void sectionStarting( SectionInfo const& _sectionInfo ) override { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& _sectionStats ) override { + void sectionEnded( SectionStats const& _sectionStats ) override { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -74,11 +73,11 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) override { + void testCaseEnded( TestCaseStats const& _testCaseStats ) override { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) override { + void testGroupEnded( TestGroupStats const& _testGroupStats ) override { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -87,7 +86,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) override { + void testRunEnded( TestRunStats const& _testRunStats ) override { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp index ca933e3e..1235281a 100644 --- a/include/reporters/catch_reporter_junit.cpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -57,20 +57,20 @@ namespace Catch { m_reporterPrefs.shouldRedirectStdOut = true; } - virtual ~JunitReporter() override; + ~JunitReporter() override; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } - virtual void noMatchingTestCases( std::string const& /*spec*/ ) override {} + void noMatchingTestCases( std::string const& /*spec*/ ) override {} - virtual void testRunStarting( TestRunInfo const& runInfo ) override { + void testRunStarting( TestRunInfo const& runInfo ) override { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) override { + void testGroupStarting( GroupInfo const& groupInfo ) override { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); @@ -78,28 +78,28 @@ namespace Catch { CumulativeReporterBase::testGroupStarting( groupInfo ); } - virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) override { + void testCaseStarting( TestCaseInfo const& testCaseInfo ) override { m_okToFail = testCaseInfo.okToFail(); } - virtual bool assertionEnded( AssertionStats const& assertionStats ) override { + bool assertionEnded( AssertionStats const& assertionStats ) override { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { + void testCaseEnded( TestCaseStats const& testCaseStats ) override { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { + void testGroupEnded( TestGroupStats const& testGroupStats ) override { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } - virtual void testRunEndedCumulative() override { + void testRunEndedCumulative() override { xml.endElement(); } diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_multi.h index ab6d5077..ce9bb87d 100644 --- a/include/reporters/catch_reporter_multi.h +++ b/include/reporters/catch_reporter_multi.h @@ -18,40 +18,27 @@ namespace Catch { public: // IStreamingReporter - virtual ReporterPreferences getPreferences() const override; + ReporterPreferences getPreferences() const override; - virtual void noMatchingTestCases( std::string const& spec ) override; + void noMatchingTestCases( std::string const& spec ) override; static std::set getSupportedVerbosities(); - virtual void testRunStarting( TestRunInfo const& testRunInfo ) override; - - virtual void testGroupStarting( GroupInfo const& groupInfo ) override; - - - virtual void testCaseStarting( TestCaseInfo const& testInfo ) override; - - virtual void sectionStarting( SectionInfo const& sectionInfo ) override; - - - virtual void assertionStarting( AssertionInfo const& assertionInfo ) override; - + void testRunStarting( TestRunInfo const& testRunInfo ) override; + void testGroupStarting( GroupInfo const& groupInfo ) override; + void testCaseStarting( TestCaseInfo const& testInfo ) override; + void sectionStarting( SectionInfo const& sectionInfo ) override; + void assertionStarting( AssertionInfo const& assertionInfo ) override; // The return value indicates if the messages buffer should be cleared: - virtual bool assertionEnded( AssertionStats const& assertionStats ) override; + bool assertionEnded( AssertionStats const& assertionStats ) override; + void sectionEnded( SectionStats const& sectionStats ) override; + void testCaseEnded( TestCaseStats const& testCaseStats ) override; + void testGroupEnded( TestGroupStats const& testGroupStats ) override; + void testRunEnded( TestRunStats const& testRunStats ) override; - virtual void sectionEnded( SectionStats const& sectionStats ) override; - - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override; - - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override; - - virtual void testRunEnded( TestRunStats const& testRunStats ) override; - - - virtual void skipTest( TestCaseInfo const& testInfo ) override; - - virtual bool isMulti() const override; + void skipTest( TestCaseInfo const& testInfo ) override; + bool isMulti() const override; }; diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index 00bd017d..1d1093b8 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -23,25 +23,25 @@ namespace Catch { using StreamingReporterBase::StreamingReporterBase; - virtual ~TAPReporter(); + ~TAPReporter() override; static std::string getDescription() { return "Reports test results in TAP format, suitable for test harneses"; } - virtual ReporterPreferences getPreferences() const { + ReporterPreferences getPreferences() const override { ReporterPreferences prefs; prefs.shouldRedirectStdOut = false; return prefs; } - virtual void noMatchingTestCases( std::string const& spec ) { + void noMatchingTestCases( std::string const& spec ) override { stream << "# No test cases matched '" << spec << "'" << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) {} + void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + bool assertionEnded( AssertionStats const& _assertionStats ) override { ++counter; AssertionPrinter printer( stream, _assertionStats, counter ); @@ -52,7 +52,7 @@ namespace Catch { return true; } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { + void testRunEnded( TestRunStats const& _testRunStats ) override { printTotals( _testRunStats.totals ); stream << "\n" << std::endl; StreamingReporterBase::testRunEnded( _testRunStats ); @@ -66,7 +66,6 @@ namespace Catch { AssertionPrinter( AssertionPrinter const& ) = delete; AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, size_t counter ) : stream( _stream ) - , stats( _stats ) , result( _stats.assertionResult ) , messages( _stats.infoMessages ) , itMessage( _stats.infoMessages.begin() ) @@ -229,7 +228,6 @@ namespace Catch { private: std::ostream& stream; - AssertionStats const& stats; AssertionResult const& result; std::vector messages; std::vector::const_iterator itMessage; diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index a0252407..c9280a69 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -42,33 +42,32 @@ namespace Catch { replaceInPlace( escaped, "]", "|]" ); return escaped; } - virtual ~TeamCityReporter() override; + ~TeamCityReporter() override; static std::string getDescription() { return "Reports test results as TeamCity service messages"; } - virtual void skipTest( TestCaseInfo const& /* testInfo */ ) override { + void skipTest( TestCaseInfo const& /* testInfo */ ) override { } - virtual void noMatchingTestCases( std::string const& /* spec */ ) override {} + void noMatchingTestCases( std::string const& /* spec */ ) override {} - virtual void testGroupStarting( GroupInfo const& groupInfo ) override { + void testGroupStarting( GroupInfo const& groupInfo ) override { StreamingReporterBase::testGroupStarting( groupInfo ); stream << "##teamcity[testSuiteStarted name='" << escape( groupInfo.name ) << "']\n"; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { + void testGroupEnded( TestGroupStats const& testGroupStats ) override { StreamingReporterBase::testGroupEnded( testGroupStats ); stream << "##teamcity[testSuiteFinished name='" << escape( testGroupStats.groupInfo.name ) << "']\n"; } - virtual void assertionStarting( AssertionInfo const& ) override { - } + void assertionStarting( AssertionInfo const& ) override {} - virtual bool assertionEnded( AssertionStats const& assertionStats ) override { + bool assertionEnded( AssertionStats const& assertionStats ) override { AssertionResult const& result = assertionStats.assertionResult; if( !result.isOk() ) { @@ -139,19 +138,19 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& sectionInfo ) override { + void sectionStarting( SectionInfo const& sectionInfo ) override { m_headerPrintedForThisSection = false; StreamingReporterBase::sectionStarting( sectionInfo ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) override { + void testCaseStarting( TestCaseInfo const& testInfo ) override { m_testTimer.start(); StreamingReporterBase::testCaseStarting( testInfo ); stream << "##teamcity[testStarted name='" << escape( testInfo.name ) << "']\n"; } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { + void testCaseEnded( TestCaseStats const& testCaseStats ) override { StreamingReporterBase::testCaseEnded( testCaseStats ); if( !testCaseStats.stdOut.empty() ) stream << "##teamcity[testStdOut name='" diff --git a/include/reporters/catch_reporter_xml.cpp b/include/reporters/catch_reporter_xml.cpp index 3685f0d4..9e2ed08b 100644 --- a/include/reporters/catch_reporter_xml.cpp +++ b/include/reporters/catch_reporter_xml.cpp @@ -23,7 +23,7 @@ namespace Catch { m_reporterPrefs.shouldRedirectStdOut = true; } - virtual ~XmlReporter() override; + ~XmlReporter() override; static std::string getDescription() { return "Reports test results as an XML document"; @@ -41,11 +41,11 @@ namespace Catch { public: // StreamingReporterBase - virtual void noMatchingTestCases( std::string const& s ) override { + void noMatchingTestCases( std::string const& s ) override { StreamingReporterBase::noMatchingTestCases( s ); } - virtual void testRunStarting( TestRunInfo const& testInfo ) override { + void testRunStarting( TestRunInfo const& testInfo ) override { StreamingReporterBase::testRunStarting( testInfo ); std::string stylesheetRef = getStylesheetRef(); if( !stylesheetRef.empty() ) @@ -55,13 +55,13 @@ namespace Catch { m_xml.writeAttribute( "name", m_config->name() ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) override { + void testGroupStarting( GroupInfo const& groupInfo ) override { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) override { + void testCaseStarting( TestCaseInfo const& testInfo ) override { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ) .writeAttribute( "name", trim( testInfo.name ) ) @@ -75,7 +75,7 @@ namespace Catch { m_xml.ensureTagClosed(); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) override { + void sectionStarting( SectionInfo const& sectionInfo ) override { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) @@ -86,9 +86,9 @@ namespace Catch { } } - virtual void assertionStarting( AssertionInfo const& ) override { } + void assertionStarting( AssertionInfo const& ) override { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) override { + bool assertionEnded( AssertionStats const& assertionStats ) override { AssertionResult const& result = assertionStats.assertionResult; @@ -163,7 +163,7 @@ namespace Catch { return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) override { + void sectionEnded( SectionStats const& sectionStats ) override { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); @@ -178,7 +178,7 @@ namespace Catch { } } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override { + void testCaseEnded( TestCaseStats const& testCaseStats ) override { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); @@ -194,7 +194,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override { + void testGroupEnded( TestGroupStats const& testGroupStats ) override { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) @@ -204,7 +204,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testRunEnded( TestRunStats const& testRunStats ) override { + void testRunEnded( TestRunStats const& testRunStats ) override { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) diff --git a/projects/SelfTest/MatchersTests.cpp b/projects/SelfTest/MatchersTests.cpp index a4f8a45f..814577e9 100644 --- a/projects/SelfTest/MatchersTests.cpp +++ b/projects/SelfTest/MatchersTests.cpp @@ -192,11 +192,11 @@ class ExceptionMatcher : public Catch::MatcherBase { int m_expected; public: ExceptionMatcher(int i):m_expected(i) {} - virtual bool match(SpecialException const& se) const override { + bool match(SpecialException const& se) const override { return se.i == m_expected; } - virtual std::string describe() const override { + std::string describe() const override { std::ostringstream ss; ss << "special exception has value of " << m_expected; return ss.str(); From b2a4dfcda41c856c80ea6764373f7691d9e591d8 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 19:42:06 +0100 Subject: [PATCH 147/398] Embedded version of Clara with TextFlow fix for embedded newlines --- include/external/clara.hpp | 21 ++++++++++++++------- third_party/clara.hpp | 21 ++++++++++++++------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 5a13080c..189e16e2 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -35,8 +35,7 @@ #endif -namespace Catch { namespace clara { namespace TextFlow -{ +namespace Catch { namespace clara { namespace TextFlow { inline auto isWhitespace( char c ) -> bool { static std::string chars = " \t\n\r"; @@ -68,6 +67,7 @@ namespace Catch { namespace clara { namespace TextFlow size_t m_pos = 0; size_t m_len = 0; + size_t m_end = 0; bool m_suffix = false; iterator( Column const& column, size_t stringIndex ) @@ -92,8 +92,12 @@ namespace Catch { namespace clara { namespace TextFlow m_suffix = false; auto width = m_column.m_width-indent(); - if( line().size() < m_pos + width ) { - m_len = line().size() - m_pos; + m_end = m_pos; + while( m_end < line().size() && line()[m_end] != '\n' ) + ++m_end; + + if( m_end < m_pos + width ) { + m_len = m_end - m_pos; } else { size_t len = width; @@ -131,15 +135,18 @@ namespace Catch { namespace clara { namespace TextFlow auto operator *() const -> std::string { assert( m_stringIndex < m_column.m_strings.size() ); - assert( m_pos < line().size() ); - if( m_pos + m_column.m_width < line().size() ) + assert( m_pos < m_end ); + if( m_pos + m_column.m_width < m_end ) return addIndentAndSuffix(line().substr(m_pos, m_len)); else - return addIndentAndSuffix(line().substr(m_pos)); + return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); } auto operator ++() -> iterator& { m_pos += m_len; + if( m_pos < line().size() && line()[m_pos] == '\n' ) + m_pos += 1; + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) ++m_pos; diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 5d7f6f4e..0cd00b94 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -33,8 +33,7 @@ #endif -namespace clara { namespace TextFlow -{ +namespace clara { namespace TextFlow { inline auto isWhitespace( char c ) -> bool { static std::string chars = " \t\n\r"; @@ -66,6 +65,7 @@ namespace clara { namespace TextFlow size_t m_pos = 0; size_t m_len = 0; + size_t m_end = 0; bool m_suffix = false; iterator( Column const& column, size_t stringIndex ) @@ -90,8 +90,12 @@ namespace clara { namespace TextFlow m_suffix = false; auto width = m_column.m_width-indent(); - if( line().size() < m_pos + width ) { - m_len = line().size() - m_pos; + m_end = m_pos; + while( m_end < line().size() && line()[m_end] != '\n' ) + ++m_end; + + if( m_end < m_pos + width ) { + m_len = m_end - m_pos; } else { size_t len = width; @@ -129,15 +133,18 @@ namespace clara { namespace TextFlow auto operator *() const -> std::string { assert( m_stringIndex < m_column.m_strings.size() ); - assert( m_pos < line().size() ); - if( m_pos + m_column.m_width < line().size() ) + assert( m_pos < m_end ); + if( m_pos + m_column.m_width < m_end ) return addIndentAndSuffix(line().substr(m_pos, m_len)); else - return addIndentAndSuffix(line().substr(m_pos)); + return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); } auto operator ++() -> iterator& { m_pos += m_len; + if( m_pos < line().size() && line()[m_pos] == '\n' ) + m_pos += 1; + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) ++m_pos; From 5c3355ad1b6d5ed57df7f0da73dfe086500a4ef2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 20:07:28 +0100 Subject: [PATCH 148/398] Embed Clara with TextFlow fix for whitespace after newline --- include/external/clara.hpp | 6 +++--- third_party/clara.hpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 189e16e2..091c2fa8 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -146,9 +146,9 @@ namespace Catch { namespace clara { namespace TextFlow { m_pos += m_len; if( m_pos < line().size() && line()[m_pos] == '\n' ) m_pos += 1; - - while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) - ++m_pos; + else + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) + ++m_pos; if( m_pos == line().size() ) { m_pos = 0; diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 0cd00b94..509c9b5a 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -144,9 +144,9 @@ namespace clara { namespace TextFlow { m_pos += m_len; if( m_pos < line().size() && line()[m_pos] == '\n' ) m_pos += 1; - - while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) - ++m_pos; + else + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) + ++m_pos; if( m_pos == line().size() ) { m_pos = 0; From 224250e2d48c7f660e4ea55aab78350ef618a18a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 19:50:47 +0100 Subject: [PATCH 149/398] listTests now only uses TextFlow (not tbd_text_format) again --- include/internal/catch_list.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index 1d5f9e49..c7e90693 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -12,12 +12,11 @@ #include "catch_interfaces_reporter.h" #include "catch_interfaces_testcase.h" -#include "catch_text.h" - #include "catch_clara.h" // For TextFlow #include "catch_console_colour.hpp" #include "catch_test_spec_parser.hpp" +#include "catch_tostring.h" #include #include @@ -45,13 +44,11 @@ namespace Catch { Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; if( config.verbosity() >= Verbosity::High ) { - TextAttributes descAttr; - descAttr.setIndent( 4 ); - Catch::cout() << Text( testCaseInfo.lineInfo, descAttr ) << std::endl; + Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; std::string description = testCaseInfo.description; if( description == "" ) description = "(NO DESCRIPTION)"; - Catch::cout() << Text( description, descAttr ) << std::endl; + Catch::cout() << Column( description ).indent(4) << std::endl; } if( !testCaseInfo.tags.empty() ) Catch::cout() << Column( testCaseInfo.tagsAsString ).indent( 6 ) << "\n"; From d3c7d424fede6e7832931846b232586ea00810c4 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:04:34 +0100 Subject: [PATCH 150/398] Removed "long text" test (not a limitation of TextFlow) --- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 1016 +---------------- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 1015 +--------------- projects/SelfTest/TestMain.cpp | 11 - 5 files changed, 7 insertions(+), 2042 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 58571bb2..a19e84c5 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1018,6 +1018,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 186 | 135 passed | 47 failed | 4 failed as expected -assertions: 939 | 822 passed | 96 failed | 21 failed as expected +test cases: 185 | 134 passed | 47 failed | 4 failed as expected +assertions: 938 | 821 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 61e865c6..4373d02f 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -2319,1018 +2319,6 @@ with expansion: " -------------------------------------------------------------------------------- -Long text is truncated -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ) -with expansion: - "***************************************************************************- - ***- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ -... message truncated due to excessive size - ------------------------------------------------------------------------------- ManuallyRegistered ------------------------------------------------------------------------------- @@ -9164,6 +8152,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 186 | 134 passed | 48 failed | 4 failed as expected -assertions: 941 | 822 passed | 98 failed | 21 failed as expected +test cases: 185 | 133 passed | 48 failed | 4 failed as expected +assertions: 940 | 821 passed | 98 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index bd931044..b567d061 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -309,7 +309,6 @@ ConditionTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 5b4ecb9e..22c8a4ca 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -2682,1017 +2682,6 @@ re>"
- - - - t.toString(), EndsWith( "... message truncated due to excessive size" ) - - - "******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -... message truncated due to excessive size" ends with: "... message truncated due to excessive size" - - - - @@ -10076,7 +9065,7 @@ spanner
- + - + diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 10a2ae4d..59fe2db5 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -465,17 +465,6 @@ TEST_CASE( "Text can be formatted using the Text class" ) { CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ); } -TEST_CASE( "Long text is truncated", "[Text][Truncated]" ) { - - std::string longLine( 90, '*' ); - - std::ostringstream oss; - for(int i = 0; i < 600; ++i ) - oss << longLine << longLine << "\n"; - Text t( oss.str() ); - CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ); - -} inline void manuallyRegisteredTestFunction() { SUCCEED( "was called" ); From 93556a1fb3244394d5708eecdd6750d41804cb17 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:06:21 +0100 Subject: [PATCH 151/398] Removed "unapproved" baselines that got checked in at some point --- .../Baselines/console.std.unapproved.txt | 1023 -- .../Baselines/console.sw.unapproved.txt | 9169 -------------- .../Baselines/console.swa4.unapproved.txt | 163 - .../Baselines/junit.sw.unapproved.txt | 821 -- .../SelfTest/Baselines/xml.sw.unapproved.txt | 10082 ---------------- 5 files changed, 21258 deletions(-) delete mode 100644 projects/SelfTest/Baselines/console.std.unapproved.txt delete mode 100644 projects/SelfTest/Baselines/console.sw.unapproved.txt delete mode 100644 projects/SelfTest/Baselines/console.swa4.unapproved.txt delete mode 100644 projects/SelfTest/Baselines/junit.sw.unapproved.txt delete mode 100644 projects/SelfTest/Baselines/xml.sw.unapproved.txt diff --git a/projects/SelfTest/Baselines/console.std.unapproved.txt b/projects/SelfTest/Baselines/console.std.unapproved.txt deleted file mode 100644 index 58571bb2..00000000 --- a/projects/SelfTest/Baselines/console.std.unapproved.txt +++ /dev/null @@ -1,1023 +0,0 @@ - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - is a host application. -Run with -? for options - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - outside assertions -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with messages: - answer := 42 - expected exception - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - inside REQUIRE_NOTHROW -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_NOTHROW( thisThrows() ) -due to unexpected exception with messages: - answer := 42 - expected exception - -------------------------------------------------------------------------------- -#835 -- errno should not be touched by Catch -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( f() == 0 ) -with expansion: - 1 == 0 - -------------------------------------------------------------------------------- -'Not' checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( false != false ) - -ConditionTests.cpp:: FAILED: - CHECK( true != true ) - -ConditionTests.cpp:: FAILED: - CHECK( !true ) -with expansion: - false - -ConditionTests.cpp:: FAILED: - CHECK_FALSE( true ) - -ConditionTests.cpp:: FAILED: - CHECK( !trueValue ) -with expansion: - false - -ConditionTests.cpp:: FAILED: - CHECK_FALSE( trueValue ) -with expansion: - !true - -ConditionTests.cpp:: FAILED: - CHECK( !(1 == 1) ) -with expansion: - false - -ConditionTests.cpp:: FAILED: - CHECK_FALSE( 1 == 1 ) -with expansion: - !(1 == 1) - -------------------------------------------------------------------------------- -A METHOD_AS_TEST_CASE based test run that fails -------------------------------------------------------------------------------- -ClassTests.cpp: -............................................................................... - -ClassTests.cpp:: FAILED: - REQUIRE( s == "world" ) -with expansion: - "hello" == "world" - -------------------------------------------------------------------------------- -A TEST_CASE_METHOD based test run that fails -------------------------------------------------------------------------------- -ClassTests.cpp: -............................................................................... - -ClassTests.cpp:: FAILED: - REQUIRE( m_a == 2 ) -with expansion: - 1 == 2 - -------------------------------------------------------------------------------- -A couple of nested sections followed by a failure -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: -explicitly with message: - to infinity and beyond - -------------------------------------------------------------------------------- -A failing expression with a non streamable type is still captured -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: FAILED: - CHECK( &o1 == &o2 ) -with expansion: - 0x == 0x - -TrickyTests.cpp:: FAILED: - CHECK( o1 == o2 ) -with expansion: - {?} == {?} - -------------------------------------------------------------------------------- -An unchecked exception reports the line of the last assertion -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - {Unknown expression after the reported line} -due to unexpected exception with message: - unexpected exception - -------------------------------------------------------------------------------- -Contains string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) -with expansion: - "this string contains 'abc' as a substring" contains: "not there" - -------------------------------------------------------------------------------- -Custom exceptions can be translated when testing for nothrow -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_NOTHROW( throwCustom() ) -due to unexpected exception with message: - custom exception - not std - -------------------------------------------------------------------------------- -Custom exceptions can be translated when testing for throwing as something else -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_THROWS_AS( throwCustom(), std::exception ) -due to unexpected exception with message: - custom exception - not std - -------------------------------------------------------------------------------- -Custom std-exceptions can be custom translated -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - custom std exception - -------------------------------------------------------------------------------- -EndsWith string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) -with expansion: - "this string contains 'abc' as a substring" ends with: "this" - -------------------------------------------------------------------------------- -Equality checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven == 6 ) -with expansion: - 7 == 6 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven == 8 ) -with expansion: - 7 == 8 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven == 0 ) -with expansion: - 7 == 0 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 9.11f ) ) -with expansion: - 9.1f == Approx( 9.1099996567 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 9.0f ) ) -with expansion: - 9.1f == Approx( 9.0 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 1 ) ) -with expansion: - 9.1f == Approx( 1.0 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 0 ) ) -with expansion: - 9.1f == Approx( 0.0 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.double_pi == Approx( 3.1415 ) ) -with expansion: - 3.1415926535 == Approx( 3.1415 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello == "goodbye" ) -with expansion: - "hello" == "goodbye" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello == "hell" ) -with expansion: - "hello" == "hell" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello == "hello1" ) -with expansion: - "hello" == "hello1" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello.size() == 6 ) -with expansion: - 5 == 6 - -ConditionTests.cpp:: FAILED: - CHECK( x == Approx( 1.301 ) ) -with expansion: - 1.3 == Approx( 1.301 ) - -------------------------------------------------------------------------------- -Equals string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) -with expansion: - "this string contains 'abc' as a substring" equals: "something else" - -------------------------------------------------------------------------------- -Exception matchers that fail - No exception -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) -because no exception was thrown where one was expected: - -MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) -because no exception was thrown where one was expected: - -------------------------------------------------------------------------------- -Exception matchers that fail - Type mismatch -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) -due to unexpected exception with message: - Unknown exception - -MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) -due to unexpected exception with message: - Unknown exception - -------------------------------------------------------------------------------- -Exception matchers that fail - Contents are wrong -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{ 1 } ) -with expansion: - {?} special exception has value of 1 - -MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{ 1 } ) -with expansion: - {?} special exception has value of 1 - -------------------------------------------------------------------------------- -Expected exceptions that don't throw or unexpected exceptions fail the test -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - CHECK_THROWS_AS( thisThrows(), std::string ) -due to unexpected exception with message: - expected exception - -ExceptionTests.cpp:: FAILED: - CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error ) -because no exception was thrown where one was expected: - -ExceptionTests.cpp:: FAILED: - CHECK_NOTHROW( thisThrows() ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -FAIL aborts the test -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - This is a failure - -------------------------------------------------------------------------------- -FAIL does not require an argument -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - -------------------------------------------------------------------------------- -FAIL_CHECK does not abort the test -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - This is a failure - -MessageTests.cpp:: -warning: - This message appears in the output - -------------------------------------------------------------------------------- -INFO and WARN do not abort tests -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -warning: - this is a warning - -------------------------------------------------------------------------------- -INFO gets logged on failure -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - REQUIRE( a == 1 ) -with expansion: - 2 == 1 -with messages: - this message should be logged - so should this - -------------------------------------------------------------------------------- -INFO gets logged on failure, even if captured before successful assertions -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - CHECK( a == 1 ) -with expansion: - 2 == 1 -with messages: - this message may be logged later - this message should be logged - -MessageTests.cpp:: FAILED: - CHECK( a == 0 ) -with expansion: - 2 == 0 -with messages: - this message may be logged later - this message should be logged - and this, but later - -------------------------------------------------------------------------------- -Inequality checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven != 7 ) -with expansion: - 7 != 7 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one != Approx( 9.1f ) ) -with expansion: - 9.1f != Approx( 9.1000003815 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.double_pi != Approx( 3.1415926535 ) ) -with expansion: - 3.1415926535 != Approx( 3.1415926535 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello != "hello" ) -with expansion: - "hello" != "hello" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello.size() != 5 ) -with expansion: - 5 != 5 - -------------------------------------------------------------------------------- -Matchers can be composed with both && and || - failing -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) -with expansion: - "this string contains 'abc' as a substring" ( ( contains: "string" or - contains: "different" ) and contains: "random" ) - -------------------------------------------------------------------------------- -Matchers can be negated (Not) with the ! operator - failing -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) -with expansion: - "this string contains 'abc' as a substring" not contains: "substring" - -------------------------------------------------------------------------------- -Mismatching exception messages failing the test -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) -with expansion: - expected exception - -------------------------------------------------------------------------------- -Nice descriptive name -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -warning: - This one ran - -------------------------------------------------------------------------------- -Non-std exceptions can be translated -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - custom exception - -------------------------------------------------------------------------------- -Ordering comparison checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven > 7 ) -with expansion: - 7 > 7 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < 7 ) -with expansion: - 7 < 7 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven > 8 ) -with expansion: - 7 > 8 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < 6 ) -with expansion: - 7 < 6 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < 0 ) -with expansion: - 7 < 0 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < -1 ) -with expansion: - 7 < -1 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven >= 8 ) -with expansion: - 7 >= 8 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven <= 6 ) -with expansion: - 7 <= 6 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one < 9 ) -with expansion: - 9.1f < 9 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one > 10 ) -with expansion: - 9.1f > 10 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one > 9.2 ) -with expansion: - 9.1f > 9.2 - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello > "hello" ) -with expansion: - "hello" > "hello" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello < "hello" ) -with expansion: - "hello" < "hello" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello > "hellp" ) -with expansion: - "hello" > "hellp" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello > "z" ) -with expansion: - "hello" > "z" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello < "hellm" ) -with expansion: - "hello" < "hellm" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello < "a" ) -with expansion: - "hello" < "a" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello >= "z" ) -with expansion: - "hello" >= "z" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello <= "a" ) -with expansion: - "hello" <= "a" - -------------------------------------------------------------------------------- -Output from all sections is reported - one -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - Message from section one - -------------------------------------------------------------------------------- -Output from all sections is reported - two -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - Message from section two - -------------------------------------------------------------------------------- -Pointers can be converted to strings -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -warning: - actual address of p: 0x - -MessageTests.cpp:: -warning: - toString(p): 0x - -------------------------------------------------------------------------------- -Reconstruction should be based on stringification: #914 -------------------------------------------------------------------------------- -DecompositionTests.cpp: -............................................................................... - -DecompositionTests.cpp:: FAILED: - CHECK( truthy(false) ) -with expansion: - Hey, its truthy! - -------------------------------------------------------------------------------- -SCOPED_INFO is reset for each loop -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - REQUIRE( i < 10 ) -with expansion: - 10 < 10 -with messages: - current counter 10 - i := 10 - -A string sent directly to stdout -A string sent directly to stderr -Message from section one -Message from section two -------------------------------------------------------------------------------- -StartsWith string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) -with expansion: - "this string contains 'abc' as a substring" starts with: "string" - -hello -hello -------------------------------------------------------------------------------- -Tabs and newlines show in output -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( s1 == s2 ) -with expansion: - "if ($b == 10) { - $a = 20; - }" - == - "if ($b == 10) { - $a = 20; - } - " - -------------------------------------------------------------------------------- -Unexpected exceptions can be translated -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - 3.14 - -------------------------------------------------------------------------------- -Vector matchers that fail - Contains (element) -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, VectorContains( -1 ) ) -with expansion: - { 1, 2, 3 } Contains: -1 - -MatchersTests.cpp:: FAILED: - CHECK_THAT( empty, VectorContains( 1 ) ) -with expansion: - { } Contains: 1 - -------------------------------------------------------------------------------- -Vector matchers that fail - Contains (vector) -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( empty, Contains( v) ) -with expansion: - { } Contains: { 1, 2, 3 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, Contains( v2 ) ) -with expansion: - { 1, 2, 3 } Contains: { 1, 2, 4 } - -------------------------------------------------------------------------------- -Vector matchers that fail - Equals -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, Equals( v2 ) ) -with expansion: - { 1, 2, 3 } Equals: { 1, 2 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v2, Equals( v ) ) -with expansion: - { 1, 2 } Equals: { 1, 2, 3 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( empty, Equals( v ) ) -with expansion: - { } Equals: { 1, 2, 3 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, Equals( empty ) ) -with expansion: - { 1, 2, 3 } Equals: { } - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown directly they are always failures -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - unexpected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown during a CHECK the test should continue -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - CHECK( thisThrows() == 0 ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown during a REQUIRE the test should abort -fail -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE( thisThrows() == 0 ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown from functions they are always failures -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - CHECK( thisThrows() == 0 ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown from sections they are always failures - section name -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - unexpected exception - -------------------------------------------------------------------------------- -Where the LHS is not a simple value -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -warning: - Uncomment the code in this test to check that it gives a sensible compiler - error - -------------------------------------------------------------------------------- -Where there is more to the expression after the RHS -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -warning: - Uncomment the code in this test to check that it gives a sensible compiler - error - -------------------------------------------------------------------------------- -checkedElse, failing -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECKED_ELSE( flag ) -with expansion: - false - -MiscTests.cpp:: FAILED: - REQUIRE( testCheckedElse( false ) ) -with expansion: - false - -------------------------------------------------------------------------------- -checkedIf, failing -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECKED_IF( flag ) -with expansion: - false - -MiscTests.cpp:: FAILED: - REQUIRE( testCheckedIf( false ) ) -with expansion: - false - -spanner------------------------------------------------------------------------------- -just failure -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - Previous info should not be seen - -------------------------------------------------------------------------------- -looped SECTION tests - s1 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( b > a ) -with expansion: - 0 > 1 - -------------------------------------------------------------------------------- -looped tests -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[0] (1) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[1] (1) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[3] (3) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[4] (5) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[6] (13) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[7] (21) is even - -------------------------------------------------------------------------------- -more nested SECTION tests - s1 - s2 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - REQUIRE( a == b ) -with expansion: - 1 == 2 - -------------------------------------------------------------------------------- -send a single char to INFO -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - REQUIRE( false ) -with message: - 3 - -------------------------------------------------------------------------------- -sends information to INFO -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - REQUIRE( false ) -with messages: - hi - i := 7 - -------------------------------------------------------------------------------- -string literals of different sizes can be compared -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: FAILED: - REQUIRE( std::string( "first" ) == "second" ) -with expansion: - "first" == "second" - -------------------------------------------------------------------------------- -toString(enum class) -------------------------------------------------------------------------------- -EnumToString.cpp: -............................................................................... - -EnumToString.cpp:: FAILED: - CHECK( ::Catch::Detail::stringify(e0) == "0" ) -with expansion: - "{?}" == "0" - -EnumToString.cpp:: FAILED: - CHECK( ::Catch::Detail::stringify(e1) == "1" ) -with expansion: - "{?}" == "1" - -=============================================================================== -test cases: 186 | 135 passed | 47 failed | 4 failed as expected -assertions: 939 | 822 passed | 96 failed | 21 failed as expected - diff --git a/projects/SelfTest/Baselines/console.sw.unapproved.txt b/projects/SelfTest/Baselines/console.sw.unapproved.txt deleted file mode 100644 index 61e865c6..00000000 --- a/projects/SelfTest/Baselines/console.sw.unapproved.txt +++ /dev/null @@ -1,9169 +0,0 @@ - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - is a host application. -Run with -? for options - -------------------------------------------------------------------------------- -# A test name that starts with a # -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: -with message: - yay - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - outside assertions -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with messages: - answer := 42 - expected exception - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - inside REQUIRE_NOTHROW -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_NOTHROW( thisThrows() ) -due to unexpected exception with messages: - answer := 42 - expected exception - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - inside REQUIRE_THROWS -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS( thisThrows() ) -with message: - answer := 42 - -------------------------------------------------------------------------------- -#809 -------------------------------------------------------------------------------- -CompilationTests.cpp: -............................................................................... - -CompilationTests.cpp:: -PASSED: - REQUIRE( 42 == f ) -with expansion: - 42 == {?} - -------------------------------------------------------------------------------- -#833 -------------------------------------------------------------------------------- -CompilationTests.cpp: -............................................................................... - -CompilationTests.cpp:: -PASSED: - REQUIRE( a == t ) -with expansion: - 3 == 3 - -CompilationTests.cpp:: -PASSED: - CHECK( a == t ) -with expansion: - 3 == 3 - -CompilationTests.cpp:: -PASSED: - REQUIRE_THROWS( throws_int(true) ) - -CompilationTests.cpp:: -PASSED: - CHECK_THROWS_AS( throws_int(true), int ) - -CompilationTests.cpp:: -PASSED: - REQUIRE_NOTHROW( throws_int(false) ) - -CompilationTests.cpp:: -PASSED: - REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") ) -with expansion: - "aaa" ends with: "aaa" - -CompilationTests.cpp:: -PASSED: - REQUIRE( templated_tests(3) ) -with expansion: - true - -------------------------------------------------------------------------------- -#835 -- errno should not be touched by Catch -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( f() == 0 ) -with expansion: - 1 == 0 - -MiscTests.cpp:: -PASSED: - REQUIRE( errno == 1 ) -with expansion: - 1 == 1 - -------------------------------------------------------------------------------- -#872 -------------------------------------------------------------------------------- -CompilationTests.cpp: -............................................................................... - -CompilationTests.cpp:: -PASSED: - REQUIRE( x == 4 ) -with expansion: - {?} == 4 -with message: - dummy := 0 - -------------------------------------------------------------------------------- -'Not' checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( false != false ) - -ConditionTests.cpp:: FAILED: - CHECK( true != true ) - -ConditionTests.cpp:: FAILED: - CHECK( !true ) -with expansion: - false - -ConditionTests.cpp:: FAILED: - CHECK_FALSE( true ) - -ConditionTests.cpp:: FAILED: - CHECK( !trueValue ) -with expansion: - false - -ConditionTests.cpp:: FAILED: - CHECK_FALSE( trueValue ) -with expansion: - !true - -ConditionTests.cpp:: FAILED: - CHECK( !(1 == 1) ) -with expansion: - false - -ConditionTests.cpp:: FAILED: - CHECK_FALSE( 1 == 1 ) -with expansion: - !(1 == 1) - -------------------------------------------------------------------------------- -'Not' checks that should succeed -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( false == false ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( true == true ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( !false ) -with expansion: - true - -ConditionTests.cpp:: -PASSED: - REQUIRE_FALSE( false ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( !falseValue ) -with expansion: - true - -ConditionTests.cpp:: -PASSED: - REQUIRE_FALSE( falseValue ) -with expansion: - !false - -ConditionTests.cpp:: -PASSED: - REQUIRE( !(1 == 2) ) -with expansion: - true - -ConditionTests.cpp:: -PASSED: - REQUIRE_FALSE( 1 == 2 ) -with expansion: - !(1 == 2) - -------------------------------------------------------------------------------- -(unimplemented) static bools can be evaluated - compare to true -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( is_true::value == true ) -with expansion: - true == true - -TrickyTests.cpp:: -PASSED: - REQUIRE( true == is_true::value ) -with expansion: - true == true - -------------------------------------------------------------------------------- -(unimplemented) static bools can be evaluated - compare to false -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( is_true::value == false ) -with expansion: - false == false - -TrickyTests.cpp:: -PASSED: - REQUIRE( false == is_true::value ) -with expansion: - false == false - -------------------------------------------------------------------------------- -(unimplemented) static bools can be evaluated - negation -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( !is_true::value ) -with expansion: - true - -------------------------------------------------------------------------------- -(unimplemented) static bools can be evaluated - double negation -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( !!is_true::value ) -with expansion: - true - -------------------------------------------------------------------------------- -(unimplemented) static bools can be evaluated - direct -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( is_true::value ) -with expansion: - true - -TrickyTests.cpp:: -PASSED: - REQUIRE_FALSE( is_true::value ) -with expansion: - !false - -------------------------------------------------------------------------------- -A METHOD_AS_TEST_CASE based test run that fails -------------------------------------------------------------------------------- -ClassTests.cpp: -............................................................................... - -ClassTests.cpp:: FAILED: - REQUIRE( s == "world" ) -with expansion: - "hello" == "world" - -------------------------------------------------------------------------------- -A METHOD_AS_TEST_CASE based test run that succeeds -------------------------------------------------------------------------------- -ClassTests.cpp: -............................................................................... - -ClassTests.cpp:: -PASSED: - REQUIRE( s == "hello" ) -with expansion: - "hello" == "hello" - -------------------------------------------------------------------------------- -A TEST_CASE_METHOD based test run that fails -------------------------------------------------------------------------------- -ClassTests.cpp: -............................................................................... - -ClassTests.cpp:: FAILED: - REQUIRE( m_a == 2 ) -with expansion: - 1 == 2 - -------------------------------------------------------------------------------- -A TEST_CASE_METHOD based test run that succeeds -------------------------------------------------------------------------------- -ClassTests.cpp: -............................................................................... - -ClassTests.cpp:: -PASSED: - REQUIRE( m_a == 1 ) -with expansion: - 1 == 1 - -------------------------------------------------------------------------------- -A couple of nested sections followed by a failure - Outer - Inner -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: -with message: - that's not flying - that's failing in style - -------------------------------------------------------------------------------- -A couple of nested sections followed by a failure -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: -explicitly with message: - to infinity and beyond - -------------------------------------------------------------------------------- -A failing expression with a non streamable type is still captured -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: FAILED: - CHECK( &o1 == &o2 ) -with expansion: - 0x == 0x - -TrickyTests.cpp:: FAILED: - CHECK( o1 == o2 ) -with expansion: - {?} == {?} - -------------------------------------------------------------------------------- -Absolute margin -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( 104.0 != Approx(100.0) ) -with expansion: - 104.0 != Approx( 100.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 104.0 == Approx(100.0).margin(5) ) -with expansion: - 104.0 == Approx( 100.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 104.0 != Approx(100.0).margin(3) ) -with expansion: - 104.0 != Approx( 100.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 100.3 != Approx(100.0) ) -with expansion: - 100.3 != Approx( 100.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 100.3 == Approx(100.0).margin(0.5) ) -with expansion: - 100.3 == Approx( 100.0 ) - -------------------------------------------------------------------------------- -AllOf matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "string" and - contains: "abc" ) - -------------------------------------------------------------------------------- -An expression with side-effects should only be evaluated once -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( i++ == 7 ) -with expansion: - 7 == 7 - -TrickyTests.cpp:: -PASSED: - REQUIRE( i++ == 8 ) -with expansion: - 8 == 8 - -------------------------------------------------------------------------------- -An unchecked exception reports the line of the last assertion -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - CHECK( 1 == 1 ) - -ExceptionTests.cpp:: FAILED: - {Unknown expression after the reported line} -due to unexpected exception with message: - unexpected exception - -------------------------------------------------------------------------------- -Anonymous test case 1 -------------------------------------------------------------------------------- -VariadicMacrosTests.cpp: -............................................................................... - -VariadicMacrosTests.cpp:: -PASSED: -with message: - anonymous test case - -------------------------------------------------------------------------------- -AnyOf matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "string" or contains: - "not there" ) - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "not there" or - contains: "string" ) - -------------------------------------------------------------------------------- -Approximate PI -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) ) -with expansion: - 3.1428571429 == Approx( 3.141 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) ) -with expansion: - 3.1428571429 != Approx( 3.141 ) - -------------------------------------------------------------------------------- -Approximate comparisons with different epsilons -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( d != Approx( 1.231 ) ) -with expansion: - 1.23 != Approx( 1.231 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ) -with expansion: - 1.23 == Approx( 1.231 ) - -------------------------------------------------------------------------------- -Approximate comparisons with floats -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( 1.23f == Approx( 1.23f ) ) -with expansion: - 1.23f == Approx( 1.2300000191 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 0.0f == Approx( 0.0f ) ) -with expansion: - 0.0f == Approx( 0.0 ) - -------------------------------------------------------------------------------- -Approximate comparisons with ints -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( 1 == Approx( 1 ) ) -with expansion: - 1 == Approx( 1.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 0 == Approx( 0 ) ) -with expansion: - 0 == Approx( 0.0 ) - -------------------------------------------------------------------------------- -Approximate comparisons with mixed numeric types -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( 1.0f == Approx( 1 ) ) -with expansion: - 1.0f == Approx( 1.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 0 == Approx( dZero) ) -with expansion: - 0 == Approx( 0.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ) -with expansion: - 0 == Approx( 0.00001 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( 1.234f == Approx( dMedium ) ) -with expansion: - 1.234f == Approx( 1.234 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( dMedium == Approx( 1.234f ) ) -with expansion: - 1.234 == Approx( 1.2339999676 ) - -------------------------------------------------------------------------------- -Assertions then sections -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( Catch::alwaysTrue() ) -with expansion: - true - -------------------------------------------------------------------------------- -Assertions then sections - A section -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( Catch::alwaysTrue() ) -with expansion: - true - -------------------------------------------------------------------------------- -Assertions then sections - A section - Another section -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( Catch::alwaysTrue() ) -with expansion: - true - -------------------------------------------------------------------------------- -Assertions then sections -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( Catch::alwaysTrue() ) -with expansion: - true - -------------------------------------------------------------------------------- -Assertions then sections - A section -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( Catch::alwaysTrue() ) -with expansion: - true - -------------------------------------------------------------------------------- -Assertions then sections - A section - Another other section -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( Catch::alwaysTrue() ) -with expansion: - true - -------------------------------------------------------------------------------- -Capture and info messages - Capture should stringify like assertions -------------------------------------------------------------------------------- -ToStringGeneralTests.cpp: -............................................................................... - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( true ) -with message: - i := 2 - -------------------------------------------------------------------------------- -Capture and info messages - Info should NOT stringify the way assertions do -------------------------------------------------------------------------------- -ToStringGeneralTests.cpp: -............................................................................... - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( true ) -with message: - 3 - -------------------------------------------------------------------------------- -Character pretty printing - Specifically escaped -------------------------------------------------------------------------------- -ToStringGeneralTests.cpp: -............................................................................... - -ToStringGeneralTests.cpp:: -PASSED: - CHECK( tab == '\t' ) -with expansion: - '\t' == '\t' - -ToStringGeneralTests.cpp:: -PASSED: - CHECK( newline == '\n' ) -with expansion: - '\n' == '\n' - -ToStringGeneralTests.cpp:: -PASSED: - CHECK( carr_return == '\r' ) -with expansion: - '\r' == '\r' - -ToStringGeneralTests.cpp:: -PASSED: - CHECK( form_feed == '\f' ) -with expansion: - '\f' == '\f' - -------------------------------------------------------------------------------- -Character pretty printing - General chars -------------------------------------------------------------------------------- -ToStringGeneralTests.cpp: -............................................................................... - -ToStringGeneralTests.cpp:: -PASSED: - CHECK( space == ' ' ) -with expansion: - ' ' == ' ' - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == chars[i] ) -with expansion: - 'a' == 'a' - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == chars[i] ) -with expansion: - 'z' == 'z' - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == chars[i] ) -with expansion: - 'A' == 'A' - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == chars[i] ) -with expansion: - 'Z' == 'Z' - -------------------------------------------------------------------------------- -Character pretty printing - Low ASCII -------------------------------------------------------------------------------- -ToStringGeneralTests.cpp: -............................................................................... - -ToStringGeneralTests.cpp:: -PASSED: - CHECK( null_terminator == '\0' ) -with expansion: - 0 == 0 - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == i ) -with expansion: - 2 == 2 - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == i ) -with expansion: - 3 == 3 - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == i ) -with expansion: - 4 == 4 - -ToStringGeneralTests.cpp:: -PASSED: - REQUIRE( c == i ) -with expansion: - 5 == 5 - -------------------------------------------------------------------------------- -Commas in various macros are allowed -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ) - -TrickyTests.cpp:: -PASSED: - CHECK_THROWS( std::vector{constructor_throws{}, constructor_throws{}} ) - -TrickyTests.cpp:: -PASSED: - REQUIRE_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ) - -TrickyTests.cpp:: -PASSED: - CHECK_NOTHROW( std::vector{1, 2, 3} == std::vector{1, 2, 3} ) - -TrickyTests.cpp:: -PASSED: - REQUIRE( std::vector{1, 2} == std::vector{1, 2} ) -with expansion: - { 1, 2 } == { 1, 2 } - -TrickyTests.cpp:: -PASSED: - CHECK( std::vector{1, 2} == std::vector{1, 2} ) -with expansion: - { 1, 2 } == { 1, 2 } - -TrickyTests.cpp:: -PASSED: - REQUIRE_FALSE( std::vector{1, 2} == std::vector{1, 2, 3} ) -with expansion: - !({ 1, 2 } == { 1, 2, 3 }) - -TrickyTests.cpp:: -PASSED: - CHECK_FALSE( std::vector{1, 2} == std::vector{1, 2, 3} ) -with expansion: - !({ 1, 2 } == { 1, 2, 3 }) - -TrickyTests.cpp:: -PASSED: - CHECK_NOFAIL( std::vector{1, 2} == std::vector{1, 2} ) -with expansion: - { 1, 2 } == { 1, 2 } - -TrickyTests.cpp:: -PASSED: - CHECKED_IF( std::vector{1, 2} == std::vector{1, 2} ) -with expansion: - { 1, 2 } == { 1, 2 } - -TrickyTests.cpp:: -PASSED: - REQUIRE( true ) - -TrickyTests.cpp:: -PASSED: - CHECKED_ELSE( std::vector{1, 2} == std::vector{1, 2} ) -with expansion: - { 1, 2 } == { 1, 2 } - -------------------------------------------------------------------------------- -Comparing function pointers -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( a ) -with expansion: - 0x - -TrickyTests.cpp:: -PASSED: - REQUIRE( a == &foo ) -with expansion: - 0x == 0x - -------------------------------------------------------------------------------- -Comparing member function pointers -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - CHECK( m == &S::f ) -with expansion: - 0x - == - 0x - -------------------------------------------------------------------------------- -Comparison with explicitly convertible types -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( td == Approx(10.0) ) -with expansion: - StrongDoubleTypedef(10) == Approx( 10.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx(10.0) == td ) -with expansion: - Approx( 10.0 ) == StrongDoubleTypedef(10) - -ApproxTests.cpp:: -PASSED: - REQUIRE( td != Approx(11.0) ) -with expansion: - StrongDoubleTypedef(10) != Approx( 11.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx(11.0) != td ) -with expansion: - Approx( 11.0 ) != StrongDoubleTypedef(10) - -ApproxTests.cpp:: -PASSED: - REQUIRE( td <= Approx(10.0) ) -with expansion: - StrongDoubleTypedef(10) <= Approx( 10.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( td <= Approx(11.0) ) -with expansion: - StrongDoubleTypedef(10) <= Approx( 11.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx(10.0) <= td ) -with expansion: - Approx( 10.0 ) <= StrongDoubleTypedef(10) - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx(9.0) <= td ) -with expansion: - Approx( 9.0 ) <= StrongDoubleTypedef(10) - -ApproxTests.cpp:: -PASSED: - REQUIRE( td >= Approx(9.0) ) -with expansion: - StrongDoubleTypedef(10) >= Approx( 9.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( td >= Approx(10.0) ) -with expansion: - StrongDoubleTypedef(10) >= Approx( 10.0 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx(10.0) >= td ) -with expansion: - Approx( 10.0 ) >= StrongDoubleTypedef(10) - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx(11.0) >= td ) -with expansion: - Approx( 11.0 ) >= StrongDoubleTypedef(10) - -------------------------------------------------------------------------------- -Comparisons between ints where one side is computed -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - CHECK( 54 == 6*9 ) -with expansion: - 54 == 54 - -------------------------------------------------------------------------------- -Comparisons between unsigned ints and negative signed ints match c++ standard -behaviour -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - CHECK( ( -1 > 2u ) ) -with expansion: - true - -ConditionTests.cpp:: -PASSED: - CHECK( -1 > 2u ) -with expansion: - -1 > 2 - -ConditionTests.cpp:: -PASSED: - CHECK( ( 2u < -1 ) ) -with expansion: - true - -ConditionTests.cpp:: -PASSED: - CHECK( 2u < -1 ) -with expansion: - 2 < -1 - -ConditionTests.cpp:: -PASSED: - CHECK( ( minInt > 2u ) ) -with expansion: - true - -ConditionTests.cpp:: -PASSED: - CHECK( minInt > 2u ) -with expansion: - -2147483648 > 2 - -------------------------------------------------------------------------------- -Comparisons with int literals don't warn when mixing signed/ unsigned -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( i == 1 ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( ui == 2 ) -with expansion: - 2 == 2 - -ConditionTests.cpp:: -PASSED: - REQUIRE( l == 3 ) -with expansion: - 3 == 3 - -ConditionTests.cpp:: -PASSED: - REQUIRE( ul == 4 ) -with expansion: - 4 == 4 - -ConditionTests.cpp:: -PASSED: - REQUIRE( c == 5 ) -with expansion: - 5 == 5 - -ConditionTests.cpp:: -PASSED: - REQUIRE( uc == 6 ) -with expansion: - 6 == 6 - -ConditionTests.cpp:: -PASSED: - REQUIRE( 1 == i ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( 2 == ui ) -with expansion: - 2 == 2 - -ConditionTests.cpp:: -PASSED: - REQUIRE( 3 == l ) -with expansion: - 3 == 3 - -ConditionTests.cpp:: -PASSED: - REQUIRE( 4 == ul ) -with expansion: - 4 == 4 - -ConditionTests.cpp:: -PASSED: - REQUIRE( 5 == c ) -with expansion: - 5 == 5 - -ConditionTests.cpp:: -PASSED: - REQUIRE( 6 == uc ) -with expansion: - 6 == 6 - -ConditionTests.cpp:: -PASSED: - REQUIRE( (std::numeric_limits::max)() > ul ) -with expansion: - 18446744073709551615 (0x) - > - 4 - -------------------------------------------------------------------------------- -Contains string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), Contains( "not there" ) ) -with expansion: - "this string contains 'abc' as a substring" contains: "not there" - -------------------------------------------------------------------------------- -Custom exceptions can be translated when testing for nothrow -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_NOTHROW( throwCustom() ) -due to unexpected exception with message: - custom exception - not std - -------------------------------------------------------------------------------- -Custom exceptions can be translated when testing for throwing as something else -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_THROWS_AS( throwCustom(), std::exception ) -due to unexpected exception with message: - custom exception - not std - -------------------------------------------------------------------------------- -Custom std-exceptions can be custom translated -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - custom std exception - -------------------------------------------------------------------------------- -Demonstrate that a non-const == is not used -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( t == 1u ) -with expansion: - {?} == 1 - -------------------------------------------------------------------------------- -EndsWith string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), EndsWith( "this" ) ) -with expansion: - "this string contains 'abc' as a substring" ends with: "this" - -------------------------------------------------------------------------------- -Equality checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven == 6 ) -with expansion: - 7 == 6 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven == 8 ) -with expansion: - 7 == 8 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven == 0 ) -with expansion: - 7 == 0 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 9.11f ) ) -with expansion: - 9.1f == Approx( 9.1099996567 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 9.0f ) ) -with expansion: - 9.1f == Approx( 9.0 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 1 ) ) -with expansion: - 9.1f == Approx( 1.0 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one == Approx( 0 ) ) -with expansion: - 9.1f == Approx( 0.0 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.double_pi == Approx( 3.1415 ) ) -with expansion: - 3.1415926535 == Approx( 3.1415 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello == "goodbye" ) -with expansion: - "hello" == "goodbye" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello == "hell" ) -with expansion: - "hello" == "hell" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello == "hello1" ) -with expansion: - "hello" == "hello1" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello.size() == 6 ) -with expansion: - 5 == 6 - -ConditionTests.cpp:: FAILED: - CHECK( x == Approx( 1.301 ) ) -with expansion: - 1.3 == Approx( 1.301 ) - -------------------------------------------------------------------------------- -Equality checks that should succeed -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven == 7 ) -with expansion: - 7 == 7 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ) -with expansion: - 9.1f == Approx( 9.1000003815 ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.double_pi == Approx( 3.1415926535 ) ) -with expansion: - 3.1415926535 == Approx( 3.1415926535 ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello == "hello" ) -with expansion: - "hello" == "hello" - -ConditionTests.cpp:: -PASSED: - REQUIRE( "hello" == data.str_hello ) -with expansion: - "hello" == "hello" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello.size() == 5 ) -with expansion: - 5 == 5 - -ConditionTests.cpp:: -PASSED: - REQUIRE( x == Approx( 1.3 ) ) -with expansion: - 1.3 == Approx( 1.3 ) - -------------------------------------------------------------------------------- -Equals -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ) -with expansion: - "this string contains 'abc' as a substring" equals: "this string contains - 'abc' as a substring" - -------------------------------------------------------------------------------- -Equals string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), Equals( "something else" ) ) -with expansion: - "this string contains 'abc' as a substring" equals: "something else" - -------------------------------------------------------------------------------- -Exception matchers that fail - No exception -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) -because no exception was thrown where one was expected: - -MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } ) -because no exception was thrown where one was expected: - -------------------------------------------------------------------------------- -Exception matchers that fail - Type mismatch -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) -due to unexpected exception with message: - Unknown exception - -MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } ) -due to unexpected exception with message: - Unknown exception - -------------------------------------------------------------------------------- -Exception matchers that fail - Contents are wrong -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{ 1 } ) -with expansion: - {?} special exception has value of 1 - -MatchersTests.cpp:: FAILED: - REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{ 1 } ) -with expansion: - {?} special exception has value of 1 - -------------------------------------------------------------------------------- -Exception matchers that succeed -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THROWS_MATCHES( throws(1), SpecialException, ExceptionMatcher{ 1 } ) -with expansion: - {?} special exception has value of 1 - -MatchersTests.cpp:: -PASSED: - REQUIRE_THROWS_MATCHES( throws(2), SpecialException, ExceptionMatcher{ 2 } ) -with expansion: - {?} special exception has value of 2 - -------------------------------------------------------------------------------- -Exception messages can be tested for - exact match -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) - -------------------------------------------------------------------------------- -Exception messages can be tested for - different case -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) - -------------------------------------------------------------------------------- -Exception messages can be tested for - wildcarded -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) - -------------------------------------------------------------------------------- -Expected exceptions that don't throw or unexpected exceptions fail the test -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - CHECK_THROWS_AS( thisThrows(), std::string ) -due to unexpected exception with message: - expected exception - -ExceptionTests.cpp:: FAILED: - CHECK_THROWS_AS( thisDoesntThrow(), std::domain_error ) -because no exception was thrown where one was expected: - -ExceptionTests.cpp:: FAILED: - CHECK_NOTHROW( thisThrows() ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -FAIL aborts the test -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - This is a failure - -------------------------------------------------------------------------------- -FAIL does not require an argument -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - -------------------------------------------------------------------------------- -FAIL_CHECK does not abort the test -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - This is a failure - -MessageTests.cpp:: -warning: - This message appears in the output - -------------------------------------------------------------------------------- -Factorials are computed -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( Factorial(0) == 1 ) -with expansion: - 1 == 1 - -MiscTests.cpp:: -PASSED: - REQUIRE( Factorial(1) == 1 ) -with expansion: - 1 == 1 - -MiscTests.cpp:: -PASSED: - REQUIRE( Factorial(2) == 2 ) -with expansion: - 2 == 2 - -MiscTests.cpp:: -PASSED: - REQUIRE( Factorial(3) == 6 ) -with expansion: - 6 == 6 - -MiscTests.cpp:: -PASSED: - REQUIRE( Factorial(10) == 3628800 ) -with expansion: - 3628800 (0x) == 3628800 (0x) - -------------------------------------------------------------------------------- -Greater-than inequalities with different epsilons -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( d >= Approx( 1.22 ) ) -with expansion: - 1.23 >= Approx( 1.22 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d >= Approx( 1.23 ) ) -with expansion: - 1.23 >= Approx( 1.23 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE_FALSE( d >= Approx( 1.24 ) ) -with expansion: - !(1.23 >= Approx( 1.24 )) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d >= Approx( 1.24 ).epsilon(0.1) ) -with expansion: - 1.23 >= Approx( 1.24 ) - -------------------------------------------------------------------------------- -INFO and WARN do not abort tests -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -warning: - this is a message - this is a warning - -------------------------------------------------------------------------------- -INFO gets logged on failure -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - REQUIRE( a == 1 ) -with expansion: - 2 == 1 -with messages: - this message should be logged - so should this - -------------------------------------------------------------------------------- -INFO gets logged on failure, even if captured before successful assertions -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -PASSED: - CHECK( a == 2 ) -with expansion: - 2 == 2 -with message: - this message may be logged later - -MessageTests.cpp:: FAILED: - CHECK( a == 1 ) -with expansion: - 2 == 1 -with messages: - this message may be logged later - this message should be logged - -MessageTests.cpp:: FAILED: - CHECK( a == 0 ) -with expansion: - 2 == 0 -with messages: - this message may be logged later - this message should be logged - and this, but later - -MessageTests.cpp:: -PASSED: - CHECK( a == 2 ) -with expansion: - 2 == 2 -with messages: - this message may be logged later - this message should be logged - and this, but later - but not this - -------------------------------------------------------------------------------- -Inequality checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven != 7 ) -with expansion: - 7 != 7 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one != Approx( 9.1f ) ) -with expansion: - 9.1f != Approx( 9.1000003815 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.double_pi != Approx( 3.1415926535 ) ) -with expansion: - 3.1415926535 != Approx( 3.1415926535 ) - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello != "hello" ) -with expansion: - "hello" != "hello" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello.size() != 5 ) -with expansion: - 5 != 5 - -------------------------------------------------------------------------------- -Inequality checks that should succeed -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven != 6 ) -with expansion: - 7 != 6 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven != 8 ) -with expansion: - 7 != 8 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ) -with expansion: - 9.1f != Approx( 9.1099996567 ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one != Approx( 9.0f ) ) -with expansion: - 9.1f != Approx( 9.0 ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one != Approx( 1 ) ) -with expansion: - 9.1f != Approx( 1.0 ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one != Approx( 0 ) ) -with expansion: - 9.1f != Approx( 0.0 ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.double_pi != Approx( 3.1415 ) ) -with expansion: - 3.1415926535 != Approx( 3.1415 ) - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello != "goodbye" ) -with expansion: - "hello" != "goodbye" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello != "hell" ) -with expansion: - "hello" != "hell" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello != "hello1" ) -with expansion: - "hello" != "hello1" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello.size() != 6 ) -with expansion: - 5 != 6 - -------------------------------------------------------------------------------- -Less-than inequalities with different epsilons -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( d <= Approx( 1.24 ) ) -with expansion: - 1.23 <= Approx( 1.24 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d <= Approx( 1.23 ) ) -with expansion: - 1.23 <= Approx( 1.23 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE_FALSE( d <= Approx( 1.22 ) ) -with expansion: - !(1.23 <= Approx( 1.22 )) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d <= Approx( 1.22 ).epsilon(0.1) ) -with expansion: - 1.23 <= Approx( 1.22 ) - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - No wrapping -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) -with expansion: - "one two three four" - == - "one two three four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) -with expansion: - "one two three four" - == - "one two three four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Wrapped once -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ) -with expansion: - "one two - three four" - == - "one two - three four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Wrapped twice -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Wrapped three times -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) -with expansion: - "one - two - three - four" - == - "one - two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ) -with expansion: - "one - two - three - four" - == - "one - two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Short wrap -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ) -with expansion: - "abc- - def" - == - "abc- - def" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ) -with expansion: - "abc- - defg" - == - "abc- - defg" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ) -with expansion: - "abc- - def- - gh" - == - "abc- - def- - gh" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ) -with expansion: - "one - two - thr- - ee - four" - == - "one - two - thr- - ee - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ) -with expansion: - "one - two - th- - ree - fo- - ur" - == - "one - two - th- - ree - fo- - ur" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - As container -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - REQUIRE( text.size() == 4 ) -with expansion: - 4 == 4 - -TestMain.cpp:: -PASSED: - CHECK( text[0] == "one" ) -with expansion: - "one" == "one" - -TestMain.cpp:: -PASSED: - CHECK( text[1] == "two" ) -with expansion: - "two" == "two" - -TestMain.cpp:: -PASSED: - CHECK( text[2] == "three" ) -with expansion: - "three" == "three" - -TestMain.cpp:: -PASSED: - CHECK( text[3] == "four" ) -with expansion: - "four" == "four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Indent first line differently -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( text.toString() == " one two\n three\n four" ) -with expansion: - " one two - three - four" - == - " one two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - No wrapping -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) -with expansion: - "one two - three four" - == - "one two - three four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) -with expansion: - "one two - three four" - == - "one two - three four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ) -with expansion: - "one two - three four" - == - "one two - three four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - Trailing newline -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" ) -with expansion: - "abcdef" == "abcdef" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) -with expansion: - "abcdef" == "abcdef" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) -with expansion: - "abcdef" == "abcdef" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" ) -with expansion: - "abcd- - ef" - == - "abcd- - ef" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - Wrapped once -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - Wrapped twice -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) -with expansion: - "one - two - three - four" - == - "one - two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With wrap-before/ after characters - No wrapping -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) -with expansion: - "one,two(three) " - == - "one,two(three) " - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString ) -with expansion: - "one,two(three) " - == - "one,two(three) " - -------------------------------------------------------------------------------- -Long strings can be wrapped - With wrap-before/ after characters - Wrap before -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n" ) -with expansion: - "one,two - (three) - " - == - "one,two - (three) - " - -------------------------------------------------------------------------------- -Long strings can be wrapped - With wrap-before/ after characters - Wrap after -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n" ) -with expansion: - "one, - two - (thre- - e) - " - == - "one, - two - (thre- - e) - " - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n" ) -with expansion: - "one, - two - (thr- - ee) - " - == - "one, - two - (thr- - ee) - " - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n" ) -with expansion: - "one, - two - (th- - ree) - " - == - "one, - two - (th- - ree) - " - -------------------------------------------------------------------------------- -Long text is truncated -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ) -with expansion: - "***************************************************************************- - ***- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ - ****************************************************************************- - **- - ****************************************************************************- - **- - ************************ -... message truncated due to excessive size - -------------------------------------------------------------------------------- -ManuallyRegistered -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: -with message: - was called - -------------------------------------------------------------------------------- -Matchers can be (AllOf) composed with the && operator -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "string" and - contains: "abc" and contains: "substring" and contains: "contains" ) - -------------------------------------------------------------------------------- -Matchers can be (AnyOf) composed with the || operator -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "string" or contains: - "different" or contains: "random" ) - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) -with expansion: - "some completely different text that contains one common word" ( contains: - "string" or contains: "different" or contains: "random" ) - -------------------------------------------------------------------------------- -Matchers can be composed with both && and || -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ) -with expansion: - "this string contains 'abc' as a substring" ( ( contains: "string" or - contains: "different" ) and contains: "substring" ) - -------------------------------------------------------------------------------- -Matchers can be composed with both && and || - failing -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) -with expansion: - "this string contains 'abc' as a substring" ( ( contains: "string" or - contains: "different" ) and contains: "random" ) - -------------------------------------------------------------------------------- -Matchers can be negated (Not) with the ! operator -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), !Contains( "different" ) ) -with expansion: - "this string contains 'abc' as a substring" not contains: "different" - -------------------------------------------------------------------------------- -Matchers can be negated (Not) with the ! operator - failing -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ) -with expansion: - "this string contains 'abc' as a substring" not contains: "substring" - -------------------------------------------------------------------------------- -Mismatching exception messages failing the test -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) - -ExceptionTests.cpp:: FAILED: - REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) -with expansion: - expected exception - -------------------------------------------------------------------------------- -Nice descriptive name -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -warning: - This one ran - -------------------------------------------------------------------------------- -Non-std exceptions can be translated -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - custom exception - -------------------------------------------------------------------------------- -Objects that evaluated in boolean contexts can be checked -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - CHECK( True ) -with expansion: - {?} - -TrickyTests.cpp:: -PASSED: - CHECK( !False ) -with expansion: - true - -TrickyTests.cpp:: -PASSED: - CHECK_FALSE( False ) -with expansion: - !{?} - -------------------------------------------------------------------------------- -Operators at different namespace levels not hijacked by Koenig lookup -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( 0x == o ) -with expansion: - 3221225472 (0x) == {?} - -------------------------------------------------------------------------------- -Ordering comparison checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven > 7 ) -with expansion: - 7 > 7 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < 7 ) -with expansion: - 7 < 7 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven > 8 ) -with expansion: - 7 > 8 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < 6 ) -with expansion: - 7 < 6 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < 0 ) -with expansion: - 7 < 0 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven < -1 ) -with expansion: - 7 < -1 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven >= 8 ) -with expansion: - 7 >= 8 - -ConditionTests.cpp:: FAILED: - CHECK( data.int_seven <= 6 ) -with expansion: - 7 <= 6 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one < 9 ) -with expansion: - 9.1f < 9 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one > 10 ) -with expansion: - 9.1f > 10 - -ConditionTests.cpp:: FAILED: - CHECK( data.float_nine_point_one > 9.2 ) -with expansion: - 9.1f > 9.2 - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello > "hello" ) -with expansion: - "hello" > "hello" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello < "hello" ) -with expansion: - "hello" < "hello" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello > "hellp" ) -with expansion: - "hello" > "hellp" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello > "z" ) -with expansion: - "hello" > "z" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello < "hellm" ) -with expansion: - "hello" < "hellm" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello < "a" ) -with expansion: - "hello" < "a" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello >= "z" ) -with expansion: - "hello" >= "z" - -ConditionTests.cpp:: FAILED: - CHECK( data.str_hello <= "a" ) -with expansion: - "hello" <= "a" - -------------------------------------------------------------------------------- -Ordering comparison checks that should succeed -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven < 8 ) -with expansion: - 7 < 8 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven > 6 ) -with expansion: - 7 > 6 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven > 0 ) -with expansion: - 7 > 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven > -1 ) -with expansion: - 7 > -1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven >= 7 ) -with expansion: - 7 >= 7 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven >= 6 ) -with expansion: - 7 >= 6 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven <= 7 ) -with expansion: - 7 <= 7 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.int_seven <= 8 ) -with expansion: - 7 <= 8 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one > 9 ) -with expansion: - 9.1f > 9 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one < 10 ) -with expansion: - 9.1f < 10 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.float_nine_point_one < 9.2 ) -with expansion: - 9.1f < 9.2 - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello <= "hello" ) -with expansion: - "hello" <= "hello" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello >= "hello" ) -with expansion: - "hello" >= "hello" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello < "hellp" ) -with expansion: - "hello" < "hellp" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello < "zebra" ) -with expansion: - "hello" < "zebra" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello > "hellm" ) -with expansion: - "hello" > "hellm" - -ConditionTests.cpp:: -PASSED: - REQUIRE( data.str_hello > "a" ) -with expansion: - "hello" > "a" - -------------------------------------------------------------------------------- -Output from all sections is reported - one -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - Message from section one - -------------------------------------------------------------------------------- -Output from all sections is reported - two -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - Message from section two - -------------------------------------------------------------------------------- -Parse test names and tags - Empty test spec should have no filters -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Test spec from empty string should have no filters -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches(tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Test spec from just a comma should have no filters -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Test spec from name should have one filter -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Test spec from quoted name should have one filter -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Test spec from name should have one filter -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Wildcard at the start -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Wildcard at the end -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Wildcard at both ends -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Redundant wildcard at the start -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Redundant wildcard at the end -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Redundant wildcard at both ends -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Wildcard at both ends, redundant at start -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Just wildcard -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Single tag -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Single tag, two matches -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Two tags -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Two tags, spare separated -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - Wildcarded name and tag -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - Single tag exclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - One tag exclusion and one tag inclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - One tag exclusion and one wldcarded name inclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - One tag exclusion, using exclude:, and one wldcarded name inclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - name exclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parse test names and tags - wildcarded name exclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - wildcarded name exclusion with tag inclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - wildcarded name exclusion, using exclude:, with tag inclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - two wildcarded names -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - empty tag -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - empty quoted name -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Parse test names and tags - quoted string followed by tag exclusion -------------------------------------------------------------------------------- -CmdLineTests.cpp: -............................................................................... - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.hasFilters() == true ) -with expansion: - true == true - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcA ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcB ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcC ) == false ) -with expansion: - false == false - -CmdLineTests.cpp:: -PASSED: - CHECK( spec.matches( tcD ) == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Parsing a std::pair -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( (std::pair( 1, 2 )) == aNicePair ) -with expansion: - { 1, 2 } == { 1, 2 } - -------------------------------------------------------------------------------- -Pointers can be compared to null -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( p == 0 ) -with expansion: - 0 == 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( p == pNULL ) -with expansion: - 0 == 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( p != 0 ) -with expansion: - 0x != 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( cp != 0 ) -with expansion: - 0x != 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( cpc != 0 ) -with expansion: - 0x != 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( returnsNull() == 0 ) -with expansion: - {null string} == 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( returnsConstNull() == 0 ) -with expansion: - {null string} == 0 - -ConditionTests.cpp:: -PASSED: - REQUIRE( 0 != p ) -with expansion: - 0 != 0x - -------------------------------------------------------------------------------- -Pointers can be converted to strings -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -warning: - actual address of p: 0x - -MessageTests.cpp:: -warning: - toString(p): 0x - -------------------------------------------------------------------------------- -Process can be configured on command line - empty args don't cause a crash -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( result ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - CHECK( config.processName == "" ) -with expansion: - "" == "" - -------------------------------------------------------------------------------- -Process can be configured on command line - default - no arguments -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( result ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - CHECK( config.processName == "test" ) -with expansion: - "test" == "test" - -TestMain.cpp:: -PASSED: - CHECK( config.shouldDebugBreak == false ) -with expansion: - false == false - -TestMain.cpp:: -PASSED: - CHECK( config.abortAfter == -1 ) -with expansion: - -1 == -1 - -TestMain.cpp:: -PASSED: - CHECK( config.noThrow == false ) -with expansion: - false == false - -TestMain.cpp:: -PASSED: - CHECK( config.reporterNames.empty() ) -with expansion: - true - -------------------------------------------------------------------------------- -Process can be configured on command line - test lists - 1 test -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( result ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( cfg.testSpec().matches(fakeTestCase("notIncluded")) == false ) -with expansion: - false == false - -TestMain.cpp:: -PASSED: - REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) ) -with expansion: - true - -------------------------------------------------------------------------------- -Process can be configured on command line - test lists - Specify one test case exclusion using exclude: -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( result ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false ) -with expansion: - false == false - -TestMain.cpp:: -PASSED: - REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) ) -with expansion: - true - -------------------------------------------------------------------------------- -Process can be configured on command line - test lists - Specify one test case exclusion using ~ -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( result ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( cfg.testSpec().matches(fakeTestCase("test1")) == false ) -with expansion: - false == false - -TestMain.cpp:: -PASSED: - REQUIRE( cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) ) -with expansion: - true - -------------------------------------------------------------------------------- -Process can be configured on command line - reporter - -r/console -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-r", "console"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.reporterNames[0] == "console" ) -with expansion: - "console" == "console" - -------------------------------------------------------------------------------- -Process can be configured on command line - reporter - -r/xml -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-r", "xml"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.reporterNames[0] == "xml" ) -with expansion: - "xml" == "xml" - -------------------------------------------------------------------------------- -Process can be configured on command line - reporter - -r xml and junit -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-r", "xml", "-r", "junit"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.reporterNames.size() == 2 ) -with expansion: - 2 == 2 - -TestMain.cpp:: -PASSED: - REQUIRE( config.reporterNames[0] == "xml" ) -with expansion: - "xml" == "xml" - -TestMain.cpp:: -PASSED: - REQUIRE( config.reporterNames[1] == "junit" ) -with expansion: - "junit" == "junit" - -------------------------------------------------------------------------------- -Process can be configured on command line - reporter - --reporter/junit -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "--reporter", "junit"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.reporterNames[0] == "junit" ) -with expansion: - "junit" == "junit" - -------------------------------------------------------------------------------- -Process can be configured on command line - debugger - -b -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-b"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.shouldDebugBreak == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Process can be configured on command line - debugger - --break -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "--break"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.shouldDebugBreak ) -with expansion: - true - -------------------------------------------------------------------------------- -Process can be configured on command line - abort - -a aborts after first failure -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-a"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.abortAfter == 1 ) -with expansion: - 1 == 1 - -------------------------------------------------------------------------------- -Process can be configured on command line - abort - -x 2 aborts after two failures -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-x", "2"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.abortAfter == 2 ) -with expansion: - 2 == 2 - -------------------------------------------------------------------------------- -Process can be configured on command line - abort - -x must be numeric -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( !result ) -with expansion: - true - -TestMain.cpp:: -PASSED: - REQUIRE_THAT( result.errorMessage(), Contains("convert") && Contains("oops") ) -with expansion: - "Unable to convert 'oops' to destination type" ( contains: "convert" and - contains: "oops" ) - -------------------------------------------------------------------------------- -Process can be configured on command line - nothrow - -e -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-e"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.noThrow ) -with expansion: - true - -------------------------------------------------------------------------------- -Process can be configured on command line - nothrow - --nothrow -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "--nothrow"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.noThrow ) -with expansion: - true - -------------------------------------------------------------------------------- -Process can be configured on command line - output filename - -o filename -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-o", "filename.ext"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.outputFilename == "filename.ext" ) -with expansion: - "filename.ext" == "filename.ext" - -------------------------------------------------------------------------------- -Process can be configured on command line - output filename - --out -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "--out", "filename.ext"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.outputFilename == "filename.ext" ) -with expansion: - "filename.ext" == "filename.ext" - -------------------------------------------------------------------------------- -Process can be configured on command line - combinations - Single character flags can be combined -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "-abe"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - CHECK( config.abortAfter == 1 ) -with expansion: - 1 == 1 - -TestMain.cpp:: -PASSED: - CHECK( config.shouldDebugBreak ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK( config.noThrow == true ) -with expansion: - true == true - -------------------------------------------------------------------------------- -Process can be configured on command line - use-colour - without option -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.useColour == UseColour::Auto ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -Process can be configured on command line - use-colour - auto -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "--use-colour", "auto"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.useColour == UseColour::Auto ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -Process can be configured on command line - use-colour - yes -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "--use-colour", "yes"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.useColour == UseColour::Yes ) -with expansion: - 1 == 1 - -------------------------------------------------------------------------------- -Process can be configured on command line - use-colour - no -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( cli.parse({"test", "--use-colour", "no"}) ) -with expansion: - {?} - -TestMain.cpp:: -PASSED: - REQUIRE( config.useColour == UseColour::No ) -with expansion: - 2 == 2 - -------------------------------------------------------------------------------- -Process can be configured on command line - use-colour - error -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( !result ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) ) -with expansion: - "colour mode must be one of: auto, yes or no. 'wrong' not recognised" - contains: "colour mode must be one of" - -------------------------------------------------------------------------------- -Reconstruction should be based on stringification: #914 -------------------------------------------------------------------------------- -DecompositionTests.cpp: -............................................................................... - -DecompositionTests.cpp:: FAILED: - CHECK( truthy(false) ) -with expansion: - Hey, its truthy! - -------------------------------------------------------------------------------- -SCOPED_INFO is reset for each loop -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 0 < 10 -with messages: - current counter 0 - i := 0 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 1 < 10 -with messages: - current counter 1 - i := 1 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 2 < 10 -with messages: - current counter 2 - i := 2 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 3 < 10 -with messages: - current counter 3 - i := 3 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 4 < 10 -with messages: - current counter 4 - i := 4 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 5 < 10 -with messages: - current counter 5 - i := 5 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 6 < 10 -with messages: - current counter 6 - i := 6 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 7 < 10 -with messages: - current counter 7 - i := 7 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 8 < 10 -with messages: - current counter 8 - i := 8 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 9 < 10 -with messages: - current counter 9 - i := 9 - -MessageTests.cpp:: FAILED: - REQUIRE( i < 10 ) -with expansion: - 10 < 10 -with messages: - current counter 10 - i := 10 - -------------------------------------------------------------------------------- -SUCCEED counts as a test pass -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -PASSED: -with message: - this is a success - -------------------------------------------------------------------------------- -SUCCESS does not require an argument -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or - methods - Given: No operations precede me -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( before == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -Scenario: BDD tests requiring Fixtures to provide commonly-accessed data or - methods - Given: No operations precede me - When: We get the count - Then: Subsequently values are higher -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( after > before ) -with expansion: - 1 > 0 - -------------------------------------------------------------------------------- -Scenario: Do that thing with the thing - Given: This stuff exists - When: I do this - Then: it should do this -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( itDoesThis() ) -with expansion: - true - -------------------------------------------------------------------------------- -Scenario: Do that thing with the thing - Given: This stuff exists - When: I do this - Then: it should do this - And: do that -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( itDoesThat() ) -with expansion: - true - -------------------------------------------------------------------------------- -Scenario: This is a really long scenario name to see how the list command deals - with wrapping - Given: A section name that is so long that it cannot fit in a single - console width - When: The test headers are printed as part of the normal running of the - scenario - Then: The, deliberately very long and overly verbose (you see what I did - there?) section names must wrap, along with an indent -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: -with message: - boo! - -------------------------------------------------------------------------------- -Scenario: Vector resizing affects size and capacity - Given: an empty vector -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( v.size() == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -Scenario: Vector resizing affects size and capacity - Given: an empty vector - When: it is made larger - Then: the size and capacity go up -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( v.size() == 10 ) -with expansion: - 10 == 10 - -BDDTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 10 ) -with expansion: - 10 >= 10 - -------------------------------------------------------------------------------- -Scenario: Vector resizing affects size and capacity - Given: an empty vector - When: it is made larger - Then: the size and capacity go up - And when: it is made smaller again - Then: the size goes down but the capacity stays the same -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( v.size() == 5 ) -with expansion: - 5 == 5 - -BDDTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 10 ) -with expansion: - 10 >= 10 - -------------------------------------------------------------------------------- -Scenario: Vector resizing affects size and capacity - Given: an empty vector -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( v.size() == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -Scenario: Vector resizing affects size and capacity - Given: an empty vector - When: we reserve more space - Then: The capacity is increased but the size remains the same -------------------------------------------------------------------------------- -BDDTests.cpp: -............................................................................... - -BDDTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 10 ) -with expansion: - 10 >= 10 - -BDDTests.cpp:: -PASSED: - REQUIRE( v.size() == 0 ) -with expansion: - 0 == 0 - -A string sent directly to stdout -A string sent directly to stderr -------------------------------------------------------------------------------- -Some simple comparisons between doubles -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( d == Approx( 1.23 ) ) -with expansion: - 1.23 == Approx( 1.23 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d != Approx( 1.22 ) ) -with expansion: - 1.23 != Approx( 1.22 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d != Approx( 1.24 ) ) -with expansion: - 1.23 != Approx( 1.24 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx( d ) == 1.23 ) -with expansion: - Approx( 1.23 ) == 1.23 - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx( d ) != 1.22 ) -with expansion: - Approx( 1.23 ) != 1.22 - -ApproxTests.cpp:: -PASSED: - REQUIRE( Approx( d ) != 1.24 ) -with expansion: - Approx( 1.23 ) != 1.24 - -Message from section one -------------------------------------------------------------------------------- -Standard output from all sections is reported - one -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'one' - -Message from section two -------------------------------------------------------------------------------- -Standard output from all sections is reported - two -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'two' - -------------------------------------------------------------------------------- -StartsWith string matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( testStringForMatching(), StartsWith( "string" ) ) -with expansion: - "this string contains 'abc' as a substring" starts with: "string" - -------------------------------------------------------------------------------- -String - empty string -------------------------------------------------------------------------------- -String.tests.cpp: -............................................................................... - -String.tests.cpp:: -PASSED: - REQUIRE( empty.empty() ) -with expansion: - true - -String.tests.cpp:: -PASSED: - REQUIRE( empty.size() == 0 ) -with expansion: - 0 == 0 - -String.tests.cpp:: -PASSED: - REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -String - from literal -------------------------------------------------------------------------------- -String.tests.cpp: -............................................................................... - -String.tests.cpp:: -PASSED: - REQUIRE( s.empty() == false ) -with expansion: - false == false - -String.tests.cpp:: -PASSED: - REQUIRE( s.size() == 5 ) -with expansion: - 5 == 5 - -------------------------------------------------------------------------------- -String matchers -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ) -with expansion: - "this string contains 'abc' as a substring" contains: "string" - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), Contains( "abc" ) ) -with expansion: - "this string contains 'abc' as a substring" contains: "abc" - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ) -with expansion: - "this string contains 'abc' as a substring" starts with: "this" - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ) -with expansion: - "this string contains 'abc' as a substring" ends with: "substring" - -------------------------------------------------------------------------------- -StringBuilder - basic -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.capacity() == 0 ) -with expansion: - 0 == 0 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.size() == 0 ) -with expansion: - 0 == 0 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.capacity() == 32 ) -with expansion: - 32 == 32 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.size() == 0 ) -with expansion: - 0 == 0 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.capacity() == 32 ) -with expansion: - 32 == 32 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.size() == 5 ) -with expansion: - 5 == 5 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello" ) -with expansion: - {?} == "hello" - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s.size() == 5 ) -with expansion: - 5 == 5 - -------------------------------------------------------------------------------- -StringBuilder - concatenation -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello world" ) -with expansion: - {?} == "hello world" - -------------------------------------------------------------------------------- -StringBuilder - concat & move -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello world" ) -with expansion: - {?} == "hello world" - -------------------------------------------------------------------------------- -StringBuilder - reserved -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb16.capacity() == 16 ) -with expansion: - 16 == 16 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb16.capacity() == 16 ) -with expansion: - 16 == 16 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello world" ) -with expansion: - {?} == "hello world" - -------------------------------------------------------------------------------- -StringBuilder - from String - copy -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2 == s ) -with expansion: - {?} == {?} - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2.c_str() != s.c_str() ) -with expansion: - "hello" != "hello" - -------------------------------------------------------------------------------- -StringBuilder - from String - move from uniquely owned string -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2 == "hello" ) -with expansion: - {?} == "hello" - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2.c_str() == originalPointer ) -with expansion: - "hello" == "hello" - -------------------------------------------------------------------------------- -StringBuilder - from String - move from shared string (copies) -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2 == "hello" ) -with expansion: - {?} == "hello" - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2.c_str() != originalPointer ) -with expansion: - "hello" != "hello" - -------------------------------------------------------------------------------- -StringRef - Empty string -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( empty.empty() ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( empty.size() == 0 ) -with expansion: - 0 == 0 - -StringRef.tests.cpp:: -PASSED: - REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -StringRef - From string literal -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( s.empty() == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( s.size() == 5 ) -with expansion: - 5 == 5 - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isSubstring( s ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( std::strcmp( rawChars, "hello" ) == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -StringRef - From string literal - c_str() does not cause copy -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( s ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( s.c_str() == rawChars ) -with expansion: - "hello" == "hello" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( s ) == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -StringRef - From sub-string -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( original == "original" ) -with expansion: - {?} == "original" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isSubstring( original ) ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( original ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isSubstring( original ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( original ) ) -with expansion: - true - -------------------------------------------------------------------------------- -StringRef - Substrings - zero-based substring -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( ss.empty() == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( ss.size() == 5 ) -with expansion: - 5 == 5 - -StringRef.tests.cpp:: -PASSED: - REQUIRE( std::strcmp( ss.c_str(), "hello" ) == 0 ) -with expansion: - 0 == 0 - -StringRef.tests.cpp:: -PASSED: - REQUIRE( ss == "hello" ) -with expansion: - {?} == "hello" - -------------------------------------------------------------------------------- -StringRef - Substrings - c_str() causes copy -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isSubstring( ss ) ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( ss ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( rawChars == data( s ) ) -with expansion: - "hello world!" == "hello world!" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( ss.c_str() != rawChars ) -with expansion: - "hello" != "hello world!" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isSubstring( ss ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( ss ) ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( data( ss ) != data( s ) ) -with expansion: - "hello" != "hello world!" - -------------------------------------------------------------------------------- -StringRef - Substrings - non-zero-based substring -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( ss.size() == 6 ) -with expansion: - 6 == 6 - -StringRef.tests.cpp:: -PASSED: - REQUIRE( std::strcmp( ss.c_str(), "world!" ) == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -StringRef - Substrings - Pointer values of full refs should match -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( s.c_str() == s2.c_str() ) -with expansion: - "hello world!" == "hello world!" - -------------------------------------------------------------------------------- -StringRef - Substrings - Pointer values of substring refs should not match -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( s.c_str() != ss.c_str() ) -with expansion: - "hello world!" != "hello" - -------------------------------------------------------------------------------- -StringRef - Comparisons -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( StringRef("hello") == StringRef("hello") ) -with expansion: - {?} == {?} - -StringRef.tests.cpp:: -PASSED: - REQUIRE( StringRef("hello") != StringRef("cello") ) -with expansion: - {?} != {?} - -------------------------------------------------------------------------------- -StringRef - From string - Copied -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( copied == "hot potato" ) -with expansion: - {?} == "hot potato" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( str == "hot potato" ) -with expansion: - {?} == "hot potato" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( copied ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( data( copied ) == originalPointer ) -with expansion: - "hot potato" == "hot potato" - -------------------------------------------------------------------------------- -StringRef - From string - Moved -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( copied == "hot potato" ) -with expansion: - {?} == "hot potato" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( copied ) ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( str.empty() ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( data( copied ) == originalPointer ) -with expansion: - "hot potato" == "hot potato" - -hello -hello -------------------------------------------------------------------------------- -Tabs and newlines show in output -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( s1 == s2 ) -with expansion: - "if ($b == 10) { - $a = 20; - }" - == - "if ($b == 10) { - $a = 20; - } - " - -------------------------------------------------------------------------------- -Tag alias can be registered against tag patterns - The same tag alias can only be registered once -------------------------------------------------------------------------------- -TagAliasTests.cpp: -............................................................................... - -TagAliasTests.cpp:: -PASSED: - CHECK_THAT( what, Contains( "[@zzz]" ) ) -with expansion: - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "[@zzz]" - -TagAliasTests.cpp:: -PASSED: - CHECK_THAT( what, Contains( "file" ) ) -with expansion: - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "file" - -TagAliasTests.cpp:: -PASSED: - CHECK_THAT( what, Contains( "2" ) ) -with expansion: - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "2" - -TagAliasTests.cpp:: -PASSED: - CHECK_THAT( what, Contains( "10" ) ) -with expansion: - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "10" - -------------------------------------------------------------------------------- -Tag alias can be registered against tag patterns - Tag aliases must be of the form [@name] -------------------------------------------------------------------------------- -TagAliasTests.cpp: -............................................................................... - -TagAliasTests.cpp:: -PASSED: - CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) ) - -TagAliasTests.cpp:: -PASSED: - CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) - -TagAliasTests.cpp:: -PASSED: - CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) ) - -TagAliasTests.cpp:: -PASSED: - CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) ) - -------------------------------------------------------------------------------- -Test case with one argument -------------------------------------------------------------------------------- -VariadicMacrosTests.cpp: -............................................................................... - -VariadicMacrosTests.cpp:: -PASSED: -with message: - no assertions - -------------------------------------------------------------------------------- -Test enum bit values -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( 0x == bit30and31 ) -with expansion: - 3221225472 (0x) == 3221225472 - -------------------------------------------------------------------------------- -Text can be formatted using the Text class -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( "hi there" ).toString() == "hi there" ) -with expansion: - "hi there" == "hi there" - -TestMain.cpp:: -PASSED: - CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ) -with expansion: - "hi - there" - == - "hi - there" - -------------------------------------------------------------------------------- -The NO_FAIL macro reports a failure but does not fail the test -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -FAILED - but was ok: - CHECK_NOFAIL( 1 == 2 ) - -------------------------------------------------------------------------------- -This test 'should' fail but doesn't -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: -with message: - oops! - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - successfully close one section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isSuccessfullyCompleted() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isSuccessfullyCompleted() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - fail one section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - fail one section - re-enter after failed section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isSuccessfullyCompleted() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - fail one section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - fail one section - re-enter after failed section and find next section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isSuccessfullyCompleted() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - successfully close one section, then find another -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - successfully close one section, then find another - Re-enter - skips S1 and enters S2 -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - successfully close one section, then find another - Re-enter - skips S1 and enters S2 - Successfully close S2 -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isSuccessfullyCompleted() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isSuccessfullyCompleted() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - successfully close one section, then find another -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - successfully close one section, then find another - Re-enter - skips S1 and enters S2 -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - successfully close one section, then find another - Re-enter - skips S1 and enters S2 - fail S2 -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( ctx.completedCycle() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase3.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1c.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2c.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase3.isSuccessfullyCompleted() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - open a nested section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - start a generator -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.index() == 0 ) -with expansion: - 0 == 0 - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - start a generator - close outer section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - start a generator - close outer section - Re-enter for second generation -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.index() == 1 ) -with expansion: - 1 == 1 - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isComplete() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - start a generator -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.index() == 0 ) -with expansion: - 0 == 0 - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - start a generator - Start a new inner section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - start a generator - Start a new inner section - Re-enter for second generation -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.index() == 1 ) -with expansion: - 1 == 1 - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isComplete() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isOpen() ) -with expansion: - true - -------------------------------------------------------------------------------- -Tracker - start a generator -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.index() == 0 ) -with expansion: - 0 == 0 - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - start a generator - Fail an inner section -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2.isSuccessfullyCompleted() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase.isComplete() == false ) -with expansion: - false == false - -------------------------------------------------------------------------------- -Tracker - start a generator - Fail an inner section - Re-enter for second generation -------------------------------------------------------------------------------- -PartTrackerTests.cpp: -............................................................................... - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.index() == 0 ) -with expansion: - 0 == 0 - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2b.isOpen() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1b.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1b.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase2.isComplete() == false ) -with expansion: - false == false - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase3.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1c.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1c.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1c.index() == 1 ) -with expansion: - 1 == 1 - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2c.isOpen() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s2c.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( g1c.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( s1c.isComplete() ) -with expansion: - true - -PartTrackerTests.cpp:: -PASSED: - REQUIRE( testCase3.isComplete() ) -with expansion: - true - -------------------------------------------------------------------------------- -Unexpected exceptions can be translated -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - 3.14 - -------------------------------------------------------------------------------- -Use a custom approx -------------------------------------------------------------------------------- -ApproxTests.cpp: -............................................................................... - -ApproxTests.cpp:: -PASSED: - REQUIRE( d == approx( 1.23 ) ) -with expansion: - 1.23 == Approx( 1.23 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d == approx( 1.22 ) ) -with expansion: - 1.23 == Approx( 1.22 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d == approx( 1.24 ) ) -with expansion: - 1.23 == Approx( 1.24 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( d != approx( 1.25 ) ) -with expansion: - 1.23 != Approx( 1.25 ) - -ApproxTests.cpp:: -PASSED: - REQUIRE( approx( d ) == 1.23 ) -with expansion: - Approx( 1.23 ) == 1.23 - -ApproxTests.cpp:: -PASSED: - REQUIRE( approx( d ) == 1.22 ) -with expansion: - Approx( 1.23 ) == 1.22 - -ApproxTests.cpp:: -PASSED: - REQUIRE( approx( d ) == 1.24 ) -with expansion: - Approx( 1.23 ) == 1.24 - -ApproxTests.cpp:: -PASSED: - REQUIRE( approx( d ) != 1.25 ) -with expansion: - Approx( 1.23 ) != 1.25 - -------------------------------------------------------------------------------- -Variadic macros - Section with one argument -------------------------------------------------------------------------------- -VariadicMacrosTests.cpp: -............................................................................... - -VariadicMacrosTests.cpp:: -PASSED: -with message: - no assertions - -------------------------------------------------------------------------------- -Vector matchers - Contains (element) -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( v, VectorContains( 1 ) ) -with expansion: - { 1, 2, 3 } Contains: 1 - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( v, VectorContains( 2 ) ) -with expansion: - { 1, 2, 3 } Contains: 2 - -------------------------------------------------------------------------------- -Vector matchers - Contains (vector) -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( v, Contains( v2 ) ) -with expansion: - { 1, 2, 3 } Contains: { 1, 2 } - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( v, Contains( v2 ) ) -with expansion: - { 1, 2, 3 } Contains: { 1, 2, 3 } - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( v, Contains( empty) ) -with expansion: - { 1, 2, 3 } Contains: { } - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( empty, Contains( empty) ) -with expansion: - { } Contains: { } - -------------------------------------------------------------------------------- -Vector matchers - Equals -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( v, Equals( v ) ) -with expansion: - { 1, 2, 3 } Equals: { 1, 2, 3 } - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( empty, Equals( empty ) ) -with expansion: - { } Equals: { } - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( v, Equals( v2 ) ) -with expansion: - { 1, 2, 3 } Equals: { 1, 2, 3 } - -------------------------------------------------------------------------------- -Vector matchers that fail - Contains (element) -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, VectorContains( -1 ) ) -with expansion: - { 1, 2, 3 } Contains: -1 - -MatchersTests.cpp:: FAILED: - CHECK_THAT( empty, VectorContains( 1 ) ) -with expansion: - { } Contains: 1 - -------------------------------------------------------------------------------- -Vector matchers that fail - Contains (vector) -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( empty, Contains( v) ) -with expansion: - { } Contains: { 1, 2, 3 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, Contains( v2 ) ) -with expansion: - { 1, 2, 3 } Contains: { 1, 2, 4 } - -------------------------------------------------------------------------------- -Vector matchers that fail - Equals -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, Equals( v2 ) ) -with expansion: - { 1, 2, 3 } Equals: { 1, 2 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v2, Equals( v ) ) -with expansion: - { 1, 2 } Equals: { 1, 2, 3 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( empty, Equals( v ) ) -with expansion: - { } Equals: { 1, 2, 3 } - -MatchersTests.cpp:: FAILED: - CHECK_THAT( v, Equals( empty ) ) -with expansion: - { 1, 2, 3 } Equals: { } - -------------------------------------------------------------------------------- -When checked exceptions are thrown they can be expected or unexpected -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_AS( thisThrows(), std::domain_error ) - -ExceptionTests.cpp:: -PASSED: - REQUIRE_NOTHROW( thisDoesntThrow() ) - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS( thisThrows() ) - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown directly they are always failures -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - unexpected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown during a CHECK the test should continue -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - CHECK( thisThrows() == 0 ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown during a REQUIRE the test should abort -fail -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE( thisThrows() == 0 ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown from functions they are always failures -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - CHECK( thisThrows() == 0 ) -due to unexpected exception with message: - expected exception - -------------------------------------------------------------------------------- -When unchecked exceptions are thrown from sections they are always failures - section name -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with message: - unexpected exception - -------------------------------------------------------------------------------- -Where the LHS is not a simple value -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -warning: - Uncomment the code in this test to check that it gives a sensible compiler - error - -------------------------------------------------------------------------------- -Where there is more to the expression after the RHS -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -warning: - Uncomment the code in this test to check that it gives a sensible compiler - error - -------------------------------------------------------------------------------- -X/level/0/a -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -X/level/0/b -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -X/level/1/a -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -X/level/1/b -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -XmlEncode - normal string -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "normal string" ) == "normal string" ) -with expansion: - "normal string" == "normal string" - -------------------------------------------------------------------------------- -XmlEncode - empty string -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "" ) == "" ) -with expansion: - "" == "" - -------------------------------------------------------------------------------- -XmlEncode - string with ampersand -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "smith & jones" ) == "smith & jones" ) -with expansion: - "smith & jones" == "smith & jones" - -------------------------------------------------------------------------------- -XmlEncode - string with less-than -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "smith < jones" ) == "smith < jones" ) -with expansion: - "smith < jones" == "smith < jones" - -------------------------------------------------------------------------------- -XmlEncode - string with greater-than -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "smith > jones" ) == "smith > jones" ) -with expansion: - "smith > jones" == "smith > jones" - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ) -with expansion: - "smith ]]> jones" - == - "smith ]]> jones" - -------------------------------------------------------------------------------- -XmlEncode - string with quotes -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ) -with expansion: - "don't "quote" me on that" - == - "don't "quote" me on that" - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ) -with expansion: - "don't "quote" me on that" - == - "don't "quote" me on that" - -------------------------------------------------------------------------------- -XmlEncode - string with control char (1) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "[\x01]" ) == "[\\x01]" ) -with expansion: - "[\x01]" == "[\x01]" - -------------------------------------------------------------------------------- -XmlEncode - string with control char (x7F) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( encode( "[\x7F]" ) == "[\\x7F]" ) -with expansion: - "[\x7F]" == "[\x7F]" - -------------------------------------------------------------------------------- -atomic if -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( x == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -boolean member -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( obj.prop != 0 ) -with expansion: - 0x != 0 - -------------------------------------------------------------------------------- -checkedElse -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - CHECKED_ELSE( flag ) -with expansion: - true - -MiscTests.cpp:: -PASSED: - REQUIRE( testCheckedElse( true ) ) -with expansion: - true - -------------------------------------------------------------------------------- -checkedElse, failing -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECKED_ELSE( flag ) -with expansion: - false - -MiscTests.cpp:: FAILED: - REQUIRE( testCheckedElse( false ) ) -with expansion: - false - -------------------------------------------------------------------------------- -checkedIf -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - CHECKED_IF( flag ) -with expansion: - true - -MiscTests.cpp:: -PASSED: - REQUIRE( testCheckedIf( true ) ) -with expansion: - true - -------------------------------------------------------------------------------- -checkedIf, failing -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECKED_IF( flag ) -with expansion: - false - -MiscTests.cpp:: FAILED: - REQUIRE( testCheckedIf( false ) ) -with expansion: - false - -------------------------------------------------------------------------------- -comparisons between const int variables -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( unsigned_char_var == 1 ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( unsigned_short_var == 1 ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( unsigned_int_var == 1 ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( unsigned_long_var == 1 ) -with expansion: - 1 == 1 - -------------------------------------------------------------------------------- -comparisons between int variables -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: -PASSED: - REQUIRE( long_var == unsigned_char_var ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( long_var == unsigned_short_var ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( long_var == unsigned_int_var ) -with expansion: - 1 == 1 - -ConditionTests.cpp:: -PASSED: - REQUIRE( long_var == unsigned_long_var ) -with expansion: - 1 == 1 - -------------------------------------------------------------------------------- -even more nested SECTION tests - c - d (leaf) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -even more nested SECTION tests - c - e (leaf) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -even more nested SECTION tests - f (leaf) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - -spanner------------------------------------------------------------------------------- -just failure -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: -explicitly with message: - Previous info should not be seen - -------------------------------------------------------------------------------- -long long -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( l == std::numeric_limits::max() ) -with expansion: - 9223372036854775807 (0x) - == - 9223372036854775807 (0x) - -------------------------------------------------------------------------------- -looped SECTION tests - s1 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( b > a ) -with expansion: - 0 > 1 - -------------------------------------------------------------------------------- -looped tests -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[0] (1) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[1] (1) is even - -MiscTests.cpp:: -PASSED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 0 == 0 -with message: - Testing if fib[2] (2) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[3] (3) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[4] (5) is even - -MiscTests.cpp:: -PASSED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 0 == 0 -with message: - Testing if fib[5] (8) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[6] (13) is even - -MiscTests.cpp:: FAILED: - CHECK( ( fib[i] % 2 ) == 0 ) -with expansion: - 1 == 0 -with message: - Testing if fib[7] (21) is even - -------------------------------------------------------------------------------- -more nested SECTION tests - s1 - s2 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - REQUIRE( a == b ) -with expansion: - 1 == 2 - -------------------------------------------------------------------------------- -more nested SECTION tests - s1 - s3 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( a != b ) -with expansion: - 1 != 2 - -------------------------------------------------------------------------------- -more nested SECTION tests - s1 - s4 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( a < b ) -with expansion: - 1 < 2 - -------------------------------------------------------------------------------- -nested SECTION tests - s1 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( a != b ) -with expansion: - 1 != 2 - -MiscTests.cpp:: -PASSED: - REQUIRE( b != a ) -with expansion: - 2 != 1 - -------------------------------------------------------------------------------- -nested SECTION tests - s1 - s2 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( a != b ) -with expansion: - 1 != 2 - -------------------------------------------------------------------------------- -non streamable - with conv. op -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( s == "7" ) -with expansion: - "7" == "7" - -------------------------------------------------------------------------------- -not allowed -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -null strings -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( makeString( false ) != static_cast(0) ) -with expansion: - "valid string" != {null string} - -MiscTests.cpp:: -PASSED: - REQUIRE( makeString( true ) == static_cast(0) ) -with expansion: - {null string} == {null string} - -------------------------------------------------------------------------------- -null_ptr -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( ptr.get() == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -pair > -> toString -------------------------------------------------------------------------------- -ToStringPair.cpp: -............................................................................... - -ToStringPair.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" ) -with expansion: - "{ { 42, "Arthur" }, { "Ford", 24 } }" - == - "{ { 42, "Arthur" }, { "Ford", 24 } }" - -------------------------------------------------------------------------------- -pointer to class -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( p == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -random SECTION tests - s1 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( a != b ) -with expansion: - 1 != 2 - -MiscTests.cpp:: -PASSED: - REQUIRE( b != a ) -with expansion: - 2 != 1 - -------------------------------------------------------------------------------- -random SECTION tests - s2 -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( a != b ) -with expansion: - 1 != 2 - -------------------------------------------------------------------------------- -replaceInPlace - replace single char -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( replaceInPlace( letters, "b", "z" ) ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK( letters == "azcdefcg" ) -with expansion: - "azcdefcg" == "azcdefcg" - -------------------------------------------------------------------------------- -replaceInPlace - replace two chars -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( replaceInPlace( letters, "c", "z" ) ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK( letters == "abzdefzg" ) -with expansion: - "abzdefzg" == "abzdefzg" - -------------------------------------------------------------------------------- -replaceInPlace - replace first char -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( replaceInPlace( letters, "a", "z" ) ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK( letters == "zbcdefcg" ) -with expansion: - "zbcdefcg" == "zbcdefcg" - -------------------------------------------------------------------------------- -replaceInPlace - replace last char -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( replaceInPlace( letters, "g", "z" ) ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK( letters == "abcdefcz" ) -with expansion: - "abcdefcz" == "abcdefcz" - -------------------------------------------------------------------------------- -replaceInPlace - replace all chars -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( replaceInPlace( letters, letters, "replaced" ) ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK( letters == "replaced" ) -with expansion: - "replaced" == "replaced" - -------------------------------------------------------------------------------- -replaceInPlace - replace no chars -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ) -with expansion: - !false - -TestMain.cpp:: -PASSED: - CHECK( letters == letters ) -with expansion: - "abcdefcg" == "abcdefcg" - -------------------------------------------------------------------------------- -replaceInPlace - escape ' -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( replaceInPlace( s, "'", "|'" ) ) -with expansion: - true - -TestMain.cpp:: -PASSED: - CHECK( s == "didn|'t" ) -with expansion: - "didn|'t" == "didn|'t" - -------------------------------------------------------------------------------- -send a single char to INFO -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - REQUIRE( false ) -with message: - 3 - -------------------------------------------------------------------------------- -sends information to INFO -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - REQUIRE( false ) -with messages: - hi - i := 7 - -------------------------------------------------------------------------------- -std::pair -> toString -------------------------------------------------------------------------------- -ToStringPair.cpp: -............................................................................... - -ToStringPair.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" ) -with expansion: - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" - -------------------------------------------------------------------------------- -std::pair -> toString -------------------------------------------------------------------------------- -ToStringPair.cpp: -............................................................................... - -ToStringPair.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" ) -with expansion: - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" - -------------------------------------------------------------------------------- -std::vector > -> toString -------------------------------------------------------------------------------- -ToStringPair.cpp: -............................................................................... - -ToStringPair.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" ) -with expansion: - "{ { "green", 55 } }" - == - "{ { "green", 55 } }" - -------------------------------------------------------------------------------- -string literals of different sizes can be compared -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: FAILED: - REQUIRE( std::string( "first" ) == "second" ) -with expansion: - "first" == "second" - -------------------------------------------------------------------------------- -stringify( has_maker ) -------------------------------------------------------------------------------- -ToStringWhich.cpp: -............................................................................... - -ToStringWhich.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ) -with expansion: - "StringMaker" - == - "StringMaker" - -------------------------------------------------------------------------------- -stringify( has_maker_and_toString ) -------------------------------------------------------------------------------- -ToStringWhich.cpp: -............................................................................... - -ToStringWhich.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify( item ) == "StringMaker" ) -with expansion: - "StringMaker" - == - "StringMaker" - -------------------------------------------------------------------------------- -stringify( has_operator ) -------------------------------------------------------------------------------- -ToStringWhich.cpp: -............................................................................... - -ToStringWhich.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" ) -with expansion: - "operator<<( has_operator )" - == - "operator<<( has_operator )" - -------------------------------------------------------------------------------- -toString on const wchar_t const pointer returns the string contents -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - CHECK( result == "\"wide load\"" ) -with expansion: - ""wide load"" == ""wide load"" - -------------------------------------------------------------------------------- -toString on const wchar_t pointer returns the string contents -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - CHECK( result == "\"wide load\"" ) -with expansion: - ""wide load"" == ""wide load"" - -------------------------------------------------------------------------------- -toString on wchar_t const pointer returns the string contents -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - CHECK( result == "\"wide load\"" ) -with expansion: - ""wide load"" == ""wide load"" - -------------------------------------------------------------------------------- -toString on wchar_t returns the string contents -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - CHECK( result == "\"wide load\"" ) -with expansion: - ""wide load"" == ""wide load"" - -------------------------------------------------------------------------------- -toString( vectors -............................................................................... - -ToStringWhich.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify( v ) == "{ StringMaker }" ) -with expansion: - "{ StringMaker }" - == - "{ StringMaker }" - -------------------------------------------------------------------------------- -toString(enum class w/operator<<) -------------------------------------------------------------------------------- -EnumToString.cpp: -............................................................................... - -EnumToString.cpp:: -PASSED: - CHECK( ::Catch::Detail::stringify(e0) == "E2/V0" ) -with expansion: - "E2/V0" == "E2/V0" - -EnumToString.cpp:: -PASSED: - CHECK( ::Catch::Detail::stringify(e1) == "E2/V1" ) -with expansion: - "E2/V1" == "E2/V1" - -EnumToString.cpp:: -PASSED: - CHECK( ::Catch::Detail::stringify(e3) == "Unknown enum value 10" ) -with expansion: - "Unknown enum value 10" - == - "Unknown enum value 10" - -------------------------------------------------------------------------------- -toString(enum class) -------------------------------------------------------------------------------- -EnumToString.cpp: -............................................................................... - -EnumToString.cpp:: FAILED: - CHECK( ::Catch::Detail::stringify(e0) == "0" ) -with expansion: - "{?}" == "0" - -EnumToString.cpp:: FAILED: - CHECK( ::Catch::Detail::stringify(e1) == "1" ) -with expansion: - "{?}" == "1" - -------------------------------------------------------------------------------- -toString(enum w/operator<<) -------------------------------------------------------------------------------- -EnumToString.cpp: -............................................................................... - -EnumToString.cpp:: -PASSED: - CHECK( ::Catch::Detail::stringify(e0) == "E2{0}" ) -with expansion: - "E2{0}" == "E2{0}" - -EnumToString.cpp:: -PASSED: - CHECK( ::Catch::Detail::stringify(e1) == "E2{1}" ) -with expansion: - "E2{1}" == "E2{1}" - -------------------------------------------------------------------------------- -toString(enum) -------------------------------------------------------------------------------- -EnumToString.cpp: -............................................................................... - -EnumToString.cpp:: -PASSED: - CHECK( ::Catch::Detail::stringify(e0) == "0" ) -with expansion: - "0" == "0" - -EnumToString.cpp:: -PASSED: - CHECK( ::Catch::Detail::stringify(e1) == "1" ) -with expansion: - "1" == "1" - -------------------------------------------------------------------------------- -tuple<> -------------------------------------------------------------------------------- -ToStringTuple.cpp: -............................................................................... - -ToStringTuple.cpp:: -PASSED: - CHECK( "{ }" == ::Catch::Detail::stringify(type{}) ) -with expansion: - "{ }" == "{ }" - -ToStringTuple.cpp:: -PASSED: - CHECK( "{ }" == ::Catch::Detail::stringify(value) ) -with expansion: - "{ }" == "{ }" - -------------------------------------------------------------------------------- -tuple -------------------------------------------------------------------------------- -ToStringTuple.cpp: -............................................................................... - -ToStringTuple.cpp:: -PASSED: - CHECK( "1.2f" == ::Catch::Detail::stringify(float(1.2)) ) -with expansion: - "1.2f" == "1.2f" - -ToStringTuple.cpp:: -PASSED: - CHECK( "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) ) -with expansion: - "{ 1.2f, 0 }" == "{ 1.2f, 0 }" - -------------------------------------------------------------------------------- -tuple -------------------------------------------------------------------------------- -ToStringTuple.cpp: -............................................................................... - -ToStringTuple.cpp:: -PASSED: - CHECK( "{ 0 }" == ::Catch::Detail::stringify(type{0}) ) -with expansion: - "{ 0 }" == "{ 0 }" - -------------------------------------------------------------------------------- -tuple<0,int,const char *> -------------------------------------------------------------------------------- -ToStringTuple.cpp: -............................................................................... - -ToStringTuple.cpp:: -PASSED: - CHECK( "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) ) -with expansion: - "{ 0, 42, "Catch me" }" - == - "{ 0, 42, "Catch me" }" - -------------------------------------------------------------------------------- -tuple -------------------------------------------------------------------------------- -ToStringTuple.cpp: -............................................................................... - -ToStringTuple.cpp:: -PASSED: - CHECK( "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) ) -with expansion: - "{ "hello", "world" }" - == - "{ "hello", "world" }" - -------------------------------------------------------------------------------- -tuple,tuple<>,float> -------------------------------------------------------------------------------- -ToStringTuple.cpp: -............................................................................... - -ToStringTuple.cpp:: -PASSED: - CHECK( "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) ) -with expansion: - "{ { 42 }, { }, 1.2f }" - == - "{ { 42 }, { }, 1.2f }" - -------------------------------------------------------------------------------- -vec> -> toString -------------------------------------------------------------------------------- -ToStringVector.cpp: -............................................................................... - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(v) == "{ }" ) -with expansion: - "{ }" == "{ }" - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" ) -with expansion: - "{ { "hello" }, { "world" } }" - == - "{ { "hello" }, { "world" } }" - -------------------------------------------------------------------------------- -vector -> toString -------------------------------------------------------------------------------- -ToStringVector.cpp: -............................................................................... - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) -with expansion: - "{ }" == "{ }" - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ) -with expansion: - "{ 42 }" == "{ 42 }" - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ) -with expansion: - "{ 42, 250 }" == "{ 42, 250 }" - -------------------------------------------------------------------------------- -vector -> toString -------------------------------------------------------------------------------- -ToStringVector.cpp: -............................................................................... - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) -with expansion: - "{ }" == "{ }" - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42 }" ) -with expansion: - "{ 42 }" == "{ 42 }" - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ 42, 250 }" ) -with expansion: - "{ 42, 250 }" == "{ 42, 250 }" - -------------------------------------------------------------------------------- -vector -> toString -------------------------------------------------------------------------------- -ToStringVector.cpp: -............................................................................... - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ }" ) -with expansion: - "{ }" == "{ }" - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\" }" ) -with expansion: - "{ "hello" }" == "{ "hello" }" - -ToStringVector.cpp:: -PASSED: - REQUIRE( ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" ) -with expansion: - "{ "hello", "world" }" - == - "{ "hello", "world" }" - -------------------------------------------------------------------------------- -vectors can be sized and resized -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 5 ) -with expansion: - 5 == 5 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 5 ) -with expansion: - 5 >= 5 - -------------------------------------------------------------------------------- -vectors can be sized and resized - resizing bigger changes size and capacity -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 10 ) -with expansion: - 10 == 10 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 10 ) -with expansion: - 10 >= 10 - -------------------------------------------------------------------------------- -vectors can be sized and resized -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 5 ) -with expansion: - 5 == 5 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 5 ) -with expansion: - 5 >= 5 - -------------------------------------------------------------------------------- -vectors can be sized and resized - resizing smaller changes size but not capacity -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 0 ) -with expansion: - 0 == 0 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 5 ) -with expansion: - 5 >= 5 - -------------------------------------------------------------------------------- -vectors can be sized and resized - resizing smaller changes size but not capacity - We can use the 'swap trick' to reset the capacity -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -vectors can be sized and resized -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 5 ) -with expansion: - 5 == 5 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 5 ) -with expansion: - 5 >= 5 - -------------------------------------------------------------------------------- -vectors can be sized and resized - reserving bigger changes capacity but not size -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 5 ) -with expansion: - 5 == 5 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 10 ) -with expansion: - 10 >= 10 - -------------------------------------------------------------------------------- -vectors can be sized and resized -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 5 ) -with expansion: - 5 == 5 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 5 ) -with expansion: - 5 >= 5 - -------------------------------------------------------------------------------- -vectors can be sized and resized - reserving smaller does not change size or capacity -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - REQUIRE( v.size() == 5 ) -with expansion: - 5 == 5 - -MiscTests.cpp:: -PASSED: - REQUIRE( v.capacity() >= 5 ) -with expansion: - 5 >= 5 - -------------------------------------------------------------------------------- -xmlentitycheck - embedded xml -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - -------------------------------------------------------------------------------- -xmlentitycheck - encoded chars -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: - -=============================================================================== -test cases: 186 | 134 passed | 48 failed | 4 failed as expected -assertions: 941 | 822 passed | 98 failed | 21 failed as expected - diff --git a/projects/SelfTest/Baselines/console.swa4.unapproved.txt b/projects/SelfTest/Baselines/console.swa4.unapproved.txt deleted file mode 100644 index fe22e2b3..00000000 --- a/projects/SelfTest/Baselines/console.swa4.unapproved.txt +++ /dev/null @@ -1,163 +0,0 @@ - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - is a host application. -Run with -? for options - -------------------------------------------------------------------------------- -# A test name that starts with a # -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: -PASSED: -with message: - yay - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - outside assertions -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: -due to unexpected exception with messages: - answer := 42 - expected exception - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - inside REQUIRE_NOTHROW -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: FAILED: - REQUIRE_NOTHROW( thisThrows() ) -due to unexpected exception with messages: - answer := 42 - expected exception - -------------------------------------------------------------------------------- -#748 - captures with unexpected exceptions - inside REQUIRE_THROWS -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS( thisThrows() ) -with message: - answer := 42 - -------------------------------------------------------------------------------- -#809 -------------------------------------------------------------------------------- -CompilationTests.cpp: -............................................................................... - -CompilationTests.cpp:: -PASSED: - REQUIRE( 42 == f ) -with expansion: - 42 == {?} - -------------------------------------------------------------------------------- -#833 -------------------------------------------------------------------------------- -CompilationTests.cpp: -............................................................................... - -CompilationTests.cpp:: -PASSED: - REQUIRE( a == t ) -with expansion: - 3 == 3 - -CompilationTests.cpp:: -PASSED: - CHECK( a == t ) -with expansion: - 3 == 3 - -CompilationTests.cpp:: -PASSED: - REQUIRE_THROWS( throws_int(true) ) - -CompilationTests.cpp:: -PASSED: - CHECK_THROWS_AS( throws_int(true), int ) - -CompilationTests.cpp:: -PASSED: - REQUIRE_NOTHROW( throws_int(false) ) - -CompilationTests.cpp:: -PASSED: - REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") ) -with expansion: - "aaa" ends with: "aaa" - -CompilationTests.cpp:: -PASSED: - REQUIRE( templated_tests(3) ) -with expansion: - true - -------------------------------------------------------------------------------- -#835 -- errno should not be touched by Catch -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - -MiscTests.cpp:: FAILED: - CHECK( f() == 0 ) -with expansion: - 1 == 0 - -MiscTests.cpp:: -PASSED: - REQUIRE( errno == 1 ) -with expansion: - 1 == 1 - -------------------------------------------------------------------------------- -#872 -------------------------------------------------------------------------------- -CompilationTests.cpp: -............................................................................... - -CompilationTests.cpp:: -PASSED: - REQUIRE( x == 4 ) -with expansion: - {?} == 4 -with message: - dummy := 0 - -------------------------------------------------------------------------------- -'Not' checks that should fail -------------------------------------------------------------------------------- -ConditionTests.cpp: -............................................................................... - -ConditionTests.cpp:: FAILED: - CHECK( false != false ) - -ConditionTests.cpp:: FAILED: - CHECK( true != true ) - -ConditionTests.cpp:: FAILED: - CHECK( !true ) -with expansion: - false - -ConditionTests.cpp:: FAILED: - CHECK_FALSE( true ) - -=============================================================================== -test cases: 7 | 4 passed | 1 failed | 2 failed as expected -assertions: 19 | 12 passed | 4 failed | 3 failed as expected - diff --git a/projects/SelfTest/Baselines/junit.sw.unapproved.txt b/projects/SelfTest/Baselines/junit.sw.unapproved.txt deleted file mode 100644 index bd931044..00000000 --- a/projects/SelfTest/Baselines/junit.sw.unapproved.txt +++ /dev/null @@ -1,821 +0,0 @@ - - - - - - -expected exception -answer := 42 -ExceptionTests.cpp: - - - - -expected exception -answer := 42 -ExceptionTests.cpp: - - - - - - - -MiscTests.cpp: - - - - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - - - - - - - - - -ClassTests.cpp: - - - - - -ClassTests.cpp: - - - - - -to infinity and beyond -MiscTests.cpp: - - - - - -TrickyTests.cpp: - - -TrickyTests.cpp: - - - - - - - -unexpected exception -ExceptionTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - - - - - -MatchersTests.cpp: - - - - -custom exception - not std -ExceptionTests.cpp: - - - - -custom exception - not std -ExceptionTests.cpp: - - - - -custom std exception -ExceptionTests.cpp: - - - - - -MatchersTests.cpp: - - - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - - - - - -MatchersTests.cpp: - - - - -MatchersTests.cpp: - - -MatchersTests.cpp: - - - - -Unknown exception -MatchersTests.cpp: - - -Unknown exception -MatchersTests.cpp: - - - - -MatchersTests.cpp: - - -MatchersTests.cpp: - - - - - - - - -expected exception -ExceptionTests.cpp: - - -ExceptionTests.cpp: - - -expected exception -ExceptionTests.cpp: - - - - -This is a failure -MessageTests.cpp: - - - - -MessageTests.cpp: - - - - -This is a failure -MessageTests.cpp: - - - - - - - -this message should be logged -so should this -MessageTests.cpp: - - - - -this message may be logged later -this message should be logged -MessageTests.cpp: - - -this message may be logged later -this message should be logged -and this, but later -MessageTests.cpp: - - - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - - - -MatchersTests.cpp: - - - - - -MatchersTests.cpp: - - - - -ExceptionTests.cpp: - - - - - -custom exception -ExceptionTests.cpp: - - - - - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - -ConditionTests.cpp: - - - - - -Message from section one -MessageTests.cpp: - - - - -Message from section two -MessageTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -DecompositionTests.cpp: - - - - -current counter 10 -i := 10 -MessageTests.cpp: - - - - - - - - - - - - - - - -A string sent directly to stdout - - -A string sent directly to stderr - - - - - -Message from section one -Message from section two - - - - -MatchersTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - - - - -hello -hello - - - - -MiscTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -3.14 -ExceptionTests.cpp: - - - - - - - - - -MatchersTests.cpp: - - -MatchersTests.cpp: - - - - -MatchersTests.cpp: - - -MatchersTests.cpp: - - - - -MatchersTests.cpp: - - -MatchersTests.cpp: - - -MatchersTests.cpp: - - -MatchersTests.cpp: - - - - - -unexpected exception -ExceptionTests.cpp: - - - - -expected exception -ExceptionTests.cpp: - - - - -expected exception -ExceptionTests.cpp: - - - - -expected exception -ExceptionTests.cpp: - - - - -unexpected exception -ExceptionTests.cpp: - - - - - - - - - - - - - - - - - - - - - -MiscTests.cpp: - - -MiscTests.cpp: - - - - - -MiscTests.cpp: - - -MiscTests.cpp: - - - - - - - - - -Previous info should not be seen -MessageTests.cpp: - - - - - -MiscTests.cpp: - - - - -Testing if fib[0] (1) is even -MiscTests.cpp: - - -Testing if fib[1] (1) is even -MiscTests.cpp: - - -Testing if fib[3] (3) is even -MiscTests.cpp: - - -Testing if fib[4] (5) is even -MiscTests.cpp: - - -Testing if fib[6] (13) is even -MiscTests.cpp: - - -Testing if fib[7] (21) is even -MiscTests.cpp: - - - - -MiscTests.cpp: - - - - - - - - - - - - - - - - - - - - - - - -3 -MiscTests.cpp: - - - - -hi -i := 7 -MessageTests.cpp: - - - - - - - -TrickyTests.cpp: - - - - - - - - - - - - - -EnumToString.cpp: - - -EnumToString.cpp: - - - - - - - - - - - - - - - - - - - - - - - -A string sent directly to stdout -Message from section one -Message from section two -hello -hello - - -A string sent directly to stderr - - - diff --git a/projects/SelfTest/Baselines/xml.sw.unapproved.txt b/projects/SelfTest/Baselines/xml.sw.unapproved.txt deleted file mode 100644 index 5b4ecb9e..00000000 --- a/projects/SelfTest/Baselines/xml.sw.unapproved.txt +++ /dev/null @@ -1,10082 +0,0 @@ - - - - - - - -
- - answer := 42 - - - expected exception - - -
-
- - answer := 42 - - - - thisThrows() - - - thisThrows() - - - expected exception - - - -
-
- - answer := 42 - - - - thisThrows() - - - thisThrows() - - - -
- -
- - - - 42 == f - - - 42 == {?} - - - - - - - - a == t - - - 3 == 3 - - - - - a == t - - - 3 == 3 - - - - - throws_int(true) - - - throws_int(true) - - - - - throws_int(true), int - - - throws_int(true), int - - - - - throws_int(false) - - - throws_int(false) - - - - - "aaa", Catch::EndsWith("aaa") - - - "aaa" ends with: "aaa" - - - - - templated_tests<int>(3) - - - true - - - - - - - - f() == 0 - - - 1 == 0 - - - - - errno == 1 - - - 1 == 1 - - - - - - - dummy := 0 - - - - x == 4 - - - {?} == 4 - - - - - - - - false != false - - - false != false - - - - - true != true - - - true != true - - - - - !true - - - false - - - - - !true - - - !true - - - - - !trueValue - - - false - - - - - !trueValue - - - !true - - - - - !(1 == 1) - - - false - - - - - !1 == 1 - - - !(1 == 1) - - - - - - - - false == false - - - false == false - - - - - true == true - - - true == true - - - - - !false - - - true - - - - - !false - - - !false - - - - - !falseValue - - - true - - - - - !falseValue - - - !false - - - - - !(1 == 2) - - - true - - - - - !1 == 2 - - - !(1 == 2) - - - - - -
- - - is_true<true>::value == true - - - true == true - - - - - true == is_true<true>::value - - - true == true - - - -
-
- - - is_true<false>::value == false - - - false == false - - - - - false == is_true<false>::value - - - false == false - - - -
-
- - - !is_true<false>::value - - - true - - - -
-
- - - !!is_true<true>::value - - - true - - - -
-
- - - is_true<true>::value - - - true - - - - - !is_true<false>::value - - - !false - - - -
- -
- - - - s == "world" - - - "hello" == "world" - - - - - - - - s == "hello" - - - "hello" == "hello" - - - - - - - - m_a == 2 - - - 1 == 2 - - - - - - - - m_a == 1 - - - 1 == 1 - - - - - -
-
- -
- -
- - to infinity and beyond - - -
- - - - &o1 == &o2 - - - 0x == 0x - - - - - o1 == o2 - - - {?} == {?} - - - - - - - - 104.0 != Approx(100.0) - - - 104.0 != Approx( 100.0 ) - - - - - 104.0 == Approx(100.0).margin(5) - - - 104.0 == Approx( 100.0 ) - - - - - 104.0 != Approx(100.0).margin(3) - - - 104.0 != Approx( 100.0 ) - - - - - 100.3 != Approx(100.0) - - - 100.3 != Approx( 100.0 ) - - - - - 100.3 == Approx(100.0).margin(0.5) - - - 100.3 == Approx( 100.0 ) - - - - - - - - testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) - - - "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) - - - - - - - - - - - i++ == 7 - - - 7 == 7 - - - - - i++ == 8 - - - 8 == 8 - - - - - - - - 1 == 1 - - - 1 == 1 - - - - - {Unknown expression after the reported line} - - - {Unknown expression after the reported line} - - - unexpected exception - - - - - - - - - - - testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) - - - "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) - - - - - testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) - - - "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) - - - - - - - - divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) - - - 3.1428571429 == Approx( 3.141 ) - - - - - divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) - - - 3.1428571429 != Approx( 3.141 ) - - - - - - - - d != Approx( 1.231 ) - - - 1.23 != Approx( 1.231 ) - - - - - d == Approx( 1.231 ).epsilon( 0.1 ) - - - 1.23 == Approx( 1.231 ) - - - - - - - - 1.23f == Approx( 1.23f ) - - - 1.23f == Approx( 1.2300000191 ) - - - - - 0.0f == Approx( 0.0f ) - - - 0.0f == Approx( 0.0 ) - - - - - - - - 1 == Approx( 1 ) - - - 1 == Approx( 1.0 ) - - - - - 0 == Approx( 0 ) - - - 0 == Approx( 0.0 ) - - - - - - - - 1.0f == Approx( 1 ) - - - 1.0f == Approx( 1.0 ) - - - - - 0 == Approx( dZero) - - - 0 == Approx( 0.0 ) - - - - - 0 == Approx( dSmall ).epsilon( 0.001 ) - - - 0 == Approx( 0.00001 ) - - - - - 1.234f == Approx( dMedium ) - - - 1.234f == Approx( 1.234 ) - - - - - dMedium == Approx( 1.234f ) - - - 1.234 == Approx( 1.2339999676 ) - - - - - - - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - - -
- -
- - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - - -
- -
- -
- -
- - i := 2 - - - - true - - - true - - - -
-
- - 3 - - - - true - - - true - - - -
- -
- -
- - - tab == '\t' - - - '\t' == '\t' - - - - - newline == '\n' - - - '\n' == '\n' - - - - - carr_return == '\r' - - - '\r' == '\r' - - - - - form_feed == '\f' - - - '\f' == '\f' - - - -
-
- - - space == ' ' - - - ' ' == ' ' - - - - - c == chars[i] - - - 'a' == 'a' - - - - - c == chars[i] - - - 'z' == 'z' - - - - - c == chars[i] - - - 'A' == 'A' - - - - - c == chars[i] - - - 'Z' == 'Z' - - - -
-
- - - null_terminator == '\0' - - - 0 == 0 - - - - - c == i - - - 2 == 2 - - - - - c == i - - - 3 == 3 - - - - - c == i - - - 4 == 4 - - - - - c == i - - - 5 == 5 - - - -
- -
- - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} - - - !({ 1, 2 } == { 1, 2, 3 }) - - - - - !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} - - - !({ 1, 2 } == { 1, 2, 3 }) - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - true - - - true - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - - - - a - - - 0x - - - - - a == &foo - - - 0x == 0x - - - - - - - - m == &S::f - - - 0x -== -0x - - - - - - - - td == Approx(10.0) - - - StrongDoubleTypedef(10) == Approx( 10.0 ) - - - - - Approx(10.0) == td - - - Approx( 10.0 ) == StrongDoubleTypedef(10) - - - - - td != Approx(11.0) - - - StrongDoubleTypedef(10) != Approx( 11.0 ) - - - - - Approx(11.0) != td - - - Approx( 11.0 ) != StrongDoubleTypedef(10) - - - - - td <= Approx(10.0) - - - StrongDoubleTypedef(10) <= Approx( 10.0 ) - - - - - td <= Approx(11.0) - - - StrongDoubleTypedef(10) <= Approx( 11.0 ) - - - - - Approx(10.0) <= td - - - Approx( 10.0 ) <= StrongDoubleTypedef(10) - - - - - Approx(9.0) <= td - - - Approx( 9.0 ) <= StrongDoubleTypedef(10) - - - - - td >= Approx(9.0) - - - StrongDoubleTypedef(10) >= Approx( 9.0 ) - - - - - td >= Approx(10.0) - - - StrongDoubleTypedef(10) >= Approx( 10.0 ) - - - - - Approx(10.0) >= td - - - Approx( 10.0 ) >= StrongDoubleTypedef(10) - - - - - Approx(11.0) >= td - - - Approx( 11.0 ) >= StrongDoubleTypedef(10) - - - - - - - - 54 == 6*9 - - - 54 == 54 - - - - - - - - ( -1 > 2u ) - - - true - - - - - -1 > 2u - - - -1 > 2 - - - - - ( 2u < -1 ) - - - true - - - - - 2u < -1 - - - 2 < -1 - - - - - ( minInt > 2u ) - - - true - - - - - minInt > 2u - - - -2147483648 > 2 - - - - - - - - i == 1 - - - 1 == 1 - - - - - ui == 2 - - - 2 == 2 - - - - - l == 3 - - - 3 == 3 - - - - - ul == 4 - - - 4 == 4 - - - - - c == 5 - - - 5 == 5 - - - - - uc == 6 - - - 6 == 6 - - - - - 1 == i - - - 1 == 1 - - - - - 2 == ui - - - 2 == 2 - - - - - 3 == l - - - 3 == 3 - - - - - 4 == ul - - - 4 == 4 - - - - - 5 == c - - - 5 == 5 - - - - - 6 == uc - - - 6 == 6 - - - - - (std::numeric_limits<unsigned long>::max)() > ul - - - 18446744073709551615 (0x) -> -4 - - - - - - - - testStringForMatching(), Contains( "not there" ) - - - "this string contains 'abc' as a substring" contains: "not there" - - - - - - - - throwCustom() - - - throwCustom() - - - custom exception - not std - - - - - - - - throwCustom(), std::exception - - - throwCustom(), std::exception - - - custom exception - not std - - - - - - - custom std exception - - - - - - - t == 1u - - - {?} == 1 - - - - - - - - testStringForMatching(), EndsWith( "this" ) - - - "this string contains 'abc' as a substring" ends with: "this" - - - - - - - - data.int_seven == 6 - - - 7 == 6 - - - - - data.int_seven == 8 - - - 7 == 8 - - - - - data.int_seven == 0 - - - 7 == 0 - - - - - data.float_nine_point_one == Approx( 9.11f ) - - - 9.1f == Approx( 9.1099996567 ) - - - - - data.float_nine_point_one == Approx( 9.0f ) - - - 9.1f == Approx( 9.0 ) - - - - - data.float_nine_point_one == Approx( 1 ) - - - 9.1f == Approx( 1.0 ) - - - - - data.float_nine_point_one == Approx( 0 ) - - - 9.1f == Approx( 0.0 ) - - - - - data.double_pi == Approx( 3.1415 ) - - - 3.1415926535 == Approx( 3.1415 ) - - - - - data.str_hello == "goodbye" - - - "hello" == "goodbye" - - - - - data.str_hello == "hell" - - - "hello" == "hell" - - - - - data.str_hello == "hello1" - - - "hello" == "hello1" - - - - - data.str_hello.size() == 6 - - - 5 == 6 - - - - - x == Approx( 1.301 ) - - - 1.3 == Approx( 1.301 ) - - - - - - - - data.int_seven == 7 - - - 7 == 7 - - - - - data.float_nine_point_one == Approx( 9.1f ) - - - 9.1f == Approx( 9.1000003815 ) - - - - - data.double_pi == Approx( 3.1415926535 ) - - - 3.1415926535 == Approx( 3.1415926535 ) - - - - - data.str_hello == "hello" - - - "hello" == "hello" - - - - - "hello" == data.str_hello - - - "hello" == "hello" - - - - - data.str_hello.size() == 5 - - - 5 == 5 - - - - - x == Approx( 1.3 ) - - - 1.3 == Approx( 1.3 ) - - - - - - - - testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) - - - "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" - - - - - - - - testStringForMatching(), Equals( "something else" ) - - - "this string contains 'abc' as a substring" equals: "something else" - - - - - -
- - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - -
-
- - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - Unknown exception - - - - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - Unknown exception - - - -
-
- - - throws(3), SpecialException, ExceptionMatcher{ 1 } - - - {?} special exception has value of 1 - - - - - throws(4), SpecialException, ExceptionMatcher{ 1 } - - - {?} special exception has value of 1 - - - -
- -
- - - - throws(1), SpecialException, ExceptionMatcher{ 1 } - - - {?} special exception has value of 1 - - - - - throws(2), SpecialException, ExceptionMatcher{ 2 } - - - {?} special exception has value of 2 - - - - - -
- - - thisThrows(), "expected exception" - - - thisThrows(), "expected exception" - - - -
-
- - - thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) - - - thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) - - - -
-
- - - thisThrows(), StartsWith( "expected" ) - - - thisThrows(), StartsWith( "expected" ) - - - - - thisThrows(), EndsWith( "exception" ) - - - thisThrows(), EndsWith( "exception" ) - - - - - thisThrows(), Contains( "except" ) - - - thisThrows(), Contains( "except" ) - - - - - thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) - - - thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) - - - -
- -
- - - - thisThrows(), std::string - - - thisThrows(), std::string - - - expected exception - - - - - thisDoesntThrow(), std::domain_error - - - thisDoesntThrow(), std::domain_error - - - - - thisThrows() - - - thisThrows() - - - expected exception - - - - - - - This is a failure - - - - - - - - - - This is a failure - - - This message appears in the output - - - - - - - Factorial(0) == 1 - - - 1 == 1 - - - - - Factorial(1) == 1 - - - 1 == 1 - - - - - Factorial(2) == 2 - - - 2 == 2 - - - - - Factorial(3) == 6 - - - 6 == 6 - - - - - Factorial(10) == 3628800 - - - 3628800 (0x) == 3628800 (0x) - - - - - - - - d >= Approx( 1.22 ) - - - 1.23 >= Approx( 1.22 ) - - - - - d >= Approx( 1.23 ) - - - 1.23 >= Approx( 1.23 ) - - - - - !d >= Approx( 1.24 ) - - - !(1.23 >= Approx( 1.24 )) - - - - - d >= Approx( 1.24 ).epsilon(0.1) - - - 1.23 >= Approx( 1.24 ) - - - - - - - this is a message - - - this is a warning - - - - - - this message should be logged - - - so should this - - - - a == 1 - - - 2 == 1 - - - - - - - this message may be logged later - - - - a == 2 - - - 2 == 2 - - - - this message may be logged later - - - this message should be logged - - - - a == 1 - - - 2 == 1 - - - - this message may be logged later - - - this message should be logged - - - and this, but later - - - - a == 0 - - - 2 == 0 - - - - this message may be logged later - - - this message should be logged - - - and this, but later - - - but not this - - - - a == 2 - - - 2 == 2 - - - - - - - - data.int_seven != 7 - - - 7 != 7 - - - - - data.float_nine_point_one != Approx( 9.1f ) - - - 9.1f != Approx( 9.1000003815 ) - - - - - data.double_pi != Approx( 3.1415926535 ) - - - 3.1415926535 != Approx( 3.1415926535 ) - - - - - data.str_hello != "hello" - - - "hello" != "hello" - - - - - data.str_hello.size() != 5 - - - 5 != 5 - - - - - - - - data.int_seven != 6 - - - 7 != 6 - - - - - data.int_seven != 8 - - - 7 != 8 - - - - - data.float_nine_point_one != Approx( 9.11f ) - - - 9.1f != Approx( 9.1099996567 ) - - - - - data.float_nine_point_one != Approx( 9.0f ) - - - 9.1f != Approx( 9.0 ) - - - - - data.float_nine_point_one != Approx( 1 ) - - - 9.1f != Approx( 1.0 ) - - - - - data.float_nine_point_one != Approx( 0 ) - - - 9.1f != Approx( 0.0 ) - - - - - data.double_pi != Approx( 3.1415 ) - - - 3.1415926535 != Approx( 3.1415 ) - - - - - data.str_hello != "goodbye" - - - "hello" != "goodbye" - - - - - data.str_hello != "hell" - - - "hello" != "hell" - - - - - data.str_hello != "hello1" - - - "hello" != "hello1" - - - - - data.str_hello.size() != 6 - - - 5 != 6 - - - - - - - - d <= Approx( 1.24 ) - - - 1.23 <= Approx( 1.24 ) - - - - - d <= Approx( 1.23 ) - - - 1.23 <= Approx( 1.23 ) - - - - - !d <= Approx( 1.22 ) - - - !(1.23 <= Approx( 1.22 )) - - - - - d <= Approx( 1.22 ).epsilon(0.1) - - - 1.23 <= Approx( 1.22 ) - - - - - -
-
- - - Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - - - "one two three four" -== -"one two three four" - - - - - Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString - - - "one two three four" -== -"one two three four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" - - - "one two -three four" -== -"one two -three four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" - - - "one -two -three -four" -== -"one -two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" - - - "one -two -three -four" -== -"one -two -three -four" - - - -
- -
-
-
- - - Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" - - - "abc- -def" -== -"abc- -def" - - - - - Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" - - - "abc- -defg" -== -"abc- -defg" - - - - - Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" - - - "abc- -def- -gh" -== -"abc- -def- -gh" - - - - - Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" - - - "one -two -thr- -ee -four" -== -"one -two -thr- -ee -four" - - - - - Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" - - - "one -two -th- -ree -fo- -ur" -== -"one -two -th- -ree -fo- -ur" - - - -
- -
-
-
- - - text.size() == 4 - - - 4 == 4 - - - - - text[0] == "one" - - - "one" == "one" - - - - - text[1] == "two" - - - "two" == "two" - - - - - text[2] == "three" - - - "three" == "three" - - - - - text[3] == "four" - - - "four" == "four" - - - -
- -
-
-
- - - text.toString() == " one two\n three\n four" - - - " one two - three - four" -== -" one two - three - four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - - - "one two -three four" -== -"one two -three four" - - - - - Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString - - - "one two -three four" -== -"one two -three four" - - - - - Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString - - - "one two -three four" -== -"one two -three four" - - - -
- -
-
-
- - - Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" - - - "abcdef" == "abcdef" - - - - - Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" - - - "abcdef" == "abcdef" - - - - - Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" - - - "abcdef" == "abcdef" - - - - - Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" - - - "abcd- -ef" -== -"abcd- -ef" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" - - - "one -two -three -four" -== -"one -two -three -four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - - - "one,two(three) <here>" -== -"one,two(three) <here>" - - - - - Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString - - - "one,two(three) <here>" -== -"one,two(three) <here>" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n<here>" - - - "one,two -(three) -<here>" -== -"one,two -(three) -<here>" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n<here>" - - - "one, -two -(thre- -e) -<here>" -== -"one, -two -(thre- -e) -<here>" - - - - - Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n<her-\ne>" - - - "one, -two -(thr- -ee) -<her- -e>" -== -"one, -two -(thr- -ee) -<her- -e>" - - - - - Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n<he-\nre>" - - - "one, -two -(th- -ree) -<he- -re>" -== -"one, -two -(th- -ree) -<he- -re>" - - - -
- -
- -
- - - - t.toString(), EndsWith( "... message truncated due to excessive size" ) - - - "******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -******************************************************************************- -************************ -******************************************************************************- -... message truncated due to excessive size" ends with: "... message truncated due to excessive size" - - - - - - - - - - - testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) - - - "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" ) - - - - - - - - testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) - - - "this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" ) - - - - - testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) - - - "some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" ) - - - - - - - - testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) - - - "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" ) - - - - - - - - testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) - - - "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) - - - - - - - - testStringForMatching(), !Contains( "different" ) - - - "this string contains 'abc' as a substring" not contains: "different" - - - - - - - - testStringForMatching(), !Contains( "substring" ) - - - "this string contains 'abc' as a substring" not contains: "substring" - - - - - - - - thisThrows(), "expected exception" - - - thisThrows(), "expected exception" - - - - - thisThrows(), "should fail" - - - expected exception - - - - - - - This one ran - - - - - - custom exception - - - - - - - True - - - {?} - - - - - !False - - - true - - - - - !False - - - !{?} - - - - - - - - 0x == o - - - 3221225472 (0x) == {?} - - - - - - - - data.int_seven > 7 - - - 7 > 7 - - - - - data.int_seven < 7 - - - 7 < 7 - - - - - data.int_seven > 8 - - - 7 > 8 - - - - - data.int_seven < 6 - - - 7 < 6 - - - - - data.int_seven < 0 - - - 7 < 0 - - - - - data.int_seven < -1 - - - 7 < -1 - - - - - data.int_seven >= 8 - - - 7 >= 8 - - - - - data.int_seven <= 6 - - - 7 <= 6 - - - - - data.float_nine_point_one < 9 - - - 9.1f < 9 - - - - - data.float_nine_point_one > 10 - - - 9.1f > 10 - - - - - data.float_nine_point_one > 9.2 - - - 9.1f > 9.2 - - - - - data.str_hello > "hello" - - - "hello" > "hello" - - - - - data.str_hello < "hello" - - - "hello" < "hello" - - - - - data.str_hello > "hellp" - - - "hello" > "hellp" - - - - - data.str_hello > "z" - - - "hello" > "z" - - - - - data.str_hello < "hellm" - - - "hello" < "hellm" - - - - - data.str_hello < "a" - - - "hello" < "a" - - - - - data.str_hello >= "z" - - - "hello" >= "z" - - - - - data.str_hello <= "a" - - - "hello" <= "a" - - - - - - - - data.int_seven < 8 - - - 7 < 8 - - - - - data.int_seven > 6 - - - 7 > 6 - - - - - data.int_seven > 0 - - - 7 > 0 - - - - - data.int_seven > -1 - - - 7 > -1 - - - - - data.int_seven >= 7 - - - 7 >= 7 - - - - - data.int_seven >= 6 - - - 7 >= 6 - - - - - data.int_seven <= 7 - - - 7 <= 7 - - - - - data.int_seven <= 8 - - - 7 <= 8 - - - - - data.float_nine_point_one > 9 - - - 9.1f > 9 - - - - - data.float_nine_point_one < 10 - - - 9.1f < 10 - - - - - data.float_nine_point_one < 9.2 - - - 9.1f < 9.2 - - - - - data.str_hello <= "hello" - - - "hello" <= "hello" - - - - - data.str_hello >= "hello" - - - "hello" >= "hello" - - - - - data.str_hello < "hellp" - - - "hello" < "hellp" - - - - - data.str_hello < "zebra" - - - "hello" < "zebra" - - - - - data.str_hello > "hellm" - - - "hello" > "hellm" - - - - - data.str_hello > "a" - - - "hello" > "a" - - - - - -
- - Message from section one - - -
-
- - Message from section two - - -
- -
- -
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches(tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - - - parseTestSpec( "*a" ).matches( tcA ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - - - parseTestSpec( "a*" ).matches( tcA ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - - - parseTestSpec( "*a*" ).matches( tcA ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == true - - - true == true - - - -
- -
- - - - (std::pair<int, int>( 1, 2 )) == aNicePair - - - { 1, 2 } == { 1, 2 } - - - - - - - - p == 0 - - - 0 == 0 - - - - - p == pNULL - - - 0 == 0 - - - - - p != 0 - - - 0x != 0 - - - - - cp != 0 - - - 0x != 0 - - - - - cpc != 0 - - - 0x != 0 - - - - - returnsNull() == 0 - - - {null string} == 0 - - - - - returnsConstNull() == 0 - - - {null string} == 0 - - - - - 0 != p - - - 0 != 0x - - - - - - - actual address of p: 0x - - - toString(p): 0x - - - - -
- - - result - - - {?} - - - - - config.processName == "" - - - "" == "" - - - -
-
- - - result - - - {?} - - - - - config.processName == "test" - - - "test" == "test" - - - - - config.shouldDebugBreak == false - - - false == false - - - - - config.abortAfter == -1 - - - -1 == -1 - - - - - config.noThrow == false - - - false == false - - - - - config.reporterNames.empty() - - - true - - - -
-
-
- - - result - - - {?} - - - - - cfg.testSpec().matches(fakeTestCase("notIncluded")) == false - - - false == false - - - - - cfg.testSpec().matches(fakeTestCase("test1")) - - - true - - - -
- -
-
-
- - - result - - - {?} - - - - - cfg.testSpec().matches(fakeTestCase("test1")) == false - - - false == false - - - - - cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) - - - true - - - -
- -
-
-
- - - result - - - {?} - - - - - cfg.testSpec().matches(fakeTestCase("test1")) == false - - - false == false - - - - - cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) - - - true - - - -
- -
-
-
- - - cli.parse({"test", "-r", "console"}) - - - {?} - - - - - config.reporterNames[0] == "console" - - - "console" == "console" - - - -
- -
-
-
- - - cli.parse({"test", "-r", "xml"}) - - - {?} - - - - - config.reporterNames[0] == "xml" - - - "xml" == "xml" - - - -
- -
-
-
- - - cli.parse({"test", "-r", "xml", "-r", "junit"}) - - - {?} - - - - - config.reporterNames.size() == 2 - - - 2 == 2 - - - - - config.reporterNames[0] == "xml" - - - "xml" == "xml" - - - - - config.reporterNames[1] == "junit" - - - "junit" == "junit" - - - -
- -
-
-
- - - cli.parse({"test", "--reporter", "junit"}) - - - {?} - - - - - config.reporterNames[0] == "junit" - - - "junit" == "junit" - - - -
- -
-
-
- - - cli.parse({"test", "-b"}) - - - {?} - - - - - config.shouldDebugBreak == true - - - true == true - - - -
- -
-
-
- - - cli.parse({"test", "--break"}) - - - {?} - - - - - config.shouldDebugBreak - - - true - - - -
- -
-
-
- - - cli.parse({"test", "-a"}) - - - {?} - - - - - config.abortAfter == 1 - - - 1 == 1 - - - -
- -
-
-
- - - cli.parse({"test", "-x", "2"}) - - - {?} - - - - - config.abortAfter == 2 - - - 2 == 2 - - - -
- -
-
-
- - - !result - - - true - - - - - result.errorMessage(), Contains("convert") && Contains("oops") - - - "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" ) - - - -
- -
-
-
- - - cli.parse({"test", "-e"}) - - - {?} - - - - - config.noThrow - - - true - - - -
- -
-
-
- - - cli.parse({"test", "--nothrow"}) - - - {?} - - - - - config.noThrow - - - true - - - -
- -
-
-
- - - cli.parse({"test", "-o", "filename.ext"}) - - - {?} - - - - - config.outputFilename == "filename.ext" - - - "filename.ext" == "filename.ext" - - - -
- -
-
-
- - - cli.parse({"test", "--out", "filename.ext"}) - - - {?} - - - - - config.outputFilename == "filename.ext" - - - "filename.ext" == "filename.ext" - - - -
- -
-
-
- - - cli.parse({"test", "-abe"}) - - - {?} - - - - - config.abortAfter == 1 - - - 1 == 1 - - - - - config.shouldDebugBreak - - - true - - - - - config.noThrow == true - - - true == true - - - -
- -
-
-
- - - cli.parse({"test"}) - - - {?} - - - - - config.useColour == UseColour::Auto - - - 0 == 0 - - - -
- -
-
-
- - - cli.parse({"test", "--use-colour", "auto"}) - - - {?} - - - - - config.useColour == UseColour::Auto - - - 0 == 0 - - - -
- -
-
-
- - - cli.parse({"test", "--use-colour", "yes"}) - - - {?} - - - - - config.useColour == UseColour::Yes - - - 1 == 1 - - - -
- -
-
-
- - - cli.parse({"test", "--use-colour", "no"}) - - - {?} - - - - - config.useColour == UseColour::No - - - 2 == 2 - - - -
- -
-
-
- - - !result - - - true - - - - - result.errorMessage(), Contains( "colour mode must be one of" ) - - - "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" - - - -
- -
- -
- - - - truthy(false) - - - Hey, its truthy! - - - - - - - current counter 0 - - - i := 0 - - - - i < 10 - - - 0 < 10 - - - - current counter 1 - - - i := 1 - - - - i < 10 - - - 1 < 10 - - - - current counter 2 - - - i := 2 - - - - i < 10 - - - 2 < 10 - - - - current counter 3 - - - i := 3 - - - - i < 10 - - - 3 < 10 - - - - current counter 4 - - - i := 4 - - - - i < 10 - - - 4 < 10 - - - - current counter 5 - - - i := 5 - - - - i < 10 - - - 5 < 10 - - - - current counter 6 - - - i := 6 - - - - i < 10 - - - 6 < 10 - - - - current counter 7 - - - i := 7 - - - - i < 10 - - - 7 < 10 - - - - current counter 8 - - - i := 8 - - - - i < 10 - - - 8 < 10 - - - - current counter 9 - - - i := 9 - - - - i < 10 - - - 9 < 10 - - - - current counter 10 - - - i := 10 - - - - i < 10 - - - 10 < 10 - - - - - - - - - - - -
- - - before == 0 - - - 0 == 0 - - -
-
- - - after > before - - - 1 > 0 - - - -
- -
- -
- -
- -
-
-
- - - itDoesThis() - - - true - - -
- - - itDoesThat() - - - true - - - -
- -
- -
- -
- -
- -
-
-
- -
- -
- -
- -
- -
- - - v.size() == 0 - - - 0 == 0 - - -
-
- - - v.size() == 10 - - - 10 == 10 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - -
-
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - - -
- -
- -
- -
- -
-
- - - v.size() == 0 - - - 0 == 0 - - -
-
- - - v.capacity() >= 10 - - - 10 >= 10 - - - - - v.size() == 0 - - - 0 == 0 - - - -
- -
- -
- -
- - - -A string sent directly to stdout - - -A string sent directly to stderr - - - - - - - d == Approx( 1.23 ) - - - 1.23 == Approx( 1.23 ) - - - - - d != Approx( 1.22 ) - - - 1.23 != Approx( 1.22 ) - - - - - d != Approx( 1.24 ) - - - 1.23 != Approx( 1.24 ) - - - - - Approx( d ) == 1.23 - - - Approx( 1.23 ) == 1.23 - - - - - Approx( d ) != 1.22 - - - Approx( 1.23 ) != 1.22 - - - - - Approx( d ) != 1.24 - - - Approx( 1.23 ) != 1.24 - - - - - -
- -
-
- -
- - -Message from section one -Message from section two - - -
- - - - testStringForMatching(), StartsWith( "string" ) - - - "this string contains 'abc' as a substring" starts with: "string" - - - - - -
- - - empty.empty() - - - true - - - - - empty.size() == 0 - - - 0 == 0 - - - - - std::strcmp( empty.c_str(), "" ) == 0 - - - 0 == 0 - - - -
-
- - - s.empty() == false - - - false == false - - - - - s.size() == 5 - - - 5 == 5 - - - -
- -
- - - - testStringForMatching(), Contains( "string" ) - - - "this string contains 'abc' as a substring" contains: "string" - - - - - testStringForMatching(), Contains( "abc" ) - - - "this string contains 'abc' as a substring" contains: "abc" - - - - - testStringForMatching(), StartsWith( "this" ) - - - "this string contains 'abc' as a substring" starts with: "this" - - - - - testStringForMatching(), EndsWith( "substring" ) - - - "this string contains 'abc' as a substring" ends with: "substring" - - - - - -
- - - sb.capacity() == 0 - - - 0 == 0 - - - - - sb.size() == 0 - - - 0 == 0 - - - - - sb.capacity() == 32 - - - 32 == 32 - - - - - sb.size() == 0 - - - 0 == 0 - - - - - sb.capacity() == 32 - - - 32 == 32 - - - - - sb.size() == 5 - - - 5 == 5 - - - - - s == "hello" - - - {?} == "hello" - - - - - s.size() == 5 - - - 5 == 5 - - - -
-
- - - s == "hello world" - - - {?} == "hello world" - - - -
-
- - - s == "hello world" - - - {?} == "hello world" - - - -
-
- - - sb16.capacity() == 16 - - - 16 == 16 - - - - - sb16.capacity() == 16 - - - 16 == 16 - - - - - s == "hello world" - - - {?} == "hello world" - - - -
-
-
- - - s2 == s - - - {?} == {?} - - - - - s2.c_str() != s.c_str() - - - "hello" != "hello" - - - -
- -
-
-
- - - s2 == "hello" - - - {?} == "hello" - - - - - s2.c_str() == originalPointer - - - "hello" == "hello" - - - -
- -
-
-
- - - s2 == "hello" - - - {?} == "hello" - - - - - s2.c_str() != originalPointer - - - "hello" != "hello" - - - -
- -
- -
- -
- - - empty.empty() - - - true - - - - - empty.size() == 0 - - - 0 == 0 - - - - - std::strcmp( empty.c_str(), "" ) == 0 - - - 0 == 0 - - - -
-
- - - s.empty() == false - - - false == false - - - - - s.size() == 5 - - - 5 == 5 - - - - - isSubstring( s ) == false - - - false == false - - - - - std::strcmp( rawChars, "hello" ) == 0 - - - 0 == 0 - - -
- - - isOwned( s ) == false - - - false == false - - - - - s.c_str() == rawChars - - - "hello" == "hello" - - - - - isOwned( s ) == false - - - false == false - - - -
- -
-
- - - original == "original" - - - {?} == "original" - - - - - isSubstring( original ) - - - true - - - - - isOwned( original ) == false - - - false == false - - - - - isSubstring( original ) == false - - - false == false - - - - - isOwned( original ) - - - true - - - -
-
-
- - - ss.empty() == false - - - false == false - - - - - ss.size() == 5 - - - 5 == 5 - - - - - std::strcmp( ss.c_str(), "hello" ) == 0 - - - 0 == 0 - - - - - ss == "hello" - - - {?} == "hello" - - - -
- -
-
-
- - - isSubstring( ss ) - - - true - - - - - isOwned( ss ) == false - - - false == false - - - - - rawChars == data( s ) - - - "hello world!" == "hello world!" - - - - - ss.c_str() != rawChars - - - "hello" != "hello world!" - - - - - isSubstring( ss ) == false - - - false == false - - - - - isOwned( ss ) - - - true - - - - - data( ss ) != data( s ) - - - "hello" != "hello world!" - - - -
- -
-
-
- - - ss.size() == 6 - - - 6 == 6 - - - - - std::strcmp( ss.c_str(), "world!" ) == 0 - - - 0 == 0 - - - -
- -
-
-
- - - s.c_str() == s2.c_str() - - - "hello world!" == "hello world!" - - - -
- -
-
-
- - - s.c_str() != ss.c_str() - - - "hello world!" != "hello" - - - -
- -
-
- - - StringRef("hello") == StringRef("hello") - - - {?} == {?} - - - - - StringRef("hello") != StringRef("cello") - - - {?} != {?} - - - -
-
-
- - - copied == "hot potato" - - - {?} == "hot potato" - - - - - str == "hot potato" - - - {?} == "hot potato" - - - - - isOwned( copied ) == false - - - false == false - - - - - data( copied ) == originalPointer - - - "hot potato" == "hot potato" - - - -
- -
-
-
- - - copied == "hot potato" - - - {?} == "hot potato" - - - - - isOwned( copied ) - - - true - - - - - str.empty() - - - true - - - - - data( copied ) == originalPointer - - - "hot potato" == "hot potato" - - - -
- -
- -
- - - -hello -hello - - - - - - - s1 == s2 - - - "if ($b == 10) { - $a = 20; -}" -== -"if ($b == 10) { - $a = 20; -} -" - - - - - -
- - - what, Contains( "[@zzz]" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "[@zzz]" - - - - - what, Contains( "file" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "file" - - - - - what, Contains( "2" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "2" - - - - - what, Contains( "10" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "10" - - - -
-
- - - registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - - - registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - - - registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - - - registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) - - - -
- -
- - - - - - - 0x == bit30and31 - - - 3221225472 (0x) == 3221225472 - - - - - - - - Text( "hi there" ).toString() == "hi there" - - - "hi there" == "hi there" - - - - - Text( "hi there", narrow ).toString() == "hi\nthere" - - - "hi -there" -== -"hi -there" - - - - - - - - 1 == 2 - - - 1 == 2 - - - - - - - - - - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s1.isSuccessfullyCompleted() - - - true - - - - - testCase.isComplete() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isSuccessfullyCompleted() - - - true - - - -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s1.isComplete() - - - true - - - - - s1.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isSuccessfullyCompleted() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isComplete() - - - true - - - - - testCase.isSuccessfullyCompleted() - - - true - - - -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s1.isComplete() - - - true - - - - - s1.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isSuccessfullyCompleted() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - s2.isOpen() - - - true - - - - - ctx.completedCycle() - - - true - - - - - testCase.isComplete() - - - true - - - - - testCase.isSuccessfullyCompleted() - - - true - - - -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s2.isOpen() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - s2b.isOpen() - - - true - - - - - ctx.completedCycle() == false - - - false == false - - -
- - - ctx.completedCycle() - - - true - - - - - s2b.isSuccessfullyCompleted() - - - true - - - - - testCase2.isComplete() == false - - - false == false - - - - - testCase2.isSuccessfullyCompleted() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s2.isOpen() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - s2b.isOpen() - - - true - - - - - ctx.completedCycle() == false - - - false == false - - -
- - - ctx.completedCycle() - - - true - - - - - s2b.isComplete() - - - true - - - - - s2b.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase2.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase3.isOpen() - - - true - - - - - s1c.isOpen() == false - - - false == false - - - - - s2c.isOpen() == false - - - false == false - - - - - testCase3.isSuccessfullyCompleted() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s2.isOpen() - - - true - - - - - s2.isComplete() - - - true - - - - - s1.isComplete() == false - - - false == false - - - - - s1.isComplete() - - - true - - - - - testCase.isComplete() == false - - - false == false - - - - - testCase.isComplete() - - - true - - - -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - g1.isOpen() - - - true - - - - - g1.index() == 0 - - - 0 == 0 - - - - - g1.isComplete() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - -
- - - s1.isComplete() == false - - - false == false - - - - - testCase.isSuccessfullyCompleted() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() - - - true - - - - - g1b.isOpen() - - - true - - - - - g1b.index() == 1 - - - 1 == 1 - - - - - s1.isComplete() == false - - - false == false - - - - - s1b.isComplete() - - - true - - - - - g1b.isComplete() - - - true - - - - - testCase2.isComplete() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - g1.isOpen() - - - true - - - - - g1.index() == 0 - - - 0 == 0 - - - - - g1.isComplete() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - -
- - - s2.isOpen() - - - true - - - - - s2.isComplete() - - - true - - - - - s1.isComplete() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() - - - true - - - - - g1b.isOpen() - - - true - - - - - g1b.index() == 1 - - - 1 == 1 - - - - - s2b.isOpen() - - - true - - - - - s2b.isComplete() - - - true - - - - - g1b.isComplete() - - - true - - - - - s1b.isComplete() - - - true - - - - - testCase2.isComplete() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - g1.isOpen() - - - true - - - - - g1.index() == 0 - - - 0 == 0 - - - - - g1.isComplete() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - -
- - - s2.isOpen() - - - true - - - - - s2.isComplete() - - - true - - - - - s2.isSuccessfullyCompleted() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() - - - true - - - - - g1b.isOpen() - - - true - - - - - g1b.index() == 0 - - - 0 == 0 - - - - - s2b.isOpen() == false - - - false == false - - - - - g1b.isComplete() == false - - - false == false - - - - - s1b.isComplete() == false - - - false == false - - - - - testCase2.isComplete() == false - - - false == false - - - - - testCase3.isOpen() - - - true - - - - - s1c.isOpen() - - - true - - - - - g1c.isOpen() - - - true - - - - - g1c.index() == 1 - - - 1 == 1 - - - - - s2c.isOpen() - - - true - - - - - s2c.isComplete() - - - true - - - - - g1c.isComplete() - - - true - - - - - s1c.isComplete() - - - true - - - - - testCase3.isComplete() - - - true - - - -
- -
- -
- -
- - - 3.14 - - - - - - - d == approx( 1.23 ) - - - 1.23 == Approx( 1.23 ) - - - - - d == approx( 1.22 ) - - - 1.23 == Approx( 1.22 ) - - - - - d == approx( 1.24 ) - - - 1.23 == Approx( 1.24 ) - - - - - d != approx( 1.25 ) - - - 1.23 != Approx( 1.25 ) - - - - - approx( d ) == 1.23 - - - Approx( 1.23 ) == 1.23 - - - - - approx( d ) == 1.22 - - - Approx( 1.23 ) == 1.22 - - - - - approx( d ) == 1.24 - - - Approx( 1.23 ) == 1.24 - - - - - approx( d ) != 1.25 - - - Approx( 1.23 ) != 1.25 - - - - - -
- -
- -
- -
- - - v, VectorContains( 1 ) - - - { 1, 2, 3 } Contains: 1 - - - - - v, VectorContains( 2 ) - - - { 1, 2, 3 } Contains: 2 - - - -
-
- - - v, Contains( v2 ) - - - { 1, 2, 3 } Contains: { 1, 2 } - - - - - v, Contains( v2 ) - - - { 1, 2, 3 } Contains: { 1, 2, 3 } - - - - - v, Contains( empty) - - - { 1, 2, 3 } Contains: { } - - - - - empty, Contains( empty) - - - { } Contains: { } - - - -
-
- - - v, Equals( v ) - - - { 1, 2, 3 } Equals: { 1, 2, 3 } - - - - - empty, Equals( empty ) - - - { } Equals: { } - - - - - v, Equals( v2 ) - - - { 1, 2, 3 } Equals: { 1, 2, 3 } - - - -
- -
- -
- - - v, VectorContains( -1 ) - - - { 1, 2, 3 } Contains: -1 - - - - - empty, VectorContains( 1 ) - - - { } Contains: 1 - - - -
-
- - - empty, Contains( v) - - - { } Contains: { 1, 2, 3 } - - - - - v, Contains( v2 ) - - - { 1, 2, 3 } Contains: { 1, 2, 4 } - - - -
-
- - - v, Equals( v2 ) - - - { 1, 2, 3 } Equals: { 1, 2 } - - - - - v2, Equals( v ) - - - { 1, 2 } Equals: { 1, 2, 3 } - - - - - empty, Equals( v ) - - - { } Equals: { 1, 2, 3 } - - - - - v, Equals( empty ) - - - { 1, 2, 3 } Equals: { } - - - -
- -
- - - - thisThrows(), std::domain_error - - - thisThrows(), std::domain_error - - - - - thisDoesntThrow() - - - thisDoesntThrow() - - - - - thisThrows() - - - thisThrows() - - - - - - - unexpected exception - - - - - - - thisThrows() == 0 - - - thisThrows() == 0 - - - expected exception - - - - - - - - thisThrows() == 0 - - - thisThrows() == 0 - - - expected exception - - - - - - - - thisThrows() == 0 - - - thisThrows() == 0 - - - expected exception - - - - - -
- - unexpected exception - - -
- -
- - - - - - Uncomment the code in this test to check that it gives a sensible compiler error - - - - - - Uncomment the code in this test to check that it gives a sensible compiler error - - - - - - - - - - - - - - - - -
- - - encode( "normal string" ) == "normal string" - - - "normal string" == "normal string" - - - -
-
- - - encode( "" ) == "" - - - "" == "" - - - -
-
- - - encode( "smith & jones" ) == "smith &amp; jones" - - - "smith &amp; jones" == "smith &amp; jones" - - - -
-
- - - encode( "smith < jones" ) == "smith &lt; jones" - - - "smith &lt; jones" == "smith &lt; jones" - - - -
-
- - - encode( "smith > jones" ) == "smith > jones" - - - "smith > jones" == "smith > jones" - - - - - encode( "smith ]]> jones" ) == "smith ]]&gt; jones" - - - "smith ]]&gt; jones" -== -"smith ]]&gt; jones" - - - -
-
- - - encode( stringWithQuotes ) == stringWithQuotes - - - "don't "quote" me on that" -== -"don't "quote" me on that" - - - - - encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" - - - "don't &quot;quote&quot; me on that" -== -"don't &quot;quote&quot; me on that" - - - -
-
- - - encode( "[\x01]" ) == "[\\x01]" - - - "[\x01]" == "[\x01]" - - - -
-
- - - encode( "[\x7F]" ) == "[\\x7F]" - - - "[\x7F]" == "[\x7F]" - - - -
- -
- - - - - - - x == 0 - - - 0 == 0 - - - - - - - - obj.prop != 0 - - - 0x != 0 - - - - - - - - flag - - - true - - - - - testCheckedElse( true ) - - - true - - - - - - - - flag - - - false - - - - - testCheckedElse( false ) - - - false - - - - - - - - flag - - - true - - - - - testCheckedIf( true ) - - - true - - - - - - - - flag - - - false - - - - - testCheckedIf( false ) - - - false - - - - - - - - unsigned_char_var == 1 - - - 1 == 1 - - - - - unsigned_short_var == 1 - - - 1 == 1 - - - - - unsigned_int_var == 1 - - - 1 == 1 - - - - - unsigned_long_var == 1 - - - 1 == 1 - - - - - - - - long_var == unsigned_char_var - - - 1 == 1 - - - - - long_var == unsigned_short_var - - - 1 == 1 - - - - - long_var == unsigned_int_var - - - 1 == 1 - - - - - long_var == unsigned_long_var - - - 1 == 1 - - - - - -
-
- -
- -
-
-
- -
- -
-
- -
- -
- - - - -spanner - - - - Previous info should not be seen - - - - - - - - - - l == std::numeric_limits<long long>::max() - - - 9223372036854775807 (0x) -== -9223372036854775807 (0x) - - - - - -
- - - b > a - - - 0 > 1 - - - -
- -
- - - Testing if fib[0] (1) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[1] (1) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[2] (2) is even - - - - ( fib[i] % 2 ) == 0 - - - 0 == 0 - - - - Testing if fib[3] (3) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[4] (5) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[5] (8) is even - - - - ( fib[i] % 2 ) == 0 - - - 0 == 0 - - - - Testing if fib[6] (13) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[7] (21) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - - -
-
- - - a == b - - - 1 == 2 - - - -
- -
-
-
- - - a != b - - - 1 != 2 - - - -
- -
-
-
- - - a < b - - - 1 < 2 - - - -
- -
- -
- -
- - - a != b - - - 1 != 2 - - - - - b != a - - - 2 != 1 - - -
- - - a != b - - - 1 != 2 - - - -
- -
- -
- - - - s == "7" - - - "7" == "7" - - - - - - - - - - - makeString( false ) != static_cast<char*>(0) - - - "valid string" != {null string} - - - - - makeString( true ) == static_cast<char*>(0) - - - {null string} == {null string} - - - - - - - - ptr.get() == 0 - - - 0 == 0 - - - - - - - - ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" - - - "{ { 42, "Arthur" }, { "Ford", 24 } }" -== -"{ { 42, "Arthur" }, { "Ford", 24 } }" - - - - - - - - p == 0 - - - 0 == 0 - - - - - -
- - - a != b - - - 1 != 2 - - - - - b != a - - - 2 != 1 - - - -
-
- - - a != b - - - 1 != 2 - - - -
- -
- -
- - - replaceInPlace( letters, "b", "z" ) - - - true - - - - - letters == "azcdefcg" - - - "azcdefcg" == "azcdefcg" - - - -
-
- - - replaceInPlace( letters, "c", "z" ) - - - true - - - - - letters == "abzdefzg" - - - "abzdefzg" == "abzdefzg" - - - -
-
- - - replaceInPlace( letters, "a", "z" ) - - - true - - - - - letters == "zbcdefcg" - - - "zbcdefcg" == "zbcdefcg" - - - -
-
- - - replaceInPlace( letters, "g", "z" ) - - - true - - - - - letters == "abcdefcz" - - - "abcdefcz" == "abcdefcz" - - - -
-
- - - replaceInPlace( letters, letters, "replaced" ) - - - true - - - - - letters == "replaced" - - - "replaced" == "replaced" - - - -
-
- - - !replaceInPlace( letters, "x", "z" ) - - - !false - - - - - letters == letters - - - "abcdefcg" == "abcdefcg" - - - -
-
- - - replaceInPlace( s, "'", "|'" ) - - - true - - - - - s == "didn|'t" - - - "didn|'t" == "didn|'t" - - - -
- -
- - - - - - 3 - - - - false - - - false - - - - - - - hi - - - i := 7 - - - - false - - - false - - - - - - - - ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" - - - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" - - - - - - - - ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" - - - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" - - - - - - - - ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" - - - "{ { "green", 55 } }" -== -"{ { "green", 55 } }" - - - - - - - - std::string( "first" ) == "second" - - - "first" == "second" - - - - - - - - ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" - - - "StringMaker<has_maker>" -== -"StringMaker<has_maker>" - - - - - - - - ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" - - - "StringMaker<has_maker_and_operator>" -== -"StringMaker<has_maker_and_operator>" - - - - - - - - ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" - - - "operator<<( has_operator )" -== -"operator<<( has_operator )" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" - - - "{ StringMaker<has_maker> }" -== -"{ StringMaker<has_maker> }" - - - - - - - - ::Catch::Detail::stringify(e0) == "E2/V0" - - - "E2/V0" == "E2/V0" - - - - - ::Catch::Detail::stringify(e1) == "E2/V1" - - - "E2/V1" == "E2/V1" - - - - - ::Catch::Detail::stringify(e3) == "Unknown enum value 10" - - - "Unknown enum value 10" -== -"Unknown enum value 10" - - - - - - - - ::Catch::Detail::stringify(e0) == "0" - - - "{?}" == "0" - - - - - ::Catch::Detail::stringify(e1) == "1" - - - "{?}" == "1" - - - - - - - - ::Catch::Detail::stringify(e0) == "E2{0}" - - - "E2{0}" == "E2{0}" - - - - - ::Catch::Detail::stringify(e1) == "E2{1}" - - - "E2{1}" == "E2{1}" - - - - - - - - ::Catch::Detail::stringify(e0) == "0" - - - "0" == "0" - - - - - ::Catch::Detail::stringify(e1) == "1" - - - "1" == "1" - - - - - - - - "{ }" == ::Catch::Detail::stringify(type{}) - - - "{ }" == "{ }" - - - - - "{ }" == ::Catch::Detail::stringify(value) - - - "{ }" == "{ }" - - - - - - - - "1.2f" == ::Catch::Detail::stringify(float(1.2)) - - - "1.2f" == "1.2f" - - - - - "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) - - - "{ 1.2f, 0 }" == "{ 1.2f, 0 }" - - - - - - - - "{ 0 }" == ::Catch::Detail::stringify(type{0}) - - - "{ 0 }" == "{ 0 }" - - - - - - - - "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) - - - "{ 0, 42, "Catch me" }" -== -"{ 0, 42, "Catch me" }" - - - - - - - - "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) - - - "{ "hello", "world" }" -== -"{ "hello", "world" }" - - - - - - - - "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) - - - "{ { 42 }, { }, 1.2f }" -== -"{ { 42 }, { }, 1.2f }" - - - - - - - - ::Catch::Detail::stringify(v) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" - - - "{ { "hello" }, { "world" } }" -== -"{ { "hello" }, { "world" } }" - - - - - - - - ::Catch::Detail::stringify(vv) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42 }" - - - "{ 42 }" == "{ 42 }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42, 250 }" - - - "{ 42, 250 }" == "{ 42, 250 }" - - - - - - - - ::Catch::Detail::stringify(vv) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42 }" - - - "{ 42 }" == "{ 42 }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42, 250 }" - - - "{ 42, 250 }" == "{ 42, 250 }" - - - - - - - - ::Catch::Detail::stringify(vv) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(vv) == "{ \"hello\" }" - - - "{ "hello" }" == "{ "hello" }" - - - - - ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" - - - "{ "hello", "world" }" -== -"{ "hello", "world" }" - - - - - - - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 10 - - - 10 == 10 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 0 - - - 0 == 0 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.capacity() == 0 - - - 0 == 0 - - - -
- -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - - -
- -
- -
- -
-
- -
- -
- -
- -
From 58d8bc6985a70e537cfcc4959dfc405ba9cb2a00 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:09:50 +0100 Subject: [PATCH 152/398] Removed Text tests (TextFlow has it's own test suite) --- .../Baselines/console.std.approved.txt | 6 +- .../Baselines/console.sw.approved.txt | 580 +--------------- .../SelfTest/Baselines/junit.sw.approved.txt | 25 +- .../SelfTest/Baselines/xml.sw.approved.txt | 642 +----------------- projects/SelfTest/TestMain.cpp | 214 +----- 5 files changed, 28 insertions(+), 1439 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index a19e84c5..9e41f7f5 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -684,8 +684,6 @@ MatchersTests.cpp:: FAILED: with expansion: "this string contains 'abc' as a substring" starts with: "string" -hello -hello ------------------------------------------------------------------------------- Tabs and newlines show in output ------------------------------------------------------------------------------- @@ -1018,6 +1016,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 185 | 134 passed | 47 failed | 4 failed as expected -assertions: 938 | 821 passed | 96 failed | 21 failed as expected +test cases: 182 | 131 passed | 47 failed | 4 failed as expected +assertions: 896 | 779 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 4373d02f..971c0e32 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1781,544 +1781,6 @@ PASSED: with expansion: 1.23 <= Approx( 1.22 ) -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - No wrapping -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) -with expansion: - "one two three four" - == - "one two three four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) -with expansion: - "one two three four" - == - "one two three four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Wrapped once -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ) -with expansion: - "one two three - four" - == - "one two three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ) -with expansion: - "one two - three four" - == - "one two - three four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Wrapped twice -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Wrapped three times -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) -with expansion: - "one - two - three - four" - == - "one - two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ) -with expansion: - "one - two - three - four" - == - "one - two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Short wrap -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ) -with expansion: - "abc- - def" - == - "abc- - def" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ) -with expansion: - "abc- - defg" - == - "abc- - defg" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ) -with expansion: - "abc- - def- - gh" - == - "abc- - def- - gh" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ) -with expansion: - "one - two - thr- - ee - four" - == - "one - two - thr- - ee - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ) -with expansion: - "one - two - th- - ree - fo- - ur" - == - "one - two - th- - ree - fo- - ur" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - As container -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - REQUIRE( text.size() == 4 ) -with expansion: - 4 == 4 - -TestMain.cpp:: -PASSED: - CHECK( text[0] == "one" ) -with expansion: - "one" == "one" - -TestMain.cpp:: -PASSED: - CHECK( text[1] == "two" ) -with expansion: - "two" == "two" - -TestMain.cpp:: -PASSED: - CHECK( text[2] == "three" ) -with expansion: - "three" == "three" - -TestMain.cpp:: -PASSED: - CHECK( text[3] == "four" ) -with expansion: - "four" == "four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - plain string - Indent first line differently -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( text.toString() == " one two\n three\n four" ) -with expansion: - " one two - three - four" - == - " one two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - No wrapping -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) -with expansion: - "one two - three four" - == - "one two - three four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ) -with expansion: - "one two - three four" - == - "one two - three four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ) -with expansion: - "one two - three four" - == - "one two - three four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - Trailing newline -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" ) -with expansion: - "abcdef" == "abcdef" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) -with expansion: - "abcdef" == "abcdef" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ) -with expansion: - "abcdef" == "abcdef" - -TestMain.cpp:: -PASSED: - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" ) -with expansion: - "abcd- - ef" - == - "abcd- - ef" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - Wrapped once -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ) -with expansion: - "one two - three - four" - == - "one two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With newlines - Wrapped twice -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ) -with expansion: - "one - two - three - four" - == - "one - two - three - four" - -------------------------------------------------------------------------------- -Long strings can be wrapped - With wrap-before/ after characters - No wrapping -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ) -with expansion: - "one,two(three) " - == - "one,two(three) " - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString ) -with expansion: - "one,two(three) " - == - "one,two(three) " - -------------------------------------------------------------------------------- -Long strings can be wrapped - With wrap-before/ after characters - Wrap before -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n" ) -with expansion: - "one,two - (three) - " - == - "one,two - (three) - " - -------------------------------------------------------------------------------- -Long strings can be wrapped - With wrap-before/ after characters - Wrap after -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n" ) -with expansion: - "one, - two - (thre- - e) - " - == - "one, - two - (thre- - e) - " - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n" ) -with expansion: - "one, - two - (thr- - ee) - " - == - "one, - two - (thr- - ee) - " - -TestMain.cpp:: -PASSED: - CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n" ) -with expansion: - "one, - two - (th- - ree) - " - == - "one, - two - (th- - ree) - " - ------------------------------------------------------------------------------- ManuallyRegistered ------------------------------------------------------------------------------- @@ -5320,8 +4782,6 @@ PASSED: with expansion: "hot potato" == "hot potato" -hello -hello ------------------------------------------------------------------------------- Tabs and newlines show in output ------------------------------------------------------------------------------- @@ -5425,28 +4885,6 @@ PASSED: with expansion: 3221225472 (0x) == 3221225472 -------------------------------------------------------------------------------- -Text can be formatted using the Text class -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - -TestMain.cpp:: -PASSED: - CHECK( Text( "hi there" ).toString() == "hi there" ) -with expansion: - "hi there" == "hi there" - -TestMain.cpp:: -PASSED: - CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ) -with expansion: - "hi - there" - == - "hi - there" - ------------------------------------------------------------------------------- The NO_FAIL macro reports a failure but does not fail the test ------------------------------------------------------------------------------- @@ -7407,7 +6845,7 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK( replaceInPlace( letters, "b", "z" ) ) + CHECK( Catch::replaceInPlace( letters, "b", "z" ) ) with expansion: true @@ -7426,7 +6864,7 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK( replaceInPlace( letters, "c", "z" ) ) + CHECK( Catch::replaceInPlace( letters, "c", "z" ) ) with expansion: true @@ -7445,7 +6883,7 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK( replaceInPlace( letters, "a", "z" ) ) + CHECK( Catch::replaceInPlace( letters, "a", "z" ) ) with expansion: true @@ -7464,7 +6902,7 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK( replaceInPlace( letters, "g", "z" ) ) + CHECK( Catch::replaceInPlace( letters, "g", "z" ) ) with expansion: true @@ -7483,7 +6921,7 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK( replaceInPlace( letters, letters, "replaced" ) ) + CHECK( Catch::replaceInPlace( letters, letters, "replaced" ) ) with expansion: true @@ -7502,7 +6940,7 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ) + CHECK_FALSE( Catch::replaceInPlace( letters, "x", "z" ) ) with expansion: !false @@ -7521,7 +6959,7 @@ TestMain.cpp: TestMain.cpp:: PASSED: - CHECK( replaceInPlace( s, "'", "|'" ) ) + CHECK( Catch::replaceInPlace( s, "'", "|'" ) ) with expansion: true @@ -8152,6 +7590,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 185 | 133 passed | 48 failed | 4 failed as expected -assertions: 940 | 821 passed | 98 failed | 21 failed as expected +test cases: 182 | 130 passed | 48 failed | 4 failed as expected +assertions: 898 | 779 passed | 98 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index b567d061..58807c18 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -295,20 +295,6 @@ ConditionTests.cpp: - - - - - - - - - - - - - - @@ -533,12 +519,6 @@ MatchersTests.cpp: - - -hello -hello - - .global" name="Tag alias can be registered against tag patterns/Tag aliases must be of the form [@name]" time="{duration}"/> - @@ -810,8 +789,6 @@ EnumToString.cpp: A string sent directly to stdout Message from section one Message from section two -hello -hello A string sent directly to stderr diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 22c8a4ca..e70ad12e 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -2089,599 +2089,6 @@ - -
-
- - - Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - - - "one two three four" -== -"one two three four" - - - - - Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString - - - "one two three four" -== -"one two three four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" - - - "one two three -four" -== -"one two three -four" - - - - - Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" - - - "one two -three four" -== -"one two -three four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" - - - "one -two -three -four" -== -"one -two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" - - - "one -two -three -four" -== -"one -two -three -four" - - - -
- -
-
-
- - - Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" - - - "abc- -def" -== -"abc- -def" - - - - - Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" - - - "abc- -defg" -== -"abc- -defg" - - - - - Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" - - - "abc- -def- -gh" -== -"abc- -def- -gh" - - - - - Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" - - - "one -two -thr- -ee -four" -== -"one -two -thr- -ee -four" - - - - - Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" - - - "one -two -th- -ree -fo- -ur" -== -"one -two -th- -ree -fo- -ur" - - - -
- -
-
-
- - - text.size() == 4 - - - 4 == 4 - - - - - text[0] == "one" - - - "one" == "one" - - - - - text[1] == "two" - - - "two" == "two" - - - - - text[2] == "three" - - - "three" == "three" - - - - - text[3] == "four" - - - "four" == "four" - - - -
- -
-
-
- - - text.toString() == " one two\n three\n four" - - - " one two - three - four" -== -" one two - three - four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - - - "one two -three four" -== -"one two -three four" - - - - - Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString - - - "one two -three four" -== -"one two -three four" - - - - - Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString - - - "one two -three four" -== -"one two -three four" - - - -
- -
-
-
- - - Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" - - - "abcdef" == "abcdef" - - - - - Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" - - - "abcdef" == "abcdef" - - - - - Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" - - - "abcdef" == "abcdef" - - - - - Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" - - - "abcd- -ef" -== -"abcd- -ef" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - - - Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" - - - "one two -three -four" -== -"one two -three -four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" - - - "one -two -three -four" -== -"one -two -three -four" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - - - "one,two(three) <here>" -== -"one,two(three) <here>" - - - - - Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString - - - "one,two(three) <here>" -== -"one,two(three) <here>" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n<here>" - - - "one,two -(three) -<here>" -== -"one,two -(three) -<here>" - - - -
- -
-
-
- - - Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n<here>" - - - "one, -two -(thre- -e) -<here>" -== -"one, -two -(thre- -e) -<here>" - - - - - Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n<her-\ne>" - - - "one, -two -(thr- -ee) -<her- -e>" -== -"one, -two -(thr- -ee) -<her- -e>" - - - - - Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n<he-\nre>" - - - "one, -two -(th- -ree) -<he- -re>" -== -"one, -two -(th- -ree) -<he- -re>" - - - -
- -
- -
@@ -6084,14 +5491,6 @@ Message from section two
- - - -hello -hello - - - @@ -6205,29 +5604,6 @@ hello - - - - Text( "hi there" ).toString() == "hi there" - - - "hi there" == "hi there" - - - - - Text( "hi there", narrow ).toString() == "hi\nthere" - - - "hi -there" -== -"hi -there" - - - - @@ -8316,7 +7692,7 @@ spanner
- replaceInPlace( letters, "b", "z" ) + Catch::replaceInPlace( letters, "b", "z" ) true @@ -8335,7 +7711,7 @@ spanner
- replaceInPlace( letters, "c", "z" ) + Catch::replaceInPlace( letters, "c", "z" ) true @@ -8354,7 +7730,7 @@ spanner
- replaceInPlace( letters, "a", "z" ) + Catch::replaceInPlace( letters, "a", "z" ) true @@ -8373,7 +7749,7 @@ spanner
- replaceInPlace( letters, "g", "z" ) + Catch::replaceInPlace( letters, "g", "z" ) true @@ -8392,7 +7768,7 @@ spanner
- replaceInPlace( letters, letters, "replaced" ) + Catch::replaceInPlace( letters, letters, "replaced" ) true @@ -8411,7 +7787,7 @@ spanner
- !replaceInPlace( letters, "x", "z" ) + !Catch::replaceInPlace( letters, "x", "z" ) !false @@ -8430,7 +7806,7 @@ spanner
- replaceInPlace( s, "'", "|'" ) + Catch::replaceInPlace( s, "'", "|'" ) true @@ -9065,7 +8441,7 @@ spanner
- + - + diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 59fe2db5..84cf35ed 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -232,239 +232,39 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" } -TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { - - using namespace Catch; - SECTION( "plain string" ) { - // guide: 123456789012345678 - std::string testString = "one two three four"; - - SECTION( "No wrapping" ) { - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); - CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); - } - SECTION( "Wrapped once" ) { - CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" ); - } - SECTION( "Wrapped twice" ) { - CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); - } - SECTION( "Wrapped three times" ) { - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" ); - } - SECTION( "Short wrap" ) { - CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ); - CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ); - CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ); - - CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" ); - } - SECTION( "As container" ) { - Text text( testString, TextAttributes().setWidth( 6 ) ); - REQUIRE( text.size() == 4 ); - CHECK( text[0] == "one" ); - CHECK( text[1] == "two" ); - CHECK( text[2] == "three" ); - CHECK( text[3] == "four" ); - } - SECTION( "Indent first line differently" ) { - Text text( testString, TextAttributes() - .setWidth( 10 ) - .setIndent( 4 ) - .setInitialIndent( 1 ) ); - CHECK( text.toString() == " one two\n three\n four" ); - } - - } - - SECTION( "With newlines" ) { - - // guide: 1234567890123456789 - std::string testString = "one two\nthree four"; - - SECTION( "No wrapping" ) { - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); - CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); - CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ); - } - SECTION( "Trailing newline" ) { - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef" ); - CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ); - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ); - CHECK( Text( "abcdef\n", TextAttributes().setWidth( 5 ) ).toString() == "abcd-\nef" ); - } - SECTION( "Wrapped once" ) { - CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); - CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" ); - } - SECTION( "Wrapped twice" ) { - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); - } - } - - SECTION( "With wrap-before/ after characters" ) { - std::string testString = "one,two(three) "; - - SECTION( "No wrapping" ) { - CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); - CHECK( Text( testString, TextAttributes().setWidth( 24 ) ).toString() == testString ); - } - SECTION( "Wrap before" ) { - CHECK( Text( testString, TextAttributes().setWidth( 11 ) ).toString() == "one,two\n(three)\n" ); - } - SECTION( "Wrap after" ) { - CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one,\ntwo\n(thre-\ne)\n" ); - CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one,\ntwo\n(thr-\nee)\n" ); - CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one,\ntwo\n(th-\nree)\n" ); - } - } - -} - -using namespace Catch; - -class ColourString { -public: - - struct ColourIndex { - ColourIndex( Colour::Code _colour, std::size_t _fromIndex, std::size_t _toIndex ) - : colour( _colour ), - fromIndex( _fromIndex ), - toIndex( _toIndex ) - {} - - Colour::Code colour; - std::size_t fromIndex; - std::size_t toIndex; - }; - - ColourString( std::string const& _string ) - : string( _string ) - {} - ColourString( std::string const& _string, std::vector const& _colours ) - : string( _string ), colours( _colours ) - {} - - ColourString& addColour( Colour::Code colour, int _index ) { - colours.push_back( ColourIndex( colour, - resolveRelativeIndex( _index ), - resolveRelativeIndex( _index )+1 ) ); - return *this; - } - ColourString& addColour( Colour::Code colour, int _fromIndex, int _toIndex ) { - colours.push_back( ColourIndex( colour, - resolveRelativeIndex(_fromIndex), - resolveLastRelativeIndex( _toIndex ) ) ); - return *this; - } - - void writeToStream( std::ostream& _stream ) const { - std::size_t last = 0; - for( std::size_t i = 0; i < colours.size(); ++i ) { - ColourIndex const& index = colours[i]; - if( index.fromIndex > last ) - _stream << string.substr( last, index.fromIndex-last ); - { - Colour colourGuard( index.colour ); - _stream << string.substr( index.fromIndex, index.toIndex-index.fromIndex ); - } - last = index.toIndex; - } - if( last < string.size() ) - _stream << string.substr( last ); - } - friend std::ostream& operator << ( std::ostream& _stream, ColourString const& _colourString ) { - _colourString.writeToStream( _stream ); - return _stream; - } - -private: - - std::size_t resolveLastRelativeIndex( int _index ) { - std::size_t index = resolveRelativeIndex( _index ); - return index == 0 ? string.size() : index; - } - std::size_t resolveRelativeIndex( int _index ) { - return static_cast( _index >= 0 - ? _index - : static_cast( string.size() )+_index ); - } - std::string string; - std::vector colours; -}; - TEST_CASE( "replaceInPlace" ) { std::string letters = "abcdefcg"; SECTION( "replace single char" ) { - CHECK( replaceInPlace( letters, "b", "z" ) ); + CHECK( Catch::replaceInPlace( letters, "b", "z" ) ); CHECK( letters == "azcdefcg" ); } SECTION( "replace two chars" ) { - CHECK( replaceInPlace( letters, "c", "z" ) ); + CHECK( Catch::replaceInPlace( letters, "c", "z" ) ); CHECK( letters == "abzdefzg" ); } SECTION( "replace first char" ) { - CHECK( replaceInPlace( letters, "a", "z" ) ); + CHECK( Catch::replaceInPlace( letters, "a", "z" ) ); CHECK( letters == "zbcdefcg" ); } SECTION( "replace last char" ) { - CHECK( replaceInPlace( letters, "g", "z" ) ); + CHECK( Catch::replaceInPlace( letters, "g", "z" ) ); CHECK( letters == "abcdefcz" ); } SECTION( "replace all chars" ) { - CHECK( replaceInPlace( letters, letters, "replaced" ) ); + CHECK( Catch::replaceInPlace( letters, letters, "replaced" ) ); CHECK( letters == "replaced" ); } SECTION( "replace no chars" ) { - CHECK_FALSE( replaceInPlace( letters, "x", "z" ) ); + CHECK_FALSE( Catch::replaceInPlace( letters, "x", "z" ) ); CHECK( letters == letters ); } SECTION( "escape '" ) { std::string s = "didn't"; - CHECK( replaceInPlace( s, "'", "|'" ) ); + CHECK( Catch::replaceInPlace( s, "'", "|'" ) ); CHECK( s == "didn|'t" ); } } -// !TBD: This will be folded into Text class -TEST_CASE( "Strings can be rendered with colour", "[.colour]" ) { - - { - ColourString cs( "hello" ); - cs .addColour( Colour::Red, 0 ) - .addColour( Colour::Green, -1 ); - - Catch::cout() << cs << std::endl; - } - - { - ColourString cs( "hello" ); - cs .addColour( Colour::Blue, 1, -2 ); - - Catch::cout() << cs << std::endl; - } - -} - -TEST_CASE( "Text can be formatted using the Text class" ) { - - CHECK( Text( "hi there" ).toString() == "hi there" ); - - TextAttributes narrow; - narrow.setWidth( 6 ); - - CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ); -} - inline void manuallyRegisteredTestFunction() { SUCCEED( "was called" ); From 6ec7709e07f89baeb01d3872236b80c3aa17bb8a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:13:08 +0100 Subject: [PATCH 153/398] removed final use of tbc_text_format (console reporter) --- include/reporters/catch_reporter_console.cpp | 12 ++++++------ projects/SelfTest/TestMain.cpp | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 3643c1df..b70df425 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -11,13 +11,15 @@ #include "../internal/catch_reporter_registrars.hpp" #include "../internal/catch_console_colour.hpp" #include "../internal/catch_version.h" -#include "../internal/catch_text.h" +#include "../internal/catch_clara.h" // For TextFlow #include #include namespace Catch { + using namespace clara::TextFlow; + struct ConsoleReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; @@ -209,7 +211,7 @@ namespace Catch { if( result.hasExpandedExpression() ) { stream << "with expansion:\n"; Colour colourGuard( Colour::ReconstructedExpression ); - stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; + stream << Column( result.getExpandedExpression() ).indent(2) << '\n'; } } void printMessage() const { @@ -218,7 +220,7 @@ namespace Catch { for( auto const& msg : messages ) { // If this assertion is a warning ignore any INFO messages if( printInfoMessages || msg.type != ResultWas::Info ) - stream << Text( msg.message, TextAttributes().setIndent(2) ) << '\n'; + stream << Column( msg.message ).indent(2) << '\n'; } } void printSourceInfo() const { @@ -311,9 +313,7 @@ namespace Catch { i+=2; else i = 0; - stream << Text( _string, TextAttributes() - .setIndent( indent+i) - .setInitialIndent( indent ) ) << '\n'; + stream << Column( _string ).indent( indent+i ).initialIndent( indent ) << '\n'; } struct SummaryColumn { diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 84cf35ed..aad1f036 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -8,7 +8,6 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include "internal/catch_text.h" // temporarily #include "../include/reporters/catch_reporter_teamcity.hpp" #include "../include/reporters/catch_reporter_tap.hpp" #include "../include/reporters/catch_reporter_automake.hpp" From 3a37f45a97276b3450f8fb86811f590fc1abf1b7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:20:42 +0100 Subject: [PATCH 154/398] Removed tbc_text_format (superceded by TextFlow) --- include/catch_session.hpp | 3 +- include/external/tbc_text_format.h | 179 ------------------ include/internal/catch_list.cpp | 4 +- include/internal/catch_text.h | 11 +- include/reporters/catch_reporter_console.cpp | 4 +- include/reporters/catch_reporter_teamcity.hpp | 2 - 6 files changed, 5 insertions(+), 198 deletions(-) delete mode 100644 include/external/tbc_text_format.h diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 05ebff47..e9a4aade 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -16,6 +16,7 @@ #include "internal/catch_version.h" #include "internal/catch_interfaces_reporter.h" #include "internal/catch_startup_exception_registry.h" +#include "internal/catch_text.h" #include #include @@ -23,8 +24,6 @@ namespace Catch { - using namespace clara::TextFlow; - IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); diff --git a/include/external/tbc_text_format.h b/include/external/tbc_text_format.h deleted file mode 100644 index d6c06c2c..00000000 --- a/include/external/tbc_text_format.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Created by Phil on 18/4/2013. - * Copyright 2013 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) - */ -// Only use header guard if we are not using an outer namespace -#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -# endif -# else -# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED -# endif -#endif -#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED -#include -#include -#include - -// Use optional outer namespace -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { -#endif - -namespace Tbc { - -#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH - const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; -#else - const unsigned int consoleWidth = 80; -#endif - - struct TextAttributes { - TextAttributes() - : initialIndent( std::string::npos ), - indent( 0 ), - width( consoleWidth-1 ) - {} - - TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } - TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } - TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } - - std::size_t initialIndent; // indent of first line, or npos - std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos - std::size_t width; // maximum width of text, including indent. Longer text will wrap - }; - - class Text { - public: - Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - init( _str ); - } - - template - Text( T const& _val, TextAttributes const& _attr = TextAttributes() ) - : attr( _attr ) - { - std::ostringstream oss; - oss << _val; - init( oss.str() ); - } - - typedef std::vector::const_iterator const_iterator; - - const_iterator begin() const { return lines.begin(); } - const_iterator end() const { return lines.end(); } - std::string const& last() const { return lines.back(); } - std::size_t size() const { return lines.size(); } - std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } - std::string toString() const { - std::ostringstream oss; - oss << *this; - return oss.str(); - } - - inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { - for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); - it != itEnd; ++it ) { - if( it != _text.begin() ) - _stream << "\n"; - _stream << *it; - } - return _stream; - } - - - private: - TextAttributes attr; - std::vector lines; - - void init( std::string const& _str ) - { - const std::string wrappableBeforeChars = "[({<\t"; - const std::string wrappableAfterChars = "])}>-,./|\\"; - const std::string wrappableInsteadOfChars = " \n\r"; - std::string indent = attr.initialIndent != std::string::npos - ? std::string( attr.initialIndent, ' ' ) - : std::string( attr.indent, ' ' ); - - typedef std::string::const_iterator iterator; - iterator it = _str.begin(); - const iterator strEnd = _str.end(); - - while( it != strEnd ) { - - if( lines.size() >= 1000 ) { - lines.push_back( "... message truncated due to excessive size" ); - return; - } - - - std::string suffix; - std::size_t width = (std::min)( static_cast( strEnd-it ), attr.width-static_cast( indent.size() ) ); - iterator itEnd = it+width; - iterator itNext = _str.end(); - - iterator itNewLine = std::find( it, itEnd, '\n' ); - if( itNewLine != itEnd ) - itEnd = itNewLine; - - if( itEnd != strEnd ) { - bool foundWrapPoint = false; - iterator findIt = itEnd; - do { - if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { - itEnd = findIt+1; - itNext = findIt+1; - foundWrapPoint = true; - } - else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { - itEnd = findIt; - itNext = findIt; - foundWrapPoint = true; - } - else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { - itNext = findIt+1; - itEnd = findIt; - foundWrapPoint = true; - } - if( findIt == it ) - break; - else - --findIt; - } - while( !foundWrapPoint ); - - if( !foundWrapPoint ) { - // No good wrap char, so we'll break mid word and add a hyphen - --itEnd; - itNext = itEnd; - suffix = "-"; - } - else { - while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) - --itEnd; - } - } - lines.push_back( indent + std::string( it, itEnd ) + suffix ); - - if( indent.size() != attr.indent ) - indent = std::string( attr.indent, ' ' ); - it = itNext; - } - } - }; - -} // end namespace Tbc - -#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE -} // end outer namespace -#endif - -#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED \ No newline at end of file diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index c7e90693..84b58ac7 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -12,7 +12,7 @@ #include "catch_interfaces_reporter.h" #include "catch_interfaces_testcase.h" -#include "catch_clara.h" // For TextFlow +#include "internal/catch_text.h" #include "catch_console_colour.hpp" #include "catch_test_spec_parser.hpp" @@ -24,8 +24,6 @@ namespace Catch { - using namespace clara::TextFlow; - std::size_t listTests( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) diff --git a/include/internal/catch_text.h b/include/internal/catch_text.h index b66751f3..eeafe8e2 100644 --- a/include/internal/catch_text.h +++ b/include/internal/catch_text.h @@ -8,17 +8,10 @@ #ifndef TWOBLUECUBES_CATCH_TEXT_H_INCLUDED #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED -#include "catch_config.hpp" - -#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - -#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -#include "../external/tbc_text_format.h" -#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#include "catch_clara.h" namespace Catch { - using Tbc::Text; - using Tbc::TextAttributes; + using namespace clara::TextFlow; } #endif // TWOBLUECUBES_CATCH_TEXT_H_INCLUDED diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index b70df425..e6f7adc8 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -11,15 +11,13 @@ #include "../internal/catch_reporter_registrars.hpp" #include "../internal/catch_console_colour.hpp" #include "../internal/catch_version.h" -#include "../internal/catch_clara.h" // For TextFlow +#include "../internal/catch_text.h" #include #include namespace Catch { - using namespace clara::TextFlow; - struct ConsoleReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index c9280a69..cb043022 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -23,8 +23,6 @@ namespace Catch { - using namespace clara::TextFlow; - struct TeamCityReporter : StreamingReporterBase { TeamCityReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ) From c91639e1d7bb4e19c9252a55c5484d61e8934a19 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:32:35 +0100 Subject: [PATCH 155/398] Use Columns to format reporter list --- include/internal/catch_list.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index 84b58ac7..c411115b 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -133,16 +133,15 @@ namespace Catch { maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); for( auto const& factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) { - auto wrapper = Column( factoryKvp.second->getDescription() ) - .initialIndent( 0 ) - .indent( 7+maxNameLen ) - .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ); Catch::cout() - << " " - << factoryKvp.first - << ':' - << std::string( maxNameLen - factoryKvp.first.size() + 2, ' ' ) - << wrapper << '\n'; + << Column( factoryKvp.first + ":" ) + .indent(2) + .width( 5+maxNameLen ) + + Column( factoryKvp.second->getDescription() ) + .initialIndent(0) + .indent(2) + .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) + << "\n"; } Catch::cout() << std::endl; return factories.size(); From b35225ff3a591fc7883c0333bb59cf781f1a3786 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:37:25 +0100 Subject: [PATCH 156/398] Removed tbc_text_format from CMakeLists.txt --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32992a3b..7b28ddc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,6 @@ CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR}) # Please keep these ordered alphabetically set(EXTERNAL_HEADERS ${HEADER_DIR}/external/clara.hpp - ${HEADER_DIR}/external/tbc_text_format.h ) CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external) From cb6963216fd5b178d4220417d18ec4fe9d311cca Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:49:03 +0100 Subject: [PATCH 157/398] Removed catch_section_info.cpp (not used) --- CMakeLists.txt | 1 - include/internal/catch_section_info.cpp | 104 ------------------------ 2 files changed, 105 deletions(-) delete mode 100644 include/internal/catch_section_info.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b28ddc4..d1edd83e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,7 +215,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_run_context.cpp ${HEADER_DIR}/internal/catch_section.cpp - ${HEADER_DIR}/internal/catch_section_info.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp ${HEADER_DIR}/internal/catch_string.cpp ${HEADER_DIR}/internal/catch_stringbuilder.cpp diff --git a/include/internal/catch_section_info.cpp b/include/internal/catch_section_info.cpp deleted file mode 100644 index 83eb4fef..00000000 --- a/include/internal/catch_section_info.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Created by Phil Nash on 4/5/2012 - * Copyright 2012 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) - */ - -#include "catch_section_info.h" - -#include - -namespace Catch { - - class RunningSection { - public: - - typedef std::vector SubSections; - - enum State { - Root, - Unknown, - Branch, - TestedBranch, - TestedLeaf - }; - - RunningSection( RunningSection* parent, std::string const& name ) - : m_state( Unknown ), - m_parent( parent ), - m_name( name ) - {} - - RunningSection( std::string const& name ) - : m_state( Root ), - m_parent( nullptr ), - m_name( name ) - {} - - ~RunningSection() { - deleteAll( m_subSections ); - } - - std::string getName() const { - return m_name; - } - - bool shouldRun() const { - return m_state < TestedBranch; - } - - bool isBranch() const { - return m_state == Branch; - } - - const RunningSection* getParent() const { - return m_parent; - } - - bool hasUntestedSections() const { - if( m_state == Unknown ) - return true; - for( auto subSection : m_subSections ) - if( subSection->hasUntestedSections() ) - return true; - return false; - } - - // Mutable methods: - - RunningSection* getParent() { - return m_parent; - } - - RunningSection* findOrAddSubSection( std::string const& name, bool& changed ) { - for( auto subSection : m_subSections ) - if( subSection->getName() == name ) - return subSection; - RunningSection* subSection = new RunningSection( this, name ); - m_subSections.push_back( subSection ); - m_state = Branch; - changed = true; - return subSection; - } - - bool ran() { - if( m_state >= Branch ) - return false; - m_state = TestedLeaf; - return true; - } - - void ranToCompletion() { - if( m_state == Branch && !hasUntestedSections() ) - m_state = TestedBranch; - } - - private: - State m_state; - RunningSection* m_parent; - std::string m_name; - SubSections m_subSections; - }; -} From 46bf7605f41a97535f63abfb2406ec408573b441 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 20 Jul 2017 23:50:07 +0100 Subject: [PATCH 158/398] Hold exception translators by unique_ptr - and removed range deleters --- include/internal/catch_common.h | 10 ---------- .../internal/catch_exception_translator_registry.cpp | 3 +-- include/internal/catch_exception_translator_registry.h | 3 ++- include/internal/catch_interfaces_exception.h | 4 ++-- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 6f037c71..bc9a0aba 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -45,16 +45,6 @@ namespace Catch { virtual ~NonCopyable(); }; - template - void deleteAll( ContainerT& container ) { - for( auto p : container ) - delete p; - } - template - void deleteAllValues( AssociativeContainerT& container ) { - for( auto const& kvp : container ) - delete kvp.second; - } bool startsWith( std::string const& s, std::string const& prefix ); bool startsWith( std::string const& s, char prefix ); diff --git a/include/internal/catch_exception_translator_registry.cpp b/include/internal/catch_exception_translator_registry.cpp index 18e7c0b6..1a857535 100644 --- a/include/internal/catch_exception_translator_registry.cpp +++ b/include/internal/catch_exception_translator_registry.cpp @@ -16,11 +16,10 @@ namespace Catch { ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { - deleteAll( m_translators ); } void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { - m_translators.push_back( translator ); + m_translators.push_back( std::unique_ptr( translator ) ); } std::string ExceptionTranslatorRegistry::translateActiveException() const { diff --git a/include/internal/catch_exception_translator_registry.h b/include/internal/catch_exception_translator_registry.h index dc5d8159..d3059f48 100644 --- a/include/internal/catch_exception_translator_registry.h +++ b/include/internal/catch_exception_translator_registry.h @@ -11,6 +11,7 @@ #include "catch_interfaces_exception.h" #include #include +#include namespace Catch { @@ -22,7 +23,7 @@ namespace Catch { std::string tryTranslators() const; private: - std::vector m_translators; + std::vector> m_translators; }; } diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index 6387ba9d..32487ffa 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -18,7 +18,7 @@ namespace Catch { typedef std::string(*exceptionTranslateFunction)(); struct IExceptionTranslator; - typedef std::vector ExceptionTranslators; + typedef std::vector> ExceptionTranslators; struct IExceptionTranslator { virtual ~IExceptionTranslator(); @@ -40,7 +40,7 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { + std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { try { if( it == itEnd ) throw; From b6f62af7d1a96482ca5df3c476e30f8fcf35df5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Jul 2017 15:45:50 +0200 Subject: [PATCH 159/398] Address more of PVS studio warnings --- include/internal/catch_list.cpp | 6 +++--- include/internal/catch_result_builder.cpp | 2 +- include/internal/catch_stringdata.h | 4 ++-- include/reporters/catch_reporter_bases.hpp | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index c411115b..de58badb 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -44,7 +44,7 @@ namespace Catch { if( config.verbosity() >= Verbosity::High ) { Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; std::string description = testCaseInfo.description; - if( description == "" ) + if( description.empty() ) description = "(NO DESCRIPTION)"; Catch::cout() << Column( description ).indent(4) << std::endl; } @@ -129,10 +129,10 @@ namespace Catch { Catch::cout() << "Available reporters:\n"; IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); std::size_t maxNameLen = 0; - for( auto const& factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) + for( auto const& factoryKvp : factories ) maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); - for( auto const& factoryKvp : getRegistryHub().getReporterRegistry().getFactories() ) { + for( auto const& factoryKvp : factories ) { Catch::cout() << Column( factoryKvp.first + ":" ) .indent(2) diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index 09a2f53e..838c43da 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -91,7 +91,7 @@ namespace Catch { std::string actualMessage = Catch::translateActiveException(); if( !matcher.match( actualMessage ) ) { data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; + data.reconstructedExpression = std::move(actualMessage); } AssertionResult result( m_assertionInfo, data ); handleResult( result ); diff --git a/include/internal/catch_stringdata.h b/include/internal/catch_stringdata.h index 5ffafad7..aaa9ec8e 100644 --- a/include/internal/catch_stringdata.h +++ b/include/internal/catch_stringdata.h @@ -30,12 +30,12 @@ namespace Catch { void addRef() const noexcept { if( m_refs > 0 ) - m_refs++; + ++m_refs; } void release() const noexcept { unsigned int refs = m_refs; if( refs > 1 ) - m_refs--; + --m_refs; else if( refs == 1 ) delete[] reinterpret_cast( this ); } diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 85adc18f..45f8bb57 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -181,7 +181,7 @@ namespace Catch { node = *it; } m_sectionStack.push_back( node ); - m_deepestSection = node; + m_deepestSection = std::move(node); } void assertionStarting(AssertionInfo const&) override {} From 1e59ccee41f269440310979a0b6ab7e4dbb1e453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Jul 2017 17:16:28 +0200 Subject: [PATCH 160/398] Addressed Resharper-C++ warnings See #958 --- include/catch_session.hpp | 2 +- include/internal/catch_commandline.cpp | 2 +- include/internal/catch_common.h | 2 +- include/internal/catch_console_colour.cpp | 15 ++++---- include/internal/catch_console_colour.hpp | 4 +-- include/internal/catch_context.cpp | 14 ++++---- include/internal/catch_evaluate.hpp | 2 +- .../catch_exception_translator_registry.h | 2 +- .../internal/catch_notimplemented_exception.h | 2 +- .../internal/catch_reporter_registrars.hpp | 8 ++--- include/internal/catch_run_context.hpp | 25 ++++++------- include/internal/catch_stream.hpp | 6 ++-- include/internal/catch_string.cpp | 2 +- include/internal/catch_string.h | 2 +- include/internal/catch_stringref.cpp | 2 +- include/internal/catch_test_case_tracker.cpp | 4 +-- include/internal/catch_test_case_tracker.hpp | 2 +- include/internal/catch_test_spec.hpp | 6 ++-- include/internal/catch_xmlwriter.cpp | 4 +-- include/internal/catch_xmlwriter.hpp | 4 +-- include/reporters/catch_reporter_bases.cpp | 6 ++++ include/reporters/catch_reporter_bases.hpp | 8 +---- include/reporters/catch_reporter_compact.cpp | 35 ++++++++++--------- include/reporters/catch_reporter_console.cpp | 29 ++++++++------- include/reporters/catch_reporter_teamcity.hpp | 2 +- 25 files changed, 97 insertions(+), 93 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index e9a4aade..f95de1c5 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -110,7 +110,7 @@ namespace Catch { Catch::cleanUp(); } - void showHelp() { + void showHelp() const { Catch::cout() << "\nCatch v" << libraryVersion() << "\n" << m_cli << std::endl diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index d5f2ab4e..087aa276 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -55,7 +55,7 @@ namespace Catch { auto const setRngSeed = [&]( std::string const& seed ) { if( seed != "time" ) return clara::detail::convertInto( seed, config.rngSeed ); - config.rngSeed = static_cast( std::time(0) ); + config.rngSeed = static_cast( std::time(nullptr) ); return ParserResult::ok( ParseResultType::Matched ); }; auto const setColourUsage = [&]( std::string const& useColour ) { diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index bc9a0aba..3ef325e0 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -98,7 +98,7 @@ namespace Catch { // as well as // >> stuff +StreamEndStop struct StreamEndStop { - std::string operator+() { + std::string operator+() const { return std::string(); } }; diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index fc6c76f2..1f382030 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -59,7 +59,7 @@ namespace { originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } - virtual void use( Colour::Code _colourCode ) { + virtual void use( Colour::Code _colourCode ) override { switch( _colourCode ) { case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); @@ -118,7 +118,7 @@ namespace { // https://github.com/philsquared/Catch/pull/131 class PosixColourImpl : public IColourImpl { public: - virtual void use( Colour::Code _colourCode ) { + virtual void use( Colour::Code _colourCode ) override { switch( _colourCode ) { case Colour::None: case Colour::White: return setColour( "[0m" ); @@ -179,10 +179,13 @@ namespace Catch { namespace Catch { Colour::Colour( Code _colourCode ) { use( _colourCode ); } - Colour::Colour( Colour&& _other ) { const_cast( _other ).m_moved = true; } - Colour& Colour::operator=( Colour&& _other ) { - m_moved = false; - const_cast( _other ).m_moved = true; + Colour::Colour( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + } + Colour& Colour::operator=( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; return *this; } diff --git a/include/internal/catch_console_colour.hpp b/include/internal/catch_console_colour.hpp index 6b5b8fa6..d1e68f87 100644 --- a/include/internal/catch_console_colour.hpp +++ b/include/internal/catch_console_colour.hpp @@ -50,8 +50,8 @@ namespace Catch { // Use constructed object for RAII guard Colour( Code _colourCode ); - Colour( Colour&& other ); - Colour& operator=( Colour&& other ); + Colour( Colour&& other ) noexcept; + Colour& operator=( Colour&& other ) noexcept; ~Colour(); // Use static method for one-shot changes diff --git a/include/internal/catch_context.cpp b/include/internal/catch_context.cpp index 48b4f4a9..7a4518bf 100644 --- a/include/internal/catch_context.cpp +++ b/include/internal/catch_context.cpp @@ -16,32 +16,30 @@ namespace Catch { class Context : public IMutableContext, NonCopyable { public: // IContext - virtual IResultCapture* getResultCapture() { + virtual IResultCapture* getResultCapture() override { return m_resultCapture; } - virtual IRunner* getRunner() { + virtual IRunner* getRunner() override { return m_runner; } - virtual IConfigPtr getConfig() const { + virtual IConfigPtr getConfig() const override { return m_config; } public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) { + virtual void setResultCapture( IResultCapture* resultCapture ) override { m_resultCapture = resultCapture; } - virtual void setRunner( IRunner* runner ) { + virtual void setRunner( IRunner* runner ) override { m_runner = runner; } - virtual void setConfig( IConfigPtr const& config ) { + virtual void setConfig( IConfigPtr const& config ) override { m_config = config; } friend IMutableContext& getCurrentMutableContext(); - private: - private: IConfigPtr m_config; IRunner* m_runner = nullptr; diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 31be0dcf..1ee53d74 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -46,7 +46,7 @@ namespace Internal { // So the compare overloads can be operator agnostic we convey the operator as a template // enum, which is used to specialise an Evaluator for doing the comparison. template - class Evaluator{}; + struct Evaluator{}; template struct Evaluator { diff --git a/include/internal/catch_exception_translator_registry.h b/include/internal/catch_exception_translator_registry.h index d3059f48..da2f4f12 100644 --- a/include/internal/catch_exception_translator_registry.h +++ b/include/internal/catch_exception_translator_registry.h @@ -19,7 +19,7 @@ namespace Catch { public: ~ExceptionTranslatorRegistry(); virtual void registerTranslator( const IExceptionTranslator* translator ); - virtual std::string translateActiveException() const; + virtual std::string translateActiveException() const override; std::string tryTranslators() const; private: diff --git a/include/internal/catch_notimplemented_exception.h b/include/internal/catch_notimplemented_exception.h index e728c363..640cc167 100644 --- a/include/internal/catch_notimplemented_exception.h +++ b/include/internal/catch_notimplemented_exception.h @@ -19,7 +19,7 @@ namespace Catch { virtual ~NotImplementedException() noexcept = default; - virtual const char* what() const noexcept; + virtual const char* what() const noexcept override; private: std::string m_what; diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 06c16cb5..f10c493c 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -17,11 +17,11 @@ namespace Catch { class ReporterFactory : public IReporterFactory { - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const { + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { return std::unique_ptr( new T( config ) ); } - virtual std::string getDescription() const { + virtual std::string getDescription() const override { return T::getDescription(); } }; @@ -38,10 +38,10 @@ namespace Catch { class ListenerFactory : public IReporterFactory { - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const { + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { return std::make_shared( config ); } - virtual std::string getDescription() const { + virtual std::string getDescription() const override { return std::string(); } }; diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index abe8c1fe..c513788b 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -63,33 +63,30 @@ namespace Catch { private: // IResultCapture - virtual void assertionEnded(AssertionResult const& result); + virtual void assertionEnded(AssertionResult const& result) override; - virtual bool sectionStarted( - SectionInfo const& sectionInfo, - Counts& assertions - ); + virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; bool testForMissingAssertions(Counts& assertions); - virtual void sectionEnded(SectionEndInfo const& endInfo); + virtual void sectionEnded(SectionEndInfo const& endInfo) override; - virtual void sectionEndedEarly(SectionEndInfo const& endInfo); + virtual void sectionEndedEarly(SectionEndInfo const& endInfo) override; - virtual void pushScopedMessage(MessageInfo const& message); + virtual void pushScopedMessage(MessageInfo const& message) override; - virtual void popScopedMessage(MessageInfo const& message); + virtual void popScopedMessage(MessageInfo const& message) override; - virtual std::string getCurrentTestName() const; + virtual std::string getCurrentTestName() const override; - virtual const AssertionResult* getLastResult() const; + virtual const AssertionResult* getLastResult() const override; - virtual void exceptionEarlyReported(); + virtual void exceptionEarlyReported() override; - virtual void handleFatalErrorCondition(std::string const& message); + virtual void handleFatalErrorCondition(std::string const& message) override; public: // !TBD We need to do this another way! - bool aborting() const; + bool aborting() const override; private: diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index b0998e3f..89f6cdea 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -30,11 +30,11 @@ namespace Catch { } ~StreamBufImpl() noexcept { - sync(); + StreamBufImpl::sync(); } private: - int overflow( int c ) { + int overflow( int c ) override { sync(); if( c != EOF ) { @@ -46,7 +46,7 @@ namespace Catch { return 0; } - int sync() { + int sync() override { if( pbase() != pptr() ) { m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); setp( pbase(), epptr() ); diff --git a/include/internal/catch_string.cpp b/include/internal/catch_string.cpp index f7cc53a5..b18f5d1b 100644 --- a/include/internal/catch_string.cpp +++ b/include/internal/catch_string.cpp @@ -32,7 +32,7 @@ namespace Catch { { m_data->addRef(); } - String::String( String&& other ) + String::String( String&& other ) noexcept : m_data( other.m_data ) { other.m_data = StringData::getEmpty(); diff --git a/include/internal/catch_string.h b/include/internal/catch_string.h index b9d310c9..5fb477a4 100644 --- a/include/internal/catch_string.h +++ b/include/internal/catch_string.h @@ -28,7 +28,7 @@ namespace Catch { String( StringRef const& stringRef ); String( char const* rawString ); String( String const& other ); - String( String&& other ); + String( String&& other ) noexcept; String( StringBuilder&& stringBuf ); ~String() noexcept; diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 3c4e292d..7cf75a75 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -55,7 +55,7 @@ namespace Catch { { size_type rawSize = rawChars == nullptr ? 0 : static_cast( std::strlen( rawChars ) ); if( rawSize < size ) - size = rawSize; + m_size = rawSize; } StringRef::StringRef( String const& other ) noexcept diff --git a/include/internal/catch_test_case_tracker.cpp b/include/internal/catch_test_case_tracker.cpp index 7efb470c..2616afe4 100644 --- a/include/internal/catch_test_case_tracker.cpp +++ b/include/internal/catch_test_case_tracker.cpp @@ -63,7 +63,7 @@ namespace TestCaseTracking { TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} - bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) { + bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const { return tracker->nameAndLocation().name == m_nameAndLocation.name && tracker->nameAndLocation().location == m_nameAndLocation.location; @@ -133,7 +133,7 @@ namespace TestCaseTracking { switch( m_runState ) { case NeedsAnotherRun: - break;; + break; case Executing: m_runState = CompletedSuccessfully; diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 39509300..df176084 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -101,7 +101,7 @@ namespace TestCaseTracking { NameAndLocation m_nameAndLocation; public: TrackerHasName( NameAndLocation const& nameAndLocation ); - bool operator ()( ITrackerPtr const& tracker ); + bool operator ()( ITrackerPtr const& tracker ) const; }; typedef std::vector Children; diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index 48788fd7..8967c5a9 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -33,7 +33,7 @@ namespace Catch { public: NamePattern( std::string const& name ); virtual ~NamePattern() = default; - virtual bool matches( TestCaseInfo const& testCase ) const; + virtual bool matches( TestCaseInfo const& testCase ) const override; private: WildcardPattern m_wildcardPattern; }; @@ -42,7 +42,7 @@ namespace Catch { public: TagPattern( std::string const& tag ); virtual ~TagPattern() = default; - virtual bool matches( TestCaseInfo const& testCase ) const; + virtual bool matches( TestCaseInfo const& testCase ) const override; private: std::string m_tag; }; @@ -51,7 +51,7 @@ namespace Catch { public: ExcludedPattern( PatternPtr const& underlyingPattern ); virtual ~ExcludedPattern() = default; - virtual bool matches( TestCaseInfo const& testCase ) const; + virtual bool matches( TestCaseInfo const& testCase ) const override; private: PatternPtr m_underlyingPattern; }; diff --git a/include/internal/catch_xmlwriter.cpp b/include/internal/catch_xmlwriter.cpp index edc1be2a..acd9b282 100644 --- a/include/internal/catch_xmlwriter.cpp +++ b/include/internal/catch_xmlwriter.cpp @@ -65,11 +65,11 @@ namespace Catch { : m_writer( writer ) {} - XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept : m_writer( other.m_writer ){ other.m_writer = nullptr; } - XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) { + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { if ( m_writer ) { m_writer->endElement(); } diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 4c9f5ca8..2570ec12 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -38,8 +38,8 @@ namespace Catch { public: ScopedElement( XmlWriter* writer ); - ScopedElement( ScopedElement&& other ); - ScopedElement& operator=( ScopedElement&& other ); + ScopedElement( ScopedElement&& other ) noexcept; + ScopedElement& operator=( ScopedElement&& other ) noexcept; ~ScopedElement(); diff --git a/include/reporters/catch_reporter_bases.cpp b/include/reporters/catch_reporter_bases.cpp index 530092cd..6457af35 100644 --- a/include/reporters/catch_reporter_bases.cpp +++ b/include/reporters/catch_reporter_bases.cpp @@ -17,6 +17,12 @@ #include namespace Catch { + void prepareExpandedExpression(AssertionResult& result) { + if (result.isOk()) + result.discardDecomposedExpression(); + else + result.expandDecomposedExpression(); + } // Because formatting using c++ streams is stateful, drop down to C is required // Alternatively we could use stringstream, but its performance is... not good. diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 45f8bb57..ce1834d5 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -17,6 +17,7 @@ #include namespace Catch { + void prepareExpandedExpression(AssertionResult& result); // Returns double formatted as %.3f (format expected on output) std::string getFormattedDuration( double duration ); @@ -230,13 +231,6 @@ namespace Catch { void skipTest(TestCaseInfo const&) override {} - void prepareExpandedExpression(AssertionResult& result) const { - if (result.isOk()) - result.discardDecomposedExpression(); - else - result.expandDecomposedExpression(); - } - IConfigPtr m_config; std::ostream& stream; std::vector m_assertions; diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp index 1c4b9d56..a1bb108f 100644 --- a/include/reporters/catch_reporter_compact.cpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -11,6 +11,25 @@ #include "../internal/catch_reporter_registrars.hpp" #include "../internal/catch_console_colour.hpp" +namespace { + +#ifdef CATCH_PLATFORM_MAC + const char* failedString() { return "FAILED"; } + const char* passedString() { return "PASSED"; } +#else + const char* failedString() { return "failed"; } + const char* passedString() { return "passed"; } +#endif + + // Colour::LightGrey + Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } + + std::string bothOrAll( std::size_t count ) { + return count == 1 ? std::string() : + count == 2 ? "both " : "all " ; + } +} + namespace Catch { struct CompactReporter : StreamingReporterBase { @@ -148,18 +167,6 @@ namespace Catch { } private: - // Colour::LightGrey - - static Colour::Code dimColour() { return Colour::FileName; } - -#ifdef CATCH_PLATFORM_MAC - static const char* failedString() { return "FAILED"; } - static const char* passedString() { return "PASSED"; } -#else - static const char* failedString() { return "failed"; } - static const char* passedString() { return "passed"; } -#endif - void printSourceInfo() const { Colour colourGuard( Colour::FileName ); stream << result.getSourceInfo() << ':'; @@ -253,10 +260,6 @@ namespace Catch { // - red: Failed N tests cases, failed M assertions. // - green: Passed [both/all] N tests cases with M assertions. - std::string bothOrAll( std::size_t count ) const { - return count == 1 ? std::string() : count == 2 ? "both " : "all " ; - } - void printTotals( const Totals& totals ) const { if( totals.testCases.total() == 0 ) { stream << "No tests ran."; diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index e6f7adc8..3b08d353 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -16,6 +16,22 @@ #include #include +namespace { + std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + + std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } +} + namespace Catch { struct ConsoleReporter : StreamingReporterBase { @@ -390,19 +406,6 @@ namespace Catch { stream << '\n'; } - static std::size_t makeRatio( std::size_t number, std::size_t total ) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; - return ( ratio == 0 && number > 0 ) ? 1 : ratio; - } - static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { - if( i > j && i > k ) - return i; - else if( j > k ) - return j; - else - return k; - } - void printTotalsDivider( Totals const& totals ) { if( totals.testCases.total() > 0 ) { std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index cb043022..15cfc016 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -187,7 +187,7 @@ namespace Catch { // if string has a : in first line will set indent to follow it on // subsequent lines - void printHeaderString( std::ostream& os, std::string const& _string, std::size_t indent = 0 ) { + static void printHeaderString( std::ostream& os, std::string const& _string, std::size_t indent = 0 ) { std::size_t i = _string.find( ": " ); if( i != std::string::npos ) i+=2; From 1a96175bb290a351c5aabbbf330ab7512635db3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Jul 2017 21:57:35 +0200 Subject: [PATCH 161/398] Split out helper functions on std::string from catch_common.h --- CMakeLists.txt | 2 + include/internal/catch_commandline.cpp | 1 + include/internal/catch_common.cpp | 65 +--------------- include/internal/catch_common.h | 25 +----- include/internal/catch_list.cpp | 3 +- include/internal/catch_matchers_string.cpp | 1 + include/internal/catch_matchers_vector.h | 2 + include/internal/catch_run_context.cpp | 1 + include/internal/catch_string_manip.cpp | 77 +++++++++++++++++++ include/internal/catch_string_manip.h | 36 +++++++++ include/internal/catch_tag_alias_registry.cpp | 1 + include/internal/catch_test_case_info.cpp | 1 + .../catch_test_case_registry_impl.hpp | 1 + include/internal/catch_test_spec.cpp | 1 + include/internal/catch_test_spec_parser.hpp | 1 + include/internal/catch_wildcard_pattern.cpp | 1 + include/reporters/catch_reporter_bases.hpp | 1 + 17 files changed, 134 insertions(+), 86 deletions(-) create mode 100644 include/internal/catch_string_manip.cpp create mode 100644 include/internal/catch_string_manip.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d1edd83e..e5ce481e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,6 +173,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_stringbuilder.h ${HEADER_DIR}/internal/catch_stringdata.h ${HEADER_DIR}/internal/catch_stringref.h + ${HEADER_DIR}/internal/catch_string_manip.h ${HEADER_DIR}/internal/catch_suppress_warnings.h ${HEADER_DIR}/internal/catch_tag_alias.h ${HEADER_DIR}/internal/catch_tag_alias_registry.h @@ -220,6 +221,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_stringbuilder.cpp ${HEADER_DIR}/internal/catch_stringdata.cpp ${HEADER_DIR}/internal/catch_stringref.cpp + ${HEADER_DIR}/internal/catch_string_manip.cpp ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp ${HEADER_DIR}/internal/catch_test_case_info.cpp ${HEADER_DIR}/internal/catch_test_case_tracker.cpp diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index 087aa276..484b7740 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -9,6 +9,7 @@ #include "catch_commandline.hpp" #include "catch_common.h" +#include "catch_string_manip.h" #include #include diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp index a35ef93a..d865cd52 100644 --- a/include/internal/catch_common.cpp +++ b/include/internal/catch_common.cpp @@ -11,70 +11,9 @@ #include "catch_interfaces_config.h" #include -#include namespace Catch { - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } - SourceLineInfo::SourceLineInfo() noexcept : file(""), line( 0 ){} SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept : file( _file ), @@ -111,4 +50,8 @@ namespace Catch { bool alwaysTrue() { return true; } bool alwaysFalse() { return false; } + std::string StreamEndStop::operator+() const { + return std::string(); + } + } diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 3ef325e0..5c5de452 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -22,7 +22,6 @@ #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) #include -#include #include namespace Catch { @@ -45,26 +44,6 @@ namespace Catch { virtual ~NonCopyable(); }; - - bool startsWith( std::string const& s, std::string const& prefix ); - bool startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - - struct pluralise { - pluralise( std::size_t count, std::string const& label ); - - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; - }; - struct SourceLineInfo { SourceLineInfo() noexcept; @@ -98,9 +77,7 @@ namespace Catch { // as well as // >> stuff +StreamEndStop struct StreamEndStop { - std::string operator+() const { - return std::string(); - } + std::string operator+() const; }; template T const& operator + ( T const& value, StreamEndStop ) { diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index de58badb..36cd0545 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -12,11 +12,12 @@ #include "catch_interfaces_reporter.h" #include "catch_interfaces_testcase.h" -#include "internal/catch_text.h" +#include "catch_text.h" #include "catch_console_colour.hpp" #include "catch_test_spec_parser.hpp" #include "catch_tostring.h" +#include "catch_string_manip.h" #include #include diff --git a/include/internal/catch_matchers_string.cpp b/include/internal/catch_matchers_string.cpp index 207193fb..2f8ffdb8 100644 --- a/include/internal/catch_matchers_string.cpp +++ b/include/internal/catch_matchers_string.cpp @@ -7,6 +7,7 @@ */ #include "catch_matchers_string.h" +#include "catch_string_manip.h" namespace Catch { namespace Matchers { diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 1f9e0a61..b176d4a3 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -10,6 +10,8 @@ #include "catch_matchers.hpp" +#include + namespace Catch { namespace Matchers { diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 7ed79950..68f824fa 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -1,6 +1,7 @@ #include "catch_run_context.hpp" #include +#include namespace Catch { diff --git a/include/internal/catch_string_manip.cpp b/include/internal/catch_string_manip.cpp new file mode 100644 index 00000000..84762044 --- /dev/null +++ b/include/internal/catch_string_manip.cpp @@ -0,0 +1,77 @@ +/* + * Created by Martin on 25/07/2017. + * + * 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) + */ + +#include "catch_string_manip.h" + +#include +#include +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); + } + bool startsWith( std::string const& s, char prefix ) { + return !s.empty() && s[0] == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); + } + bool endsWith( std::string const& s, char suffix ) { + return !s.empty() && s[s.size()-1] == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << 's'; + return os; + } + +} diff --git a/include/internal/catch_string_manip.h b/include/internal/catch_string_manip.h new file mode 100644 index 00000000..6292cd57 --- /dev/null +++ b/include/internal/catch_string_manip.h @@ -0,0 +1,36 @@ +/* + * Created by Martin on 25/07/2017. + * + * 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) + */ +#ifndef TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED +#define TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED + +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ); + bool startsWith( std::string const& s, char prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool endsWith( std::string const& s, char suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; +} + +#endif // TWOBLUECUBES_CATCH_STRING_MANIP_H_INCLUDED + diff --git a/include/internal/catch_tag_alias_registry.cpp b/include/internal/catch_tag_alias_registry.cpp index d0ee2f7c..c0969445 100644 --- a/include/internal/catch_tag_alias_registry.cpp +++ b/include/internal/catch_tag_alias_registry.cpp @@ -10,6 +10,7 @@ #include "catch_console_colour.hpp" #include "catch_interfaces_registry_hub.h" #include "catch_stream.h" +#include "catch_string_manip.h" namespace Catch { diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index f75f5a3c..0e4ac1d2 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -10,6 +10,7 @@ #include "catch_test_case_info.h" #include "catch_interfaces_testcase.h" #include "catch_common.h" +#include "catch_string_manip.h" #include #include diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 068ffe58..7008ae9f 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -13,6 +13,7 @@ #include "catch_test_spec.hpp" #include "catch_context.h" #include "catch_interfaces_config.h" +#include "catch_string_manip.h" #include #include diff --git a/include/internal/catch_test_spec.cpp b/include/internal/catch_test_spec.cpp index 878d8424..0809fc5b 100644 --- a/include/internal/catch_test_spec.cpp +++ b/include/internal/catch_test_spec.cpp @@ -6,6 +6,7 @@ */ #include "catch_test_spec.hpp" +#include "catch_string_manip.h" #include #include diff --git a/include/internal/catch_test_spec_parser.hpp b/include/internal/catch_test_spec_parser.hpp index 3e003685..497253d2 100644 --- a/include/internal/catch_test_spec_parser.hpp +++ b/include/internal/catch_test_spec_parser.hpp @@ -14,6 +14,7 @@ #endif #include "catch_test_spec.hpp" +#include "catch_string_manip.h" #include "catch_interfaces_tag_alias_registry.h" namespace Catch { diff --git a/include/internal/catch_wildcard_pattern.cpp b/include/internal/catch_wildcard_pattern.cpp index e99ff5f2..f33035dd 100644 --- a/include/internal/catch_wildcard_pattern.cpp +++ b/include/internal/catch_wildcard_pattern.cpp @@ -6,6 +6,7 @@ */ #include "catch_wildcard_pattern.hpp" +#include "catch_string_manip.h" namespace Catch { diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index ce1834d5..6fd40243 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -10,6 +10,7 @@ #include "../internal/catch_interfaces_reporter.h" +#include #include #include #include From 9de729b515ec129c5436d2da46d54c1cdca2fc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Jul 2017 22:13:14 +0200 Subject: [PATCH 162/398] General cleanup --- CMakeLists.txt | 1 + include/internal/catch_commandline.cpp | 1 - include/internal/catch_context.cpp | 5 ----- include/internal/catch_option.hpp | 2 -- include/internal/catch_result_builder.cpp | 6 ++++++ include/internal/catch_result_builder.h | 6 +----- include/internal/catch_tag_alias.h | 2 +- include/internal/catch_tag_alias_registry.cpp | 9 --------- include/internal/catch_test_case_info.cpp | 1 - include/internal/catch_test_case_info.h | 2 -- include/internal/catch_tostring.h | 9 +++------ 11 files changed, 12 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e5ce481e..6489e3a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,6 +222,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_stringdata.cpp ${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_string_manip.cpp + ${HEADER_DIR}/internal/catch_tag_alias.cpp ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp ${HEADER_DIR}/internal/catch_test_case_info.cpp ${HEADER_DIR}/internal/catch_test_case_tracker.cpp diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index 484b7740..b94bc2d2 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -8,7 +8,6 @@ #include "catch_commandline.hpp" -#include "catch_common.h" #include "catch_string_manip.h" #include diff --git a/include/internal/catch_context.cpp b/include/internal/catch_context.cpp index 7a4518bf..3d406dda 100644 --- a/include/internal/catch_context.cpp +++ b/include/internal/catch_context.cpp @@ -5,9 +5,6 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED - #include "catch_context.h" #include "catch_common.h" @@ -63,5 +60,3 @@ namespace Catch { currentContext = nullptr; } } - -#endif // TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED diff --git a/include/internal/catch_option.hpp b/include/internal/catch_option.hpp index 6653649e..d790b245 100644 --- a/include/internal/catch_option.hpp +++ b/include/internal/catch_option.hpp @@ -8,8 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED -#include "catch_common.h" - namespace Catch { // An optional type diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index 838c43da..a1fed54e 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -168,4 +168,10 @@ namespace Catch { m_guardException = false; } + CopyableStream& ResultBuilder::m_stream() { + static CopyableStream s; + return s; + } + + } // end namespace Catch diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 4c5c5d80..45bc8920 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -75,11 +75,7 @@ namespace Catch { AssertionInfo m_assertionInfo; AssertionResultData m_data; - static CopyableStream &m_stream() - { - static CopyableStream s; - return s; - } + static CopyableStream& m_stream(); bool m_shouldDebugBreak = false; bool m_shouldThrow = false; diff --git a/include/internal/catch_tag_alias.h b/include/internal/catch_tag_alias.h index bb23bc8d..7dd6337f 100644 --- a/include/internal/catch_tag_alias.h +++ b/include/internal/catch_tag_alias.h @@ -15,7 +15,7 @@ namespace Catch { struct TagAlias { - TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); std::string tag; SourceLineInfo lineInfo; diff --git a/include/internal/catch_tag_alias_registry.cpp b/include/internal/catch_tag_alias_registry.cpp index c0969445..921740e0 100644 --- a/include/internal/catch_tag_alias_registry.cpp +++ b/include/internal/catch_tag_alias_registry.cpp @@ -53,13 +53,4 @@ namespace Catch { return getRegistryHub().getTagAliasRegistry(); } - RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { - try { - getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); - } catch (...) { - // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException(std::current_exception()); - } - } - } // end namespace Catch diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 0e4ac1d2..6f6b141d 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -9,7 +9,6 @@ #include "catch_test_spec.hpp" #include "catch_test_case_info.h" #include "catch_interfaces_testcase.h" -#include "catch_common.h" #include "catch_string_manip.h" #include diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index 7f6d5a85..ebb1f406 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -8,8 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED -#include "catch_common.h" - #include #include #include diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index e4cded72..81d122d6 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -8,21 +8,18 @@ #ifndef TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED -#include "catch_common.h" #include #include #include +#include +#include +#include #ifdef __OBJC__ #include "catch_objc_arc.hpp" #endif -#include - -#include - -#include // We need a dummy global operator<< so we can bring it into Catch namespace later struct Catch_global_namespace_dummy; From a75eaa3c5a0ecc802472fb4963655025167ed686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 25 Jul 2017 22:41:35 +0200 Subject: [PATCH 163/398] Split out more headers into separate .cpp files --- CMakeLists.txt | 2 + .../catch_test_case_registry_impl.cpp | 113 +++++++++++++++ .../catch_test_case_registry_impl.hpp | 131 +++--------------- include/internal/catch_test_registry.cpp | 35 +++++ include/internal/catch_test_registry.hpp | 6 +- 5 files changed, 171 insertions(+), 116 deletions(-) create mode 100644 include/internal/catch_test_case_registry_impl.cpp create mode 100644 include/internal/catch_test_registry.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6489e3a0..9c56cca3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,7 +225,9 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_tag_alias.cpp ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp ${HEADER_DIR}/internal/catch_test_case_info.cpp + ${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp ${HEADER_DIR}/internal/catch_test_case_tracker.cpp + ${HEADER_DIR}/internal/catch_test_registry.cpp ${HEADER_DIR}/internal/catch_test_spec.cpp ${HEADER_DIR}/internal/catch_test_spec_parser.cpp ${HEADER_DIR}/internal/catch_timer.cpp diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp new file mode 100644 index 00000000..d7cab1d8 --- /dev/null +++ b/include/internal/catch_test_case_registry_impl.cpp @@ -0,0 +1,113 @@ +/* + * Created by Martin on 25/07/2017 + * + * 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) + */ + +#include "catch_test_case_registry_impl.hpp" + +#include "catch_context.h" +#include "catch_interfaces_registry_hub.h" +#include "catch_string_manip.h" +#include "catch_test_case_info.h" + +#include + +namespace Catch { + + RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { return std::rand() % n; } + RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { return std::rand() % max(); } + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end() ); + break; + case RunTests::InRandomOrder: + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( auto const& function : functions ) { + auto prev = seenFunctions.insert( function ); + CATCH_ENFORCE( prev.second, + "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( auto const& testCase : testCases ) + if( matchTest( testCase, testSpec, config ) ) + filtered.push_back( testCase ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + void TestRegistry::registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name.empty() ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + std::vector const& TestRegistry::getAllTests() const { + return m_functions; + } + std::vector const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + + + /////////////////////////////////////////////////////////////////////////// + TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} + + void TestInvokerAsFunction::invoke() const { + m_testAsFunction(); + } + + std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, '&' ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + +} // end namespace Catch diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 7008ae9f..27b64eb8 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -9,28 +9,27 @@ #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED #include "catch_test_registry.hpp" -#include "catch_test_case_info.h" #include "catch_test_spec.hpp" -#include "catch_context.h" #include "catch_interfaces_config.h" -#include "catch_string_manip.h" #include #include -#include #include namespace Catch { - struct RandomNumberGenerator { - typedef std::ptrdiff_t result_type; + class TestCase; + class IConfig; - result_type operator()( result_type n ) const { return std::rand() % n; } + struct RandomNumberGenerator { + using result_type = std::ptrdiff_t; + + result_type operator()( result_type n ) const; static constexpr result_type min() { return 0; } static constexpr result_type max() { return 1000000; } - result_type operator()() const { return std::rand() % max(); } + result_type operator()() const; template static void shuffle( V& vector ) { RandomNumberGenerator rng; @@ -38,78 +37,22 @@ namespace Catch { } }; - inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector sorted = unsortedTestCases; + void enforceNoDuplicateTestCases( std::vector const& functions ); - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end() ); - break; - case RunTests::InRandomOrder: - seedRng( config ); - RandomNumberGenerator::shuffle( sorted ); - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - return sorted; - } - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); - } - - void enforceNoDuplicateTestCases( std::vector const& functions ) { - std::set seenFunctions; - for( auto const& function : functions ) { - auto prev = seenFunctions.insert( function ); - CATCH_ENFORCE( prev.second, - "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); - } - } - - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { - std::vector filtered; - filtered.reserve( testCases.size() ); - for( auto const& testCase : testCases ) - if( matchTest( testCase, testSpec, config ) ) - filtered.push_back( testCase ); - return filtered; - } - std::vector const& getAllTestCasesSorted( IConfig const& config ) { - return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); - } + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); class TestRegistry : public ITestCaseRegistry { public: - virtual ~TestRegistry(); + virtual ~TestRegistry() = default; - virtual void registerTest( TestCase const& testCase ) { - std::string name = testCase.getTestCaseInfo().name; - if( name.empty() ) { - std::ostringstream oss; - oss << "Anonymous test case " << ++m_unnamedCount; - return registerTest( testCase.withName( oss.str() ) ); - } - m_functions.push_back( testCase ); - } + virtual void registerTest( TestCase const& testCase ); - std::vector const& getAllTests() const override { - return m_functions; - } - std::vector const& getAllTestsSorted( IConfig const& config ) const override { - if( m_sortedFunctions.empty() ) - enforceNoDuplicateTestCases( m_functions ); - - if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { - m_sortedFunctions = sortTests( config, m_functions ); - m_currentSortOrder = config.runOrder(); - } - return m_sortedFunctions; - } + std::vector const& getAllTests() const override; + std::vector const& getAllTestsSorted( IConfig const& config ) const override; private: std::vector m_functions; @@ -119,57 +62,21 @@ namespace Catch { std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; - TestRegistry::~TestRegistry() {} - - /////////////////////////////////////////////////////////////////////////// class TestInvokerAsFunction : public ITestInvoker { void(*m_testAsFunction)(); public: - TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} + TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; - void invoke() const override { - m_testAsFunction(); - } + void invoke() const override; }; - auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { - return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); - } - inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { - std::string className = classOrQualifiedMethodName; - if( startsWith( className, '&' ) ) - { - std::size_t lastColons = className.rfind( "::" ); - std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); - if( penultimateColons == std::string::npos ) - penultimateColons = 1; - className = className.substr( penultimateColons, lastColons-penultimateColons ); - } - return className; - } + std::string extractClassName( std::string const& classOrQualifiedMethodName ); /////////////////////////////////////////////////////////////////////////// - AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept - { - try { - getMutableRegistryHub() - .registerTest( - makeTestCase( - invoker, - extractClassName( classOrMethod.c_str() ), - nameAndTags.name.c_str(), - nameAndTags.tags.c_str(), - lineInfo)); - } catch (...) { - // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException( std::current_exception() ); - } - } - AutoReg::~AutoReg() {} } // end namespace Catch diff --git a/include/internal/catch_test_registry.cpp b/include/internal/catch_test_registry.cpp new file mode 100644 index 00000000..28517628 --- /dev/null +++ b/include/internal/catch_test_registry.cpp @@ -0,0 +1,35 @@ +/* + * Created by Martin on 25/07/2017. + * + * 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) + */ + +#include "catch_test_registry.hpp" +#include "catch_test_case_registry_impl.hpp" +#include "catch_interfaces_registry_hub.h" + +namespace Catch { + + auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); + } + + NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {} + + AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept { + try { + getMutableRegistryHub() + .registerTest( + makeTestCase( + invoker, + extractClassName( classOrMethod.c_str() ), + nameAndTags.name.c_str(), + nameAndTags.tags.c_str(), + lineInfo)); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException( std::current_exception() ); + } + } +} diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index c8538a2c..1cd5fa40 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -35,16 +35,14 @@ auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { } struct NameAndTags { - - NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept : name( name_ ), tags( tags_ ) {} - + NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept; StringRef name; StringRef tags; }; struct AutoReg : NonCopyable { AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; - ~AutoReg(); + ~AutoReg() = default; }; } // end namespace Catch From ab0f1dcde9a9a2ad418c3843abca4db056a07b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 26 Jul 2017 21:24:01 +0200 Subject: [PATCH 164/398] Remove superfluous include --- include/internal/catch_approx.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index bb930a4b..cf06bbe0 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -11,7 +11,6 @@ #include "catch_tostring.h" #include -#include #include From a40add315382ef4673279d5c71282715ff7b2247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 27 Jul 2017 10:45:39 +0200 Subject: [PATCH 165/398] Clean up Approx to take arguments by const& --- include/internal/catch_approx.hpp | 38 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index cf06bbe0..9d6cb9f8 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -24,7 +24,7 @@ namespace Detail { static Approx custom(); template ::value>::type> - Approx operator()( T value ) { + Approx operator()( T const& value ) { Approx approx( static_cast(value) ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); @@ -33,14 +33,14 @@ namespace Detail { } template ::value>::type> - explicit Approx( T value ): Approx(static_cast(value)) + explicit Approx( T const& value ): Approx(static_cast(value)) {} template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula - auto lhs_v = double(lhs); + auto lhs_v = static_cast(lhs); bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); if (relativeOK) { return true; @@ -54,50 +54,50 @@ namespace Detail { } template ::value>::type> - friend bool operator != ( T lhs, Approx const& rhs ) { + friend bool operator != ( T const& lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } template ::value>::type> - friend bool operator != ( Approx const& lhs, T rhs ) { + friend bool operator != ( Approx const& lhs, T const& rhs ) { return !operator==( rhs, lhs ); } template ::value>::type> - friend bool operator <= ( T lhs, Approx const& rhs ) { - return double(lhs) < rhs.m_value || lhs == rhs; + friend bool operator <= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) < rhs.m_value || lhs == rhs; } template ::value>::type> - friend bool operator <= ( Approx const& lhs, T rhs ) { - return lhs.m_value < double(rhs) || lhs == rhs; + friend bool operator <= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value < static_cast(rhs) || lhs == rhs; } template ::value>::type> - friend bool operator >= ( T lhs, Approx const& rhs ) { - return double(lhs) > rhs.m_value || lhs == rhs; + friend bool operator >= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) > rhs.m_value || lhs == rhs; } template ::value>::type> - friend bool operator >= ( Approx const& lhs, T rhs ) { - return lhs.m_value > double(rhs) || lhs == rhs; + friend bool operator >= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value > static_cast(rhs) || lhs == rhs; } template ::value>::type> - Approx& epsilon( T newEpsilon ) { - m_epsilon = double(newEpsilon); + Approx& epsilon( T const& newEpsilon ) { + m_epsilon = static_cast(newEpsilon); return *this; } template ::value>::type> - Approx& margin( T newMargin ) { - m_margin = double(newMargin); + Approx& margin( T const& newMargin ) { + m_margin = static_cast(newMargin); return *this; } template ::value>::type> - Approx& scale( T newScale ) { - m_scale = double(newScale); + Approx& scale( T const& newScale ) { + m_scale = static_cast(newScale); return *this; } From 5ebbec7dabf4ed7bef108d6d01cc29b4b096c99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 27 Jul 2017 10:46:18 +0200 Subject: [PATCH 166/398] Move all stringref function bodies out of line --- include/internal/catch_stringref.cpp | 12 ++++++++++++ include/internal/catch_stringref.h | 12 +++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 7cf75a75..9572c56f 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -124,6 +124,18 @@ namespace Catch { auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { return !operator==( other ); } + + auto StringRef::operator[](size_type index) const noexcept -> char { + return m_start[index]; + } + + auto StringRef::empty() const noexcept -> bool { + return m_size == 0; + } + + auto StringRef::size() const noexcept -> size_type { + return m_size; + } auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> String { StringBuilder buf; diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index dd223beb..d7f1efbe 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -51,17 +51,11 @@ namespace Catch { auto operator == ( StringRef const& other ) const noexcept -> bool; auto operator != ( StringRef const& other ) const noexcept -> bool; - auto operator[] ( size_type index ) const noexcept -> char { - return m_start[index]; - } + 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 empty() const noexcept -> bool; + auto size() const noexcept -> size_type; auto c_str() const -> char const*; public: // substrings and searches From 918eca5ee959cf9e61f9a136439bc9cd0ca42bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 27 Jul 2017 10:50:20 +0200 Subject: [PATCH 167/398] Improve single header generator --- scripts/generateSingleHeader.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index 3b6f722d..7e96a1a3 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -14,10 +14,10 @@ from releaseCommon import Version includesParser = re.compile( r'\s*#\s*include\s*"(.*)"' ) -guardParser = re.compile( r'\s*#.*TWOBLUECUBES_CATCH_.*_INCLUDED') -defineParser = re.compile( r'\s*#define') -ifParser = re.compile( r'\s*#ifndef TWOBLUECUBES_CATCH_.*_INCLUDED') -endIfParser = re.compile( r'\s*#endif // TWOBLUECUBES_CATCH_.*_INCLUDED') +guardParser = re.compile( r'\s*#.*(TWOBLUECUBES_)?CATCH_.*_INCLUDED') +defineParser = re.compile( r'\s*#define\s+(TWOBLUECUBES_)?CATCH_.*_INCLUDED') +ifParser = re.compile( r'\s*#ifndef (TWOBLUECUBES_)?CATCH_.*_INCLUDED') +endIfParser = re.compile( r'\s*#endif // (TWOBLUECUBES_)?CATCH_.*_INCLUDED') ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' ) commentParser1 = re.compile( r'^\s*/\*') commentParser2 = re.compile( r'^ \*') @@ -70,7 +70,7 @@ def parseFile( path, filename ): for line in f: if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line: insertCpps() - if ifParser.match( line ): + elif ifParser.match( line ): ifdefs = ifdefs + 1 elif endIfParser.match( line ): ifdefs = ifdefs - 1 @@ -99,8 +99,9 @@ def parseFile( path, filename ): blanks = blanks + 1 else: blanks = 0 - if blanks < 2: + if blanks < 2 and not defineParser.match(line): write( line.rstrip() + "\n" ) + write( '// end {}\n'.format(filename) ) v = Version() @@ -109,7 +110,7 @@ out.write( " * Catch v{0}\n".format( v.getVersionString() ) ) out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) ) out.write( " * ----------------------------------------------------------\n" ) out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" ) -out.write( " * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.\n" ) +out.write( " * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) ) out.write( " *\n" ) out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" ) out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" ) From 33fd54a673f723ca0dbb590047fe5bd6e6c1a297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 27 Jul 2017 11:55:30 +0200 Subject: [PATCH 168/398] Split Option and TagAlias definitions away from the main include path --- CMakeLists.txt | 2 ++ include/catch.hpp | 1 + .../catch_interfaces_tag_alias_registry.h | 8 ++++--- include/internal/catch_tag_alias.cpp | 5 +++++ include/internal/catch_tag_alias.h | 6 ----- .../catch_tag_alias_autoregistrar.cpp | 15 +++++++++++++ .../internal/catch_tag_alias_autoregistrar.h | 22 +++++++++++++++++++ include/internal/catch_tag_alias_registry.cpp | 6 ++--- include/internal/catch_tag_alias_registry.h | 3 ++- 9 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 include/internal/catch_tag_alias.cpp create mode 100644 include/internal/catch_tag_alias_autoregistrar.cpp create mode 100644 include/internal/catch_tag_alias_autoregistrar.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c56cca3..bc5280b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_string_manip.h ${HEADER_DIR}/internal/catch_suppress_warnings.h ${HEADER_DIR}/internal/catch_tag_alias.h + ${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h ${HEADER_DIR}/internal/catch_tag_alias_registry.h ${HEADER_DIR}/internal/catch_test_case_info.h ${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp @@ -223,6 +224,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_string_manip.cpp ${HEADER_DIR}/internal/catch_tag_alias.cpp + ${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.cpp ${HEADER_DIR}/internal/catch_tag_alias_registry.cpp ${HEADER_DIR}/internal/catch_test_case_info.cpp ${HEADER_DIR}/internal/catch_test_case_registry_impl.cpp diff --git a/include/catch.hpp b/include/catch.hpp index 920e17b0..32effe1e 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -29,6 +29,7 @@ #endif #include "internal/catch_context.h" +#include "internal/catch_tag_alias_autoregistrar.h" #include "internal/catch_test_registry.hpp" #include "internal/catch_capture.hpp" #include "internal/catch_section.h" diff --git a/include/internal/catch_interfaces_tag_alias_registry.h b/include/internal/catch_interfaces_tag_alias_registry.h index cd6ac51d..24bc535c 100644 --- a/include/internal/catch_interfaces_tag_alias_registry.h +++ b/include/internal/catch_interfaces_tag_alias_registry.h @@ -8,14 +8,16 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED -#include "catch_tag_alias.h" -#include "catch_option.hpp" +#include namespace Catch { + struct TagAlias; + struct ITagAliasRegistry { virtual ~ITagAliasRegistry(); - virtual Option find( std::string const& alias ) const = 0; + // Nullptr if not present + virtual TagAlias const* find( std::string const& alias ) const = 0; virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; static ITagAliasRegistry const& get(); diff --git a/include/internal/catch_tag_alias.cpp b/include/internal/catch_tag_alias.cpp new file mode 100644 index 00000000..2ea4540e --- /dev/null +++ b/include/internal/catch_tag_alias.cpp @@ -0,0 +1,5 @@ +#include "catch_tag_alias.h" + +namespace Catch { + TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} +} diff --git a/include/internal/catch_tag_alias.h b/include/internal/catch_tag_alias.h index 7dd6337f..a9e6eb37 100644 --- a/include/internal/catch_tag_alias.h +++ b/include/internal/catch_tag_alias.h @@ -21,12 +21,6 @@ namespace Catch { SourceLineInfo lineInfo; }; - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - } // end namespace Catch #endif // TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } diff --git a/include/internal/catch_tag_alias_autoregistrar.cpp b/include/internal/catch_tag_alias_autoregistrar.cpp new file mode 100644 index 00000000..a2f01cba --- /dev/null +++ b/include/internal/catch_tag_alias_autoregistrar.cpp @@ -0,0 +1,15 @@ +#include "catch_tag_alias_autoregistrar.h" +#include "catch_interfaces_registry_hub.h" + +namespace Catch { + + RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { + try { + getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(std::current_exception()); + } + } + +} diff --git a/include/internal/catch_tag_alias_autoregistrar.h b/include/internal/catch_tag_alias_autoregistrar.h new file mode 100644 index 00000000..e9b961e4 --- /dev/null +++ b/include/internal/catch_tag_alias_autoregistrar.h @@ -0,0 +1,22 @@ +/* + * Created by Martin on 27/07/2017. + * + * 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) + */ +#ifndef TWOBLUECUBES_CATCH_TAG_ALIAS_AUTOREGISTRAR_H_INCLUDED +#define TWOBLUECUBES_CATCH_TAG_ALIAS_AUTOREGISTRAR_H_INCLUDED + +#include "catch_common.h" + +namespace Catch { + + 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 ); } + +#endif // TWOBLUECUBES_CATCH_TAG_ALIAS_AUTOREGISTRAR_H_INCLUDED diff --git a/include/internal/catch_tag_alias_registry.cpp b/include/internal/catch_tag_alias_registry.cpp index 921740e0..3bf14c82 100644 --- a/include/internal/catch_tag_alias_registry.cpp +++ b/include/internal/catch_tag_alias_registry.cpp @@ -16,12 +16,12 @@ namespace Catch { TagAliasRegistry::~TagAliasRegistry() {} - Option TagAliasRegistry::find( std::string const& alias ) const { + TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { auto it = m_registry.find( alias ); if( it != m_registry.end() ) - return it->second; + return &(it->second); else - return Option(); + return nullptr; } std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { diff --git a/include/internal/catch_tag_alias_registry.h b/include/internal/catch_tag_alias_registry.h index d05c7739..d3bb8ffb 100644 --- a/include/internal/catch_tag_alias_registry.h +++ b/include/internal/catch_tag_alias_registry.h @@ -9,6 +9,7 @@ #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED #include "catch_interfaces_tag_alias_registry.h" +#include "catch_tag_alias.h" #include @@ -17,7 +18,7 @@ namespace Catch { class TagAliasRegistry : public ITagAliasRegistry { public: ~TagAliasRegistry() override; - Option find( std::string const& alias ) const override; + TagAlias const* find( std::string const& alias ) const override; std::string expandAliases( std::string const& unexpandedTestSpec ) const override; void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); From 307eeefa8f0cab5d31059a417f944b6126a19d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 27 Jul 2017 12:24:21 +0200 Subject: [PATCH 169/398] Change typedefs to using --- include/internal/catch_interfaces_exception.h | 5 ++--- include/internal/catch_test_case_tracker.hpp | 2 +- include/reporters/catch_reporter_multi.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index 32487ffa..43e4fbf4 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -14,11 +14,10 @@ #include "catch_interfaces_registry_hub.h" namespace Catch { - - typedef std::string(*exceptionTranslateFunction)(); + using exceptionTranslateFunction = std::string(*)(); struct IExceptionTranslator; - typedef std::vector> ExceptionTranslators; + using ExceptionTranslators = std::vector>; struct IExceptionTranslator { virtual ~IExceptionTranslator(); diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index df176084..c9738252 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -104,7 +104,7 @@ namespace TestCaseTracking { bool operator ()( ITrackerPtr const& tracker ) const; }; - typedef std::vector Children; + using Children = std::vector; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_multi.h index ce9bb87d..a69729ec 100644 --- a/include/reporters/catch_reporter_multi.h +++ b/include/reporters/catch_reporter_multi.h @@ -10,7 +10,7 @@ namespace Catch { class MultipleReporters : public IStreamingReporter { - typedef std::vector Reporters; + using Reporters = std::vector; Reporters m_reporters; public: From 446bad752f7b5c11aa4d0123ee48634ff8314bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 27 Jul 2017 12:24:52 +0200 Subject: [PATCH 170/398] Move std::exception_ptr out of interfaces --- include/internal/catch_interfaces_registry_hub.h | 2 +- include/internal/catch_registry_hub.cpp | 4 ++-- include/internal/catch_tag_alias_autoregistrar.cpp | 2 +- include/internal/catch_test_registry.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index f71178be..1afbbec7 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -46,7 +46,7 @@ namespace Catch { virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; - virtual void registerStartupException( std::exception_ptr const& exception ) noexcept = 0; + virtual void registerStartupException() noexcept = 0; }; IRegistryHub& getRegistryHub(); diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 01208e77..454b5e06 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -56,8 +56,8 @@ namespace Catch { void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { m_tagAliasRegistry.add( alias, tag, lineInfo ); } - void registerStartupException( std::exception_ptr const& exception ) noexcept override { - m_exceptionRegistry.add(exception); + void registerStartupException() noexcept override { + m_exceptionRegistry.add(std::current_exception()); } private: diff --git a/include/internal/catch_tag_alias_autoregistrar.cpp b/include/internal/catch_tag_alias_autoregistrar.cpp index a2f01cba..35ed059f 100644 --- a/include/internal/catch_tag_alias_autoregistrar.cpp +++ b/include/internal/catch_tag_alias_autoregistrar.cpp @@ -8,7 +8,7 @@ namespace Catch { getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); } catch (...) { // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException(std::current_exception()); + getMutableRegistryHub().registerStartupException(); } } diff --git a/include/internal/catch_test_registry.cpp b/include/internal/catch_test_registry.cpp index 28517628..2862879c 100644 --- a/include/internal/catch_test_registry.cpp +++ b/include/internal/catch_test_registry.cpp @@ -29,7 +29,7 @@ namespace Catch { lineInfo)); } catch (...) { // Do not throw when constructing global objects, instead register the exception to be processed later - getMutableRegistryHub().registerStartupException( std::current_exception() ); + getMutableRegistryHub().registerStartupException(); } } } From 287cc92b2ce605fd4ca7809667581d820f448330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 27 Jul 2017 22:31:27 +0200 Subject: [PATCH 171/398] Remove include from the common test path --- include/catch_session.hpp | 4 +-- include/internal/catch_list.cpp | 2 +- include/internal/catch_list.h | 2 ++ include/internal/catch_test_case_info.cpp | 40 +++++++++++++++------- include/internal/catch_test_case_info.h | 13 +++---- include/internal/catch_test_spec.cpp | 5 ++- include/reporters/catch_reporter_junit.cpp | 16 +++++---- include/reporters/catch_reporter_xml.cpp | 2 +- 8 files changed, 54 insertions(+), 30 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index f95de1c5..7bbd34b2 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -78,7 +78,7 @@ namespace Catch { void applyFilenamesAsTags( IConfig const& config ) { auto& tests = const_cast&>( getAllTestCasesSorted( config ) ); for( auto& testCase : tests ) { - std::set tags = testCase.tags; + auto tags = testCase.tags; std::string filename = testCase.lineInfo.file; std::string::size_type lastSlash = filename.find_last_of( "\\/" ); @@ -89,7 +89,7 @@ namespace Catch { if( lastDot != std::string::npos ) filename = filename.substr( 0, lastDot ); - tags.insert( "#" + filename ); + tags.push_back( "#" + filename ); setTags( testCase, tags ); } } diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index 36cd0545..fa1b8793 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -50,7 +50,7 @@ namespace Catch { Catch::cout() << Column( description ).indent(4) << std::endl; } if( !testCaseInfo.tags.empty() ) - Catch::cout() << Column( testCaseInfo.tagsAsString ).indent( 6 ) << "\n"; + Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; } if( !config.testSpec().hasFilters() ) diff --git a/include/internal/catch_list.h b/include/internal/catch_list.h index daf158d0..4bc96ec5 100644 --- a/include/internal/catch_list.h +++ b/include/internal/catch_list.h @@ -11,6 +11,8 @@ #include "catch_option.hpp" #include "catch_config.hpp" +#include + namespace Catch { std::size_t listTests( Config const& config ); diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 6f6b141d..4a392da6 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -13,6 +13,7 @@ #include #include +#include namespace Catch { @@ -51,7 +52,7 @@ namespace Catch { bool isHidden( startsWith( _name, "./" ) ); // Legacy support // Parse out tags - std::set tags; + std::vector tags; std::string desc, tag; bool inTag = false; for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { @@ -70,7 +71,7 @@ namespace Catch { else if( prop == TestCaseInfo::None ) enforceNotReservedTag( tag, _lineInfo ); - tags.insert( tag ); + tags.push_back( tag ); tag.clear(); inTag = false; } @@ -79,33 +80,31 @@ namespace Catch { } } if( isHidden ) { - tags.insert( "hide" ); - tags.insert( "." ); + tags.push_back( "hide" ); + tags.push_back( "." ); } TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); return TestCase( _testCase, info ); } - void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) - { - testCaseInfo.tags = tags; + void setTags( TestCaseInfo& testCaseInfo, std::vector tags ) { + std::sort(begin(tags), end(tags)); + tags.erase(std::unique(begin(tags), end(tags)), end(tags)); testCaseInfo.lcaseTags.clear(); - std::ostringstream oss; for( auto const& tag : tags ) { - oss << '[' << tag << ']'; std::string lcaseTag = toLower( tag ); testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); - testCaseInfo.lcaseTags.insert( lcaseTag ); + testCaseInfo.lcaseTags.push_back( lcaseTag ); } - testCaseInfo.tagsAsString = oss.str(); + testCaseInfo.tags = std::move(tags); } TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, - std::set const& _tags, + std::vector const& _tags, SourceLineInfo const& _lineInfo ) : name( _name ), className( _className ), @@ -129,6 +128,23 @@ namespace Catch { return ( properties & (ShouldFail ) ) != 0; } + std::string TestCaseInfo::tagsAsString() const { + std::string ret; + // '[' and ']' per tag + size_t full_size = 2 * tags.size(); + for (const auto& tag : tags) { + full_size += tag.size(); + } + ret.reserve(full_size); + for (const auto& tag : tags) { + ret.push_back('['); + ret.append(tag); + ret.push_back(']'); + } + + return ret; + } + TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index ebb1f406..44b9fa38 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -9,7 +9,7 @@ #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED #include -#include +#include #include #ifdef __clang__ @@ -34,22 +34,23 @@ namespace Catch { TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, - std::set const& _tags, + std::vector const& _tags, SourceLineInfo const& _lineInfo ); - friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + friend void setTags( TestCaseInfo& testCaseInfo, std::vector tags ); bool isHidden() const; bool throws() const; bool okToFail() const; bool expectedToFail() const; + std::string tagsAsString() const; + std::string name; std::string className; std::string description; - std::set tags; - std::set lcaseTags; - std::string tagsAsString; + std::vector tags; + std::vector lcaseTags; SourceLineInfo lineInfo; SpecialProperties properties; }; diff --git a/include/internal/catch_test_spec.cpp b/include/internal/catch_test_spec.cpp index 0809fc5b..c7f64f30 100644 --- a/include/internal/catch_test_spec.cpp +++ b/include/internal/catch_test_spec.cpp @@ -8,6 +8,7 @@ #include "catch_test_spec.hpp" #include "catch_string_manip.h" +#include #include #include #include @@ -23,7 +24,9 @@ namespace Catch { TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { - return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + return std::find(begin(testCase.lcaseTags), + end(testCase.lcaseTags), + m_tag) != end(testCase.lcaseTags); } TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp index 1235281a..ae3ea384 100644 --- a/include/reporters/catch_reporter_junit.cpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -16,6 +16,7 @@ #include #include +#include namespace Catch { @@ -46,6 +47,14 @@ namespace Catch { return std::string(timeStamp); } + std::string fileNameTag(const std::vector &tags) { + auto it = std::find_if(begin(tags), + end(tags), + [] (std::string const& tag) {return tag.front() == '#'; }); + if (it != tags.end()) + return it->substr(1); + return std::string(); + } } class JunitReporter : public CumulativeReporterBase { @@ -125,13 +134,6 @@ namespace Catch { xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); } - static std::string fileNameTag( const std::set &tags ) { - std::set::const_iterator it = tags.lower_bound("#"); - if( it != tags.end() && !it->empty() && it->front() == '#' ) - return it->substr(1); - return std::string(); - } - void writeTestCase( TestCaseNode const& testCaseNode ) { TestCaseStats const& stats = testCaseNode.value; diff --git a/include/reporters/catch_reporter_xml.cpp b/include/reporters/catch_reporter_xml.cpp index 9e2ed08b..128899a9 100644 --- a/include/reporters/catch_reporter_xml.cpp +++ b/include/reporters/catch_reporter_xml.cpp @@ -66,7 +66,7 @@ namespace Catch { m_xml.startElement( "TestCase" ) .writeAttribute( "name", trim( testInfo.name ) ) .writeAttribute( "description", testInfo.description ) - .writeAttribute( "tags", testInfo.tagsAsString ); + .writeAttribute( "tags", testInfo.tagsAsString() ); writeSourceInfo( testInfo.lineInfo ); From d01fe03ba630b5f7be7cfd52dc91cf4a8a20532e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 28 Jul 2017 15:11:05 +0200 Subject: [PATCH 172/398] Removed include from the main path --- include/internal/catch_matchers_vector.h | 22 +++++++++++++++++----- projects/SelfTest/MiscTests.cpp | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index b176d4a3..4bf39d70 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -10,8 +10,6 @@ #include "catch_matchers.hpp" -#include - namespace Catch { namespace Matchers { @@ -23,7 +21,12 @@ namespace Matchers { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} bool match(std::vector const &v) const override { - return std::find(v.begin(), v.end(), m_comparator) != v.end(); + for (auto const& el : v) { + if (el == m_comparator) { + return true; + } + } + return false; } std::string describe() const override { @@ -42,9 +45,18 @@ namespace Matchers { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; - for ( auto const& comparator : m_comparator ) - if (std::find(v.begin(), v.end(), comparator) == v.end()) + for (auto const& comparator : m_comparator) { + auto present = false; + for (const auto& el : v) { + if (el == comparator) { + present = true; + break; + } + } + if (!present) { return false; + } + } return true; } std::string describe() const override { diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 5b3e9ed7..c8a7b302 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -17,6 +17,7 @@ #include #include +#include TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) { int a = 1; From 35c1301bd58222eace4afe61b666b580a0814d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 28 Jul 2017 21:04:18 +0200 Subject: [PATCH 173/398] Fix missing CATCH_ prefixed macros --- include/catch.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 32effe1e..a58fdb1c 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -77,7 +77,8 @@ #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) @@ -88,7 +89,8 @@ #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) From 0ca4cfb7432d37dbca4164c274a6b4f6e37d2dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 28 Jul 2017 21:34:34 +0200 Subject: [PATCH 174/398] Introduce compile time toggle to remove Matchers from TU The toggle is `CATCH_CONFIG_DISABLE_MATCHERS` and the only use is to speed up compilation of small TUs. For large ones it is likely insignificant, because the speed up is constant relative to number of tests/assertions in TU. --- docs/configuration.md | 8 ++++++++ include/catch.hpp | 18 ++++++++++++++---- include/internal/catch_capture.hpp | 7 ++++--- include/internal/catch_matchers.cpp | 4 ++++ include/internal/catch_matchers.hpp | 4 ++++ include/internal/catch_matchers_string.cpp | 4 ++++ include/internal/catch_matchers_string.h | 4 ++++ include/internal/catch_matchers_vector.h | 5 +++++ include/internal/catch_objc.hpp | 4 ++++ include/internal/catch_result_builder.cpp | 4 ++-- include/internal/catch_result_builder.h | 2 ++ 11 files changed, 55 insertions(+), 9 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 48250b62..b7855383 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -57,6 +57,7 @@ This can be useful on certain platforms that do not provide ```std::cout``` and CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows CATCH_CONFIG_FAST_COMPILE // Sacrifices some (rather minor) features for compilation speed + CATCH_CONFIG_DISABLE_MATCHERS // Do not compile Matchers in this compilation unit CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap @@ -75,6 +76,13 @@ Defining this flag speeds up compilation of test files by ~20%, by making 2 chan `CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable. + +## `CATCH_CONFIG_DISABLE_MATCHERS` +When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU. + +_Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._ + + # Windows header clutter On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros: diff --git a/include/catch.hpp b/include/catch.hpp index a58fdb1c..ead6c337 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -63,7 +63,6 @@ #endif ////// - // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL @@ -77,8 +76,10 @@ #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif// CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) @@ -89,10 +90,13 @@ #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) @@ -100,7 +104,7 @@ #else #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #endif - +#endif // CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) @@ -144,8 +148,10 @@ #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) @@ -156,18 +162,22 @@ #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #else #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif - +#endif // CATCH_CONFIG_FAST_COMPILE +#endif // CATCH_CONFIG_DISABLE_MATCHERS #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 1c862505..fa6952e4 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -42,7 +42,7 @@ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. - +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ @@ -51,7 +51,7 @@ __catchResult.unsetExceptionGuard(); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) - +#endif // CATCH_CONFIG_DISABLE_MATCHERS #else /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked @@ -155,6 +155,7 @@ #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ @@ -204,7 +205,7 @@ __catchResult.captureResult( Catch::ResultWas::Ok ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) - +#endif // CATCH_CONFIG_DISABLE_MATCHERS #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED diff --git a/include/internal/catch_matchers.cpp b/include/internal/catch_matchers.cpp index 38ae8c77..a2620bc5 100644 --- a/include/internal/catch_matchers.cpp +++ b/include/internal/catch_matchers.cpp @@ -5,6 +5,8 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) + #include "catch_matchers.hpp" namespace Catch { @@ -24,3 +26,5 @@ using namespace Matchers; using Matchers::Impl::MatcherBase; } // namespace Catch + +#endif // CATCH_CONFIG_DISABLE_MATCHERS \ No newline at end of file diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 4f41cb01..37787a9c 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) + #include "catch_common.h" #include @@ -179,4 +181,6 @@ using Matchers::Impl::MatcherBase; } // namespace Catch +#endif // CATCH_CONFIG_DISABLE_MATCHERS + #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED diff --git a/include/internal/catch_matchers_string.cpp b/include/internal/catch_matchers_string.cpp index 2f8ffdb8..54f44d6d 100644 --- a/include/internal/catch_matchers_string.cpp +++ b/include/internal/catch_matchers_string.cpp @@ -6,6 +6,8 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) + #include "catch_matchers_string.h" #include "catch_string_manip.h" @@ -92,3 +94,5 @@ namespace Matchers { } // namespace Matchers } // namespace Catch + +#endif // CATCH_CONFIG_DISABLE_MATCHERS diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index eca35789..ab3f1c44 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) + #include "catch_matchers.hpp" #include @@ -66,4 +68,6 @@ namespace Matchers { } // namespace Matchers } // namespace Catch +#endif // CATCH_CONFIG_DISABLE_MATCHERS + #endif // TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 4bf39d70..de1c52b2 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -8,6 +8,9 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) + + #include "catch_matchers.hpp" namespace Catch { @@ -112,4 +115,6 @@ namespace Matchers { } // namespace Matchers } // namespace Catch +#endif // CATCH_CONFIG_DISABLE_MATCHERS + #endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 350dc72c..2a8ec2f9 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -101,6 +101,8 @@ namespace Catch { return noTestMethods; } +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) + namespace Matchers { namespace Impl { namespace NSStringMatchers { @@ -189,6 +191,8 @@ namespace Catch { using namespace Matchers; +#endif // CATCH_CONFIG_DISABLE_MATCHERS + } // namespace Catch /////////////////////////////////////////////////////////////////////////////// diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index a1fed54e..cf0b1b16 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -72,7 +72,7 @@ namespace Catch { setResultType( resultType ); captureExpression(); } - +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { if( expectedMessage.empty() ) captureExpectedException( Matchers::Impl::MatchAllOf() ); @@ -96,7 +96,7 @@ namespace Catch { AssertionResult result( m_assertionInfo, data ); handleResult( result ); } - +#endif // CATCH_CONFIG_DISABLE_MATCHERS void ResultBuilder::captureExpression() { AssertionResult result = build(); handleResult( result ); diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 45bc8920..2b5dd145 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -58,8 +58,10 @@ namespace Catch { void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) void captureExpectedException( std::string const& expectedMessage ); void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); +#endif // CATCH_CONFIG_DISABLE_MATCHERS void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; From d08e31d89e8f117732af07b501c8718c867f8342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 29 Jul 2017 08:43:32 +0200 Subject: [PATCH 175/398] Fix inverted CATCH_CONFIG_DISABLE_MATCHERS toggle --- include/catch.hpp | 12 ++++++------ include/internal/catch_capture.hpp | 4 ++-- include/internal/catch_matchers.cpp | 2 +- include/internal/catch_matchers.hpp | 2 +- include/internal/catch_matchers_string.cpp | 2 +- include/internal/catch_matchers_string.h | 2 +- include/internal/catch_matchers_vector.h | 2 +- include/internal/catch_objc.hpp | 2 +- include/internal/catch_result_builder.cpp | 2 +- include/internal/catch_result_builder.h | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index ead6c337..0acd25da 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -76,7 +76,7 @@ #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #endif// CATCH_CONFIG_DISABLE_MATCHERS @@ -90,13 +90,13 @@ #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #endif // CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) @@ -148,7 +148,7 @@ #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #endif // CATCH_CONFIG_DISABLE_MATCHERS @@ -162,14 +162,14 @@ #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #endif // CATCH_CONFIG_DISABLE_MATCHERS #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index fa6952e4..574361d0 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -42,7 +42,7 @@ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ @@ -155,7 +155,7 @@ #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ diff --git a/include/internal/catch_matchers.cpp b/include/internal/catch_matchers.cpp index a2620bc5..76d0332c 100644 --- a/include/internal/catch_matchers.cpp +++ b/include/internal/catch_matchers.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #include "catch_matchers.hpp" diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 37787a9c..12aa0d7b 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #include "catch_common.h" diff --git a/include/internal/catch_matchers_string.cpp b/include/internal/catch_matchers_string.cpp index 54f44d6d..2f899e8d 100644 --- a/include/internal/catch_matchers_string.cpp +++ b/include/internal/catch_matchers_string.cpp @@ -6,7 +6,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #include "catch_matchers_string.h" #include "catch_string_manip.h" diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index ab3f1c44..27e5b4cc 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #include "catch_matchers.hpp" diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index de1c52b2..a2f5cb6c 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #include "catch_matchers.hpp" diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 2a8ec2f9..188f5577 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -101,7 +101,7 @@ namespace Catch { return noTestMethods; } -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) namespace Matchers { namespace Impl { diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index cf0b1b16..6268f8d1 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -72,7 +72,7 @@ namespace Catch { setResultType( resultType ); captureExpression(); } -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { if( expectedMessage.empty() ) captureExpectedException( Matchers::Impl::MatchAllOf() ); diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 2b5dd145..9ea6d038 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -58,7 +58,7 @@ namespace Catch { void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); -#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) void captureExpectedException( std::string const& expectedMessage ); void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); #endif // CATCH_CONFIG_DISABLE_MATCHERS From d118ce191d0f92a8f11202851f82ba788ca5c32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 29 Jul 2017 08:44:40 +0200 Subject: [PATCH 176/398] Disable build broken by travis changes It should be reenabled at some point, but I don't have the time ATM --- .travis.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5036d053..bc196146 100644 --- a/.travis.yml +++ b/.travis.yml @@ -150,16 +150,16 @@ matrix: addons: *gcc6 env: COMPILER='g++-6' BUILD_TYPE='Debug' CPP14=1 - # 4b/ Linux C++14 Clang builds - - os: linux - compiler: clang - addons: *clang38 - env: COMPILER='clang++-3.8' BUILD_TYPE='Release' CPP14=1 - - - os: linux - compiler: clang - addons: *clang38 - env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' CPP14=1 +# # 4b/ Linux C++14 Clang builds +# - os: linux +# compiler: clang +# addons: *clang38 +# env: COMPILER='clang++-3.8' BUILD_TYPE='Release' CPP14=1 +# +# - os: linux +# compiler: clang +# addons: *clang38 +# env: COMPILER='clang++-3.8' BUILD_TYPE='Debug' CPP14=1 # 5/ OSX Clang Builds From 0a3f899d6a63ae01bdc33c6a7c2d2eb8086db702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 31 Jul 2017 08:35:27 +0200 Subject: [PATCH 177/398] Move windows.h reduction logic into windows.h proxy header Fixes #965 (at least the primary problem, the separate warnings can be taken care of later) --- include/internal/catch_platform.h | 6 ------ include/internal/catch_windows_h_proxy.h | 20 +++++++++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/internal/catch_platform.h b/include/internal/catch_platform.h index 87250c60..90cf0eb7 100644 --- a/include/internal/catch_platform.h +++ b/include/internal/catch_platform.h @@ -22,12 +22,6 @@ #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) # define CATCH_PLATFORM_WINDOWS -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINES_NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# endif #endif #endif // TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED diff --git a/include/internal/catch_windows_h_proxy.h b/include/internal/catch_windows_h_proxy.h index 4f059b4a..bbb1ee82 100644 --- a/include/internal/catch_windows_h_proxy.h +++ b/include/internal/catch_windows_h_proxy.h @@ -8,11 +8,17 @@ #ifndef TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED -#ifdef CATCH_DEFINES_NOMINMAX -# define NOMINMAX -#endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN +#include "catch_platform.h" + +#if defined(CATCH_PLATFORM_WINDOWS) +# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +# endif +# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif #endif #ifdef __AFXDLL @@ -21,10 +27,10 @@ #include #endif -#ifdef CATCH_DEFINES_NOMINMAX +#ifdef CATCH_DEFINED_NOMINMAX # undef NOMINMAX #endif -#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN # undef WIN32_LEAN_AND_MEAN #endif From d4e796c1382b850d020ff197bfc0ca82c70d05e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 1 Aug 2017 17:51:32 +0200 Subject: [PATCH 178/398] Move Section(End)Info bodies to proper .cpp file --- CMakeLists.txt | 1 + include/internal/catch_section.cpp | 9 --------- include/internal/catch_section_info.cpp | 25 +++++++++++++++++++++++++ include/internal/catch_section_info.h | 4 +--- 4 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 include/internal/catch_section_info.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bc5280b9..6af88fdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,6 +217,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_run_context.cpp ${HEADER_DIR}/internal/catch_section.cpp + ${HEADER_DIR}/internal/catch_section_info.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp ${HEADER_DIR}/internal/catch_string.cpp ${HEADER_DIR}/internal/catch_stringbuilder.cpp diff --git a/include/internal/catch_section.cpp b/include/internal/catch_section.cpp index 8c300415..4f192446 100644 --- a/include/internal/catch_section.cpp +++ b/include/internal/catch_section.cpp @@ -12,15 +12,6 @@ namespace Catch { - SectionInfo::SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description ) - : name( _name ), - description( _description ), - lineInfo( _lineInfo ) - {} - Section::Section( SectionInfo const& info ) : m_info( info ), m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) diff --git a/include/internal/catch_section_info.cpp b/include/internal/catch_section_info.cpp new file mode 100644 index 00000000..e2846b8a --- /dev/null +++ b/include/internal/catch_section_info.cpp @@ -0,0 +1,25 @@ +/* + * Created by Martin on 01/08/2017. + * + * 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) + */ + +#include "catch_section_info.h" + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + +} // end namespace Catch diff --git a/include/internal/catch_section_info.h b/include/internal/catch_section_info.h index c9f1c7f1..a10b2b77 100644 --- a/include/internal/catch_section_info.h +++ b/include/internal/catch_section_info.h @@ -27,9 +27,7 @@ namespace Catch { }; struct SectionEndInfo { - SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) - : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ); SectionInfo sectionInfo; Counts prevAssertions; From c815ad1d534e630fbb6f7f30ffe5322ccbe6d9be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 1 Aug 2017 17:52:02 +0200 Subject: [PATCH 179/398] Fix fwd declaration of IConfig in catch_test_case_registry_impl.hpp --- include/internal/catch_test_case_registry_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 27b64eb8..956b3dbf 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -20,7 +20,7 @@ namespace Catch { class TestCase; - class IConfig; + struct IConfig; struct RandomNumberGenerator { using result_type = std::ptrdiff_t; From feca97dfde802825222b1ac8eb715ba636b42586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 1 Aug 2017 18:46:33 +0200 Subject: [PATCH 180/398] Split out internal error macros from the common path --- CMakeLists.txt | 1 + include/catch_session.hpp | 1 + include/internal/catch_common.cpp | 1 + include/internal/catch_common.h | 13 +++------- include/internal/catch_config.cpp | 1 + include/internal/catch_console_colour.cpp | 1 + include/internal/catch_enforce.h | 24 +++++++++++++++++++ include/internal/catch_matchers.hpp | 1 + include/internal/catch_message.h | 1 + .../internal/catch_notimplemented_exception.h | 2 ++ include/internal/catch_result_builder.h | 2 ++ include/internal/catch_run_context.cpp | 1 + include/internal/catch_stream.hpp | 1 + include/internal/catch_tag_alias_registry.cpp | 1 + include/internal/catch_test_case_info.cpp | 3 ++- include/internal/catch_test_case_info.h | 2 ++ .../catch_test_case_registry_impl.cpp | 1 + .../catch_test_case_registry_impl.hpp | 2 +- include/internal/catch_test_case_tracker.cpp | 2 ++ include/internal/catch_wildcard_pattern.cpp | 1 + include/reporters/catch_reporter_bases.hpp | 2 ++ 21 files changed, 52 insertions(+), 12 deletions(-) create mode 100644 include/internal/catch_enforce.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6af88fdd..715ac0ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_context.h ${HEADER_DIR}/internal/catch_debugger.h ${HEADER_DIR}/internal/catch_default_main.hpp + ${HEADER_DIR}/internal/catch_enforce.h ${HEADER_DIR}/internal/catch_errno_guard.h ${HEADER_DIR}/internal/catch_evaluate.hpp ${HEADER_DIR}/internal/catch_exception_translator_registry.h diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 7bbd34b2..93c75cf3 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -10,6 +10,7 @@ #include "internal/catch_commandline.hpp" #include "internal/catch_console_colour.hpp" +#include "internal/catch_enforce.h" #include "internal/catch_list.h" #include "internal/catch_run_context.hpp" #include "internal/catch_test_spec.hpp" diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp index d865cd52..753b9487 100644 --- a/include/internal/catch_common.cpp +++ b/include/internal/catch_common.cpp @@ -11,6 +11,7 @@ #include "catch_interfaces_config.h" #include +#include namespace Catch { diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 5c5de452..c62fafe2 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -21,8 +21,9 @@ #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) -#include -#include +#include +#include +#include namespace Catch { @@ -87,14 +88,6 @@ namespace Catch { #define CATCH_INTERNAL_LINEINFO \ ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) -#define CATCH_PREPARE_EXCEPTION( type, msg ) \ - type( static_cast( std::ostringstream() << msg ).str() ) -#define CATCH_INTERNAL_ERROR( msg ) \ - throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); -#define CATCH_ERROR( msg ) \ - throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) -#define CATCH_ENFORCE( condition, msg ) \ - do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED diff --git a/include/internal/catch_config.cpp b/include/internal/catch_config.cpp index dd3bbdc6..ae1e95dd 100644 --- a/include/internal/catch_config.cpp +++ b/include/internal/catch_config.cpp @@ -6,6 +6,7 @@ */ #include "catch_config.hpp" +#include "catch_enforce.h" namespace Catch { diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index 1f382030..a444b076 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -7,6 +7,7 @@ */ #include "catch_console_colour.hpp" +#include "catch_enforce.h" #include "catch_errno_guard.h" #include "catch_interfaces_config.h" #include "catch_stream.h" diff --git a/include/internal/catch_enforce.h b/include/internal/catch_enforce.h new file mode 100644 index 00000000..b500949d --- /dev/null +++ b/include/internal/catch_enforce.h @@ -0,0 +1,24 @@ +/* + * Created by Martin on 01/08/2017. + * + * 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) + */ +#ifndef TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED +#define TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED + +#include "catch_common.h" + +#include +#include + +#define CATCH_PREPARE_EXCEPTION( type, msg ) \ + type( static_cast( std::ostringstream() << msg ).str() ) +#define CATCH_INTERNAL_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); +#define CATCH_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) +#define CATCH_ENFORCE( condition, msg ) \ + do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) + +#endif // TWOBLUECUBES_CATCH_ENFORCE_H_INCLUDED diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 12aa0d7b..c120bbf3 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -12,6 +12,7 @@ #include "catch_common.h" +#include #include namespace Catch { diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h index e2cc65aa..2550fb41 100644 --- a/include/internal/catch_message.h +++ b/include/internal/catch_message.h @@ -9,6 +9,7 @@ #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED #include +#include #include "catch_result_type.h" #include "catch_common.h" diff --git a/include/internal/catch_notimplemented_exception.h b/include/internal/catch_notimplemented_exception.h index 640cc167..4769c57d 100644 --- a/include/internal/catch_notimplemented_exception.h +++ b/include/internal/catch_notimplemented_exception.h @@ -10,6 +10,8 @@ #include "catch_common.h" +#include + namespace Catch { class NotImplementedException : public std::exception diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 9ea6d038..90cbf5be 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -13,6 +13,8 @@ #include "catch_common.h" #include "catch_matchers.hpp" +#include + namespace Catch { struct TestFailureException{}; diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 68f824fa..31d6b8a6 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -1,4 +1,5 @@ #include "catch_run_context.hpp" +#include "catch_enforce.h" #include #include diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index 89f6cdea..3b7bbe60 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -10,6 +10,7 @@ #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED #include "catch_common.h" +#include "catch_enforce.h" #include "catch_stream.h" #include "catch_debugger.h" diff --git a/include/internal/catch_tag_alias_registry.cpp b/include/internal/catch_tag_alias_registry.cpp index 3bf14c82..f100ea9d 100644 --- a/include/internal/catch_tag_alias_registry.cpp +++ b/include/internal/catch_tag_alias_registry.cpp @@ -8,6 +8,7 @@ #include "catch_tag_alias_registry.h" #include "catch_console_colour.hpp" +#include "catch_enforce.h" #include "catch_interfaces_registry_hub.h" #include "catch_stream.h" #include "catch_string_manip.h" diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 4a392da6..5a8d8c0f 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -6,8 +6,9 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_test_spec.hpp" #include "catch_test_case_info.h" +#include "catch_enforce.h" +#include "catch_test_spec.hpp" #include "catch_interfaces_testcase.h" #include "catch_string_manip.h" diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index 44b9fa38..626f95cb 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED +#include "catch_common.h" + #include #include #include diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp index d7cab1d8..0bf0000f 100644 --- a/include/internal/catch_test_case_registry_impl.cpp +++ b/include/internal/catch_test_case_registry_impl.cpp @@ -8,6 +8,7 @@ #include "catch_test_case_registry_impl.hpp" #include "catch_context.h" +#include "catch_enforce.h" #include "catch_interfaces_registry_hub.h" #include "catch_string_manip.h" #include "catch_test_case_info.h" diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 956b3dbf..ee412d9e 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -15,7 +15,7 @@ #include #include #include - +#include namespace Catch { diff --git a/include/internal/catch_test_case_tracker.cpp b/include/internal/catch_test_case_tracker.cpp index 2616afe4..6960c75f 100644 --- a/include/internal/catch_test_case_tracker.cpp +++ b/include/internal/catch_test_case_tracker.cpp @@ -7,6 +7,8 @@ #include "catch_test_case_tracker.hpp" +#include "catch_enforce.h" + #include #include #include diff --git a/include/internal/catch_wildcard_pattern.cpp b/include/internal/catch_wildcard_pattern.cpp index f33035dd..106e49b4 100644 --- a/include/internal/catch_wildcard_pattern.cpp +++ b/include/internal/catch_wildcard_pattern.cpp @@ -6,6 +6,7 @@ */ #include "catch_wildcard_pattern.hpp" +#include "catch_enforce.h" #include "catch_string_manip.h" diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 6fd40243..6d627839 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -8,8 +8,10 @@ #ifndef TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED +#include "../internal/catch_enforce.h" #include "../internal/catch_interfaces_reporter.h" + #include #include #include From 85e14c5fb53a413dff7cba1bb196b6e619ee1d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 1 Aug 2017 21:58:09 +0200 Subject: [PATCH 181/398] Move some compile-time dispatch to runtime The runtime performance is likely to be negligible, but compile times need every improvement they can get. --- CMakeLists.txt | 1 + include/internal/catch_evaluate.cpp | 38 +++++++++++++++++++++++ include/internal/catch_evaluate.hpp | 12 ++----- include/internal/catch_expression_lhs.hpp | 2 +- 4 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 include/internal/catch_evaluate.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 715ac0ae..05cc5c8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,6 +204,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_context.cpp ${HEADER_DIR}/internal/catch_debugger.cpp ${HEADER_DIR}/internal/catch_errno_guard.cpp + ${HEADER_DIR}/internal/catch_evaluate.cpp ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp ${HEADER_DIR}/internal/catch_fatal_condition.cpp ${HEADER_DIR}/internal/catch_list.cpp diff --git a/include/internal/catch_evaluate.cpp b/include/internal/catch_evaluate.cpp new file mode 100644 index 00000000..349f71e7 --- /dev/null +++ b/include/internal/catch_evaluate.cpp @@ -0,0 +1,38 @@ +/* + * Created by Martin on 01/08/2017. + * + * 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) + */ + +#include "catch_evaluate.hpp" + +#include "catch_enforce.h" + +namespace Catch { +namespace Internal { + + const char* operatorName(Operator op) { + switch (op) { + case IsEqualTo: + return "=="; + case IsNotEqualTo: + return "!="; + case IsLessThan: + return "<"; + case IsGreaterThan: + return ">"; + case IsLessThanOrEqualTo: + return "<="; + case IsGreaterThanOrEqualTo: + return ">="; + default: + CATCH_ERROR("Attempting to translate unknown operator!"); + } + } + + // nullptr_t support based on pull request #154 from Konstantin Baumann + std::nullptr_t opCast(std::nullptr_t) { return nullptr; } + +} // end of namespace Internal +} // end of namespace Catch diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 1ee53d74..730032fd 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -28,19 +28,11 @@ namespace Internal { IsGreaterThanOrEqualTo }; - template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; - template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; - template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; - template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + const char* operatorName(Operator op); template T& opCast(T const& t) { return const_cast(t); } - - // nullptr_t support based on pull request #154 from Konstantin Baumann - inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } + std::nullptr_t opCast(std::nullptr_t); // So the compare overloads can be operator agnostic we convey the operator as a template diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 67db9d65..192f001a 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -134,7 +134,7 @@ public: // 1 for negation (conditionally added later) dest = lhs; dest += delim; - dest += Internal::OperatorTraits::getName(); + dest += Internal::operatorName(Op); dest += delim; dest += rhs; } From 6d4673505dee65a7c109153b21c458f17198ffa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 1 Aug 2017 22:02:00 +0200 Subject: [PATCH 182/398] Add missing include in catch_approx.hpp --- include/internal/catch_approx.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index 9d6cb9f8..590c8f5b 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -10,6 +10,7 @@ #include "catch_tostring.h" +#include #include #include From 249bf116e8e384889bced2c675ba118a165647b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 1 Aug 2017 22:09:32 +0200 Subject: [PATCH 183/398] Route all T* comparisons through const void* comparisons This should stop the evaluate machinery from instantiating all the templates for every ptr type that is compared, instead generating it for single one. --- include/internal/catch_evaluate.hpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 730032fd..9d9da64c 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -91,6 +91,11 @@ namespace Internal { return Evaluator::evaluate( lhs, rhs ); } + template + bool compare( void const* lhs, void const* rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + // unsigned X to int template bool compare( unsigned int lhs, int rhs ) { return applyEvaluator( lhs, static_cast( rhs ) ); @@ -137,18 +142,18 @@ namespace Internal { // pointer to long (when comparing against NULL) template bool compare( long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); } template bool compare( T* lhs, long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } // pointer to int (when comparing against NULL) template bool compare( int lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); } template bool compare( T* lhs, int rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } // long long to unsigned X @@ -181,18 +186,18 @@ namespace Internal { // pointer to long long (when comparing against NULL) template bool compare( long long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); } template bool compare( T* lhs, long long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( nullptr, rhs ); + return Evaluator::evaluate( nullptr, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, nullptr ); + return Evaluator::evaluate( lhs, nullptr ); } } // end of namespace Internal From cde987a92ee6f299462e5fb11fc35f4587e047c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 1 Aug 2017 22:20:14 +0200 Subject: [PATCH 184/398] Note start of .cpp files in single header --- scripts/generateSingleHeader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index 7e96a1a3..acc1720d 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -67,6 +67,7 @@ def parseFile( path, filename ): f = open( os.path.join(path, filename), 'r' ) blanks = 0 + write( "// start {0}\n".format( filename ) ) for line in f: if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line: insertCpps() @@ -83,7 +84,6 @@ def parseFile( path, filename ): if not headerFile in seenHeaders: if headerFile != "tbc_text_format.h" and headerFile != "clara.h": seenHeaders.add( headerFile ) - write( "// #included from: {0}\n".format( header ) ) if headerPath == "internal" and path.endswith("internal/"): headerPath = "" sep = "" From 4f72202c040ac02b9dcee0166faea514775b2127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Garc=C3=ADa=20Salom=C3=B3n?= Date: Sun, 23 Jul 2017 17:13:44 +0200 Subject: [PATCH 185/398] Fix for JUnit reporter when using dynamically generated sections (#963) * BySectionInfo should also take into account the section name in addition to the source code line --- include/reporters/catch_reporter_bases.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 6d627839..5e86e7c2 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -125,10 +125,11 @@ namespace Catch { }; struct BySectionInfo { - BySectionInfo(SectionInfo const& other) : m_other(other) {} - BySectionInfo(BySectionInfo const& other) : m_other(other.m_other) {} + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} bool operator() (std::shared_ptr const& node) const { - return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + return ((node->stats.sectionInfo.name == m_other.name) && + (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); } void operator=(BySectionInfo const&) = delete; From 7a76ff161ba106a55225418a11a79ee4ed839b54 Mon Sep 17 00:00:00 2001 From: Ivan Kush Date: Tue, 4 Jul 2017 16:45:56 +0300 Subject: [PATCH 186/398] added 'args' argument parser library --- docs/opensource-users.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/opensource-users.md b/docs/opensource-users.md index d4a96902..ab7a8ae1 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -55,6 +55,9 @@ A library of algorithms for values-distributed-in-time ### [Trompeloeil](https://github.com/rollbear/trompeloeil) A thread safe header only mocking framework for C++14 +### [args](https://github.com/Taywee/args) +A simple header-only C++ argument parser library. + ## Applications & Tools ### [ArangoDB](https://github.com/arangodb/arangodb) From 28741467d51bbe84cc299b2b5de8c6ed80bcdad8 Mon Sep 17 00:00:00 2001 From: Markus Werle Date: Wed, 28 Jun 2017 17:22:54 +0200 Subject: [PATCH 187/398] Update tutorial.md --- docs/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial.md b/docs/tutorial.md index 3a0f9468..600ba3ba 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -80,7 +80,7 @@ unsigned int Factorial( unsigned int number ) { Now all the tests pass. -Of course there are still more issues to do deal with. For example we'll hit problems when the return value starts to exceed the range of an unsigned int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here. +Of course there are still more issues to deal with. For example we'll hit problems when the return value starts to exceed the range of an unsigned int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here. ## What did we do here? From 2212cdfe26415586c06e379a2400b1ee171382d3 Mon Sep 17 00:00:00 2001 From: Neal Coombes Date: Mon, 26 Jun 2017 14:30:23 -0500 Subject: [PATCH 188/398] Eliminate some work when results won't be reported. --- include/internal/catch_capture.hpp | 4 +- include/internal/catch_interfaces_capture.h | 4 ++ include/internal/catch_result_builder.cpp | 45 +++++++++++++-------- include/internal/catch_result_builder.h | 6 ++- include/internal/catch_run_context.cpp | 14 +++++++ include/internal/catch_run_context.hpp | 7 ++++ 6 files changed, 60 insertions(+), 20 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 574361d0..d331e19b 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -83,12 +83,12 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ - if( Catch::getResultCapture().getLastResult()->succeeded() ) + if( Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ - if( !Catch::getResultCapture().getLastResult()->succeeded() ) + if( !Catch::getResultCapture().lastAssertionPassed() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index 35b62dd9..54cf0e4d 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -41,6 +41,10 @@ namespace Catch { virtual void exceptionEarlyReported() = 0; virtual void handleFatalErrorCondition( std::string const& message ) = 0; + + virtual bool lastAssertionPassed() = 0; + virtual void assertionPassed() = 0; + virtual void assertionRun() = 0; }; IResultCapture& getResultCapture(); diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index 6268f8d1..c5ea8119 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -34,14 +34,12 @@ namespace Catch { char const* capturedExpression, ResultDisposition::Flags resultDisposition ) : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition) - { - m_stream().oss.str(""); - } + {} ResultBuilder::~ResultBuilder() { #if defined(CATCH_CONFIG_FAST_COMPILE) if ( m_guardException ) { - m_stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; + stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; captureResult( ResultWas::ThrewException ); getCurrentContext().getResultCapture()->exceptionEarlyReported(); } @@ -58,13 +56,25 @@ namespace Catch { } void ResultBuilder::endExpression( DecomposedExpression const& expr ) { - AssertionResult result = build( expr ); - handleResult( result ); + // Flip bool results if FalseTest flag is set + if( isFalseTest( m_assertionInfo.resultDisposition ) ) { + m_data.negate( expr.isBinaryExpression() ); + } + + getResultCapture().assertionRun(); + + if(getCurrentContext().getConfig()->includeSuccessfulResults() + || m_data.resultType != ResultWas::Ok) { + AssertionResult result = build( expr ); + handleResult( result ); + } + else + getResultCapture().assertionPassed(); } void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { m_assertionInfo.resultDisposition = resultDisposition; - m_stream().oss << Catch::translateActiveException(); + stream().oss << Catch::translateActiveException(); captureResult( ResultWas::ThrewException ); } @@ -142,17 +152,12 @@ namespace Catch { // It should immediately be passed to handleResult; if the expression // needs to be reported, its string expansion must be composed before // the temporaries are destroyed. - AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const - { + AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const { assert( m_data.resultType != ResultWas::Unknown ); AssertionResultData data = m_data; - // Flip bool results if FalseTest flag is set - if( isFalseTest( m_assertionInfo.resultDisposition ) ) { - data.negate( expr.isBinaryExpression() ); - } - - data.message = m_stream().oss.str(); + if(m_usedStream) + data.message = m_stream().oss.str(); data.decomposedExpression = &expr; // for lazy reconstruction return AssertionResult( m_assertionInfo, data ); } @@ -168,7 +173,15 @@ namespace Catch { m_guardException = false; } - CopyableStream& ResultBuilder::m_stream() { + CopyableStream& ResultBuilder::stream() { + if( !m_usedStream ) { + m_usedStream = true; + s_stream().oss.str(""); + } + return s_stream(); + } + + CopyableStream& ResultBuilder::s_stream() { static CopyableStream s; return s; } diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 90cbf5be..6639b541 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -43,7 +43,7 @@ namespace Catch { template ResultBuilder& operator << ( T const& value ) { - m_stream().oss << value; + stream().oss << value; return *this; } @@ -79,11 +79,13 @@ namespace Catch { AssertionInfo m_assertionInfo; AssertionResultData m_data; - static CopyableStream& m_stream(); + CopyableStream& stream(); + static CopyableStream& s_stream(); bool m_shouldDebugBreak = false; bool m_shouldThrow = false; bool m_guardException = false; + bool m_usedStream = false; }; } // namespace Catch diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 31d6b8a6..bfde432b 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -213,6 +213,20 @@ namespace Catch { m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); } + bool RunContext::lastAssertionPassed() { + return m_totals.assertions.passed == (m_prevPassed + 1); + } + + void RunContext::assertionPassed() { + ++m_totals.assertions.passed; + m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; + m_lastAssertionInfo.macroName = ""; + } + + void RunContext::assertionRun() { + m_prevPassed = m_totals.assertions.passed; + } + bool RunContext::aborting() const { return m_totals.assertions.failed == static_cast(m_config->abortAfter()); } diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index c513788b..9d065ae5 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -84,6 +84,12 @@ namespace Catch { virtual void handleFatalErrorCondition(std::string const& message) override; + virtual bool lastAssertionPassed() override; + + virtual void assertionPassed(); + + virtual void assertionRun(); + public: // !TBD We need to do this another way! bool aborting() const override; @@ -113,6 +119,7 @@ namespace Catch { std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; + size_t m_prevPassed = 0; bool m_shouldReportUnexpected = true; }; From eab56d6656845f541c9a3633f2c9bbe3a18dc1a2 Mon Sep 17 00:00:00 2001 From: Anton Vorobyev Date: Mon, 31 Jul 2017 11:47:42 +0300 Subject: [PATCH 189/398] Initial support for native IBM i ILE C++ (#976) * - Initial support for native IBM i ILE C++ Signed-off-by: zeromem --- include/internal/catch_compiler_capabilities.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index b9f3fb1e..c1066a56 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -61,6 +61,10 @@ #endif +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif //////////////////////////////////////////////////////////////////////////////// // Cygwin From 887fe1d5d273a5ff906b110769dcc110acb6b174 Mon Sep 17 00:00:00 2001 From: Danila Sukharev Date: Tue, 1 Aug 2017 18:33:53 +0300 Subject: [PATCH 190/398] Adding more flexibility into the cmake catch parsing script (#971) * Adding more flexibility into the cmake catch parsing script --- contrib/ParseAndAddCatchTests.cmake | 44 ++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/contrib/ParseAndAddCatchTests.cmake b/contrib/ParseAndAddCatchTests.cmake index bd1da755..700357fd 100644 --- a/contrib/ParseAndAddCatchTests.cmake +++ b/contrib/ParseAndAddCatchTests.cmake @@ -30,12 +30,21 @@ # # # PARSE_CATCH_TESTS_VERBOSE (Default OFF) # # -- enables debug messages # +# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) # +# -- excludes tests marked with [!hide], [.] or [.foo] tags # +# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) # +# -- adds fixture class name to the test name # +# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) # +# -- adds cmake target name to the test name # # # #==================================================================================================# cmake_minimum_required(VERSION 2.8.8) option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF) +option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF) +option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON) +option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON) function(PrintDebugMessage) if(PARSE_CATCH_TESTS_VERBOSE) @@ -103,12 +112,14 @@ function(ParseFile SourceFile TestTarget) if("${TestType}" STREQUAL "SCENARIO") set(Name "Scenario: ${Name}") endif() - if(TestFixture) + if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture) set(CTestName "${TestFixture}:${Name}") else() set(CTestName "${Name}") endif() - set(CTestName "${TestTarget}:${CTestName}") + if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME) + set(CTestName "${TestTarget}:${CTestName}") + endif() # add target to labels to enable running all tests added from this target set(Labels ${TestTarget}) if(TestStringsLength EQUAL 2) @@ -124,15 +135,28 @@ function(ParseFile SourceFile TestTarget) list(APPEND Labels ${Tags}) - PrintDebugMessage("Adding test \"${CTestName}\"") - if(Labels) - PrintDebugMessage("Setting labels to ${Labels}") - endif() + list(FIND Labels "!hide" IndexOfHideLabel) + set(HiddenTagFound OFF) + foreach(label ${Labels}) + string(REGEX MATCH "^!hide|^\\." result ${label}) + if(result) + set(HiddenTagFound ON) + break() + endif(result) + endforeach(label) + if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound}) + PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label") + else() + PrintDebugMessage("Adding test \"${CTestName}\"") + if(Labels) + PrintDebugMessage("Setting labels to ${Labels}") + endif() - # Add the test and set its properties - add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters}) - set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran" - LABELS "${Labels}") + # Add the test and set its properties + add_test(NAME "\"${CTestName}\"" COMMAND ${TestTarget} ${Name} ${AdditionalCatchParameters}) + set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran" + LABELS "${Labels}") + endif() endforeach() endfunction() From e8b785b1775a59e40b05fd5bd861ec2c09df5dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 2 Aug 2017 00:04:26 +0200 Subject: [PATCH 191/398] Fixup bad merge in 2212cdfe --- include/internal/catch_result_builder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index c5ea8119..8cc624c7 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -157,7 +157,7 @@ namespace Catch { AssertionResultData data = m_data; if(m_usedStream) - data.message = m_stream().oss.str(); + data.message = s_stream().oss.str(); data.decomposedExpression = &expr; // for lazy reconstruction return AssertionResult( m_assertionInfo, data ); } From 3882ac1a1936a31abdc110bdaea9c64aa27daae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 2 Aug 2017 00:26:52 +0200 Subject: [PATCH 192/398] Include proper exception header in enforce.h --- include/internal/catch_enforce.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_enforce.h b/include/internal/catch_enforce.h index b500949d..e489cf7e 100644 --- a/include/internal/catch_enforce.h +++ b/include/internal/catch_enforce.h @@ -10,7 +10,7 @@ #include "catch_common.h" #include -#include +#include #define CATCH_PREPARE_EXCEPTION( type, msg ) \ type( static_cast( std::ostringstream() << msg ).str() ) From 5450de2acd296e7c4b25e2c738f1d4f7199161b4 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 4 Aug 2017 12:13:58 +0100 Subject: [PATCH 193/398] Added some missing `override`s and removed some `virtual`s from overrides --- include/internal/catch_run_context.hpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 9d065ae5..0619816b 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -63,32 +63,32 @@ namespace Catch { private: // IResultCapture - virtual void assertionEnded(AssertionResult const& result) override; + void assertionEnded(AssertionResult const& result) override; - virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; + bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; bool testForMissingAssertions(Counts& assertions); - virtual void sectionEnded(SectionEndInfo const& endInfo) override; + void sectionEnded(SectionEndInfo const& endInfo) override; - virtual void sectionEndedEarly(SectionEndInfo const& endInfo) override; + void sectionEndedEarly(SectionEndInfo const& endInfo) override; - virtual void pushScopedMessage(MessageInfo const& message) override; + void pushScopedMessage(MessageInfo const& message) override; - virtual void popScopedMessage(MessageInfo const& message) override; + void popScopedMessage(MessageInfo const& message) override; - virtual std::string getCurrentTestName() const override; + std::string getCurrentTestName() const override; - virtual const AssertionResult* getLastResult() const override; + const AssertionResult* getLastResult() const override; - virtual void exceptionEarlyReported() override; + void exceptionEarlyReported() override; - virtual void handleFatalErrorCondition(std::string const& message) override; + void handleFatalErrorCondition(std::string const& message) override; - virtual bool lastAssertionPassed() override; + bool lastAssertionPassed() override; - virtual void assertionPassed(); + void assertionPassed() override; - virtual void assertionRun(); + void assertionRun() override; public: // !TBD We need to do this another way! From c7028f7bc76e011f23fcc2baf308f5c27ef1f019 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 4 Aug 2017 12:16:05 +0100 Subject: [PATCH 194/398] Made most of Timer class inline - and export getCurrentMicrosecondsSinceEpoch() --- include/internal/catch_timer.cpp | 19 ++----------------- include/internal/catch_timer.h | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/include/internal/catch_timer.cpp b/include/internal/catch_timer.cpp index d4066fa9..3253f1f4 100644 --- a/include/internal/catch_timer.cpp +++ b/include/internal/catch_timer.cpp @@ -12,23 +12,8 @@ namespace Catch { - namespace { - uint64_t getCurrentMicrosecondsSinceEpoch() { - return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); - } - } - - void Timer::start() { - m_microSeconds = getCurrentMicrosecondsSinceEpoch(); - } - unsigned int Timer::getElapsedMicroseconds() const { - return static_cast(getCurrentMicrosecondsSinceEpoch() - m_microSeconds); - } - unsigned int Timer::getElapsedMilliseconds() const { - return static_cast(getElapsedMicroseconds()/1000); - } - double Timer::getElapsedSeconds() const { - return getElapsedMicroseconds()/1000000.0; + auto getCurrentMicrosecondsSinceEpoch() -> uint64_t { + return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); } } // namespace Catch diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 60115c80..2533b02f 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -11,15 +11,24 @@ #include namespace Catch { - class Timer { - public: - void start(); - unsigned int getElapsedMicroseconds() const; - unsigned int getElapsedMilliseconds() const; - double getElapsedSeconds() const; - private: + auto getCurrentMicrosecondsSinceEpoch() -> uint64_t; + + class Timer { uint64_t m_microSeconds = 0; + public: + void start() { + m_microSeconds = getCurrentMicrosecondsSinceEpoch(); + } + auto getElapsedMicroseconds() const -> unsigned int { + return static_cast(getCurrentMicrosecondsSinceEpoch() - m_microSeconds); + } + auto getElapsedMilliseconds() const -> unsigned int { + return static_cast(getElapsedMicroseconds()/1000); + } + auto getElapsedSeconds() const -> double { + return getElapsedMicroseconds()/1000000.0; + } }; } // namespace Catch From 39d37d9f341e0cefc52a2abfdefbe1071fe0bc56 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 4 Aug 2017 12:22:16 +0100 Subject: [PATCH 195/398] Timer resolution is now nanoseconds --- include/internal/catch_timer.cpp | 4 ++-- include/internal/catch_timer.h | 11 +++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/internal/catch_timer.cpp b/include/internal/catch_timer.cpp index 3253f1f4..fad86f85 100644 --- a/include/internal/catch_timer.cpp +++ b/include/internal/catch_timer.cpp @@ -12,8 +12,8 @@ namespace Catch { - auto getCurrentMicrosecondsSinceEpoch() -> uint64_t { - return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); + auto getCurrentNanosecondsSinceEpoch() -> uint64_t { + return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); } } // namespace Catch diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 2533b02f..d9c381c1 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -12,16 +12,19 @@ namespace Catch { - auto getCurrentMicrosecondsSinceEpoch() -> uint64_t; + auto getCurrentNanosecondsSinceEpoch() -> uint64_t; class Timer { - uint64_t m_microSeconds = 0; + uint64_t m_nanoseconds = 0; public: void start() { - m_microSeconds = getCurrentMicrosecondsSinceEpoch(); + m_nanoseconds = getCurrentNanosecondsSinceEpoch(); + } + auto getElapsedNanoseconds() const -> unsigned int { + return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); } auto getElapsedMicroseconds() const -> unsigned int { - return static_cast(getCurrentMicrosecondsSinceEpoch() - m_microSeconds); + return static_cast(getElapsedNanoseconds()/1000); } auto getElapsedMilliseconds() const -> unsigned int { return static_cast(getElapsedMicroseconds()/1000); From a1e3f0b62446afe9b46b0872d373ab0e4e8a4357 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 4 Aug 2017 13:53:47 +0100 Subject: [PATCH 196/398] Moved Timer impl back to cpp (I thought it wasn't included on the non-main path, but it is) --- include/internal/catch_timer.cpp | 17 +++++++++++++++++ include/internal/catch_timer.h | 20 +++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/include/internal/catch_timer.cpp b/include/internal/catch_timer.cpp index fad86f85..ca09d7bc 100644 --- a/include/internal/catch_timer.cpp +++ b/include/internal/catch_timer.cpp @@ -16,4 +16,21 @@ namespace Catch { return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); } + void Timer::start() { + m_nanoseconds = getCurrentNanosecondsSinceEpoch(); + } + auto Timer::getElapsedNanoseconds() const -> unsigned int { + return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); + } + auto Timer::getElapsedMicroseconds() const -> unsigned int { + return static_cast(getElapsedNanoseconds()/1000); + } + auto Timer::getElapsedMilliseconds() const -> unsigned int { + return static_cast(getElapsedMicroseconds()/1000); + } + auto Timer::getElapsedSeconds() const -> double { + return getElapsedMicroseconds()/1000000.0; + } + + } // namespace Catch diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index d9c381c1..09182866 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -17,21 +17,11 @@ namespace Catch { class Timer { uint64_t m_nanoseconds = 0; public: - void start() { - m_nanoseconds = getCurrentNanosecondsSinceEpoch(); - } - auto getElapsedNanoseconds() const -> unsigned int { - return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); - } - auto getElapsedMicroseconds() const -> unsigned int { - return static_cast(getElapsedNanoseconds()/1000); - } - auto getElapsedMilliseconds() const -> unsigned int { - return static_cast(getElapsedMicroseconds()/1000); - } - auto getElapsedSeconds() const -> double { - return getElapsedMicroseconds()/1000000.0; - } + void start(); + auto getElapsedNanoseconds() const -> unsigned int; + auto getElapsedMicroseconds() const -> unsigned int; + auto getElapsedMilliseconds() const -> unsigned int; + auto getElapsedSeconds() const -> double; }; } // namespace Catch From a9b6813ad9e423ddcd6559f52b503a68fe0f624c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 4 Aug 2017 19:23:30 +0100 Subject: [PATCH 197/398] First draft of (experimental) benchmarking support --- CMakeLists.txt | 2 + include/catch.hpp | 1 + include/internal/catch_benchmark.cpp | 30 +++++++++++ include/internal/catch_benchmark.h | 55 ++++++++++++++++++++ include/internal/catch_interfaces_capture.h | 6 +++ include/internal/catch_interfaces_reporter.h | 14 +++++ include/internal/catch_result_builder.cpp | 4 +- include/internal/catch_run_context.cpp | 9 ++++ include/internal/catch_run_context.hpp | 6 ++- include/internal/catch_section.cpp | 1 - include/internal/catch_timer.cpp | 54 ++++++++++++++----- include/internal/catch_timer.h | 1 + include/reporters/catch_reporter_bases.hpp | 10 ++++ include/reporters/catch_reporter_console.cpp | 54 ++++++++++++++++++- 14 files changed, 227 insertions(+), 20 deletions(-) create mode 100644 include/internal/catch_benchmark.cpp create mode 100644 include/internal/catch_benchmark.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 05cc5c8e..37111da0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_result_builder.h ${HEADER_DIR}/internal/catch_result_type.h ${HEADER_DIR}/internal/catch_run_context.hpp + ${HEADER_DIR}/internal/catch_benchmark.h ${HEADER_DIR}/internal/catch_section.h ${HEADER_DIR}/internal/catch_section_info.h ${HEADER_DIR}/internal/catch_startup_exception_registry.h @@ -197,6 +198,7 @@ set(INTERNAL_HEADERS set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_approx.cpp ${HEADER_DIR}/internal/catch_assertionresult.cpp + ${HEADER_DIR}/internal/catch_benchmark.cpp ${HEADER_DIR}/internal/catch_commandline.cpp ${HEADER_DIR}/internal/catch_common.cpp ${HEADER_DIR}/internal/catch_config.cpp diff --git a/include/catch.hpp b/include/catch.hpp index 0acd25da..00a49956 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -33,6 +33,7 @@ #include "internal/catch_test_registry.hpp" #include "internal/catch_capture.hpp" #include "internal/catch_section.h" +#include "internal/catch_benchmark.h" #include "internal/catch_interfaces_exception.h" #include "internal/catch_approx.hpp" #include "internal/catch_matchers_string.h" diff --git a/include/internal/catch_benchmark.cpp b/include/internal/catch_benchmark.cpp new file mode 100644 index 00000000..34af42a5 --- /dev/null +++ b/include/internal/catch_benchmark.cpp @@ -0,0 +1,30 @@ +/* + * Created by Phil on 04/07/2017. + * Copyright 2017 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) + */ + +#include "catch_benchmark.h" +#include "catch_capture.hpp" + +namespace Catch { + + void BenchmarkLooper::reportStart() const { + getResultCapture().benchmarkStarting( { m_name } ); + } + auto BenchmarkLooper::needsMoreIterations() -> bool { + auto elapsed = m_timer.getElapsedNanoseconds(); + + // Exponentially increasing iterations until we're confident in our timer resolution + if( elapsed < m_resolution ) { + m_iterationsToRun *= 10; + return true; + } + + getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); + return false; + } + +} // end namespace Catch diff --git a/include/internal/catch_benchmark.h b/include/internal/catch_benchmark.h new file mode 100644 index 00000000..7b01507a --- /dev/null +++ b/include/internal/catch_benchmark.h @@ -0,0 +1,55 @@ +/* + * Created by Phil on 04/07/2017. + * Copyright 2017 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) + */ +#ifndef TWOBLUECUBES_CATCH_BENCHMARK_H_INCLUDED +#define TWOBLUECUBES_CATCH_BENCHMARK_H_INCLUDED + +#include "catch_stringref.h" +#include "catch_timer.h" + +#include +#include + +namespace Catch { + + class BenchmarkLooper { + + std::string m_name; + size_t m_count = 0; + size_t m_iterationsToRun = 1; + uint64_t m_resolution; + Timer m_timer; + public: + // Keep most of this inline as it's on the code path that is being timed + BenchmarkLooper( StringRef name ) + : m_name( name.c_str() ), + m_resolution( getEstimatedClockResolution()*10 ) + { + reportStart(); + m_timer.start(); + } + + explicit operator bool() { + if( m_count < m_iterationsToRun ) + return true; + return needsMoreIterations(); + } + + void increment() { + ++m_count; + } + + void reportStart() const; + auto needsMoreIterations() -> bool; + }; + +} // end namespace Catch + +#define BENCHMARK( name ) \ + for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) + +#endif // TWOBLUECUBES_CATCH_BENCHMARK_H_INCLUDED diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index 54cf0e4d..4d8766dd 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -11,6 +11,7 @@ #include #include "catch_result_type.h" #include "catch_common.h" +#include "catch_interfaces_reporter.h" namespace Catch { @@ -27,11 +28,16 @@ namespace Catch { virtual ~IResultCapture(); + virtual void assertionStarting( AssertionInfo const& info ) = 0; virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + + virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; + virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 0aa2d241..def3684b 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -158,6 +158,14 @@ namespace Catch { bool aborting; }; + struct BenchmarkInfo { + std::string name; + }; + struct BenchmarkStats { + BenchmarkInfo info; + size_t iterations; + uint64_t elapsedTimeInNanoseconds; + }; class MultipleReporters; struct IStreamingReporter { @@ -177,11 +185,17 @@ namespace Catch { virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + // *** experimental *** + virtual void benchmarkStarting( BenchmarkInfo const& ) {} + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + // *** experimental *** + virtual void benchmarkEnded( BenchmarkStats const& ) {} + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index 8cc624c7..8670136f 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -34,7 +34,9 @@ namespace Catch { char const* capturedExpression, ResultDisposition::Flags resultDisposition ) : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition) - {} + { + getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); + } ResultBuilder::~ResultBuilder() { #if defined(CATCH_CONFIG_FAST_COMPILE) diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index bfde432b..b54742ff 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -90,6 +90,9 @@ namespace Catch { return *m_reporter; } + void RunContext::assertionStarting(AssertionInfo const& info) { + m_reporter->assertionStarting( info ); + } void RunContext::assertionEnded(AssertionResult const & result) { if (result.getResultType() == ResultWas::Ok) { m_totals.assertions.passed++; @@ -155,6 +158,12 @@ namespace Catch { m_unfinishedSections.push_back(endInfo); } + void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { + m_reporter->benchmarkStarting( info ); + } + void RunContext::benchmarkEnded( BenchmarkStats const& stats ) { + m_reporter->benchmarkEnded( stats ); + } void RunContext::pushScopedMessage(MessageInfo const & message) { m_messages.push_back(message); diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 0619816b..ee923e88 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -63,17 +63,19 @@ namespace Catch { private: // IResultCapture + void assertionStarting(AssertionInfo const& info) override; void assertionEnded(AssertionResult const& result) override; bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; bool testForMissingAssertions(Counts& assertions); void sectionEnded(SectionEndInfo const& endInfo) override; - void sectionEndedEarly(SectionEndInfo const& endInfo) override; - void pushScopedMessage(MessageInfo const& message) override; + void benchmarkStarting( BenchmarkInfo const& info ) override; + void benchmarkEnded( BenchmarkStats const& stats ) override; + void pushScopedMessage(MessageInfo const& message) override; void popScopedMessage(MessageInfo const& message) override; std::string getCurrentTestName() const override; diff --git a/include/internal/catch_section.cpp b/include/internal/catch_section.cpp index 4f192446..c2572d5e 100644 --- a/include/internal/catch_section.cpp +++ b/include/internal/catch_section.cpp @@ -8,7 +8,6 @@ #include "catch_section.h" #include "catch_capture.hpp" -#include "catch_compiler_capabilities.h" namespace Catch { diff --git a/include/internal/catch_timer.cpp b/include/internal/catch_timer.cpp index ca09d7bc..9635ccea 100644 --- a/include/internal/catch_timer.cpp +++ b/include/internal/catch_timer.cpp @@ -16,21 +16,47 @@ namespace Catch { return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); } - void Timer::start() { - m_nanoseconds = getCurrentNanosecondsSinceEpoch(); - } - auto Timer::getElapsedNanoseconds() const -> unsigned int { - return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); - } - auto Timer::getElapsedMicroseconds() const -> unsigned int { - return static_cast(getElapsedNanoseconds()/1000); - } - auto Timer::getElapsedMilliseconds() const -> unsigned int { - return static_cast(getElapsedMicroseconds()/1000); - } - auto Timer::getElapsedSeconds() const -> double { - return getElapsedMicroseconds()/1000000.0; + auto estimateClockResolution() -> double { + uint64_t sum = 0; + static const uint64_t iterations = 1000000; + + for( size_t i = 0; i < iterations; ++i ) { + + uint64_t ticks; + uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); + do { + ticks = getCurrentNanosecondsSinceEpoch(); + } + while( ticks == baseTicks ); + + auto delta = ticks - baseTicks; + sum += delta; } + // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers + // - and potentially do more iterations if there's a high variance. + return sum/(double)iterations; + } + auto getEstimatedClockResolution() -> double { + static auto s_resolution = estimateClockResolution(); + return s_resolution; + } + + void Timer::start() { + m_nanoseconds = getCurrentNanosecondsSinceEpoch(); + } + auto Timer::getElapsedNanoseconds() const -> unsigned int { + return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); + } + auto Timer::getElapsedMicroseconds() const -> unsigned int { + return static_cast(getElapsedNanoseconds()/1000); + } + auto Timer::getElapsedMilliseconds() const -> unsigned int { + return static_cast(getElapsedMicroseconds()/1000); + } + auto Timer::getElapsedSeconds() const -> double { + return getElapsedMicroseconds()/1000000.0; + } + } // namespace Catch diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 09182866..1871c24a 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -13,6 +13,7 @@ namespace Catch { auto getCurrentNanosecondsSinceEpoch() -> uint64_t; + auto getEstimatedClockResolution() -> double; class Timer { uint64_t m_nanoseconds = 0; diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 5e86e7c2..37cc4e00 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -259,6 +259,16 @@ namespace Catch { } return line; } + inline char const* getBoxCharsAcross() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + std::memset( line, '-', CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + line[0] = '+'; + line[CATCH_CONFIG_CONSOLE_WIDTH-2] = '+'; + } + return line; + } struct TestEventListenerBase : StreamingReporterBase { diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 3b08d353..d99415f7 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -34,9 +34,19 @@ namespace { namespace Catch { + template + auto leftPad( const T& value, int width ) -> std::string { + // !TBD: could do with being optimised + std::ostringstream oss; + oss << value; + std::string converted = oss.str(); + return std::string( width - converted.size(), ' ' ) + converted; + } + + struct ConsoleReporter : StreamingReporterBase { using StreamingReporterBase::StreamingReporterBase; - + bool m_benchmarkTableOpen = false; ~ConsoleReporter() override; static std::string getDescription() { @@ -47,7 +57,9 @@ namespace Catch { stream << "No test cases matched '" << spec << '\'' << std::endl; } - void assertionStarting( AssertionInfo const& ) override {} + void assertionStarting( AssertionInfo const& ) override { + closeBenchmarkTable(); + } bool assertionEnded( AssertionStats const& _assertionStats ) override { AssertionResult const& result = _assertionStats.assertionResult; @@ -71,6 +83,7 @@ namespace Catch { StreamingReporterBase::sectionStarting( _sectionInfo ); } void sectionEnded( SectionStats const& _sectionStats ) override { + closeBenchmarkTable(); if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -89,7 +102,44 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } + void benchmarkStarting( BenchmarkInfo const& info ) override { + lazyPrint(); + auto nameColWidth = CATCH_CONFIG_CONSOLE_WIDTH-40; + auto nameCol = Column( info.name ).width( nameColWidth ); + if( !m_benchmarkTableOpen ) { + stream + << getBoxCharsAcross() << "\n" + << "| benchmark name" << std::string( nameColWidth-14, ' ' ) << " | it'ns | elapsed ns | average |\n" + << getBoxCharsAcross() << "\n"; + m_benchmarkTableOpen = true; + } + bool firstLine = true; + for( auto line : nameCol ) { + if( !firstLine ) + stream << " | | |" << "\n"; + else + firstLine = false; + + stream << "| " << line << std::string( nameColWidth-line.size(), ' ' ) << " |"; + } + } + void benchmarkEnded( BenchmarkStats const& stats ) override { + // !TBD: report average times in natural units? + stream + << " " << leftPad( stats.iterations, 6 ) + << " | " << leftPad( stats.elapsedTimeInNanoseconds, 10 ) + << " | " << leftPad( stats.elapsedTimeInNanoseconds/stats.iterations, 7 ) + << " ns |" << std::endl; + } + void closeBenchmarkTable() { + if( m_benchmarkTableOpen ) { + stream << getBoxCharsAcross() << "\n" << std::endl; + m_benchmarkTableOpen = false; + } + } + void testCaseEnded( TestCaseStats const& _testCaseStats ) override { + closeBenchmarkTable(); StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } From 97d6b08087b4afd335bfacfda0537581f6ef3f9b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 4 Aug 2017 21:31:28 +0100 Subject: [PATCH 198/398] Changed clock resolution estimator to return uint64_t --- include/internal/catch_timer.cpp | 6 +++--- include/internal/catch_timer.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_timer.cpp b/include/internal/catch_timer.cpp index 9635ccea..ec1d8bb5 100644 --- a/include/internal/catch_timer.cpp +++ b/include/internal/catch_timer.cpp @@ -16,7 +16,7 @@ namespace Catch { return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); } - auto estimateClockResolution() -> double { + auto estimateClockResolution() -> uint64_t { uint64_t sum = 0; static const uint64_t iterations = 1000000; @@ -35,9 +35,9 @@ namespace Catch { // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers // - and potentially do more iterations if there's a high variance. - return sum/(double)iterations; + return sum/iterations; } - auto getEstimatedClockResolution() -> double { + auto getEstimatedClockResolution() -> uint64_t { static auto s_resolution = estimateClockResolution(); return s_resolution; } diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index 1871c24a..e01a1cb7 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -13,7 +13,7 @@ namespace Catch { auto getCurrentNanosecondsSinceEpoch() -> uint64_t; - auto getEstimatedClockResolution() -> double; + auto getEstimatedClockResolution() -> uint64_t; class Timer { uint64_t m_nanoseconds = 0; From 22e9ebef0d6265731591cb44ceca151e465092a1 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 4 Aug 2017 23:54:51 +0100 Subject: [PATCH 199/398] Factored table writing code out into a TablePrinter class (removes a lot of magic numbers and ad-hoc formatting) --- include/reporters/catch_reporter_console.cpp | 150 ++++++++++++++----- 1 file changed, 112 insertions(+), 38 deletions(-) diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index d99415f7..8ba14f5f 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -30,24 +30,105 @@ namespace { else return k; } + + struct ColumnInfo { + enum Justification { Left, Right }; + std::string name; + int width; + Justification justification; + }; + struct ColumnBreak {}; + struct RowBreak {}; + + class TablePrinter { + std::ostream& m_os; + std::vector m_columnInfos; + std::ostringstream m_oss; + int m_currentColumn = -1; + bool m_isOpen = false; + + public: + TablePrinter( std::ostream& os, std::vector const& columnInfos ) + : m_os( os ), + m_columnInfos( columnInfos ) + {} + + auto columnInfos() const -> std::vector const& { + return m_columnInfos; + } + + void open() { + if( !m_isOpen ) { + m_isOpen = true; + *this << RowBreak(); + for( auto const& info : m_columnInfos ) + *this << info.name << ColumnBreak(); + *this << RowBreak(); + } + } + void close() { + if( m_isOpen ) { + *this << RowBreak(); + m_os << std::endl; + m_isOpen = false; + } + } + + template + friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { + tp.m_oss << value; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { + auto colStr = tp.m_oss.str(); + tp.m_oss.str(""); + tp.open(); + if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { + tp.m_currentColumn = -1; + tp.m_os << "\n"; + } + if( tp.m_currentColumn == -1 ) + tp.m_os << "|"; + tp.m_currentColumn++; + + auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; + auto padding = ( colStr.size()+2 < static_cast( colInfo.width ) ) + ? std::string( colInfo.width-(colStr.size()+2), ' ' ) + : std::string(); + if( colInfo.justification == ColumnInfo::Left ) + tp.m_os << " " << colStr << padding << " |"; + else + tp.m_os << " " << padding << colStr << " |"; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { + if( tp.m_currentColumn > 0 ) { + tp.m_os << "\n"; + tp.m_currentColumn = -1; + } + tp.m_os << Catch::getBoxCharsAcross() << "\n"; + return tp; + } + }; } namespace Catch { - template - auto leftPad( const T& value, int width ) -> std::string { - // !TBD: could do with being optimised - std::ostringstream oss; - oss << value; - std::string converted = oss.str(); - return std::string( width - converted.size(), ' ' ) + converted; - } - - struct ConsoleReporter : StreamingReporterBase { - using StreamingReporterBase::StreamingReporterBase; - bool m_benchmarkTableOpen = false; + TablePrinter m_tablePrinter; + ConsoleReporter( ReporterConfig const& config ) + : StreamingReporterBase( config ), + m_tablePrinter( config.stream(), + { + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-38, ColumnInfo::Left }, + { "iters", 8, ColumnInfo::Right }, + { "elapsed ns", 12, ColumnInfo::Right }, + { "average", 12, ColumnInfo::Right } + } ) + {} ~ConsoleReporter() override; static std::string getDescription() { return "Reports test results as plain lines of text"; @@ -58,7 +139,6 @@ namespace Catch { } void assertionStarting( AssertionInfo const& ) override { - closeBenchmarkTable(); } bool assertionEnded( AssertionStats const& _assertionStats ) override { @@ -83,7 +163,7 @@ namespace Catch { StreamingReporterBase::sectionStarting( _sectionInfo ); } void sectionEnded( SectionStats const& _sectionStats ) override { - closeBenchmarkTable(); + m_tablePrinter.close(); if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -102,44 +182,32 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } + void benchmarkStarting( BenchmarkInfo const& info ) override { - lazyPrint(); - auto nameColWidth = CATCH_CONFIG_CONSOLE_WIDTH-40; - auto nameCol = Column( info.name ).width( nameColWidth ); - if( !m_benchmarkTableOpen ) { - stream - << getBoxCharsAcross() << "\n" - << "| benchmark name" << std::string( nameColWidth-14, ' ' ) << " | it'ns | elapsed ns | average |\n" - << getBoxCharsAcross() << "\n"; - m_benchmarkTableOpen = true; - } + lazyPrintWithoutClosingBenchmarkTable(); + + auto nameCol = Column( info.name ).width( m_tablePrinter.columnInfos()[0].width-2 ); + bool firstLine = true; for( auto line : nameCol ) { if( !firstLine ) - stream << " | | |" << "\n"; + m_tablePrinter << ColumnBreak() << ColumnBreak() << ColumnBreak(); else firstLine = false; - stream << "| " << line << std::string( nameColWidth-line.size(), ' ' ) << " |"; + m_tablePrinter << line << ColumnBreak(); } } void benchmarkEnded( BenchmarkStats const& stats ) override { // !TBD: report average times in natural units? - stream - << " " << leftPad( stats.iterations, 6 ) - << " | " << leftPad( stats.elapsedTimeInNanoseconds, 10 ) - << " | " << leftPad( stats.elapsedTimeInNanoseconds/stats.iterations, 7 ) - << " ns |" << std::endl; - } - void closeBenchmarkTable() { - if( m_benchmarkTableOpen ) { - stream << getBoxCharsAcross() << "\n" << std::endl; - m_benchmarkTableOpen = false; - } + m_tablePrinter + << stats.iterations << ColumnBreak() + << stats.elapsedTimeInNanoseconds << ColumnBreak() + << stats.elapsedTimeInNanoseconds/stats.iterations << " ns" << ColumnBreak(); } void testCaseEnded( TestCaseStats const& _testCaseStats ) override { - closeBenchmarkTable(); + m_tablePrinter.close(); StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } @@ -305,6 +373,12 @@ namespace Catch { void lazyPrint() { + m_tablePrinter.close(); + lazyPrintWithoutClosingBenchmarkTable(); + } + + void lazyPrintWithoutClosingBenchmarkTable() { + if( !currentTestRunInfo.used ) lazyPrintRunInfo(); if( !currentGroupInfo.used ) From f45d35c9804be1a53360fed1f8fcb8d3432ce8ea Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 5 Aug 2017 11:12:29 +0100 Subject: [PATCH 200/398] Added benchmark tests --- CMakeLists.txt | 3 +- .../Baselines/console.std.approved.txt | 20 +++++- .../Baselines/console.sw.approved.txt | 65 ++++++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 39 ++++++++++- projects/SelfTest/Benchmark.tests.cpp | 43 ++++++++++++ 6 files changed, 165 insertions(+), 8 deletions(-) create mode 100644 projects/SelfTest/Benchmark.tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 37111da0..211bfd9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ endfunction() set(TEST_SOURCES ${SELF_TEST_DIR}/ApproxTests.cpp ${SELF_TEST_DIR}/BDDTests.cpp + ${SELF_TEST_DIR}/Benchmark.tests.cpp ${SELF_TEST_DIR}/ClassTests.cpp ${SELF_TEST_DIR}/CmdLineTests.cpp ${SELF_TEST_DIR}/CompilationTests.cpp @@ -96,9 +97,9 @@ set(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp + ${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp ) CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 9e41f7f5..acd58b94 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -850,6 +850,22 @@ warning: Uncomment the code in this test to check that it gives a sensible compiler error +------------------------------------------------------------------------------- +benchmarked +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + ++-----------------------------------------------------------------------------+ +| benchmark name | iters | elapsed ns | average | ++-----------------------------------------------------------------------------+ + +| Load up a vector | 1 | 8459 | 8459 ns | +| Load up a map | 1 | 28774 | 28774 ns | +| Reserved vector | 1 | 2430 | 2430 ns | +| A fixed size array that should require | | | | +| no allocations | 10 | 2563 | 256 ns | ++-----------------------------------------------------------------------------+ ------------------------------------------------------------------------------- checkedElse, failing ------------------------------------------------------------------------------- @@ -1016,6 +1032,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 182 | 131 passed | 47 failed | 4 failed as expected -assertions: 896 | 779 passed | 96 failed | 21 failed as expected +test cases: 183 | 132 passed | 47 failed | 4 failed as expected +assertions: 900 | 783 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 971c0e32..7f4861d4 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -6381,6 +6381,67 @@ PASSED: with expansion: 0 == 0 +------------------------------------------------------------------------------- +benchmarked +------------------------------------------------------------------------------- +String.tests.cpp: +............................................................................... + ++-----------------------------------------------------------------------------+ +| benchmark name | iters | elapsed ns | average | ++-----------------------------------------------------------------------------+ + +| Load up a vector | 1 | 6957 | 6957 ns | ++-----------------------------------------------------------------------------+ +String.tests.cpp:: +PASSED: + REQUIRE( v.size() == size ) +with expansion: + 100 == 100 + + ++-----------------------------------------------------------------------------+ + +| benchmark name | iters | elapsed ns | average | ++-----------------------------------------------------------------------------+ + +| Load up a map | 1 | 27868 | 27868 ns | ++-----------------------------------------------------------------------------+ +String.tests.cpp:: +PASSED: + REQUIRE( m.size() == size ) +with expansion: + 100 == 100 + + ++-----------------------------------------------------------------------------+ + +| benchmark name | iters | elapsed ns | average | ++-----------------------------------------------------------------------------+ + +| Reserved vector | 1 | 2711 | 2711 ns | ++-----------------------------------------------------------------------------+ +String.tests.cpp:: +PASSED: + REQUIRE( v.size() == size ) +with expansion: + 100 == 100 + + ++-----------------------------------------------------------------------------+ + +| benchmark name | iters | elapsed ns | average | ++-----------------------------------------------------------------------------+ + +| A fixed size array that should require | | | | +| no allocations | 1 | 530 | 530 ns | ++-----------------------------------------------------------------------------+ +String.tests.cpp:: +PASSED: + REQUIRE( sum > size ) +with expansion: + 4950 (0x) > 100 + ------------------------------------------------------------------------------- boolean member ------------------------------------------------------------------------------- @@ -7590,6 +7651,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 182 | 130 passed | 48 failed | 4 failed as expected -assertions: 898 | 779 passed | 98 failed | 21 failed as expected +test cases: 183 | 131 passed | 48 failed | 4 failed as expected +assertions: 902 | 783 passed | 98 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 58807c18..31ad3c5a 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -641,6 +641,7 @@ ExceptionTests.cpp: + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index e70ad12e..01ec013c 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -7201,6 +7201,41 @@ Message from section two
+ + + + v.size() == size + + + 100 == 100 + + + + + m.size() == size + + + 100 == 100 + + + + + v.size() == size + + + 100 == 100 + + + + + sum > size + + + 4950 (0x) > 100 + + + + @@ -8441,7 +8476,7 @@ spanner
- + - + diff --git a/projects/SelfTest/Benchmark.tests.cpp b/projects/SelfTest/Benchmark.tests.cpp new file mode 100644 index 00000000..ff1ec479 --- /dev/null +++ b/projects/SelfTest/Benchmark.tests.cpp @@ -0,0 +1,43 @@ +#include "catch.hpp" + +#include + +TEST_CASE( "benchmarked", "[.][benchmark]" ) { + + static const int size = 100; + + std::vector v; + std::map m; + + BENCHMARK( "Load up a vector" ) { + v = std::vector(); + for(int i =0; i < size; ++i ) + v.push_back( i ); + } + REQUIRE( v.size() == size ); + + BENCHMARK( "Load up a map" ) { + m = std::map(); + for(int i =0; i < size; ++i ) + m.insert( { i, i+1 } ); + } + REQUIRE( m.size() == size ); + + BENCHMARK( "Reserved vector" ) { + v = std::vector(); + v.reserve(size); + for(int i =0; i < size; ++i ) + v.push_back( i ); + } + REQUIRE( v.size() == size ); + + int array[size]; + BENCHMARK( "A fixed size array that should require no allocations" ) { + for(int i =0; i < size; ++i ) + array[i] = i; + } + int sum = 0; + for(int i =0; i < size; ++i ) + sum += array[i]; + REQUIRE( sum > size ); +} From 4421672fb869318d3445a80deb5de09761f8a119 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 5 Aug 2017 11:26:20 +0100 Subject: [PATCH 201/398] Removed benchmark tests from approval tests (for now) --- include/internal/catch_test_case_info.cpp | 2 + include/internal/catch_test_case_info.h | 3 +- .../Baselines/console.std.approved.txt | 20 +----- .../Baselines/console.sw.approved.txt | 65 +------------------ .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 39 +---------- projects/SelfTest/Benchmark.tests.cpp | 2 +- scripts/approvalTests.py | 10 +-- 8 files changed, 17 insertions(+), 127 deletions(-) diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 5a8d8c0f..9c707307 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -31,6 +31,8 @@ namespace Catch { return TestCaseInfo::MayFail; else if( tag == "!nonportable" ) return TestCaseInfo::NonPortable; + else if( tag == "!benchmark" ) + return static_cast( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); else return TestCaseInfo::None; } diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index 626f95cb..2a911b06 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -30,7 +30,8 @@ namespace Catch { ShouldFail = 1 << 2, MayFail = 1 << 3, Throws = 1 << 4, - NonPortable = 1 << 5 + NonPortable = 1 << 5, + Benchmark = 1 << 6 }; TestCaseInfo( std::string const& _name, diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index acd58b94..9e41f7f5 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -850,22 +850,6 @@ warning: Uncomment the code in this test to check that it gives a sensible compiler error -------------------------------------------------------------------------------- -benchmarked -------------------------------------------------------------------------------- -String.tests.cpp: -............................................................................... - -+-----------------------------------------------------------------------------+ -| benchmark name | iters | elapsed ns | average | -+-----------------------------------------------------------------------------+ - -| Load up a vector | 1 | 8459 | 8459 ns | -| Load up a map | 1 | 28774 | 28774 ns | -| Reserved vector | 1 | 2430 | 2430 ns | -| A fixed size array that should require | | | | -| no allocations | 10 | 2563 | 256 ns | -+-----------------------------------------------------------------------------+ ------------------------------------------------------------------------------- checkedElse, failing ------------------------------------------------------------------------------- @@ -1032,6 +1016,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 183 | 132 passed | 47 failed | 4 failed as expected -assertions: 900 | 783 passed | 96 failed | 21 failed as expected +test cases: 182 | 131 passed | 47 failed | 4 failed as expected +assertions: 896 | 779 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 7f4861d4..971c0e32 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -6381,67 +6381,6 @@ PASSED: with expansion: 0 == 0 -------------------------------------------------------------------------------- -benchmarked -------------------------------------------------------------------------------- -String.tests.cpp: -............................................................................... - -+-----------------------------------------------------------------------------+ -| benchmark name | iters | elapsed ns | average | -+-----------------------------------------------------------------------------+ - -| Load up a vector | 1 | 6957 | 6957 ns | -+-----------------------------------------------------------------------------+ -String.tests.cpp:: -PASSED: - REQUIRE( v.size() == size ) -with expansion: - 100 == 100 - - -+-----------------------------------------------------------------------------+ - -| benchmark name | iters | elapsed ns | average | -+-----------------------------------------------------------------------------+ - -| Load up a map | 1 | 27868 | 27868 ns | -+-----------------------------------------------------------------------------+ -String.tests.cpp:: -PASSED: - REQUIRE( m.size() == size ) -with expansion: - 100 == 100 - - -+-----------------------------------------------------------------------------+ - -| benchmark name | iters | elapsed ns | average | -+-----------------------------------------------------------------------------+ - -| Reserved vector | 1 | 2711 | 2711 ns | -+-----------------------------------------------------------------------------+ -String.tests.cpp:: -PASSED: - REQUIRE( v.size() == size ) -with expansion: - 100 == 100 - - -+-----------------------------------------------------------------------------+ - -| benchmark name | iters | elapsed ns | average | -+-----------------------------------------------------------------------------+ - -| A fixed size array that should require | | | | -| no allocations | 1 | 530 | 530 ns | -+-----------------------------------------------------------------------------+ -String.tests.cpp:: -PASSED: - REQUIRE( sum > size ) -with expansion: - 4950 (0x) > 100 - ------------------------------------------------------------------------------- boolean member ------------------------------------------------------------------------------- @@ -7651,6 +7590,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 183 | 131 passed | 48 failed | 4 failed as expected -assertions: 902 | 783 passed | 98 failed | 21 failed as expected +test cases: 182 | 130 passed | 48 failed | 4 failed as expected +assertions: 898 | 779 passed | 98 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 31ad3c5a..58807c18 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,6 +1,6 @@ - + @@ -641,7 +641,6 @@ ExceptionTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 01ec013c..e70ad12e 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -7201,41 +7201,6 @@ Message from section two
- - - - v.size() == size - - - 100 == 100 - - - - - m.size() == size - - - 100 == 100 - - - - - v.size() == size - - - 100 == 100 - - - - - sum > size - - - 4950 (0x) > 100 - - - - @@ -8476,7 +8441,7 @@ spanner
- + - + diff --git a/projects/SelfTest/Benchmark.tests.cpp b/projects/SelfTest/Benchmark.tests.cpp index ff1ec479..ddf69504 100644 --- a/projects/SelfTest/Benchmark.tests.cpp +++ b/projects/SelfTest/Benchmark.tests.cpp @@ -2,7 +2,7 @@ #include -TEST_CASE( "benchmarked", "[.][benchmark]" ) { +TEST_CASE( "benchmarked", "[!benchmark]" ) { static const int size = 100; diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py index 016997cc..49553349 100755 --- a/scripts/approvalTests.py +++ b/scripts/approvalTests.py @@ -145,15 +145,15 @@ print("Running approvals against executable:") print(" " + cmdPath) # Standard console reporter -approve("console.std", ["~[!nonportable]", "--order", "lex"]) +approve("console.std", ["~[!nonportable]~[!benchmark]", "--order", "lex"]) # console reporter, include passes, warn about No Assertions -approve("console.sw", ["~[!nonportable]", "-s", "-w", "NoAssertions", "--order", "lex"]) +approve("console.sw", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "--order", "lex"]) # console reporter, include passes, warn about No Assertions, limit failures to first 4 -approve("console.swa4", ["~[!nonportable]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"]) +approve("console.swa4", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"]) # junit reporter, include passes, warn about No Assertions -approve("junit.sw", ["~[!nonportable]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"]) +approve("junit.sw", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"]) # xml reporter, include passes, warn about No Assertions -approve("xml.sw", ["~[!nonportable]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"]) +approve("xml.sw", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"]) if overallResult != 0: print("If these differences are expected, run approve.py to approve new baselines.") From 519db85758220faa34b587249c335dcc79b0192a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 5 Aug 2017 21:41:56 +0100 Subject: [PATCH 202/398] Report benchmark durations in natural units (and extended StringRef to be able to report utf8 char lengths --- include/internal/catch_string.cpp | 3 + include/internal/catch_string.h | 2 + include/internal/catch_stringref.cpp | 18 +++- include/internal/catch_stringref.h | 1 + include/reporters/catch_reporter_console.cpp | 90 ++++++++++++++++++-- 5 files changed, 106 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_string.cpp b/include/internal/catch_string.cpp index b18f5d1b..73d9d77a 100644 --- a/include/internal/catch_string.cpp +++ b/include/internal/catch_string.cpp @@ -64,6 +64,9 @@ namespace Catch { auto String::size() const noexcept -> size_type { return m_data->size; } + auto String::numberOfCharacters() const noexcept -> size_type { + return StringRef( *this ).numberOfCharacters(); + } auto String::c_str() const noexcept -> char const* { return m_data->chars; } diff --git a/include/internal/catch_string.h b/include/internal/catch_string.h index 5fb477a4..04552037 100644 --- a/include/internal/catch_string.h +++ b/include/internal/catch_string.h @@ -40,6 +40,8 @@ namespace Catch { auto empty() const noexcept -> bool; auto size() const noexcept -> size_type; + auto numberOfCharacters() const noexcept -> size_type; + auto c_str() const noexcept -> char const*; }; diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 9572c56f..44db6858 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -136,7 +136,23 @@ namespace Catch { auto StringRef::size() const noexcept -> size_type { return m_size; } - + auto StringRef::numberOfCharacters() const noexcept -> size_type { + size_type noChars = m_size; + // Make adjustments for uft encodings + for( size_type i=0; i < m_size; ++i ) { + char c = m_start[i]; + if( ( c & 0b11000000 ) == 0b11000000 ) { + if( ( c & 0b11100000 ) == 0b11000000 ) + noChars--; + else if( ( c & 0b11110000 ) == 0b11100000 ) + noChars-=2; + else if( ( c & 0b11111000 ) == 0b11110000 ) + noChars-=3; + } + } + return noChars; + } + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> String { StringBuilder buf; buf.reserve( lhs.size() + rhs.size() ); diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index d7f1efbe..55a99aee 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -56,6 +56,7 @@ namespace Catch { 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*; public: // substrings and searches diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 8ba14f5f..33259041 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -12,6 +12,7 @@ #include "../internal/catch_console_colour.hpp" #include "../internal/catch_version.h" #include "../internal/catch_text.h" +#include "../internal/catch_stringref.h" #include #include @@ -82,6 +83,8 @@ namespace { friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { auto colStr = tp.m_oss.str(); + // This takes account of utf8 encodings + auto strSize = Catch::StringRef( colStr.c_str(), colStr.size() ).numberOfCharacters(); tp.m_oss.str(""); tp.open(); if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { @@ -93,8 +96,8 @@ namespace { tp.m_currentColumn++; auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = ( colStr.size()+2 < static_cast( colInfo.width ) ) - ? std::string( colInfo.width-(colStr.size()+2), ' ' ) + auto padding = ( strSize+2 < static_cast( colInfo.width ) ) + ? std::string( colInfo.width-(strSize+2), ' ' ) : std::string(); if( colInfo.justification == ColumnInfo::Left ) tp.m_os << " " << colStr << padding << " |"; @@ -112,6 +115,79 @@ namespace { return tp; } }; + + class Duration { + enum class Unit { + Auto, + Nanoseconds, + Microseconds, + Milliseconds, + Seconds, + Minutes + }; + static const uint64_t s_nanosecondsInAMicrosecond = 1000; + static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; + static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; + static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; + + uint64_t m_inNanoseconds; + Unit m_units; + + public: + Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) + : m_inNanoseconds( inNanoseconds ), + m_units( units ) + { + if( m_units == Unit::Auto ) { + if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) + m_units = Unit::Nanoseconds; + else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) + m_units = Unit::Microseconds; + else if( m_inNanoseconds < s_nanosecondsInASecond ) + m_units = Unit::Milliseconds; + else if( m_inNanoseconds < s_nanosecondsInAMinute ) + m_units = Unit::Seconds; + else + m_units = Unit::Minutes; + } + + } + + auto value() const -> double { + switch( m_units ) { + case Unit::Microseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); + case Unit::Milliseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); + case Unit::Seconds: + return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); + case Unit::Minutes: + return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); + default: + return static_cast( m_inNanoseconds ); + } + } + auto unitsAsString() const -> std::string { + switch( m_units ) { + case Unit::Nanoseconds: + return "ns"; + case Unit::Microseconds: + return "µs"; + case Unit::Milliseconds: + return "ms"; + case Unit::Seconds: + return "s"; + case Unit::Minutes: + return "m"; + default: + return "** internal error **"; + } + + } + friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { + return os << duration.value() << " " << duration.unitsAsString(); + } + }; } namespace Catch { @@ -123,10 +199,10 @@ namespace Catch { : StreamingReporterBase( config ), m_tablePrinter( config.stream(), { - { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-38, ColumnInfo::Left }, + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-42, ColumnInfo::Left }, { "iters", 8, ColumnInfo::Right }, - { "elapsed ns", 12, ColumnInfo::Right }, - { "average", 12, ColumnInfo::Right } + { "elapsed ns", 14, ColumnInfo::Right }, + { "average", 14, ColumnInfo::Right } } ) {} ~ConsoleReporter() override; @@ -199,11 +275,11 @@ namespace Catch { } } void benchmarkEnded( BenchmarkStats const& stats ) override { - // !TBD: report average times in natural units? + Duration average( stats.elapsedTimeInNanoseconds/stats.iterations ); m_tablePrinter << stats.iterations << ColumnBreak() << stats.elapsedTimeInNanoseconds << ColumnBreak() - << stats.elapsedTimeInNanoseconds/stats.iterations << " ns" << ColumnBreak(); + << average << ColumnBreak(); } void testCaseEnded( TestCaseStats const& _testCaseStats ) override { From cff3818e68158275d4d0353dc4bf359bbba1c57f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 5 Aug 2017 22:24:17 +0100 Subject: [PATCH 203/398] Correctly handle special tags that also imply being hidden (!benchmark) --- include/internal/catch_test_case_info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 9c707307..a811f1df 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -69,7 +69,7 @@ namespace Catch { else { if( c == ']' ) { TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); - if( prop == TestCaseInfo::IsHidden ) + if( ( prop & TestCaseInfo::IsHidden ) != 0 ) isHidden = true; else if( prop == TestCaseInfo::None ) enforceNotReservedTag( tag, _lineInfo ); From b3b29f4b4c45752d95e2cae3a224d2f5844cb4e8 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 5 Aug 2017 22:53:21 +0100 Subject: [PATCH 204/398] Use size_t for String size types --- include/internal/catch_string.h | 4 +++- include/internal/catch_stringbuilder.h | 4 +++- include/internal/catch_stringdata.cpp | 4 ++-- include/internal/catch_stringdata.h | 7 ++++--- include/internal/catch_stringref.h | 4 +++- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_string.h b/include/internal/catch_string.h index 04552037..5691be8d 100644 --- a/include/internal/catch_string.h +++ b/include/internal/catch_string.h @@ -7,6 +7,8 @@ #ifndef CATCH_STRING_H_INCLUDED #define CATCH_STRING_H_INCLUDED +#include + namespace Catch { class StringData; @@ -22,7 +24,7 @@ namespace Catch { StringData const* m_data = nullptr; public: - using size_type = unsigned long; + using size_type = size_t; String(); String( StringRef const& stringRef ); diff --git a/include/internal/catch_stringbuilder.h b/include/internal/catch_stringbuilder.h index c3d99d81..2f7d8a2d 100644 --- a/include/internal/catch_stringbuilder.h +++ b/include/internal/catch_stringbuilder.h @@ -9,6 +9,8 @@ #include "catch_stringref.h" +#include + namespace Catch { class String; @@ -22,7 +24,7 @@ namespace Catch { class StringBuilder { friend class String; public: - using size_type = unsigned long; + using size_type = size_t; StringBuilder(); StringBuilder( size_type initialCapacity ); diff --git a/include/internal/catch_stringdata.cpp b/include/internal/catch_stringdata.cpp index 434368de..5261739a 100644 --- a/include/internal/catch_stringdata.cpp +++ b/include/internal/catch_stringdata.cpp @@ -21,7 +21,7 @@ namespace Catch { auto StringData::create( StringRef const& stringRef ) -> StringData* { return create( stringRef, stringRef.size() ); } - auto StringData::create( StringRef const& stringRef, unsigned long capacity ) -> StringData* { + auto StringData::create( StringRef const& stringRef, size_t capacity ) -> StringData* { if( capacity == 0 ) { return getEmpty(); } @@ -37,7 +37,7 @@ namespace Catch { : m_refs( initialRef ), size( 0 ) {} - StringData::StringData( StringRef const& stringRef, unsigned long capacity ) + StringData::StringData( StringRef const& stringRef, size_t capacity ) : m_refs( 1 ), size( capacity) { diff --git a/include/internal/catch_stringdata.h b/include/internal/catch_stringdata.h index aaa9ec8e..d4016976 100644 --- a/include/internal/catch_stringdata.h +++ b/include/internal/catch_stringdata.h @@ -8,6 +8,7 @@ #define CATCH_STRINGDATA_H_INCLUDED #include +#include namespace Catch { @@ -16,7 +17,7 @@ namespace Catch { class StringData { mutable std::atomic m_refs; public: - unsigned int size; + size_t size; union { char chars[1]; }; @@ -26,7 +27,7 @@ namespace Catch { } static auto getEmpty() -> StringData*; static auto create( StringRef const& stringRef ) -> StringData*; - static auto create( StringRef const& stringRef, unsigned long capacity ) -> StringData*; + static auto create( StringRef const& stringRef, size_t capacity ) -> StringData*; void addRef() const noexcept { if( m_refs > 0 ) @@ -41,7 +42,7 @@ namespace Catch { } private: StringData( unsigned int initialRef = 1 ); - StringData( StringRef const& stringRef, unsigned long capacity ); + StringData( StringRef const& stringRef, size_t capacity ); StringData( StringData const& ) = delete; StringData& operator=( StringData const& ) = delete; diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index 55a99aee..f84ce99a 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -7,6 +7,8 @@ #ifndef CATCH_STRINGREF_H_INCLUDED #define CATCH_STRINGREF_H_INCLUDED +#include + namespace Catch { class String; @@ -24,7 +26,7 @@ namespace Catch { friend class StringData; friend class StringBuilder; - using size_type = unsigned long; + using size_type = size_t; char const* m_start; size_type m_size; From 0a2ce87d32be210f62800e8e5711551e8ba8fbc6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sun, 6 Aug 2017 00:13:00 +0100 Subject: [PATCH 205/398] Removed compare layer from expression evaluation --- include/internal/catch_evaluate.hpp | 162 +++++----------------- include/internal/catch_expression_lhs.hpp | 2 +- 2 files changed, 33 insertions(+), 131 deletions(-) diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 9d9da64c..8c9a69f9 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -31,8 +31,7 @@ namespace Internal { const char* operatorName(Operator op); template - T& opCast(T const& t) { return const_cast(t); } - std::nullptr_t opCast(std::nullptr_t); + T& removeConst(T const &t) { return const_cast(t); } // So the compare overloads can be operator agnostic we convey the operator as a template @@ -43,162 +42,65 @@ namespace Internal { template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs) { - return bool( opCast( lhs ) == opCast( rhs ) ); + return bool(removeConst(lhs) == removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) != opCast( rhs ) ); + return bool(removeConst(lhs) != removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) < opCast( rhs ) ); + return bool(removeConst(lhs) < removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) > opCast( rhs ) ); + return bool(removeConst(lhs) > removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) >= opCast( rhs ) ); + return bool(removeConst(lhs) >= removeConst(rhs) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool( opCast( lhs ) <= opCast( rhs ) ); + return bool(removeConst(lhs) <= removeConst(rhs) ); } }; - template - bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // This level of indirection allows us to specialise for integer types - // to avoid signed/ unsigned warnings - - // "base" overload - template - bool compare( T1 const& lhs, T2 const& rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - template - bool compare( void const* lhs, void const* rhs ) { - return Evaluator::evaluate( lhs, rhs ); - } - - // unsigned X to int - template bool compare( unsigned int lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, int rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // unsigned X to long - template bool compare( unsigned int lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned long lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - template bool compare( unsigned char lhs, long rhs ) { - return applyEvaluator( lhs, static_cast( rhs ) ); - } - - // int to unsigned X - template bool compare( int lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( int lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // long to unsigned X - template bool compare( long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long (when comparing against NULL) - template bool compare( long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - - // pointer to int (when comparing against NULL) - template bool compare( int lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, int rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - - // long long to unsigned X - template bool compare( long long lhs, unsigned int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( long long lhs, unsigned char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // unsigned long long to X - template bool compare( unsigned long long lhs, int rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, long long rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - template bool compare( unsigned long long lhs, char rhs ) { - return applyEvaluator( static_cast( lhs ), rhs ); - } - - // pointer to long long (when comparing against NULL) - template bool compare( long long lhs, T* rhs ) { - return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); - } - template bool compare( T* lhs, long long rhs ) { - return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); - } - - // pointer to nullptr_t (when comparing against nullptr) - template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( nullptr, rhs ); - } - template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, nullptr ); - } + // Special case for comparing a pointer to an int (deduced for p==0) + template + struct Evaluator { + static bool evaluate( int lhs, T* rhs) { + return reinterpret_cast( lhs ) == rhs; + } + }; + template + struct Evaluator { + static bool evaluate( T* lhs, int rhs) { + return lhs == reinterpret_cast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( int lhs, T* rhs) { + return reinterpret_cast( lhs ) != rhs; + } + }; + template + struct Evaluator { + static bool evaluate( T* lhs, int rhs) { + return lhs != reinterpret_cast( rhs ); + } + }; } // end of namespace Internal } // end of namespace Catch diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 192f001a..35675aee 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -113,7 +113,7 @@ public: void endExpression() const { m_rb - .setResultType( Internal::compare( m_lhs, m_rhs ) ) + .setResultType( Internal::Evaluator::evaluate( m_lhs, m_rhs ) ) .endExpression( *this ); } From 63392e095ea5c172f828c8a3d947b9c62bc7bd08 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sun, 6 Aug 2017 00:29:37 +0100 Subject: [PATCH 206/398] Refactored Evaluator templates to only be specialised on Op, with Lhs/Rhs types templated on method instead --- include/internal/catch_evaluate.hpp | 88 +++++++++++------------ include/internal/catch_expression_lhs.hpp | 2 +- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 8c9a69f9..91e01908 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -36,71 +36,67 @@ namespace Internal { // So the compare overloads can be operator agnostic we convey the operator as a template // enum, which is used to specialise an Evaluator for doing the comparison. - template + template struct Evaluator{}; - template - struct Evaluator { + template<> + struct Evaluator { + template static bool evaluate( T1 const& lhs, T2 const& rhs) { return bool(removeConst(lhs) == removeConst(rhs) ); } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) != removeConst(rhs) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) < removeConst(rhs) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) > removeConst(rhs) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) >= removeConst(rhs) ); - } - }; - template - struct Evaluator { - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) <= removeConst(rhs) ); - } - }; - - // Special case for comparing a pointer to an int (deduced for p==0) - template - struct Evaluator { + template static bool evaluate( int lhs, T* rhs) { return reinterpret_cast( lhs ) == rhs; } - }; - template - struct Evaluator { + template static bool evaluate( T* lhs, int rhs) { return lhs == reinterpret_cast( rhs ); } }; - template - struct Evaluator { + template<> + struct Evaluator { + template + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool(removeConst(lhs) != removeConst(rhs) ); + } + template static bool evaluate( int lhs, T* rhs) { return reinterpret_cast( lhs ) != rhs; } - }; - template - struct Evaluator { + template static bool evaluate( T* lhs, int rhs) { return lhs != reinterpret_cast( rhs ); } }; + template<> + struct Evaluator { + template + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool(removeConst(lhs) < removeConst(rhs) ); + } + }; + template<> + struct Evaluator { + template + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool(removeConst(lhs) > removeConst(rhs) ); + } + }; + template<> + struct Evaluator { + template + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool(removeConst(lhs) >= removeConst(rhs) ); + } + }; + template<> + struct Evaluator { + template + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return bool(removeConst(lhs) <= removeConst(rhs) ); + } + }; } // end of namespace Internal } // end of namespace Catch diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp index 35675aee..08625019 100644 --- a/include/internal/catch_expression_lhs.hpp +++ b/include/internal/catch_expression_lhs.hpp @@ -113,7 +113,7 @@ public: void endExpression() const { m_rb - .setResultType( Internal::Evaluator::evaluate( m_lhs, m_rhs ) ) + .setResultType( Internal::Evaluator::evaluate( m_lhs, m_rhs ) ) .endExpression( *this ); } From 3a409e9fd4858f46bb0c753f1e967b23005e2aef Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sun, 6 Aug 2017 00:38:03 +0100 Subject: [PATCH 207/398] Suppress more signed/ unsigned mismatches during Evaluator calls on MSVC --- include/internal/catch_evaluate.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 91e01908..33ccd5ef 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -11,6 +11,7 @@ #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(disable:4018) // more "signed/unsigned mismatch" #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) #endif From e658bacb04ef5c14c1dcb192c9e5c99cef390582 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 7 Aug 2017 00:09:54 +0100 Subject: [PATCH 208/398] Refactored how FAST_COMPILE affects internal test macros (less duplication) --- include/catch.hpp | 19 ---------- include/internal/catch_capture.hpp | 45 +++++++---------------- include/internal/catch_result_builder.cpp | 1 + 3 files changed, 14 insertions(+), 51 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 00a49956..58d8c9d5 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -67,13 +67,8 @@ // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#else #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#endif #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) @@ -100,11 +95,7 @@ #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif #endif // CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) @@ -138,14 +129,8 @@ // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) -#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) - -#else #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) -#endif #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) @@ -173,11 +158,7 @@ #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) -#if defined(CATCH_CONFIG_FAST_COMPILE) -#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#else #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) -#endif // CATCH_CONFIG_FAST_COMPILE #endif // CATCH_CONFIG_DISABLE_MATCHERS #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index d331e19b..c5438266 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -31,28 +31,11 @@ // macros. // This can potentially cause false negative, if the test code catches // the exception before it propagates back up to the runner. -#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= expr ).endExpression(); \ - CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look -// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - __catchResult.setExceptionGuard(); \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - __catchResult.unsetExceptionGuard(); \ - INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::alwaysFalse() ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS -#else +#define INTERNAL_CATCH_TRY +#define INTERNAL_CATCH_CATCH( capturer, disposition ) + +#else // CATCH_CONFIG_FAST_COMPILE + /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. @@ -61,21 +44,21 @@ #define INTERNAL_CATCH_REACT( resultBuilder ) \ if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ resultBuilder.react(); -#endif +#define INTERNAL_CATCH_TRY try +#define INTERNAL_CATCH_CATCH( capturer, disposition ) catch(...) { capturer.useActiveException( disposition ); } + +#endif /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ - try { \ + INTERNAL_CATCH_TRY { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ ( __catchResult <= __VA_ARGS__ ).endExpression(); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } \ - catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ + } INTERNAL_CATCH_CATCH( __catchResult, resultDisposition ) \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. @@ -160,11 +143,9 @@ #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - try { \ + INTERNAL_CATCH_TRY { \ __catchResult.captureMatch( arg, matcher, #matcher ); \ - } catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ - } \ + } INTERNAL_CATCH_CATCH( __catchResult, resultDisposition ) \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index 8670136f..b3a7f28f 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -14,6 +14,7 @@ #include "catch_interfaces_registry_hub.h" #include "catch_matchers_string.h" #include "catch_wildcard_pattern.hpp" +#include "catch_debugger.h" #include From 5e60050299ace9652c50103b8febbb0e4be67475 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 01:02:24 +0100 Subject: [PATCH 209/398] Removed default ctors for AssertionInfo, AssertionResult and SourceLineInfo --- include/internal/catch_assertionresult.cpp | 2 -- include/internal/catch_assertionresult.h | 3 +-- include/internal/catch_common.cpp | 1 - include/internal/catch_common.h | 4 ++-- include/internal/catch_notimplemented_exception.cpp | 3 +-- include/internal/catch_notimplemented_exception.h | 1 - include/internal/catch_run_context.cpp | 8 +++++--- include/internal/catch_run_context.hpp | 2 +- projects/SelfTest/PartTrackerTests.cpp | 2 +- 9 files changed, 11 insertions(+), 15 deletions(-) diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 9a4b0c65..63c8b22c 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -49,8 +49,6 @@ namespace Catch { return reconstructedExpression; } - AssertionResult::AssertionResult() {} - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) : m_info( info ), m_resultData( data ) diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 89a96298..eac589c6 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -39,7 +39,7 @@ namespace Catch { struct AssertionInfo { - AssertionInfo() = default; + AssertionInfo() = delete; AssertionInfo( char const * _macroName, SourceLineInfo const& _lineInfo, char const * _capturedExpression, @@ -66,7 +66,6 @@ namespace Catch { class AssertionResult { public: - AssertionResult(); AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); ~AssertionResult(); diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp index 753b9487..01c18ba4 100644 --- a/include/internal/catch_common.cpp +++ b/include/internal/catch_common.cpp @@ -15,7 +15,6 @@ namespace Catch { - SourceLineInfo::SourceLineInfo() noexcept : file(""), line( 0 ){} SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept : file( _file ), line( _line ) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index c62fafe2..269643ae 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -47,10 +47,10 @@ namespace Catch { struct SourceLineInfo { - SourceLineInfo() noexcept; + SourceLineInfo() = delete; SourceLineInfo( char const* _file, std::size_t _line ) noexcept; - SourceLineInfo(SourceLineInfo const& other) = default; + SourceLineInfo( SourceLineInfo const& other ) = default; SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; diff --git a/include/internal/catch_notimplemented_exception.cpp b/include/internal/catch_notimplemented_exception.cpp index 62188ef3..f44d8e10 100644 --- a/include/internal/catch_notimplemented_exception.cpp +++ b/include/internal/catch_notimplemented_exception.cpp @@ -11,8 +11,7 @@ namespace Catch { - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) - : m_lineInfo( lineInfo ) { + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) { std::ostringstream oss; oss << lineInfo << ": function "; oss << "not implemented"; diff --git a/include/internal/catch_notimplemented_exception.h b/include/internal/catch_notimplemented_exception.h index 4769c57d..19e185b6 100644 --- a/include/internal/catch_notimplemented_exception.h +++ b/include/internal/catch_notimplemented_exception.h @@ -25,7 +25,6 @@ namespace Catch { private: std::string m_what; - SourceLineInfo m_lineInfo; }; } // end namespace Catch diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index b54742ff..57e79ef6 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -19,10 +19,12 @@ namespace Catch { } RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) - : m_runInfo(_config->name()), + : m_runInfo(_config->name()), m_context(getCurrentMutableContext()), m_config(_config), - m_reporter(std::move(reporter)) { + m_reporter(std::move(reporter)), + m_lastAssertionInfo( "", SourceLineInfo("",0), "", ResultDisposition::Normal ) + { m_context.setRunner(this); m_context.setConfig(m_config); m_context.setResultCapture(this); @@ -180,7 +182,7 @@ namespace Catch { } const AssertionResult * RunContext::getLastResult() const { - return &m_lastResult; + return &(*m_lastResult); } void RunContext::exceptionEarlyReported() { diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index ee923e88..9e9f8974 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -111,7 +111,7 @@ namespace Catch { IMutableContext& m_context; TestCase const* m_activeTestCase = nullptr; ITracker* m_testCaseTracker; - AssertionResult m_lastResult; + Option m_lastResult; IConfigPtr m_config; Totals m_totals; diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index ff21e74d..26473de2 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -37,7 +37,7 @@ using namespace Catch; //} Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) { - return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo() ); + return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo("",0) ); } TEST_CASE( "Tracker" ) { From 59f9bcf1ed38afc363dbb899e38821a44132589c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 01:08:07 +0100 Subject: [PATCH 210/398] Reduced AssertionInfo to a pure record type --- include/internal/catch_assertionresult.cpp | 14 +------------- include/internal/catch_assertionresult.h | 21 ++++++--------------- include/internal/catch_result_builder.cpp | 2 +- include/internal/catch_run_context.cpp | 6 +++--- 4 files changed, 11 insertions(+), 32 deletions(-) diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 63c8b22c..f6bb2cfb 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -14,17 +14,7 @@ namespace Catch { bool DecomposedExpression::isBinaryExpression() const { return false; } - - AssertionInfo::AssertionInfo( char const * _macroName, - SourceLineInfo const& _lineInfo, - char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition) - : macroName( _macroName ), - lineInfo( _lineInfo ), - capturedExpression( _capturedExpression ), - resultDisposition( _resultDisposition ) - {} - + void AssertionResultData::negate( bool parenthesize ) { negated = !negated; parenthesized = parenthesize; @@ -54,8 +44,6 @@ namespace Catch { m_resultData( data ) {} - AssertionResult::~AssertionResult() {} - // Result was a success bool AssertionResult::succeeded() const { return Catch::isOk( m_resultData.resultType ); diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index eac589c6..8c0d198a 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -39,16 +39,12 @@ namespace Catch { struct AssertionInfo { - AssertionInfo() = delete; - AssertionInfo( char const * _macroName, - SourceLineInfo const& _lineInfo, - char const * _capturedExpression, - ResultDisposition::Flags _resultDisposition); - - char const * macroName = nullptr; + char const * macroName; SourceLineInfo lineInfo; - char const * capturedExpression = nullptr; - ResultDisposition::Flags resultDisposition = ResultDisposition::Normal; + char const * capturedExpression; + ResultDisposition::Flags resultDisposition; + + AssertionInfo() = delete; }; struct AssertionResultData @@ -66,13 +62,8 @@ namespace Catch { class AssertionResult { public: + AssertionResult() = delete; AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); - ~AssertionResult(); - - AssertionResult( AssertionResult const& ) = default; - AssertionResult( AssertionResult && ) = default; - AssertionResult& operator = ( AssertionResult const& ) = default; - AssertionResult& operator = ( AssertionResult && ) = default; bool isOk() const; bool succeeded() const; diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index b3a7f28f..c154010a 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -34,7 +34,7 @@ namespace Catch { SourceLineInfo const& lineInfo, char const* capturedExpression, ResultDisposition::Flags resultDisposition ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition) + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } { getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); } diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 57e79ef6..8b89df9c 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -23,7 +23,7 @@ namespace Catch { m_context(getCurrentMutableContext()), m_config(_config), m_reporter(std::move(reporter)), - m_lastAssertionInfo( "", SourceLineInfo("",0), "", ResultDisposition::Normal ) + m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal } { m_context.setRunner(this); m_context.setConfig(m_config); @@ -107,7 +107,7 @@ namespace Catch { static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); // Reset working state - m_lastAssertionInfo = AssertionInfo("", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition); + m_lastAssertionInfo = { "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition }; m_lastResult = result; } @@ -250,7 +250,7 @@ namespace Catch { double duration = 0; m_shouldReportUnexpected = true; try { - m_lastAssertionInfo = AssertionInfo("TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal); + m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal }; seedRng(*m_config); From f8148ebae1e07c5609ed0af5993694e2972d0dfd Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 01:22:21 +0100 Subject: [PATCH 211/398] Made macroName and capturedExpression StringRefs --- include/internal/catch_assertionresult.cpp | 12 ++++++------ include/internal/catch_assertionresult.h | 5 +++-- include/internal/catch_interfaces_reporter.cpp | 2 +- include/internal/catch_result_builder.cpp | 8 ++++---- include/internal/catch_result_builder.h | 4 ++-- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index f6bb2cfb..6819cd63 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -14,7 +14,7 @@ namespace Catch { bool DecomposedExpression::isBinaryExpression() const { return false; } - + void AssertionResultData::negate( bool parenthesize ) { negated = !negated; parenthesized = parenthesize; @@ -68,16 +68,16 @@ namespace Catch { std::string AssertionResult::getExpression() const { if (isFalseTest(m_info.resultDisposition)) - return '!' + std::string(m_info.capturedExpression); + return '!' + std::string(m_info.capturedExpression.c_str()); else - return std::string(m_info.capturedExpression); + return std::string(m_info.capturedExpression.c_str()); } std::string AssertionResult::getExpressionInMacro() const { if( m_info.macroName[0] == 0 ) - return std::string(m_info.capturedExpression); + return std::string(m_info.capturedExpression.c_str()); else - return std::string(m_info.macroName) + "( " + m_info.capturedExpression + " )"; + return std::string(m_info.macroName.c_str()) + "( " + m_info.capturedExpression.c_str() + " )"; } bool AssertionResult::hasExpandedExpression() const { @@ -96,7 +96,7 @@ namespace Catch { } std::string AssertionResult::getTestMacroName() const { - return m_info.macroName; + return m_info.macroName.c_str(); } void AssertionResult::discardDecomposedExpression() const { diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 8c0d198a..7e67faaa 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -11,6 +11,7 @@ #include #include "catch_result_type.h" #include "catch_common.h" +#include "catch_stringref.h" namespace Catch { @@ -39,9 +40,9 @@ namespace Catch { struct AssertionInfo { - char const * macroName; + StringRef macroName; SourceLineInfo lineInfo; - char const * capturedExpression; + StringRef capturedExpression; ResultDisposition::Flags resultDisposition; AssertionInfo() = delete; diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp index 8ad16248..2f820bf8 100644 --- a/include/internal/catch_interfaces_reporter.cpp +++ b/include/internal/catch_interfaces_reporter.cpp @@ -40,7 +40,7 @@ namespace Catch { if( assertionResult.hasMessage() ) { // Copy message into messages list. // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + MessageBuilder builder( assertionResult.getTestMacroName().c_str(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); builder << assertionResult.getMessage(); builder.m_info.message = builder.m_stream.str(); diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index c154010a..a908c359 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -30,9 +30,9 @@ namespace Catch { } - ResultBuilder::ResultBuilder( char const* macroName, + ResultBuilder::ResultBuilder( StringRef macroName, SourceLineInfo const& lineInfo, - char const* capturedExpression, + StringRef capturedExpression, ResultDisposition::Flags resultDisposition ) : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } { @@ -99,7 +99,7 @@ namespace Catch { assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; - data.reconstructedExpression = m_assertionInfo.capturedExpression; + data.reconstructedExpression = m_assertionInfo.capturedExpression.c_str(); std::string actualMessage = Catch::translateActiveException(); if( !matcher.match( actualMessage ) ) { @@ -166,7 +166,7 @@ namespace Catch { } void ResultBuilder::reconstructExpression( std::string& dest ) const { - dest = m_assertionInfo.capturedExpression; + dest = m_assertionInfo.capturedExpression.c_str(); } void ResultBuilder::setExceptionGuard() { diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 6639b541..1ccdd9c0 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -31,9 +31,9 @@ namespace Catch { class ResultBuilder : public DecomposedExpression { public: - ResultBuilder( char const* macroName, + ResultBuilder( StringRef macroName, SourceLineInfo const& lineInfo, - char const* capturedExpression, + StringRef capturedExpression, ResultDisposition::Flags resultDisposition); ~ResultBuilder(); From f247ce5bff025281d4a7e9fa76aa78eb8479ddfe Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 17:53:01 +0100 Subject: [PATCH 212/398] First cut of new AssertionHandler/ Decomposer - integrated into INTERNAL_CATCH_TEST. Needs more work to fully replace existing stuff --- CMakeLists.txt | 5 + include/internal/catch_assertionhandler.cpp | 135 ++++++++++++++++ include/internal/catch_assertionhandler.h | 61 +++++++ include/internal/catch_assertioninfo.h | 29 ++++ include/internal/catch_assertionresult.cpp | 36 +++-- include/internal/catch_assertionresult.h | 36 +++-- include/internal/catch_capture.hpp | 14 +- include/internal/catch_decomposer.cpp | 23 +++ include/internal/catch_decomposer.h | 149 ++++++++++++++++++ .../internal/catch_interfaces_reporter.cpp | 2 + include/internal/catch_result_builder.cpp | 4 +- include/internal/catch_result_builder.h | 6 +- include/internal/catch_run_context.cpp | 2 +- include/reporters/catch_reporter_bases.hpp | 6 +- 14 files changed, 469 insertions(+), 39 deletions(-) create mode 100644 include/internal/catch_assertionhandler.cpp create mode 100644 include/internal/catch_assertionhandler.h create mode 100644 include/internal/catch_assertioninfo.h create mode 100644 include/internal/catch_decomposer.cpp create mode 100644 include/internal/catch_decomposer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 211bfd9d..e454e330 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,8 @@ CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external) # Please keep these ordered alphabetically set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_approx.hpp + ${HEADER_DIR}/internal/catch_assertionhandler.h + ${HEADER_DIR}/internal/catch_assertioninfo.h ${HEADER_DIR}/internal/catch_assertionresult.h ${HEADER_DIR}/internal/catch_capture.hpp ${HEADER_DIR}/internal/catch_clara.h @@ -132,6 +134,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_console_colour.hpp ${HEADER_DIR}/internal/catch_context.h ${HEADER_DIR}/internal/catch_debugger.h + ${HEADER_DIR}/internal/catch_decomposer.h ${HEADER_DIR}/internal/catch_default_main.hpp ${HEADER_DIR}/internal/catch_enforce.h ${HEADER_DIR}/internal/catch_errno_guard.h @@ -198,6 +201,7 @@ set(INTERNAL_HEADERS ) set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_approx.cpp + ${HEADER_DIR}/internal/catch_assertionhandler.cpp ${HEADER_DIR}/internal/catch_assertionresult.cpp ${HEADER_DIR}/internal/catch_benchmark.cpp ${HEADER_DIR}/internal/catch_commandline.cpp @@ -206,6 +210,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_console_colour.cpp ${HEADER_DIR}/internal/catch_context.cpp ${HEADER_DIR}/internal/catch_debugger.cpp + ${HEADER_DIR}/internal/catch_decomposer.cpp ${HEADER_DIR}/internal/catch_errno_guard.cpp ${HEADER_DIR}/internal/catch_evaluate.cpp ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp new file mode 100644 index 00000000..a71a2dc2 --- /dev/null +++ b/include/internal/catch_assertionhandler.cpp @@ -0,0 +1,135 @@ +/* + * Created by Phil on 8/8/2017. + * Copyright 2017 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) + */ + +#include "catch_assertionhandler.h" +#include "catch_assertionresult.h" +#include "catch_interfaces_capture.h" +#include "catch_interfaces_runner.h" +#include "catch_context.h" +#include "catch_debugger.h" +#include "catch_interfaces_registry_hub.h" + +#include // !TBD + +namespace Catch { + + auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { + expr.streamReconstructedExpression( os ); + return os; + } + + LazyExpression::LazyExpression( bool isNegated ) + : m_isNegated( isNegated ) + {} + + LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} + + LazyExpression::operator bool() const { + return m_transientExpression != nullptr; + } + + auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { + if( lazyExpr.m_isNegated ) + os << "!"; + + if( lazyExpr ) { + if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) + os << "(" << *lazyExpr.m_transientExpression << ")"; + else + os << *lazyExpr.m_transientExpression; + } + else { + os << "{** error - unchecked empty expression requested **}"; + } + return os; + } + + AssertionHandler::AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } + { + getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); + } + + void AssertionHandler::handle( ITransientExpression const& expr ) { + + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + bool result = expr.getResult() != negated; + + AssertionResultData data( result ? ResultWas::Ok : ResultWas::ExpressionFailed, LazyExpression( negated ) ); + + // Deprecated +// data.negated = negated; +// data.parenthesized = negated && expr.isBinaryExpression(); // !TBD: needed? +// data.decomposedExpression = nullptr; // !TBD +// data.reconstructedExpression = ""; // !TBD + + + getResultCapture().assertionRun(); + + AssertionResult assertionResult{ m_assertionInfo, data }; + assertionResult.m_resultData.lazyExpression.m_transientExpression = &expr; + + getResultCapture().assertionEnded( assertionResult ); + + if( !assertionResult.isOk() ) { + m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); + m_shouldThrow = + getCurrentContext().getRunner()->aborting() || + (m_assertionInfo.resultDisposition & ResultDisposition::Normal); + } + } + + auto AssertionHandler::shouldDebugBreak() const -> bool { + return m_shouldDebugBreak; + } + void AssertionHandler::reactWithDebugBreak() const { + if (m_shouldDebugBreak) { + /////////////////////////////////////////////////////////////////// + // To inspect the state during test, you need to go one level up the callstack + // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call + /////////////////////////////////////////////////////////////////// + CATCH_BREAK_INTO_DEBUGGER(); + } + reactWithoutDebugBreak(); + } + void AssertionHandler::reactWithoutDebugBreak() const { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + void AssertionHandler::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + useActiveException(); + } + void AssertionHandler::useActiveException() { + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + + AssertionResultData data( ResultWas::ThrewException, LazyExpression( negated ) ); + data.message = Catch::translateActiveException(); + + //data.decomposedExpression = &expr; // for lazy reconstruction + + AssertionResult result( m_assertionInfo, data ); + + getResultCapture().assertionEnded( result ); + + // !TBD: factor this out? handleResult()? + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + + } + +} // namespace Catch diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h new file mode 100644 index 00000000..8c8dff67 --- /dev/null +++ b/include/internal/catch_assertionhandler.h @@ -0,0 +1,61 @@ +/* + * Created by Phil on 8/8/2017. + * Copyright 2017 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) + */ +#ifndef TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED +#define TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED + +#include "catch_decomposer.h" +#include "catch_assertioninfo.h" + +namespace Catch { + + struct TestFailureException{}; + + class LazyExpression { + friend class AssertionHandler; + friend struct AssertionStats; + + ITransientExpression const* m_transientExpression = nullptr; + bool m_isNegated; + public: + LazyExpression( bool isNegated ); + LazyExpression( LazyExpression const& other ); + LazyExpression& operator = ( LazyExpression const& ) = delete; + + explicit operator bool() const; + + friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; + }; + + class AssertionHandler { + AssertionInfo m_assertionInfo; + bool m_shouldDebugBreak = false; + bool m_shouldThrow = false; + public: + AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ); + + void handle( ITransientExpression const& expr ); + + template + void handle( ExprLhs const& expr ) { + handle( expr.makeUnaryExpr() ); + } + + auto shouldDebugBreak() const -> bool; + void reactWithDebugBreak() const; + void reactWithoutDebugBreak() const; + void useActiveException( ResultDisposition::Flags resultDisposition ); + void useActiveException(); + }; + +} // namespace Catch + +#endif // TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED diff --git a/include/internal/catch_assertioninfo.h b/include/internal/catch_assertioninfo.h new file mode 100644 index 00000000..21646b21 --- /dev/null +++ b/include/internal/catch_assertioninfo.h @@ -0,0 +1,29 @@ +/* + * Created by Phil on 8/8/2017. + * Copyright 2017 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) + */ +#ifndef TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED +#define TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED + +#include "catch_result_type.h" +#include "catch_common.h" +#include "catch_stringref.h" + +namespace Catch { + + struct AssertionInfo + { + StringRef macroName; + SourceLineInfo lineInfo; + StringRef capturedExpression; + ResultDisposition::Flags resultDisposition; + + AssertionInfo() = delete; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 6819cd63..877f53bf 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -24,17 +24,30 @@ namespace Catch { resultType = ResultWas::Ok; } - std::string const& AssertionResultData::reconstructExpression() const { - if( decomposedExpression != nullptr ) { - decomposedExpression->reconstructExpression( reconstructedExpression ); - if( parenthesized ) { - reconstructedExpression.insert( 0, 1, '(' ); - reconstructedExpression.append( 1, ')' ); + std::string AssertionResultData::reconstructExpression() const { + + if( reconstructedExpression.empty() ) { + + // Try new LazyExpression first... + if( lazyExpression ) { + // !TBD Use stringstream for now, but rework above to pass stream in + std::ostringstream oss; + oss << lazyExpression; + reconstructedExpression = oss.str(); } - if( negated ) { - reconstructedExpression.insert( 0, 1, '!' ); + + // ... if not, fall back to decomposedExpression + else if( decomposedExpression != nullptr ) { + decomposedExpression->reconstructExpression( reconstructedExpression ); + if( parenthesized ) { + reconstructedExpression.insert( 0, 1, '(' ); + reconstructedExpression.append( 1, ')' ); + } + if( negated ) { + reconstructedExpression.insert( 0, 1, '!' ); + } + decomposedExpression = nullptr; } - decomposedExpression = nullptr; } return reconstructedExpression; } @@ -85,7 +98,10 @@ namespace Catch { } std::string AssertionResult::getExpandedExpression() const { - return m_resultData.reconstructExpression(); + std::string expr = m_resultData.reconstructExpression(); + return expr.empty() + ? getExpression() + : expr; } std::string AssertionResult::getMessage() const { diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 7e67faaa..9bd8e39d 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -9,9 +9,11 @@ #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED #include +#include "catch_assertioninfo.h" #include "catch_result_type.h" #include "catch_common.h" #include "catch_stringref.h" +#include "catch_assertionhandler.h" namespace Catch { @@ -37,28 +39,32 @@ namespace Catch { template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); }; +} - struct AssertionInfo - { - StringRef macroName; - SourceLineInfo lineInfo; - StringRef capturedExpression; - ResultDisposition::Flags resultDisposition; - - AssertionInfo() = delete; - }; +namespace Catch { struct AssertionResultData { - void negate( bool parenthesize ); - std::string const& reconstructExpression() const; + AssertionResultData() = delete; + + // !TBD We won't need this constructor once the deprecated fields are removed + AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ) + : resultType( _resultType ), + lazyExpression( _lazyExpression ) + {} - mutable DecomposedExpression const* decomposedExpression = nullptr; - mutable std::string reconstructedExpression; - std::string message; ResultWas::OfType resultType = ResultWas::Unknown; + std::string message; + + LazyExpression lazyExpression; + + // deprecated: bool negated = false; bool parenthesized = false; + void negate( bool parenthesize ); + std::string reconstructExpression() const; + mutable DecomposedExpression const* decomposedExpression = nullptr; + mutable std::string reconstructedExpression; }; class AssertionResult { @@ -81,7 +87,7 @@ namespace Catch { void discardDecomposedExpression() const; void expandDecomposedExpression() const; - protected: + //protected: AssertionInfo m_info; AssertionResultData m_resultData; }; diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index c5438266..aafafeef 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -8,6 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED +#include "catch_assertionhandler.h" #include "catch_result_builder.h" #include "catch_message.h" #include "catch_interfaces_capture.h" @@ -43,7 +44,10 @@ // source code rather than in Catch library code #define INTERNAL_CATCH_REACT( resultBuilder ) \ if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - resultBuilder.react(); + resultBuilder.react(); +#define INTERNAL_CATCH_REACT2( handler ) \ + if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + handler.reactWithDebugBreak(); #define INTERNAL_CATCH_TRY try #define INTERNAL_CATCH_CATCH( capturer, disposition ) catch(...) { capturer.useActiveException( disposition ); } @@ -53,13 +57,13 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ INTERNAL_CATCH_TRY { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - ( __catchResult <= __VA_ARGS__ ).endExpression(); \ + catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } INTERNAL_CATCH_CATCH( __catchResult, resultDisposition ) \ - INTERNAL_CATCH_REACT( __catchResult ) \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler, resultDisposition ) \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. diff --git a/include/internal/catch_decomposer.cpp b/include/internal/catch_decomposer.cpp new file mode 100644 index 00000000..6e69bc43 --- /dev/null +++ b/include/internal/catch_decomposer.cpp @@ -0,0 +1,23 @@ +/* + * Created by Phil Nash on 8/8/2017. + * Copyright 2017 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) + */ + +#include "catch_decomposer.h" +#include "catch_config.hpp" + +namespace Catch { + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) { + + if( lhs.size() + rhs.size() < 40 && + lhs.find('\n') == std::string::npos && + rhs.find('\n') == std::string::npos ) + os << lhs << " " << op << " " << rhs; + else + os << lhs << "\n" << op << "\n" << rhs; + } +} \ No newline at end of file diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h new file mode 100644 index 00000000..82e386a5 --- /dev/null +++ b/include/internal/catch_decomposer.h @@ -0,0 +1,149 @@ +/* + * Created by Phil Nash on 8/8/2017. + * Copyright 2017 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) + */ +#ifndef TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED +#define TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED + +#include "catch_tostring.h" +#include "catch_stringref.h" + +#include + +namespace Catch { + + struct ITransientExpression { + virtual auto isBinaryExpression() const -> bool = 0; + virtual auto getResult() const -> bool = 0; + virtual void streamReconstructedExpression( std::ostream &os ) const = 0; + }; + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); + + template + class BinaryExpr : public ITransientExpression { + bool m_result; + LhsT m_lhs; + std::string m_op; + RhsT m_rhs; + + auto isBinaryExpression() const -> bool override { return true; } + auto getResult() const -> bool override { return m_result; } + + void streamReconstructedExpression( std::ostream &os ) const override { + formatReconstructedExpression + ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); + } + + public: + BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) + : m_result( comparisionResult ), + m_lhs( lhs ), + m_op( op.c_str() ), + m_rhs( rhs ) + {} + }; + + template + class UnaryExpr : public ITransientExpression { + LhsT m_lhs; + + auto isBinaryExpression() const -> bool override { return false; } + auto getResult() const -> bool override { return m_lhs ? true : false; } + + void streamReconstructedExpression( std::ostream &os ) const override { + os << Catch::Detail::stringify( m_lhs ); + } + + public: + UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {} + }; + + + // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) + template + auto compareEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; + template + auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + template + auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + + template + auto compareNotEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; + template + auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + template + auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + + + template + class ExprLhs { + LhsT m_lhs; + public: + ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} + + template + auto operator == ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); + } + auto operator == ( bool rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs == rhs, m_lhs, "==", rhs ); + } + + template + auto operator != ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); + } + auto operator != ( bool rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs != rhs, m_lhs, "!=", rhs ); + } + + template + auto operator > ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); + } + template + auto operator < ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); + } + template + auto operator >= ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); + } + template + auto operator <= ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); + } + + auto makeUnaryExpr() const -> UnaryExpr { + return UnaryExpr( m_lhs ); + } + }; + + void handleExpression( ITransientExpression const& expr ); + + template + void handleExpression( ExprLhs const& expr ) { + handleExpression( expr.makeUnaryExpr() ); + } + + struct Decomposer { + template + auto operator <= ( T& lhs ) -> ExprLhs { + return ExprLhs( lhs ); + } + template + auto operator <= ( T const& lhs ) -> ExprLhs { + return ExprLhs( lhs ); + } + auto operator <=( bool value ) -> ExprLhs { + return ExprLhs( value ); + } + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp index 2f820bf8..05117f9e 100644 --- a/include/internal/catch_interfaces_reporter.cpp +++ b/include/internal/catch_interfaces_reporter.cpp @@ -37,6 +37,8 @@ namespace Catch { infoMessages( _infoMessages ), totals( _totals ) { + assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; + if( assertionResult.hasMessage() ) { // Copy message into messages list. // !TBD This should have been done earlier, somewhere diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp index a908c359..db7dfb14 100644 --- a/include/internal/catch_result_builder.cpp +++ b/include/internal/catch_result_builder.cpp @@ -13,7 +13,6 @@ #include "catch_interfaces_capture.h" #include "catch_interfaces_registry_hub.h" #include "catch_matchers_string.h" -#include "catch_wildcard_pattern.hpp" #include "catch_debugger.h" #include @@ -34,7 +33,8 @@ namespace Catch { SourceLineInfo const& lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition ) - : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, + m_data( ResultWas::Unknown, LazyExpression( false ) ) { getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); } diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index 1ccdd9c0..6d3a9efc 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -8,8 +8,10 @@ #ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED -#include "catch_result_type.h" #include "catch_assertionresult.h" +#include "catch_decomposer.h" + +#include "catch_result_type.h" #include "catch_common.h" #include "catch_matchers.hpp" @@ -17,8 +19,6 @@ namespace Catch { - struct TestFailureException{}; - template class ExpressionLhs; struct CopyableStream { diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 8b89df9c..509a18e6 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -192,7 +192,7 @@ namespace Catch { void RunContext::handleFatalErrorCondition(std::string const & message) { // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. - AssertionResultData tempResult; + AssertionResultData tempResult( ResultWas::Unknown, { false } ); tempResult.resultType = ResultWas::FatalErrorCondition; tempResult.message = message; AssertionResult result(m_lastAssertionInfo, tempResult); diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 37cc4e00..2f9a8013 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -193,14 +193,14 @@ namespace Catch { bool assertionEnded(AssertionStats const& assertionStats) override { assert(!m_sectionStack.empty()); - SectionNode& sectionNode = *m_sectionStack.back(); - sectionNode.assertions.push_back(assertionStats); // AssertionResult holds a pointer to a temporary DecomposedExpression, // which getExpandedExpression() calls to build the expression string. // Our section stack copy of the assertionResult will likely outlive the // temporary, so it must be expanded or discarded now to avoid calling // a destroyed object later. - prepareExpandedExpression(sectionNode.assertions.back().assertionResult); + prepareExpandedExpression(const_cast( assertionStats.assertionResult ) ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back(assertionStats); return true; } void sectionEnded(SectionStats const& sectionStats) override { From f033f4f1842cb3859b97855261d3119488783b20 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 19:36:18 +0100 Subject: [PATCH 213/398] integrated AssertionHandler into INTERNAL_CATCH_NO_THROW --- include/internal/catch_assertionhandler.cpp | 46 ++++++++------------- include/internal/catch_assertionhandler.h | 4 ++ include/internal/catch_capture.hpp | 11 ++--- 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index a71a2dc2..1b7e1346 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -59,24 +59,17 @@ namespace Catch { getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); } - void AssertionHandler::handle( ITransientExpression const& expr ) { - - bool negated = isFalseTest( m_assertionInfo.resultDisposition ); - bool result = expr.getResult() != negated; - - AssertionResultData data( result ? ResultWas::Ok : ResultWas::ExpressionFailed, LazyExpression( negated ) ); - - // Deprecated -// data.negated = negated; -// data.parenthesized = negated && expr.isBinaryExpression(); // !TBD: needed? -// data.decomposedExpression = nullptr; // !TBD -// data.reconstructedExpression = ""; // !TBD + void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { + AssertionResultData data( resultType, LazyExpression( negated ) ); + handle( data, expr ); + } + void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) { getResultCapture().assertionRun(); - AssertionResult assertionResult{ m_assertionInfo, data }; - assertionResult.m_resultData.lazyExpression.m_transientExpression = &expr; + AssertionResult assertionResult{ m_assertionInfo, resultData }; + assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; getResultCapture().assertionEnded( assertionResult ); @@ -87,6 +80,16 @@ namespace Catch { (m_assertionInfo.resultDisposition & ResultDisposition::Normal); } } + void AssertionHandler::handle( ITransientExpression const& expr ) { + + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + bool result = expr.getResult() != negated; + + handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); + } + void AssertionHandler::handle( ResultWas::OfType resultType ) { + handle( resultType, nullptr, false ); + } auto AssertionHandler::shouldDebugBreak() const -> bool { return m_shouldDebugBreak; @@ -116,20 +119,7 @@ namespace Catch { AssertionResultData data( ResultWas::ThrewException, LazyExpression( negated ) ); data.message = Catch::translateActiveException(); - //data.decomposedExpression = &expr; // for lazy reconstruction - - AssertionResult result( m_assertionInfo, data ); - - getResultCapture().assertionEnded( result ); - - // !TBD: factor this out? handleResult()? - if( !result.isOk() ) { - if( getCurrentContext().getConfig()->shouldDebugBreak() ) - m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) - m_shouldThrow = true; - } - + handle( data, nullptr ); } } // namespace Catch diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h index 8c8dff67..0c8b020b 100644 --- a/include/internal/catch_assertionhandler.h +++ b/include/internal/catch_assertionhandler.h @@ -14,6 +14,7 @@ namespace Catch { struct TestFailureException{}; + struct AssertionResultData; class LazyExpression { friend class AssertionHandler; @@ -48,6 +49,9 @@ namespace Catch { void handle( ExprLhs const& expr ) { handle( expr.makeUnaryExpr() ); } + void handle( ResultWas::OfType resultType ); + void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ); + void handle( AssertionResultData const& resultData, ITransientExpression const* expr ); auto shouldDebugBreak() const -> bool; void reactWithDebugBreak() const; diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index aafafeef..9510d7a5 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -51,6 +51,7 @@ #define INTERNAL_CATCH_TRY try #define INTERNAL_CATCH_CATCH( capturer, disposition ) catch(...) { capturer.useActiveException( disposition ); } +#define INTERNAL_CATCH_CATCH2( capturer ) catch(...) { capturer.useActiveException(); } #endif @@ -62,7 +63,7 @@ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } INTERNAL_CATCH_CATCH( catchAssertionHandler, resultDisposition ) \ + } INTERNAL_CATCH_CATCH2( catchAssertionHandler ) \ INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. @@ -80,15 +81,15 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ try { \ static_cast(__VA_ARGS__); \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ + catchAssertionHandler.useActiveException(); \ } \ - INTERNAL_CATCH_REACT( __catchResult ) \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// From 8a97beece21ac02ba71b03fe33f5ccaba36ff4c0 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 19:43:07 +0100 Subject: [PATCH 214/398] integrated AssertionHandler into INTERNAL_CATCH_THROWS_AS --- include/internal/catch_assertionhandler.cpp | 3 +++ include/internal/catch_assertionhandler.h | 1 + include/internal/catch_capture.hpp | 14 +++++++------- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index 1b7e1346..fe8e32a0 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -90,6 +90,9 @@ namespace Catch { void AssertionHandler::handle( ResultWas::OfType resultType ) { handle( resultType, nullptr, false ); } + auto AssertionHandler::allowThrows() const -> bool { + return getCurrentContext().getConfig()->allowThrows(); + } auto AssertionHandler::shouldDebugBreak() const -> bool { return m_shouldDebugBreak; diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h index 0c8b020b..6e140e44 100644 --- a/include/internal/catch_assertionhandler.h +++ b/include/internal/catch_assertionhandler.h @@ -54,6 +54,7 @@ namespace Catch { void handle( AssertionResultData const& resultData, ITransientExpression const* expr ); auto shouldDebugBreak() const -> bool; + auto allowThrows() const -> bool; void reactWithDebugBreak() const; void reactWithoutDebugBreak() const; void useActiveException( ResultDisposition::Flags resultDisposition ); diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 9510d7a5..68859412 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -112,21 +112,21 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ - if( __catchResult.allowThrows() ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ } \ catch( exceptionType const& ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ + catchAssertionHandler.useActiveException(); \ } \ else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) From 5f9172436883c535de4a119bd3b2314a2a5f9f70 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 20:17:09 +0100 Subject: [PATCH 215/398] integrated AssertionHandler into INTERNAL_CATCH_MSG --- include/internal/catch_assertionhandler.cpp | 32 ++++++++++----------- include/internal/catch_assertionhandler.h | 1 + include/internal/catch_capture.hpp | 7 ++--- include/internal/catch_message.h | 15 ++++++++-- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index fe8e32a0..d53b09fa 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -59,8 +59,22 @@ namespace Catch { getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); } - void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { + void AssertionHandler::handle( ITransientExpression const& expr ) { + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + bool result = expr.getResult() != negated; + + handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); + } + void AssertionHandler::handle( ResultWas::OfType resultType ) { + handle( resultType, nullptr, false ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { + AssertionResultData data( resultType, LazyExpression( false ) ); + data.message = message.c_str(); + handle( data, nullptr ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { AssertionResultData data( resultType, LazyExpression( negated ) ); handle( data, expr ); } @@ -80,16 +94,7 @@ namespace Catch { (m_assertionInfo.resultDisposition & ResultDisposition::Normal); } } - void AssertionHandler::handle( ITransientExpression const& expr ) { - bool negated = isFalseTest( m_assertionInfo.resultDisposition ); - bool result = expr.getResult() != negated; - - handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); - } - void AssertionHandler::handle( ResultWas::OfType resultType ) { - handle( resultType, nullptr, false ); - } auto AssertionHandler::allowThrows() const -> bool { return getCurrentContext().getConfig()->allowThrows(); } @@ -117,12 +122,7 @@ namespace Catch { useActiveException(); } void AssertionHandler::useActiveException() { - bool negated = isFalseTest( m_assertionInfo.resultDisposition ); - - AssertionResultData data( ResultWas::ThrewException, LazyExpression( negated ) ); - data.message = Catch::translateActiveException(); - - handle( data, nullptr ); + handle( ResultWas::ThrewException, Catch::translateActiveException().c_str() ); } } // namespace Catch diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h index 6e140e44..18137448 100644 --- a/include/internal/catch_assertionhandler.h +++ b/include/internal/catch_assertionhandler.h @@ -50,6 +50,7 @@ namespace Catch { handle( expr.makeUnaryExpr() ); } void handle( ResultWas::OfType resultType ); + void handle( ResultWas::OfType resultType, StringRef const& message ); void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ); void handle( AssertionResultData const& resultData, ITransientExpression const* expr ); diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 68859412..13101ec6 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -133,10 +133,9 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ - __catchResult.captureResult( messageType ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str().c_str() ); \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h index 2550fb41..553882b7 100644 --- a/include/internal/catch_message.h +++ b/include/internal/catch_message.h @@ -32,7 +32,19 @@ namespace Catch { static unsigned int globalCount; }; - struct MessageBuilder { + struct MessageStream { + + template + MessageStream& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + // !TBD reuse a global/ thread-local stream + std::ostringstream m_stream; + }; + + struct MessageBuilder : MessageStream { MessageBuilder( std::string const& macroName, SourceLineInfo const& lineInfo, ResultWas::OfType type ); @@ -44,7 +56,6 @@ namespace Catch { } MessageInfo m_info; - std::ostringstream m_stream; }; class ScopedMessage { From 2832e23aa9b4dab95e9391bfc2a8bf86a778b0fb Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 21:07:30 +0100 Subject: [PATCH 216/398] Restored exceptionGuard functionality under CATCH_CONFIG_FAST_COMPILE --- include/internal/catch_assertionhandler.cpp | 18 +++++++++++++++++- include/internal/catch_assertionhandler.h | 5 +++++ include/internal/catch_capture.hpp | 15 +++++++++------ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index d53b09fa..8d99e3d0 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -14,7 +14,7 @@ #include "catch_debugger.h" #include "catch_interfaces_registry_hub.h" -#include // !TBD +#include namespace Catch { @@ -58,6 +58,12 @@ namespace Catch { { getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); } + AssertionHandler::~AssertionHandler() { + if ( m_inExceptionGuard ) { + handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ); + getCurrentContext().getResultCapture()->exceptionEarlyReported(); + } + } void AssertionHandler::handle( ITransientExpression const& expr ) { @@ -125,4 +131,14 @@ namespace Catch { handle( ResultWas::ThrewException, Catch::translateActiveException().c_str() ); } + void AssertionHandler::setExceptionGuard() { + assert( m_inExceptionGuard == false ); + m_inExceptionGuard = true; + } + void AssertionHandler::unsetExceptionGuard() { + assert( m_inExceptionGuard == true ); + m_inExceptionGuard = false; + } + + } // namespace Catch diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h index 18137448..dbbd5157 100644 --- a/include/internal/catch_assertionhandler.h +++ b/include/internal/catch_assertionhandler.h @@ -36,12 +36,15 @@ namespace Catch { AssertionInfo m_assertionInfo; bool m_shouldDebugBreak = false; bool m_shouldThrow = false; + bool m_inExceptionGuard = false; + public: AssertionHandler ( StringRef macroName, SourceLineInfo const& lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition ); + ~AssertionHandler(); void handle( ITransientExpression const& expr ); @@ -60,6 +63,8 @@ namespace Catch { void reactWithoutDebugBreak() const; void useActiveException( ResultDisposition::Flags resultDisposition ); void useActiveException(); + void setExceptionGuard(); + void unsetExceptionGuard(); }; } // namespace Catch diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 13101ec6..b13b9fe6 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -26,14 +26,17 @@ // macro in each assertion #define INTERNAL_CATCH_REACT( resultBuilder ) \ resultBuilder.react(); +#define INTERNAL_CATCH_REACT2( handler ) \ + handler.reactWithDebugBreak(); /////////////////////////////////////////////////////////////////////////////// // Another way to speed-up compilation is to omit local try-catch for REQUIRE* // macros. // This can potentially cause false negative, if the test code catches // the exception before it propagates back up to the runner. -#define INTERNAL_CATCH_TRY -#define INTERNAL_CATCH_CATCH( capturer, disposition ) +#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); +#define INTERNAL_CATCH_CATCH( capturer, disposition ) capturer.unsetExceptionGuard(); +#define INTERNAL_CATCH_CATCH2( capturer ) capturer.unsetExceptionGuard(); #else // CATCH_CONFIG_FAST_COMPILE @@ -47,9 +50,9 @@ resultBuilder.react(); #define INTERNAL_CATCH_REACT2( handler ) \ if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - handler.reactWithDebugBreak(); + handler.reactWithoutDebugBreak(); -#define INTERNAL_CATCH_TRY try +#define INTERNAL_CATCH_TRY( capturer ) try #define INTERNAL_CATCH_CATCH( capturer, disposition ) catch(...) { capturer.useActiveException( disposition ); } #define INTERNAL_CATCH_CATCH2( capturer ) catch(...) { capturer.useActiveException(); } @@ -59,7 +62,7 @@ #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ - INTERNAL_CATCH_TRY { \ + INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ @@ -147,7 +150,7 @@ #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - INTERNAL_CATCH_TRY { \ + INTERNAL_CATCH_TRY( __catchResult ) { \ __catchResult.captureMatch( arg, matcher, #matcher ); \ } INTERNAL_CATCH_CATCH( __catchResult, resultDisposition ) \ INTERNAL_CATCH_REACT( __catchResult ) \ From 9668410b8e415c22d2665a820a1e113acfd6ae64 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 23:31:43 +0100 Subject: [PATCH 217/398] integrated INTERNAL_CHECK_THAT with new AssertionHandler --- include/internal/catch_capture.hpp | 10 ++++----- include/internal/catch_decomposer.h | 32 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index b13b9fe6..ef152dae 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -149,11 +149,11 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - INTERNAL_CATCH_TRY( __catchResult ) { \ - __catchResult.captureMatch( arg, matcher, #matcher ); \ - } INTERNAL_CATCH_CATCH( __catchResult, resultDisposition ) \ - INTERNAL_CATCH_REACT( __catchResult ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ + catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ + } INTERNAL_CATCH_CATCH2( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 82e386a5..f289387a 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -144,6 +144,38 @@ namespace Catch { } }; + // !TBD: this is just here temporarily + template + class MatchExpr : public ITransientExpression { + ArgT const& m_arg; + MatcherT const& m_matcher; + StringRef m_matcherString; + bool m_result; + public: + MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) + : m_arg( arg ), + m_matcher( matcher ), + m_matcherString( matcherString ), + m_result( matcher.match( arg ) ) + {} + + auto isBinaryExpression() const -> bool override { return true; } + auto getResult() const -> bool override { return m_result; } + + void streamReconstructedExpression( std::ostream &os ) const override { + auto matcherAsString = m_matcher.toString(); + os << Catch::Detail::stringify( m_arg ) << ' '; + if( matcherAsString == Detail::unprintableString ) + os << m_matcherString.c_str(); + else + os << matcherAsString; + } + }; + template + auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { + return MatchExpr( arg, matcher, matcherString ); + } + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED From ef4fa56b71e7013fe39609abfb25819b618c1177 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 8 Aug 2017 23:41:55 +0100 Subject: [PATCH 218/398] integrated INTERNAL_CATCH_THROWS_MATCHES with new AssertionHandler --- include/internal/catch_capture.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index ef152dae..ee63e044 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -175,23 +175,23 @@ /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, expr ) \ +#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType ", " #matcher, resultDisposition ); \ - if( __catchResult.allowThrows() ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ try { \ - static_cast(expr); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + static_cast(__VA_ARGS__ ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ } \ catch( exceptionType const& ex ) { \ - __catchResult.captureMatch( ex, matcher, #matcher ); \ + catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ } \ catch( ... ) { \ - __catchResult.useActiveException( resultDisposition ); \ + catchAssertionHandler.useActiveException(); \ } \ else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) #endif // CATCH_CONFIG_DISABLE_MATCHERS From 27fd8f80bd883df36c243bc355429977fd665c50 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 00:44:30 +0100 Subject: [PATCH 219/398] Integrated INTERNAL_CATCH_THROWS_STR_MATCHES with new AssertionHandler --- include/internal/catch_assertionhandler.cpp | 10 ++++++++++ include/internal/catch_assertionhandler.h | 6 ++++++ include/internal/catch_capture.hpp | 12 ++++++------ include/internal/catch_decomposer.cpp | 3 +-- include/internal/catch_decomposer.h | 4 +++- .../SelfTest/Baselines/console.std.approved.txt | 2 +- .../SelfTest/Baselines/console.sw.approved.txt | 16 +++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 2 +- projects/SelfTest/Baselines/xml.sw.approved.txt | 16 ++++++++-------- 9 files changed, 51 insertions(+), 20 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index 8d99e3d0..26f727a9 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -13,6 +13,7 @@ #include "catch_context.h" #include "catch_debugger.h" #include "catch_interfaces_registry_hub.h" +#include "catch_matchers_string.h" #include @@ -140,5 +141,14 @@ namespace Catch { m_inExceptionGuard = false; } + using StringMatcher = Matchers::Impl::MatcherBase; + + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { + MatchExpr expr( Catch::translateActiveException(), matcher, matcherString ); + handler.handle( expr ); + } + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) { + handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); + } } // namespace Catch diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h index dbbd5157..21a09875 100644 --- a/include/internal/catch_assertionhandler.h +++ b/include/internal/catch_assertionhandler.h @@ -10,6 +10,7 @@ #include "catch_decomposer.h" #include "catch_assertioninfo.h" +#include "catch_matchers_string.h" // !TBD: for exception matchers namespace Catch { @@ -67,6 +68,11 @@ namespace Catch { void unsetExceptionGuard(); }; + using StringMatcher = Matchers::Impl::MatcherBase; + + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); + } // namespace Catch #endif // TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index ee63e044..6615edf1 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -159,18 +159,18 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #matcher, resultDisposition); \ - if( __catchResult.allowThrows() ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #matcher, resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureExpectedException( matcher ); \ + handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ } \ else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) diff --git a/include/internal/catch_decomposer.cpp b/include/internal/catch_decomposer.cpp index 6e69bc43..f7da22b5 100644 --- a/include/internal/catch_decomposer.cpp +++ b/include/internal/catch_decomposer.cpp @@ -12,7 +12,6 @@ namespace Catch { void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) { - if( lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && rhs.find('\n') == std::string::npos ) @@ -20,4 +19,4 @@ namespace Catch { else os << lhs << "\n" << op << "\n" << rhs; } -} \ No newline at end of file +} diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index f289387a..3182b84a 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -10,6 +10,7 @@ #include "catch_tostring.h" #include "catch_stringref.h" +#include "catch_matchers.hpp" // !TBD: for exception matchers - move this #include @@ -148,7 +149,7 @@ namespace Catch { template class MatchExpr : public ITransientExpression { ArgT const& m_arg; - MatcherT const& m_matcher; + MatcherT m_matcher; StringRef m_matcherString; bool m_result; public: @@ -171,6 +172,7 @@ namespace Catch { os << matcherAsString; } }; + template auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { return MatchExpr( arg, matcher, matcherString ); diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 9e41f7f5..cd406b0c 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -485,7 +485,7 @@ ExceptionTests.cpp: ExceptionTests.cpp:: FAILED: REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) with expansion: - expected exception + "expected exception" equals: "should fail" ------------------------------------------------------------------------------- Nice descriptive name diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 971c0e32..80fd38c9 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1428,6 +1428,8 @@ ExceptionTests.cpp: ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) +with expansion: + "expected exception" equals: "expected exception" ------------------------------------------------------------------------------- Exception messages can be tested for @@ -1439,6 +1441,8 @@ ExceptionTests.cpp: ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) +with expansion: + "expected exception" equals: "expected exception" (case insensitive) ------------------------------------------------------------------------------- Exception messages can be tested for @@ -1450,18 +1454,26 @@ ExceptionTests.cpp: ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) +with expansion: + "expected exception" starts with: "expected" ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) +with expansion: + "expected exception" ends with: "exception" ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) +with expansion: + "expected exception" contains: "except" ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) +with expansion: + "expected exception" contains: "except" (case insensitive) ------------------------------------------------------------------------------- Expected exceptions that don't throw or unexpected exceptions fail the test @@ -1882,11 +1894,13 @@ ExceptionTests.cpp: ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) +with expansion: + "expected exception" equals: "expected exception" ExceptionTests.cpp:: FAILED: REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) with expansion: - expected exception + "expected exception" equals: "should fail" ------------------------------------------------------------------------------- Nice descriptive name diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 58807c18..3a1ebdab 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -311,7 +311,7 @@ MatchersTests.cpp: - + ExceptionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index e70ad12e..9cec8235 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1646,7 +1646,7 @@ thisThrows(), "expected exception" - thisThrows(), "expected exception" + "expected exception" equals: "expected exception"
@@ -1657,7 +1657,7 @@ thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) - thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + "expected exception" equals: "expected exception" (case insensitive) @@ -1668,7 +1668,7 @@ thisThrows(), StartsWith( "expected" ) - thisThrows(), StartsWith( "expected" ) + "expected exception" starts with: "expected" @@ -1676,7 +1676,7 @@ thisThrows(), EndsWith( "exception" ) - thisThrows(), EndsWith( "exception" ) + "expected exception" ends with: "exception" @@ -1684,7 +1684,7 @@ thisThrows(), Contains( "except" ) - thisThrows(), Contains( "except" ) + "expected exception" contains: "except" @@ -1692,7 +1692,7 @@ thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) - thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + "expected exception" contains: "except" (case insensitive) @@ -2172,7 +2172,7 @@ thisThrows(), "expected exception" - thisThrows(), "expected exception" + "expected exception" equals: "expected exception" @@ -2180,7 +2180,7 @@ thisThrows(), "should fail" - expected exception + "expected exception" equals: "should fail" From 201028d6ec787aa92ae12656804b807d2ec849a2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 00:52:20 +0100 Subject: [PATCH 220/398] Integrated INTERNAL_CATCH_THROWS with new AssertionHandler --- include/internal/catch_capture.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 6615edf1..6c51a3b1 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -98,18 +98,18 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \ - if( __catchResult.allowThrows() ) \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \ + if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__); \ - __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureExpectedException( "" ); \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ } \ else \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( __catchResult ) \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// From 7df290dfc1a064d087f5252bc1aac5e832a16d7e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 08:49:59 +0100 Subject: [PATCH 221/398] Integrated new AssertionHandler into unexpected exception handling in RunContext --- include/internal/catch_run_context.cpp | 13 +++++-------- include/internal/catch_run_context.hpp | 2 -- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 509a18e6..b0479797 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -270,7 +270,11 @@ namespace Catch { // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions // are reported without translation at the point of origin. if (m_shouldReportUnexpected) { - makeUnexpectedResultBuilder().useActiveException(); + AssertionHandler + ( m_lastAssertionInfo.macroName, + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression, + m_lastAssertionInfo.resultDisposition ).useActiveException(); } } m_testCaseTracker->close(); @@ -296,13 +300,6 @@ namespace Catch { fatalConditionHandler.reset(); } - ResultBuilder RunContext::makeUnexpectedResultBuilder() const { - return ResultBuilder(m_lastAssertionInfo.macroName, - m_lastAssertionInfo.lineInfo, - m_lastAssertionInfo.capturedExpression, - m_lastAssertionInfo.resultDisposition); - } - void RunContext::handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 9e9f8974..a356e3bf 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -103,8 +103,6 @@ namespace Catch { private: - ResultBuilder makeUnexpectedResultBuilder() const; - void handleUnfinishedSections(); TestRunInfo m_runInfo; From 8c95a81448d8216d8d133f6e98f3aae81c44cb76 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 09:08:33 +0100 Subject: [PATCH 222/398] Removed all (well, most) of the redundant, ResultBuilder-based, code --- CMakeLists.txt | 5 - include/internal/catch_assertionresult.cpp | 37 ---- include/internal/catch_assertionresult.h | 34 --- include/internal/catch_capture.hpp | 1 - include/internal/catch_evaluate.cpp | 38 ---- include/internal/catch_evaluate.hpp | 109 ---------- .../catch_exception_translator_registry.cpp | 2 +- include/internal/catch_expression_lhs.hpp | 176 ---------------- include/internal/catch_result_builder.cpp | 193 ------------------ include/internal/catch_result_builder.h | 118 ----------- include/internal/catch_run_context.hpp | 2 +- include/reporters/catch_reporter_bases.cpp | 5 +- 12 files changed, 3 insertions(+), 717 deletions(-) delete mode 100644 include/internal/catch_evaluate.cpp delete mode 100644 include/internal/catch_evaluate.hpp delete mode 100644 include/internal/catch_expression_lhs.hpp delete mode 100644 include/internal/catch_result_builder.cpp delete mode 100644 include/internal/catch_result_builder.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e454e330..94f06f40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,9 +138,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_default_main.hpp ${HEADER_DIR}/internal/catch_enforce.h ${HEADER_DIR}/internal/catch_errno_guard.h - ${HEADER_DIR}/internal/catch_evaluate.hpp ${HEADER_DIR}/internal/catch_exception_translator_registry.h - ${HEADER_DIR}/internal/catch_expression_lhs.hpp ${HEADER_DIR}/internal/catch_fatal_condition.h ${HEADER_DIR}/internal/catch_impl.hpp ${HEADER_DIR}/internal/catch_interfaces_capture.h @@ -165,7 +163,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_reenable_warnings.h ${HEADER_DIR}/internal/catch_reporter_registrars.hpp ${HEADER_DIR}/internal/catch_reporter_registry.hpp - ${HEADER_DIR}/internal/catch_result_builder.h ${HEADER_DIR}/internal/catch_result_type.h ${HEADER_DIR}/internal/catch_run_context.hpp ${HEADER_DIR}/internal/catch_benchmark.h @@ -212,7 +209,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_debugger.cpp ${HEADER_DIR}/internal/catch_decomposer.cpp ${HEADER_DIR}/internal/catch_errno_guard.cpp - ${HEADER_DIR}/internal/catch_evaluate.cpp ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp ${HEADER_DIR}/internal/catch_fatal_condition.cpp ${HEADER_DIR}/internal/catch_list.cpp @@ -223,7 +219,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp ${HEADER_DIR}/internal/catch_registry_hub.cpp ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp - ${HEADER_DIR}/internal/catch_result_builder.cpp ${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_run_context.cpp ${HEADER_DIR}/internal/catch_section.cpp diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 877f53bf..04402000 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -10,44 +10,15 @@ namespace Catch { - - bool DecomposedExpression::isBinaryExpression() const { - return false; - } - - void AssertionResultData::negate( bool parenthesize ) { - negated = !negated; - parenthesized = parenthesize; - if( resultType == ResultWas::Ok ) - resultType = ResultWas::ExpressionFailed; - else if( resultType == ResultWas::ExpressionFailed ) - resultType = ResultWas::Ok; - } - std::string AssertionResultData::reconstructExpression() const { if( reconstructedExpression.empty() ) { - - // Try new LazyExpression first... if( lazyExpression ) { // !TBD Use stringstream for now, but rework above to pass stream in std::ostringstream oss; oss << lazyExpression; reconstructedExpression = oss.str(); } - - // ... if not, fall back to decomposedExpression - else if( decomposedExpression != nullptr ) { - decomposedExpression->reconstructExpression( reconstructedExpression ); - if( parenthesized ) { - reconstructedExpression.insert( 0, 1, '(' ); - reconstructedExpression.append( 1, ')' ); - } - if( negated ) { - reconstructedExpression.insert( 0, 1, '!' ); - } - decomposedExpression = nullptr; - } } return reconstructedExpression; } @@ -115,12 +86,4 @@ namespace Catch { return m_info.macroName.c_str(); } - void AssertionResult::discardDecomposedExpression() const { - m_resultData.decomposedExpression = nullptr; - } - - void AssertionResult::expandDecomposedExpression() const { - m_resultData.reconstructExpression(); - } - } // end namespace Catch diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 9bd8e39d..b1177fa4 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -15,39 +15,12 @@ #include "catch_stringref.h" #include "catch_assertionhandler.h" -namespace Catch { - - struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; - - struct DecomposedExpression - { - DecomposedExpression() = default; - DecomposedExpression( DecomposedExpression const& ) = default; - DecomposedExpression& operator = ( DecomposedExpression const& ) = delete; - - virtual ~DecomposedExpression() = default; - virtual bool isBinaryExpression() const; - virtual void reconstructExpression( std::string& dest ) const = 0; - - // Only simple binary comparisons can be decomposed. - // If more complex check is required then wrap sub-expressions in parentheses. - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); - }; -} - namespace Catch { struct AssertionResultData { AssertionResultData() = delete; - // !TBD We won't need this constructor once the deprecated fields are removed AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ) : resultType( _resultType ), lazyExpression( _lazyExpression ) @@ -58,12 +31,7 @@ namespace Catch { LazyExpression lazyExpression; - // deprecated: - bool negated = false; - bool parenthesized = false; - void negate( bool parenthesize ); std::string reconstructExpression() const; - mutable DecomposedExpression const* decomposedExpression = nullptr; mutable std::string reconstructedExpression; }; @@ -84,8 +52,6 @@ namespace Catch { std::string getMessage() const; SourceLineInfo getSourceInfo() const; std::string getTestMacroName() const; - void discardDecomposedExpression() const; - void expandDecomposedExpression() const; //protected: AssertionInfo m_info; diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 6c51a3b1..5332df35 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -9,7 +9,6 @@ #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED #include "catch_assertionhandler.h" -#include "catch_result_builder.h" #include "catch_message.h" #include "catch_interfaces_capture.h" #include "catch_debugger.h" diff --git a/include/internal/catch_evaluate.cpp b/include/internal/catch_evaluate.cpp deleted file mode 100644 index 349f71e7..00000000 --- a/include/internal/catch_evaluate.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Created by Martin on 01/08/2017. - * - * 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) - */ - -#include "catch_evaluate.hpp" - -#include "catch_enforce.h" - -namespace Catch { -namespace Internal { - - const char* operatorName(Operator op) { - switch (op) { - case IsEqualTo: - return "=="; - case IsNotEqualTo: - return "!="; - case IsLessThan: - return "<"; - case IsGreaterThan: - return ">"; - case IsLessThanOrEqualTo: - return "<="; - case IsGreaterThanOrEqualTo: - return ">="; - default: - CATCH_ERROR("Attempting to translate unknown operator!"); - } - } - - // nullptr_t support based on pull request #154 from Konstantin Baumann - std::nullptr_t opCast(std::nullptr_t) { return nullptr; } - -} // end of namespace Internal -} // end of namespace Catch diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp deleted file mode 100644 index 33ccd5ef..00000000 --- a/include/internal/catch_evaluate.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Created by Phil on 04/03/2011. - * Copyright 2011 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) - */ -#ifndef TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#pragma warning(disable:4018) // more "signed/unsigned mismatch" -#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) -#endif - -#include - -namespace Catch { -namespace Internal { - - enum Operator { - IsEqualTo, - IsNotEqualTo, - IsLessThan, - IsGreaterThan, - IsLessThanOrEqualTo, - IsGreaterThanOrEqualTo - }; - - const char* operatorName(Operator op); - - template - T& removeConst(T const &t) { return const_cast(t); } - - - // So the compare overloads can be operator agnostic we convey the operator as a template - // enum, which is used to specialise an Evaluator for doing the comparison. - template - struct Evaluator{}; - - template<> - struct Evaluator { - template - static bool evaluate( T1 const& lhs, T2 const& rhs) { - return bool(removeConst(lhs) == removeConst(rhs) ); - } - template - static bool evaluate( int lhs, T* rhs) { - return reinterpret_cast( lhs ) == rhs; - } - template - static bool evaluate( T* lhs, int rhs) { - return lhs == reinterpret_cast( rhs ); - } - }; - template<> - struct Evaluator { - template - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) != removeConst(rhs) ); - } - template - static bool evaluate( int lhs, T* rhs) { - return reinterpret_cast( lhs ) != rhs; - } - template - static bool evaluate( T* lhs, int rhs) { - return lhs != reinterpret_cast( rhs ); - } - }; - template<> - struct Evaluator { - template - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) < removeConst(rhs) ); - } - }; - template<> - struct Evaluator { - template - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) > removeConst(rhs) ); - } - }; - template<> - struct Evaluator { - template - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) >= removeConst(rhs) ); - } - }; - template<> - struct Evaluator { - template - static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return bool(removeConst(lhs) <= removeConst(rhs) ); - } - }; - -} // end of namespace Internal -} // end of namespace Catch - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED diff --git a/include/internal/catch_exception_translator_registry.cpp b/include/internal/catch_exception_translator_registry.cpp index 1a857535..98b92316 100644 --- a/include/internal/catch_exception_translator_registry.cpp +++ b/include/internal/catch_exception_translator_registry.cpp @@ -6,8 +6,8 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ +#include "catch_assertionhandler.h" #include "catch_exception_translator_registry.h" -#include "catch_result_builder.h" #ifdef __OBJC__ #import "Foundation/Foundation.h" diff --git a/include/internal/catch_expression_lhs.hpp b/include/internal/catch_expression_lhs.hpp deleted file mode 100644 index 08625019..00000000 --- a/include/internal/catch_expression_lhs.hpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Created by Phil on 11/5/2012. - * Copyright 2012 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) - */ -#ifndef TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED - -#include "catch_result_builder.h" -#include "catch_evaluate.hpp" -#include "catch_tostring.h" - -namespace Catch { - -template -class BinaryExpression; - -template -class MatchExpression; - -// Wraps the LHS of an expression and overloads comparison operators -// for also capturing those and RHS (if any) -template -class ExpressionLhs : public DecomposedExpression { -public: - ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} - - ExpressionLhs( ExpressionLhs const& ) = default; - ExpressionLhs& operator = ( const ExpressionLhs& ) = delete; - - template - BinaryExpression - operator == ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator != ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator < ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator > ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator <= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - template - BinaryExpression - operator >= ( RhsT const& rhs ) { - return captureExpression( rhs ); - } - - BinaryExpression operator == ( bool rhs ) { - return captureExpression( rhs ); - } - - BinaryExpression operator != ( bool rhs ) { - return captureExpression( rhs ); - } - - void endExpression() { - m_truthy = m_lhs ? true : false; - m_rb - .setResultType( m_truthy ) - .endExpression( *this ); - } - - void reconstructExpression( std::string& dest ) const override { - dest = ::Catch::Detail::stringify( m_lhs ); - } - -private: - template - BinaryExpression captureExpression( RhsT& rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } - - template - BinaryExpression captureExpression( bool rhs ) const { - return BinaryExpression( m_rb, m_lhs, rhs ); - } - -private: - ResultBuilder& m_rb; - T m_lhs; - bool m_truthy = false; -}; - -template -class BinaryExpression : public DecomposedExpression { -public: - BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) - : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} - - BinaryExpression( BinaryExpression const& ) = default; - BinaryExpression& operator = ( BinaryExpression const& ) = delete; - - void endExpression() const { - m_rb - .setResultType( Internal::Evaluator::evaluate( m_lhs, m_rhs ) ) - .endExpression( *this ); - } - - bool isBinaryExpression() const override { - return true; - } - - void reconstructExpression( std::string& dest ) const override { - std::string lhs = ::Catch::Detail::stringify( m_lhs ); - std::string rhs = ::Catch::Detail::stringify( m_rhs ); - char delim = lhs.size() + rhs.size() < 40 && - lhs.find('\n') == std::string::npos && - rhs.find('\n') == std::string::npos ? ' ' : '\n'; - dest.reserve( 7 + lhs.size() + rhs.size() ); - // 2 for spaces around operator - // 2 for operator - // 2 for parentheses (conditionally added later) - // 1 for negation (conditionally added later) - dest = lhs; - dest += delim; - dest += Internal::operatorName(Op); - dest += delim; - dest += rhs; - } - -private: - ResultBuilder& m_rb; - LhsT m_lhs; - RhsT m_rhs; -}; - -template -class MatchExpression : public DecomposedExpression { -public: - MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) - : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} - - bool isBinaryExpression() const override { - return true; - } - - void reconstructExpression( std::string& dest ) const override { - std::string matcherAsString = m_matcher.toString(); - dest = ::Catch::Detail::stringify( m_arg ); - dest += ' '; - if( matcherAsString == Detail::unprintableString ) - dest += m_matcherString; - else - dest += matcherAsString; - } - -private: - ArgT m_arg; - MatcherT m_matcher; - char const* m_matcherString; -}; - -} // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED diff --git a/include/internal/catch_result_builder.cpp b/include/internal/catch_result_builder.cpp deleted file mode 100644 index db7dfb14..00000000 --- a/include/internal/catch_result_builder.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Created by Phil on 28/5/2014. - * Copyright 2014 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) - */ - -#include "catch_result_builder.h" -#include "catch_context.h" -#include "catch_interfaces_config.h" -#include "catch_interfaces_runner.h" -#include "catch_interfaces_capture.h" -#include "catch_interfaces_registry_hub.h" -#include "catch_matchers_string.h" -#include "catch_debugger.h" - -#include - -namespace Catch { - - CopyableStream::CopyableStream( CopyableStream const& other ) { - oss << other.oss.str(); - } - CopyableStream& CopyableStream::operator=( CopyableStream const& other ) { - oss.str(std::string()); - oss << other.oss.str(); - return *this; - } - - - ResultBuilder::ResultBuilder( StringRef macroName, - SourceLineInfo const& lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, - m_data( ResultWas::Unknown, LazyExpression( false ) ) - { - getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); - } - - ResultBuilder::~ResultBuilder() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if ( m_guardException ) { - stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; - captureResult( ResultWas::ThrewException ); - getCurrentContext().getResultCapture()->exceptionEarlyReported(); - } -#endif - } - - ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { - m_data.resultType = result; - return *this; - } - ResultBuilder& ResultBuilder::setResultType( bool result ) { - m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; - return *this; - } - - void ResultBuilder::endExpression( DecomposedExpression const& expr ) { - // Flip bool results if FalseTest flag is set - if( isFalseTest( m_assertionInfo.resultDisposition ) ) { - m_data.negate( expr.isBinaryExpression() ); - } - - getResultCapture().assertionRun(); - - if(getCurrentContext().getConfig()->includeSuccessfulResults() - || m_data.resultType != ResultWas::Ok) { - AssertionResult result = build( expr ); - handleResult( result ); - } - else - getResultCapture().assertionPassed(); - } - - void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { - m_assertionInfo.resultDisposition = resultDisposition; - stream().oss << Catch::translateActiveException(); - captureResult( ResultWas::ThrewException ); - } - - void ResultBuilder::captureResult( ResultWas::OfType resultType ) { - setResultType( resultType ); - captureExpression(); - } -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { - if( expectedMessage.empty() ) - captureExpectedException( Matchers::Impl::MatchAllOf() ); - else - captureExpectedException( Matchers::Equals( expectedMessage ) ); - } - - - void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase const& matcher ) { - - assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); - AssertionResultData data = m_data; - data.resultType = ResultWas::Ok; - data.reconstructedExpression = m_assertionInfo.capturedExpression.c_str(); - - std::string actualMessage = Catch::translateActiveException(); - if( !matcher.match( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = std::move(actualMessage); - } - AssertionResult result( m_assertionInfo, data ); - handleResult( result ); - } -#endif // CATCH_CONFIG_DISABLE_MATCHERS - void ResultBuilder::captureExpression() { - AssertionResult result = build(); - handleResult( result ); - } - - void ResultBuilder::handleResult( AssertionResult const& result ) - { - getResultCapture().assertionEnded( result ); - - if( !result.isOk() ) { - if( getCurrentContext().getConfig()->shouldDebugBreak() ) - m_shouldDebugBreak = true; - if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) - m_shouldThrow = true; - } - } - - void ResultBuilder::react() { -#if defined(CATCH_CONFIG_FAST_COMPILE) - if (m_shouldDebugBreak) { - /////////////////////////////////////////////////////////////////// - // To inspect the state during test, you need to go one level up the callstack - // To go back to the test and change execution, jump over the throw statement - /////////////////////////////////////////////////////////////////// - CATCH_BREAK_INTO_DEBUGGER(); - } -#endif - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - - bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } - bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } - - AssertionResult ResultBuilder::build() const - { - return build( *this ); - } - - // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, - // a temporary DecomposedExpression, which in turn holds references to - // operands, possibly temporary as well. - // It should immediately be passed to handleResult; if the expression - // needs to be reported, its string expansion must be composed before - // the temporaries are destroyed. - AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const { - assert( m_data.resultType != ResultWas::Unknown ); - AssertionResultData data = m_data; - - if(m_usedStream) - data.message = s_stream().oss.str(); - data.decomposedExpression = &expr; // for lazy reconstruction - return AssertionResult( m_assertionInfo, data ); - } - - void ResultBuilder::reconstructExpression( std::string& dest ) const { - dest = m_assertionInfo.capturedExpression.c_str(); - } - - void ResultBuilder::setExceptionGuard() { - m_guardException = true; - } - void ResultBuilder::unsetExceptionGuard() { - m_guardException = false; - } - - CopyableStream& ResultBuilder::stream() { - if( !m_usedStream ) { - m_usedStream = true; - s_stream().oss.str(""); - } - return s_stream(); - } - - CopyableStream& ResultBuilder::s_stream() { - static CopyableStream s; - return s; - } - - -} // end namespace Catch diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h deleted file mode 100644 index 6d3a9efc..00000000 --- a/include/internal/catch_result_builder.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Created by Phil on 28/5/2014. - * Copyright 2014 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) - */ -#ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED -#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED - -#include "catch_assertionresult.h" -#include "catch_decomposer.h" - -#include "catch_result_type.h" -#include "catch_common.h" -#include "catch_matchers.hpp" - -#include - -namespace Catch { - - template class ExpressionLhs; - - struct CopyableStream { - CopyableStream() = default; - CopyableStream( CopyableStream const& other ); - CopyableStream& operator=( CopyableStream const& other ); - - std::ostringstream oss; - }; - - class ResultBuilder : public DecomposedExpression { - public: - ResultBuilder( StringRef macroName, - SourceLineInfo const& lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition); - ~ResultBuilder(); - - template - ExpressionLhs operator <= ( T const& operand ); - ExpressionLhs operator <= ( bool value ); - - template - ResultBuilder& operator << ( T const& value ) { - stream().oss << value; - return *this; - } - - ResultBuilder& setResultType( ResultWas::OfType result ); - ResultBuilder& setResultType( bool result ); - - void endExpression( DecomposedExpression const& expr ); - - void reconstructExpression( std::string& dest ) const override; - - AssertionResult build() const; - AssertionResult build( DecomposedExpression const& expr ) const; - - void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); - void captureResult( ResultWas::OfType resultType ); - void captureExpression(); -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - void captureExpectedException( std::string const& expectedMessage ); - void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); -#endif // CATCH_CONFIG_DISABLE_MATCHERS - void handleResult( AssertionResult const& result ); - void react(); - bool shouldDebugBreak() const; - bool allowThrows() const; - - template - void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); - - void setExceptionGuard(); - void unsetExceptionGuard(); - - private: - AssertionInfo m_assertionInfo; - AssertionResultData m_data; - - CopyableStream& stream(); - static CopyableStream& s_stream(); - - bool m_shouldDebugBreak = false; - bool m_shouldThrow = false; - bool m_guardException = false; - bool m_usedStream = false; - }; - -} // namespace Catch - -// Include after due to circular dependency: -#include "catch_expression_lhs.hpp" - -namespace Catch { - - template - ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { - return ExpressionLhs( *this, operand ); - } - - inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { - return ExpressionLhs( *this, value ); - } - - template - void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, - char const* matcherString ) { - MatchExpression expr( arg, matcher, matcherString ); - setResultType( matcher.match( arg ) ); - endExpression( expr ); - } - - -} // namespace Catch - -#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index a356e3bf..d5ad4558 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -19,7 +19,7 @@ #include "catch_test_spec.hpp" #include "catch_test_case_tracker.hpp" #include "catch_timer.h" -#include "catch_result_builder.h" +#include "catch_assertionhandler.h" #include "catch_fatal_condition.h" #include diff --git a/include/reporters/catch_reporter_bases.cpp b/include/reporters/catch_reporter_bases.cpp index 6457af35..1db7868c 100644 --- a/include/reporters/catch_reporter_bases.cpp +++ b/include/reporters/catch_reporter_bases.cpp @@ -18,10 +18,7 @@ namespace Catch { void prepareExpandedExpression(AssertionResult& result) { - if (result.isOk()) - result.discardDecomposedExpression(); - else - result.expandDecomposedExpression(); + result.getExpandedExpression(); } // Because formatting using c++ streams is stateful, drop down to C is required From dc1df297e3f1d03a36bc7c39cde33b47c8b942a5 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 09:29:44 +0100 Subject: [PATCH 223/398] Suppressed some warnings - signed/ unsigned mismatches - virtual destructor on ITransientExpression (even though not needed) --- include/internal/catch_decomposer.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 3182b84a..6889d873 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -14,12 +14,23 @@ #include +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(disable:4018) // more "signed/unsigned mismatch" +#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#endif + namespace Catch { struct ITransientExpression { virtual auto isBinaryExpression() const -> bool = 0; virtual auto getResult() const -> bool = 0; virtual void streamReconstructedExpression( std::ostream &os ) const = 0; + + // We don't actually need a virtual destructore, but many static analysers + // complain if it's not here :-( + virtual ~ITransientExpression() = default; }; void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); @@ -180,4 +191,8 @@ namespace Catch { } // end namespace Catch +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED From 8382d99081d497947652b87f12cc0b10c2e4b0de Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 10:18:31 +0100 Subject: [PATCH 224/398] Workaround for GCC 4.8 "deleted ctor in aggregate" bug --- include/internal/catch_assertioninfo.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/internal/catch_assertioninfo.h b/include/internal/catch_assertioninfo.h index 21646b21..1ac304e1 100644 --- a/include/internal/catch_assertioninfo.h +++ b/include/internal/catch_assertioninfo.h @@ -21,6 +21,8 @@ namespace Catch { 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; }; From 4b5ac4d3d93e78b6735cb787307ea44c4fc76a47 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 10:29:05 +0100 Subject: [PATCH 225/398] Actually do what the previous commit claimed to do! :-s --- include/internal/catch_assertioninfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_assertioninfo.h b/include/internal/catch_assertioninfo.h index 1ac304e1..5f136bf7 100644 --- a/include/internal/catch_assertioninfo.h +++ b/include/internal/catch_assertioninfo.h @@ -23,7 +23,7 @@ namespace Catch { // We want to delete this constructor but a compiler bug in 4.8 means // the struct is then treated as non-aggregate - AssertionInfo() = delete; + //AssertionInfo() = delete; }; } // end namespace Catch From 8d21b4a916031bfead5b51c3e5334a0bec2ad84e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 10:51:50 +0100 Subject: [PATCH 226/398] Removed some unnecessary #includes - and don't #include "catch_debugger.h" in the header path when CATCH_CONFIG_FAST_COMPILE is defined --- include/internal/catch_assertionhandler.cpp | 1 + include/internal/catch_benchmark.cpp | 1 + include/internal/catch_capture.hpp | 7 ++----- include/internal/catch_interfaces_capture.h | 5 ++--- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index 26f727a9..8ccd60f2 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -10,6 +10,7 @@ #include "catch_assertionresult.h" #include "catch_interfaces_capture.h" #include "catch_interfaces_runner.h" +#include "catch_interfaces_config.h" #include "catch_context.h" #include "catch_debugger.h" #include "catch_interfaces_registry_hub.h" diff --git a/include/internal/catch_benchmark.cpp b/include/internal/catch_benchmark.cpp index 34af42a5..51a844f6 100644 --- a/include/internal/catch_benchmark.cpp +++ b/include/internal/catch_benchmark.cpp @@ -8,6 +8,7 @@ #include "catch_benchmark.h" #include "catch_capture.hpp" +#include "catch_interfaces_reporter.h" namespace Catch { diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 5332df35..8afcb74d 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -11,11 +11,6 @@ #include "catch_assertionhandler.h" #include "catch_message.h" #include "catch_interfaces_capture.h" -#include "catch_debugger.h" -#include "catch_common.h" -#include "catch_tostring.h" -#include "catch_interfaces_runner.h" -#include "catch_compiler_capabilities.h" #if defined(CATCH_CONFIG_FAST_COMPILE) @@ -39,6 +34,8 @@ #else // CATCH_CONFIG_FAST_COMPILE +#include "catch_debugger.h" + /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index 4d8766dd..e8000154 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -9,9 +9,6 @@ #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED #include -#include "catch_result_type.h" -#include "catch_common.h" -#include "catch_interfaces_reporter.h" namespace Catch { @@ -23,6 +20,8 @@ namespace Catch { struct MessageInfo; class ScopedMessageBuilder; struct Counts; + struct BenchmarkInfo; + struct BenchmarkStats; struct IResultCapture { From b59e0ed48a4d94f9e595a5936434e9bad7834ece Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 11:36:33 +0100 Subject: [PATCH 227/398] Collapsed alternate capture macros now originals are redundant --- include/internal/catch_assertionhandler.cpp | 4 --- include/internal/catch_assertionhandler.h | 1 - include/internal/catch_capture.hpp | 35 +++++++++------------ 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index 8ccd60f2..ea4f75af 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -125,10 +125,6 @@ namespace Catch { throw Catch::TestFailureException(); } - void AssertionHandler::useActiveException( ResultDisposition::Flags resultDisposition ) { - m_assertionInfo.resultDisposition = resultDisposition; - useActiveException(); - } void AssertionHandler::useActiveException() { handle( ResultWas::ThrewException, Catch::translateActiveException().c_str() ); } diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h index 21a09875..a1b1777a 100644 --- a/include/internal/catch_assertionhandler.h +++ b/include/internal/catch_assertionhandler.h @@ -62,7 +62,6 @@ namespace Catch { auto allowThrows() const -> bool; void reactWithDebugBreak() const; void reactWithoutDebugBreak() const; - void useActiveException( ResultDisposition::Flags resultDisposition ); void useActiveException(); void setExceptionGuard(); void unsetExceptionGuard(); diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 8afcb74d..257d057f 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -18,9 +18,7 @@ // We can speedup compilation significantly by breaking into debugger lower in // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER // macro in each assertion -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - resultBuilder.react(); -#define INTERNAL_CATCH_REACT2( handler ) \ +#define INTERNAL_CATCH_REACT( handler ) \ handler.reactWithDebugBreak(); /////////////////////////////////////////////////////////////////////////////// @@ -29,8 +27,7 @@ // This can potentially cause false negative, if the test code catches // the exception before it propagates back up to the runner. #define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); -#define INTERNAL_CATCH_CATCH( capturer, disposition ) capturer.unsetExceptionGuard(); -#define INTERNAL_CATCH_CATCH2( capturer ) capturer.unsetExceptionGuard(); +#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard(); #else // CATCH_CONFIG_FAST_COMPILE @@ -41,16 +38,12 @@ // and/or an exception thrown and takes appropriate action. // This needs to be done as a macro so the debugger will stop in the user // source code rather than in Catch library code -#define INTERNAL_CATCH_REACT( resultBuilder ) \ - if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ - resultBuilder.react(); -#define INTERNAL_CATCH_REACT2( handler ) \ +#define INTERNAL_CATCH_REACT( handler ) \ if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ handler.reactWithoutDebugBreak(); #define INTERNAL_CATCH_TRY( capturer ) try -#define INTERNAL_CATCH_CATCH( capturer, disposition ) catch(...) { capturer.useActiveException( disposition ); } -#define INTERNAL_CATCH_CATCH2( capturer ) catch(...) { capturer.useActiveException(); } +#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); } #endif @@ -62,8 +55,8 @@ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ - } INTERNAL_CATCH_CATCH2( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. @@ -88,7 +81,7 @@ catch( ... ) { \ catchAssertionHandler.useActiveException(); \ } \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// @@ -105,7 +98,7 @@ } \ else \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// @@ -125,7 +118,7 @@ } \ else \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) @@ -134,7 +127,7 @@ do { \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str().c_str() ); \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// @@ -148,8 +141,8 @@ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ - } INTERNAL_CATCH_CATCH2( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// @@ -166,7 +159,7 @@ } \ else \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) @@ -187,7 +180,7 @@ } \ else \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT2( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) #endif // CATCH_CONFIG_DISABLE_MATCHERS From ee9b19efd3737afc93e14023cc0b4a9fd2a21b7c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 12:10:14 +0100 Subject: [PATCH 228/398] Moved matcher-based capture macros into their own file - this file excluded from the CATCH_CONFIG_DISABLE_MATCHERS path. - matchers are always compiled in to the impl file - _THROWS_WITH macros are still available with matchers disabled - but only the ones that take a string - tests that use matchers have #ifdefs, so the whole SelfTest project can compile with matchers disable. --- CMakeLists.txt | 2 + include/catch.hpp | 12 ++- include/internal/catch_assertionhandler.cpp | 10 +-- include/internal/catch_assertionhandler.h | 4 - include/internal/catch_capture.hpp | 34 +------- include/internal/catch_capture_matchers.cpp | 23 ++++++ include/internal/catch_capture_matchers.h | 87 +++++++++++++++++++++ include/internal/catch_decomposer.h | 34 -------- include/internal/catch_matchers.cpp | 4 - include/internal/catch_matchers.hpp | 4 - include/internal/catch_matchers_string.cpp | 4 - include/internal/catch_matchers_string.h | 4 - include/internal/catch_matchers_vector.h | 5 -- projects/SelfTest/CompilationTests.cpp | 2 + projects/SelfTest/ExceptionTests.cpp | 4 + projects/SelfTest/MatchersTests.cpp | 4 + projects/SelfTest/TagAliasTests.cpp | 5 +- projects/SelfTest/TestMain.cpp | 6 ++ 18 files changed, 143 insertions(+), 105 deletions(-) create mode 100644 include/internal/catch_capture_matchers.cpp create mode 100644 include/internal/catch_capture_matchers.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 94f06f40..4e8c8734 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_assertioninfo.h ${HEADER_DIR}/internal/catch_assertionresult.h ${HEADER_DIR}/internal/catch_capture.hpp + ${HEADER_DIR}/internal/catch_capture_matchers.h ${HEADER_DIR}/internal/catch_clara.h ${HEADER_DIR}/internal/catch_commandline.hpp ${HEADER_DIR}/internal/catch_common.h @@ -201,6 +202,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_assertionhandler.cpp ${HEADER_DIR}/internal/catch_assertionresult.cpp ${HEADER_DIR}/internal/catch_benchmark.cpp + ${HEADER_DIR}/internal/catch_capture_matchers.cpp ${HEADER_DIR}/internal/catch_commandline.cpp ${HEADER_DIR}/internal/catch_common.cpp ${HEADER_DIR}/internal/catch_config.cpp diff --git a/include/catch.hpp b/include/catch.hpp index 58d8c9d5..a2fd8bb2 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -41,6 +41,10 @@ #include "internal/catch_compiler_capabilities.h" #include "internal/catch_interfaces_tag_alias_registry.h" +#ifndef CATCH_CONFIG_DISABLE_MATCHERS +#include "internal/catch_capture_matchers.h" +#endif + // These files are included here so the single_include script doesn't put them // in the conditionally compiled sections #include "internal/catch_test_case_info.h" @@ -72,8 +76,8 @@ #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #endif// CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) @@ -86,8 +90,8 @@ #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #endif // CATCH_CONFIG_DISABLE_MATCHERS #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) @@ -134,8 +138,8 @@ #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #endif // CATCH_CONFIG_DISABLE_MATCHERS #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) @@ -148,8 +152,8 @@ #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #endif // CATCH_CONFIG_DISABLE_MATCHERS #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index ea4f75af..9e7c8453 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -14,7 +14,7 @@ #include "catch_context.h" #include "catch_debugger.h" #include "catch_interfaces_registry_hub.h" -#include "catch_matchers_string.h" +#include "catch_capture_matchers.h" #include @@ -138,12 +138,8 @@ namespace Catch { m_inExceptionGuard = false; } - using StringMatcher = Matchers::Impl::MatcherBase; - - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { - MatchExpr expr( Catch::translateActiveException(), matcher, matcherString ); - handler.handle( expr ); - } + // 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 ) { handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); } diff --git a/include/internal/catch_assertionhandler.h b/include/internal/catch_assertionhandler.h index a1b1777a..9fdbee4f 100644 --- a/include/internal/catch_assertionhandler.h +++ b/include/internal/catch_assertionhandler.h @@ -10,7 +10,6 @@ #include "catch_decomposer.h" #include "catch_assertioninfo.h" -#include "catch_matchers_string.h" // !TBD: for exception matchers namespace Catch { @@ -67,9 +66,6 @@ namespace Catch { void unsetExceptionGuard(); }; - using StringMatcher = Matchers::Impl::MatcherBase; - - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); } // namespace Catch diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 257d057f..2f631bd3 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -134,18 +134,8 @@ #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ - INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ - catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ - } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( Catch::alwaysFalse() ) - /////////////////////////////////////////////////////////////////////////////// +// 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, #__VA_ARGS__ ", " #matcher, resultDisposition ); \ @@ -163,26 +153,4 @@ } while( Catch::alwaysFalse() ) -/////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ - do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \ - if( catchAssertionHandler.allowThrows() ) \ - try { \ - static_cast(__VA_ARGS__ ); \ - catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ - } \ - catch( exceptionType const& ex ) { \ - catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ - } \ - catch( ... ) { \ - catchAssertionHandler.useActiveException(); \ - } \ - else \ - catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ - INTERNAL_CATCH_REACT( catchAssertionHandler ) \ - } while( Catch::alwaysFalse() ) -#endif // CATCH_CONFIG_DISABLE_MATCHERS - - #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED diff --git a/include/internal/catch_capture_matchers.cpp b/include/internal/catch_capture_matchers.cpp new file mode 100644 index 00000000..8c30a154 --- /dev/null +++ b/include/internal/catch_capture_matchers.cpp @@ -0,0 +1,23 @@ +/* + * Created by Phil on 9/8/2017. + * Copyright 2017 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) + */ +#include "catch_capture_matchers.h" +#include "catch_interfaces_registry_hub.h" + +namespace Catch { + + using StringMatcher = Matchers::Impl::MatcherBase; + + // This is the general overload that takes a any string matcher + // There is another overload, in catch_assertinhandler.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 ) { + MatchExpr expr( Catch::translateActiveException(), matcher, matcherString ); + handler.handle( expr ); + } + +} // namespace Catch diff --git a/include/internal/catch_capture_matchers.h b/include/internal/catch_capture_matchers.h new file mode 100644 index 00000000..e3e43568 --- /dev/null +++ b/include/internal/catch_capture_matchers.h @@ -0,0 +1,87 @@ +/* + * Created by Phil on 9/8/2017 + * Copyright 2017 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) + */ +#ifndef TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED + +#include "catch_capture.hpp" +#include "catch_matchers.hpp" +#include "catch_matchers_string.h" + +namespace Catch { + + template + class MatchExpr : public ITransientExpression { + ArgT const& m_arg; + MatcherT m_matcher; + StringRef m_matcherString; + bool m_result; + public: + MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) + : m_arg( arg ), + m_matcher( matcher ), + m_matcherString( matcherString ), + m_result( matcher.match( arg ) ) + {} + + auto isBinaryExpression() const -> bool override { return true; } + auto getResult() const -> bool override { return m_result; } + + void streamReconstructedExpression( std::ostream &os ) const override { + auto matcherAsString = m_matcher.toString(); + os << Catch::Detail::stringify( m_arg ) << ' '; + if( matcherAsString == Detail::unprintableString ) + os << m_matcherString.c_str(); + else + os << matcherAsString; + } + }; + + using StringMatcher = Matchers::Impl::MatcherBase; + + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); + + template + auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { + return MatchExpr( arg, matcher, matcherString ); + } + +} // namespace Catch + + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ + catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__ ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType const& ex ) { \ + catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ + } \ + catch( ... ) { \ + catchAssertionHandler.useActiveException(); \ + } \ + else \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +#endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 6889d873..e1c2f217 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -10,7 +10,6 @@ #include "catch_tostring.h" #include "catch_stringref.h" -#include "catch_matchers.hpp" // !TBD: for exception matchers - move this #include @@ -156,39 +155,6 @@ namespace Catch { } }; - // !TBD: this is just here temporarily - template - class MatchExpr : public ITransientExpression { - ArgT const& m_arg; - MatcherT m_matcher; - StringRef m_matcherString; - bool m_result; - public: - MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) - : m_arg( arg ), - m_matcher( matcher ), - m_matcherString( matcherString ), - m_result( matcher.match( arg ) ) - {} - - auto isBinaryExpression() const -> bool override { return true; } - auto getResult() const -> bool override { return m_result; } - - void streamReconstructedExpression( std::ostream &os ) const override { - auto matcherAsString = m_matcher.toString(); - os << Catch::Detail::stringify( m_arg ) << ' '; - if( matcherAsString == Detail::unprintableString ) - os << m_matcherString.c_str(); - else - os << matcherAsString; - } - }; - - template - auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { - return MatchExpr( arg, matcher, matcherString ); - } - } // end namespace Catch #ifdef _MSC_VER diff --git a/include/internal/catch_matchers.cpp b/include/internal/catch_matchers.cpp index 76d0332c..38ae8c77 100644 --- a/include/internal/catch_matchers.cpp +++ b/include/internal/catch_matchers.cpp @@ -5,8 +5,6 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - #include "catch_matchers.hpp" namespace Catch { @@ -26,5 +24,3 @@ using namespace Matchers; using Matchers::Impl::MatcherBase; } // namespace Catch - -#endif // CATCH_CONFIG_DISABLE_MATCHERS \ No newline at end of file diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index c120bbf3..5a3f0818 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -8,8 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - #include "catch_common.h" #include @@ -182,6 +180,4 @@ using Matchers::Impl::MatcherBase; } // namespace Catch -#endif // CATCH_CONFIG_DISABLE_MATCHERS - #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED diff --git a/include/internal/catch_matchers_string.cpp b/include/internal/catch_matchers_string.cpp index 2f899e8d..2f8ffdb8 100644 --- a/include/internal/catch_matchers_string.cpp +++ b/include/internal/catch_matchers_string.cpp @@ -6,8 +6,6 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - #include "catch_matchers_string.h" #include "catch_string_manip.h" @@ -94,5 +92,3 @@ namespace Matchers { } // namespace Matchers } // namespace Catch - -#endif // CATCH_CONFIG_DISABLE_MATCHERS diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index 27e5b4cc..eca35789 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -8,8 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - #include "catch_matchers.hpp" #include @@ -68,6 +66,4 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -#endif // CATCH_CONFIG_DISABLE_MATCHERS - #endif // TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index a2f5cb6c..4bf39d70 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -8,9 +8,6 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED -#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) - - #include "catch_matchers.hpp" namespace Catch { @@ -115,6 +112,4 @@ namespace Matchers { } // namespace Matchers } // namespace Catch -#endif // CATCH_CONFIG_DISABLE_MATCHERS - #endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED diff --git a/projects/SelfTest/CompilationTests.cpp b/projects/SelfTest/CompilationTests.cpp index e6c31f65..4dd260f8 100644 --- a/projects/SelfTest/CompilationTests.cpp +++ b/projects/SelfTest/CompilationTests.cpp @@ -43,7 +43,9 @@ bool templated_tests(T t) { REQUIRE_THROWS(throws_int(true)); CHECK_THROWS_AS(throws_int(true), int); REQUIRE_NOTHROW(throws_int(false)); +#ifndef CATCH_CONFIG_DISABLE_MATCHERS REQUIRE_THAT("aaa", Catch::EndsWith("aaa")); +#endif return true; } diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 2ec64c71..566065e6 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -181,6 +181,8 @@ TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]" ) throw double( 3.14 ); } +#ifndef CATCH_CONFIG_DISABLE_MATCHERS + TEST_CASE( "Exception messages can be tested for", "[!throws]" ) { using namespace Catch::Matchers; SECTION( "exact match" ) @@ -195,6 +197,8 @@ TEST_CASE( "Exception messages can be tested for", "[!throws]" ) { } } +#endif + TEST_CASE( "Mismatching exception messages failing the test", "[.][failing][!throws]" ) { REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); diff --git a/projects/SelfTest/MatchersTests.cpp b/projects/SelfTest/MatchersTests.cpp index 814577e9..52a49230 100644 --- a/projects/SelfTest/MatchersTests.cpp +++ b/projects/SelfTest/MatchersTests.cpp @@ -8,6 +8,8 @@ #include "catch.hpp" +#ifndef CATCH_CONFIG_DISABLE_MATCHERS + inline const char* testStringForMatching() { return "this string contains 'abc' as a substring"; @@ -223,3 +225,5 @@ TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.fail REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{ 1 }); } } + +#endif // CATCH_CONFIG_DISABLE_MATCHERS diff --git a/projects/SelfTest/TagAliasTests.cpp b/projects/SelfTest/TagAliasTests.cpp index 840601e7..b533c454 100644 --- a/projects/SelfTest/TagAliasTests.cpp +++ b/projects/SelfTest/TagAliasTests.cpp @@ -11,8 +11,6 @@ TEST_CASE( "Tag alias can be registered against tag patterns" ) { - using namespace Catch::Matchers; - Catch::TagAliasRegistry registry; registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) ); @@ -24,11 +22,14 @@ TEST_CASE( "Tag alias can be registered against tag patterns" ) { FAIL( "expected exception" ); } catch( std::exception& ex ) { +#ifndef CATCH_CONFIG_DISABLE_MATCHERS std::string what = ex.what(); + using namespace Catch::Matchers; CHECK_THAT( what, Contains( "[@zzz]" ) ); CHECK_THAT( what, Contains( "file" ) ); CHECK_THAT( what, Contains( "2" ) ); CHECK_THAT( what, Contains( "10" ) ); +#endif } } diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index aad1f036..c3b1f29b 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -47,7 +47,9 @@ inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { +#ifndef CATCH_CONFIG_DISABLE_MATCHERS using namespace Catch::Matchers; +#endif Catch::ConfigData config; auto cli = Catch::makeCommandLineParser(config); @@ -153,7 +155,9 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" auto result = cli.parse({"test", "-x", "oops"}); CHECK(!result); +#ifndef CATCH_CONFIG_DISABLE_MATCHERS REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops")); +#endif } } @@ -225,7 +229,9 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" SECTION( "error" ) { auto result = cli.parse({"test", "--use-colour", "wrong"}); CHECK( !result ); +#ifndef CATCH_CONFIG_DISABLE_MATCHERS CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) ); +#endif } } } From 11295a26634fc06dc1d8ccb2aeb1a7df1150966b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 10 Aug 2017 11:45:05 +0200 Subject: [PATCH 229/398] Make catch_stream.hpp a standard .cpp file --- CMakeLists.txt | 2 +- include/internal/catch_impl.hpp | 1 - include/internal/{catch_stream.hpp => catch_stream.cpp} | 4 ---- 3 files changed, 1 insertion(+), 6 deletions(-) rename include/internal/{catch_stream.hpp => catch_stream.cpp} (94%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 211bfd9d..4e0cb755 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_section_info.h ${HEADER_DIR}/internal/catch_startup_exception_registry.h ${HEADER_DIR}/internal/catch_stream.h - ${HEADER_DIR}/internal/catch_stream.hpp ${HEADER_DIR}/internal/catch_streambuf.h ${HEADER_DIR}/internal/catch_string.h ${HEADER_DIR}/internal/catch_stringbuilder.h @@ -224,6 +223,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_section.cpp ${HEADER_DIR}/internal/catch_section_info.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp + ${HEADER_DIR}/internal/catch_stream.cpp ${HEADER_DIR}/internal/catch_string.cpp ${HEADER_DIR}/internal/catch_stringbuilder.cpp ${HEADER_DIR}/internal/catch_stringdata.cpp diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 03fa6e46..0d846e1d 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -29,7 +29,6 @@ #include "../catch_session.hpp" -#include "catch_stream.hpp" #include "catch_test_spec.hpp" #include "catch_test_case_tracker.hpp" diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.cpp similarity index 94% rename from include/internal/catch_stream.hpp rename to include/internal/catch_stream.cpp index dbcda110..81dbdd47 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.cpp @@ -6,8 +6,6 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * */ -#ifndef TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED #include "catch_common.h" #include "catch_enforce.h" @@ -106,5 +104,3 @@ namespace Catch { } #endif } - -#endif // TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED From 5da76bb7be3b05c83b70bbd6e9a766a14cc54e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 10 Aug 2017 16:24:31 +0200 Subject: [PATCH 230/398] Allow specifying default reporter at compile time --- include/catch_session.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index d31896c7..61b99049 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -32,10 +32,14 @@ namespace Catch { return reporter; } +#ifndef CATCH_CONFIG_DEFAULT_REPORTER +#define CATCH_CONFIG_DEFAULT_REPORTER "console" +#endif + IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { auto const& reporterNames = config->getReporterNames(); if( reporterNames.empty() ) - return createReporter( "console", config ); + return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config ); IStreamingReporterPtr reporter; for( auto const& name : reporterNames ) From 3382312bd8300f6b11fc627632ed4e5b466650d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 10 Aug 2017 17:06:32 +0200 Subject: [PATCH 231/398] Remove obsoleted `SCOPED_MSG` and `SCOPED_CAPTURE` Standard `MSG` and `CAPTURE` behave the same way these used to, and are recommended instead. --- include/catch.hpp | 4 - .../Baselines/console.std.approved.txt | 28 +-- .../Baselines/console.sw.approved.txt | 208 +++++++++--------- projects/SelfTest/MessageTests.cpp | 6 +- 4 files changed, 121 insertions(+), 125 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 58d8c9d5..b830c97e 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -100,9 +100,7 @@ #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) -#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) @@ -163,9 +161,7 @@ #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) -#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index c01923c1..7f854c3e 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -422,6 +422,20 @@ with messages: this message should be logged and this, but later +------------------------------------------------------------------------------- +INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + ------------------------------------------------------------------------------- Inequality checks that should fail ------------------------------------------------------------------------------- @@ -655,20 +669,6 @@ DecompositionTests.cpp:: FAILED: with expansion: Hey, its truthy! -------------------------------------------------------------------------------- -SCOPED_INFO is reset for each loop -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: FAILED: - REQUIRE( i < 10 ) -with expansion: - 10 < 10 -with messages: - current counter 10 - i := 10 - A string sent directly to stdout A string sent directly to stderr Write to std::cerr diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 6b64aee8..012ac260 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1648,6 +1648,110 @@ with messages: and this, but later but not this +------------------------------------------------------------------------------- +INFO is reset for each loop +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 0 < 10 +with messages: + current counter 0 + i := 0 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 1 < 10 +with messages: + current counter 1 + i := 1 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 2 < 10 +with messages: + current counter 2 + i := 2 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 3 < 10 +with messages: + current counter 3 + i := 3 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 4 < 10 +with messages: + current counter 4 + i := 4 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 5 < 10 +with messages: + current counter 5 + i := 5 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 6 < 10 +with messages: + current counter 6 + i := 6 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 7 < 10 +with messages: + current counter 7 + i := 7 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 8 < 10 +with messages: + current counter 8 + i := 8 + +MessageTests.cpp:: +PASSED: + REQUIRE( i < 10 ) +with expansion: + 9 < 10 +with messages: + current counter 9 + i := 9 + +MessageTests.cpp:: FAILED: + REQUIRE( i < 10 ) +with expansion: + 10 < 10 +with messages: + current counter 10 + i := 10 + ------------------------------------------------------------------------------- Inequality checks that should fail ------------------------------------------------------------------------------- @@ -3839,110 +3943,6 @@ DecompositionTests.cpp:: FAILED: with expansion: Hey, its truthy! -------------------------------------------------------------------------------- -SCOPED_INFO is reset for each loop -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 0 < 10 -with messages: - current counter 0 - i := 0 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 1 < 10 -with messages: - current counter 1 - i := 1 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 2 < 10 -with messages: - current counter 2 - i := 2 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 3 < 10 -with messages: - current counter 3 - i := 3 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 4 < 10 -with messages: - current counter 4 - i := 4 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 5 < 10 -with messages: - current counter 5 - i := 5 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 6 < 10 -with messages: - current counter 6 - i := 6 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 7 < 10 -with messages: - current counter 7 - i := 7 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 8 < 10 -with messages: - current counter 8 - i := 8 - -MessageTests.cpp:: -PASSED: - REQUIRE( i < 10 ) -with expansion: - 9 < 10 -with messages: - current counter 9 - i := 9 - -MessageTests.cpp:: FAILED: - REQUIRE( i < 10 ) -with expansion: - 10 < 10 -with messages: - current counter 10 - i := 10 - ------------------------------------------------------------------------------- SUCCEED counts as a test pass ------------------------------------------------------------------------------- diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp index 0faa4d72..437ba53d 100644 --- a/projects/SelfTest/MessageTests.cpp +++ b/projects/SelfTest/MessageTests.cpp @@ -102,11 +102,11 @@ TEST_CASE( "Standard error is reported and redirected", "[messages][.]" ) { } } -TEST_CASE( "SCOPED_INFO is reset for each loop", "[messages][failing][.]" ) { +TEST_CASE( "INFO is reset for each loop", "[messages][failing][.]" ) { for( int i=0; i<100; i++ ) { - SCOPED_INFO( "current counter " << i ); - SCOPED_CAPTURE( i ); + INFO( "current counter " << i ); + CAPTURE( i ); REQUIRE( i < 10 ); } } From 6282999291f604c27d515cfeb9bb50ba01987d40 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 10 Aug 2017 17:00:22 +0100 Subject: [PATCH 232/398] Rebased approvals with info loop change --- .../SelfTest/Baselines/junit.sw.approved.txt | 14 +- .../SelfTest/Baselines/xml.sw.approved.txt | 314 +++++++++--------- 2 files changed, 164 insertions(+), 164 deletions(-) diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 57fe9349..de6224e5 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -273,6 +273,13 @@ MessageTests.cpp: this message may be logged later this message should be logged and this, but later +MessageTests.cpp: + + + + +current counter 10 +i := 10 MessageTests.cpp: @@ -459,13 +466,6 @@ MessageTests.cpp: DecompositionTests.cpp: - - -current counter 10 -i := 10 -MessageTests.cpp: - - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index d2b9bf80..64105e60 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1920,6 +1920,163 @@ + + + current counter 0 + + + i := 0 + + + + i < 10 + + + 0 < 10 + + + + current counter 1 + + + i := 1 + + + + i < 10 + + + 1 < 10 + + + + current counter 2 + + + i := 2 + + + + i < 10 + + + 2 < 10 + + + + current counter 3 + + + i := 3 + + + + i < 10 + + + 3 < 10 + + + + current counter 4 + + + i := 4 + + + + i < 10 + + + 4 < 10 + + + + current counter 5 + + + i := 5 + + + + i < 10 + + + 5 < 10 + + + + current counter 6 + + + i := 6 + + + + i < 10 + + + 6 < 10 + + + + current counter 7 + + + i := 7 + + + + i < 10 + + + 7 < 10 + + + + current counter 8 + + + i := 8 + + + + i < 10 + + + 8 < 10 + + + + current counter 9 + + + i := 9 + + + + i < 10 + + + 9 < 10 + + + + current counter 10 + + + i := 10 + + + + i < 10 + + + 10 < 10 + + + + @@ -4431,163 +4588,6 @@ - - - current counter 0 - - - i := 0 - - - - i < 10 - - - 0 < 10 - - - - current counter 1 - - - i := 1 - - - - i < 10 - - - 1 < 10 - - - - current counter 2 - - - i := 2 - - - - i < 10 - - - 2 < 10 - - - - current counter 3 - - - i := 3 - - - - i < 10 - - - 3 < 10 - - - - current counter 4 - - - i := 4 - - - - i < 10 - - - 4 < 10 - - - - current counter 5 - - - i := 5 - - - - i < 10 - - - 5 < 10 - - - - current counter 6 - - - i := 6 - - - - i < 10 - - - 6 < 10 - - - - current counter 7 - - - i := 7 - - - - i < 10 - - - 7 < 10 - - - - current counter 8 - - - i := 8 - - - - i < 10 - - - 8 < 10 - - - - current counter 9 - - - i := 9 - - - - i < 10 - - - 9 < 10 - - - - current counter 10 - - - i := 10 - - - - i < 10 - - - 10 < 10 - - - - From 684cbb2631fbb31c60e3a9cf1eedae22aa5227d0 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 10 Aug 2017 17:10:13 +0100 Subject: [PATCH 233/398] Fixes issue with fatal errors and non-failing assertions Fixes #990 --- include/internal/catch_run_context.cpp | 1 + projects/SelfTest/TrickyTests.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index d1dd4168..d29ef54d 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -227,6 +227,7 @@ namespace Catch { Totals deltaTotals; deltaTotals.testCases.failed = 1; + deltaTotals.assertions.failed = 1; m_reporter->testCaseEnded(TestCaseStats(testInfo, deltaTotals, std::string(), diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 0fe377ce..96a8b2b6 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -429,3 +429,9 @@ TEST_CASE("Commas in various macros are allowed") { CHECK(true); } } + +TEST_CASE( "null deref", "[.][failing][!nonportable]" ) { + CHECK( false ); + int *x = NULL; + *x = 1; +} From df5c31bb1938d39d8916365a676e708fdb15d4c9 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 11 Aug 2017 10:38:29 +0100 Subject: [PATCH 234/398] Cleaned up the output a bit - removed [!shouldfail] test from "green" path - changed "spanner" to more descriptive text --- projects/SelfTest/Baselines/console.std.approved.txt | 3 ++- projects/SelfTest/Baselines/console.sw.approved.txt | 3 ++- projects/SelfTest/Baselines/junit.sw.approved.txt | 3 ++- projects/SelfTest/Baselines/xml.sw.approved.txt | 7 ++++--- projects/SelfTest/ExceptionTests.cpp | 2 +- projects/SelfTest/MiscTests.cpp | 2 +- projects/SelfTest/TrickyTests.cpp | 4 ++-- 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 1312ad4b..f0a61f56 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -885,7 +885,8 @@ MiscTests.cpp:: FAILED: with expansion: false -spanner------------------------------------------------------------------------------- +loose text artifact +------------------------------------------------------------------------------- just failure ------------------------------------------------------------------------------- MessageTests.cpp: diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 10f9830b..db766fab 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -6600,7 +6600,8 @@ MiscTests.cpp: MiscTests.cpp:: PASSED: -spanner------------------------------------------------------------------------------- +loose text artifact +------------------------------------------------------------------------------- just failure ------------------------------------------------------------------------------- MessageTests.cpp: diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index de6224e5..b99c0964 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,6 @@ - + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 64105e60..5aebbe28 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -4,7 +4,7 @@ - +
answer := 42 @@ -117,7 +117,7 @@ - + f() == 0 @@ -7398,7 +7398,8 @@ Message from section two -spanner +loose text artifact + diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 566065e6..6c7cdb2c 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -205,7 +205,7 @@ TEST_CASE( "Mismatching exception messages failing the test", "[.][failing][!thr REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); } -TEST_CASE( "#748 - captures with unexpected exceptions", "[!shouldfail][!throws]" ) { +TEST_CASE( "#748 - captures with unexpected exceptions", "[.][failing][!throws][!shouldfail]" ) { int answer = 42; CAPTURE( answer ); // the message should be printed on the first two sections but not on the third diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index c8a7b302..500e876a 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -353,7 +353,7 @@ static int f() { return 1; } -TEST_CASE( "#835 -- errno should not be touched by Catch", "[!shouldfail]" ) { +TEST_CASE( "#835 -- errno should not be touched by Catch", "[.][failing][!shouldfail]" ) { errno = 1; CHECK(f() == 0); REQUIRE(errno == 1); // Check that f() doesn't touch errno. diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 96a8b2b6..a03b21ff 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -396,8 +396,8 @@ TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); } TEST_CASE( "has printf" ) { - // This can cause problems as, currently, stdout itself is not redirect - only the cout (and cerr) buffer - printf( "spanner" ); + // This can cause problems as, currently, stdout itself is not redirected - only the cout (and cerr) buffer + printf( "loose text artifact\n" ); } TEST_CASE( "assertions with commas are allowed" ) { From eed4ae86ad38b2d04670e44a941bd96129906f4c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 22:26:17 +0100 Subject: [PATCH 235/398] Added config to control multiple of clock resolution to run benchmark iterations for --- include/internal/catch_benchmark.cpp | 6 +++++- include/internal/catch_benchmark.h | 6 ++++-- include/internal/catch_commandline.cpp | 3 +++ include/internal/catch_config.cpp | 1 + include/internal/catch_config.hpp | 2 ++ include/internal/catch_interfaces_config.h | 1 + 6 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_benchmark.cpp b/include/internal/catch_benchmark.cpp index 51a844f6..d92b255c 100644 --- a/include/internal/catch_benchmark.cpp +++ b/include/internal/catch_benchmark.cpp @@ -12,7 +12,11 @@ namespace Catch { - void BenchmarkLooper::reportStart() const { + auto BenchmarkLooper::getResolution() -> uint64_t { + return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); + } + + void BenchmarkLooper::reportStart() { getResultCapture().benchmarkStarting( { m_name } ); } auto BenchmarkLooper::needsMoreIterations() -> bool { diff --git a/include/internal/catch_benchmark.h b/include/internal/catch_benchmark.h index 7b01507a..ffb1db78 100644 --- a/include/internal/catch_benchmark.h +++ b/include/internal/catch_benchmark.h @@ -23,11 +23,13 @@ namespace Catch { size_t m_iterationsToRun = 1; uint64_t m_resolution; Timer m_timer; + + static auto getResolution() -> uint64_t; public: // Keep most of this inline as it's on the code path that is being timed BenchmarkLooper( StringRef name ) : m_name( name.c_str() ), - m_resolution( getEstimatedClockResolution()*10 ) + m_resolution( getResolution() ) { reportStart(); m_timer.start(); @@ -43,7 +45,7 @@ namespace Catch { ++m_count; } - void reportStart() const; + void reportStart(); auto needsMoreIterations() -> bool; }; diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index b94bc2d2..7342ac42 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -153,6 +153,9 @@ namespace Catch { + Opt( setColourUsage, "yes|no" ) ["--use-colour"] ( "should output be colourised" ) + + Opt( config.benchmarkResolutionMultiple, "multiplier" ) + ["--benchmark-resolution-multiple"] + ( "multiple of clock resolution to run benchmarks" ) + Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); diff --git a/include/internal/catch_config.cpp b/include/internal/catch_config.cpp index ae1e95dd..d88a3d14 100644 --- a/include/internal/catch_config.cpp +++ b/include/internal/catch_config.cpp @@ -49,6 +49,7 @@ namespace Catch { ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } unsigned int Config::rngSeed() const { return m_data.rngSeed; } + int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; } UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } int Config::abortAfter() const { return m_data.abortAfter; } diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 531543c2..6bf792b0 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -38,6 +38,7 @@ namespace Catch { int abortAfter = -1; unsigned int rngSeed = 0; + int benchmarkResolutionMultiple = 10; Verbosity verbosity = Verbosity::Normal; WarnAbout::What warnings = WarnAbout::Nothing; @@ -88,6 +89,7 @@ namespace Catch { ShowDurations::OrNot showDurations() const override; RunTests::InWhatOrder runOrder() const override; unsigned int rngSeed() const override; + int benchmarkResolutionMultiple() const override; UseColour::YesOrNo useColour() const override; bool shouldDebugBreak() const override; int abortAfter() const override; diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index d2d7602c..436b80eb 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -62,6 +62,7 @@ namespace Catch { virtual TestSpec const& testSpec() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; + virtual int benchmarkResolutionMultiple() const = 0; virtual UseColour::YesOrNo useColour() const = 0; virtual std::vector const& getSectionsToRun() const = 0; virtual Verbosity verbosity() const = 0; From 1aab791d67a8a4072156db22d80c1a863dcdb593 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 9 Aug 2017 23:27:29 +0100 Subject: [PATCH 236/398] reformatted benchmark output a bit --- include/reporters/catch_reporter_bases.hpp | 10 ---------- include/reporters/catch_reporter_console.cpp | 10 ++++------ 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 2f9a8013..cfba9415 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -259,16 +259,6 @@ namespace Catch { } return line; } - inline char const* getBoxCharsAcross() { - static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; - if( !*line ) { - std::memset( line, '-', CATCH_CONFIG_CONSOLE_WIDTH-1 ); - line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; - line[0] = '+'; - line[CATCH_CONFIG_CONSOLE_WIDTH-2] = '+'; - } - return line; - } struct TestEventListenerBase : StreamingReporterBase { diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 33259041..ca102df6 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -65,6 +65,7 @@ namespace { for( auto const& info : m_columnInfos ) *this << info.name << ColumnBreak(); *this << RowBreak(); + m_os << Catch::getLineOfChars<'-'>() << "\n"; } } void close() { @@ -91,8 +92,6 @@ namespace { tp.m_currentColumn = -1; tp.m_os << "\n"; } - if( tp.m_currentColumn == -1 ) - tp.m_os << "|"; tp.m_currentColumn++; auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; @@ -100,9 +99,9 @@ namespace { ? std::string( colInfo.width-(strSize+2), ' ' ) : std::string(); if( colInfo.justification == ColumnInfo::Left ) - tp.m_os << " " << colStr << padding << " |"; + tp.m_os << colStr << padding << " "; else - tp.m_os << " " << padding << colStr << " |"; + tp.m_os << padding << colStr << " "; return tp; } @@ -111,7 +110,6 @@ namespace { tp.m_os << "\n"; tp.m_currentColumn = -1; } - tp.m_os << Catch::getBoxCharsAcross() << "\n"; return tp; } }; @@ -199,7 +197,7 @@ namespace Catch { : StreamingReporterBase( config ), m_tablePrinter( config.stream(), { - { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-42, ColumnInfo::Left }, + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-32, ColumnInfo::Left }, { "iters", 8, ColumnInfo::Right }, { "elapsed ns", 14, ColumnInfo::Right }, { "average", 14, ColumnInfo::Right } From c659e0fd3dadd397dfed17e59a624fb693d77646 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 14 Aug 2017 08:39:14 +0100 Subject: [PATCH 237/398] StringRef conversions to/ from std::string --- include/internal/catch_stringref.cpp | 12 ++++++-- include/internal/catch_stringref.h | 3 ++ projects/SelfTest/StringRef.tests.cpp | 42 +++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 44db6858..9a1eaf4c 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -60,8 +60,7 @@ namespace Catch { StringRef::StringRef( String const& other ) noexcept : m_start( other.c_str() ), - m_size( other.size() ), - m_data( nullptr ) + m_size( other.size() ) {} StringRef::StringRef( String&& str ) noexcept @@ -71,7 +70,11 @@ namespace Catch { { str.m_data = StringData::getEmpty(); } - + StringRef::StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + StringRef::~StringRef() noexcept { if( isOwned() ) m_data->release(); @@ -81,6 +84,9 @@ namespace Catch { swap( other ); return *this; } + StringRef::operator std::string() const { + return std::string( m_start, m_size ); + } void StringRef::swap( StringRef& other ) noexcept { std::swap( m_start, other.m_start ); diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index f84ce99a..cde0667a 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -8,6 +8,7 @@ #define CATCH_STRINGREF_H_INCLUDED #include +#include namespace Catch { @@ -43,9 +44,11 @@ namespace Catch { StringRef( char const* rawChars, size_type size ) noexcept; StringRef( String const& other ) noexcept; StringRef( String&& other ) noexcept; + StringRef( std::string const& stdString ) noexcept; ~StringRef() noexcept; auto operator = ( StringRef other ) noexcept -> StringRef&; + operator std::string() const; void swap( StringRef& other ) noexcept; diff --git a/projects/SelfTest/StringRef.tests.cpp b/projects/SelfTest/StringRef.tests.cpp index 4ebaa878..6ebbdb13 100644 --- a/projects/SelfTest/StringRef.tests.cpp +++ b/projects/SelfTest/StringRef.tests.cpp @@ -150,4 +150,46 @@ TEST_CASE( "StringRef", "[Strings]" ) { REQUIRE( data( copied ) == originalPointer ); } } + + SECTION( "from std::string" ) { + std::string stdStr = "a standard string"; + + SECTION( "implicitly constructed" ) { + StringRef sr = stdStr; + REQUIRE( sr == "a standard string" ); + REQUIRE( sr.size() == stdStr.size() ); + } + SECTION( "explicitly constructed" ) { + StringRef sr( stdStr ); + REQUIRE( sr == "a standard string" ); + REQUIRE( sr.size() == stdStr.size() ); + } + SECTION( "assigned" ) { + StringRef sr; + sr = stdStr; + REQUIRE( sr == "a standard string" ); + REQUIRE( sr.size() == stdStr.size() ); + } + } + + SECTION( "to std::string" ) { + StringRef sr = "a stringref"; + + SECTION( "implicitly constructed" ) { + std::string stdStr = sr; + REQUIRE( stdStr == "a stringref" ); + REQUIRE( stdStr.size() == sr.size() ); + } + SECTION( "explicitly constructed" ) { + std::string stdStr( sr ); + REQUIRE( stdStr == "a stringref" ); + REQUIRE( stdStr.size() == sr.size() ); + } + SECTION( "assigned" ) { + std::string stdStr; + stdStr = sr; + REQUIRE( stdStr == "a stringref" ); + REQUIRE( stdStr.size() == sr.size() ); + } + } } From bb8c1fb17f5d0369c2a49505ca4ea0f77d0f636d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 14 Aug 2017 08:43:33 +0100 Subject: [PATCH 238/398] Rebased with string conversion tests --- .../Baselines/console.std.approved.txt | 2 +- .../Baselines/console.sw.approved.txt | 122 +++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 8 +- .../SelfTest/Baselines/xml.sw.approved.txt | 136 +++++++++++++++++- 4 files changed, 263 insertions(+), 5 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index f0a61f56..2618ba11 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1021,5 +1021,5 @@ with expansion: =============================================================================== test cases: 183 | 132 passed | 47 failed | 4 failed as expected -assertions: 896 | 779 passed | 96 failed | 21 failed as expected +assertions: 908 | 791 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index db766fab..f3d8d63d 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -4829,6 +4829,126 @@ PASSED: with expansion: "hot potato" == "hot potato" +------------------------------------------------------------------------------- +StringRef + from std::string + implicitly constructed +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( sr == "a standard string" ) +with expansion: + {?} == "a standard string" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( sr.size() == stdStr.size() ) +with expansion: + 17 == 17 + +------------------------------------------------------------------------------- +StringRef + from std::string + explicitly constructed +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( sr == "a standard string" ) +with expansion: + {?} == "a standard string" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( sr.size() == stdStr.size() ) +with expansion: + 17 == 17 + +------------------------------------------------------------------------------- +StringRef + from std::string + assigned +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( sr == "a standard string" ) +with expansion: + {?} == "a standard string" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( sr.size() == stdStr.size() ) +with expansion: + 17 == 17 + +------------------------------------------------------------------------------- +StringRef + to std::string + implicitly constructed +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( stdStr == "a stringref" ) +with expansion: + "a stringref" == "a stringref" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( stdStr.size() == sr.size() ) +with expansion: + 11 == 11 + +------------------------------------------------------------------------------- +StringRef + to std::string + explicitly constructed +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( stdStr == "a stringref" ) +with expansion: + "a stringref" == "a stringref" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( stdStr.size() == sr.size() ) +with expansion: + 11 == 11 + +------------------------------------------------------------------------------- +StringRef + to std::string + assigned +------------------------------------------------------------------------------- +StringRef.tests.cpp: +............................................................................... + +StringRef.tests.cpp:: +PASSED: + REQUIRE( stdStr == "a stringref" ) +with expansion: + "a stringref" == "a stringref" + +StringRef.tests.cpp:: +PASSED: + REQUIRE( stdStr.size() == sr.size() ) +with expansion: + 11 == 11 + ------------------------------------------------------------------------------- Tabs and newlines show in output ------------------------------------------------------------------------------- @@ -7639,5 +7759,5 @@ PASSED: =============================================================================== test cases: 183 | 130 passed | 49 failed | 4 failed as expected -assertions: 901 | 779 passed | 101 failed | 21 failed as expected +assertions: 913 | 791 passed | 101 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index b99c0964..390e7297 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -527,6 +527,12 @@ MatchersTests.cpp: + + + + + +
+
+
+ + + sr == "a standard string" + + + {?} == "a standard string" + + + + + sr.size() == stdStr.size() + + + 17 == 17 + + + +
+ +
+
+
+ + + sr == "a standard string" + + + {?} == "a standard string" + + + + + sr.size() == stdStr.size() + + + 17 == 17 + + + +
+ +
+
+
+ + + sr == "a standard string" + + + {?} == "a standard string" + + + + + sr.size() == stdStr.size() + + + 17 == 17 + + + +
+ +
+
+
+ + + stdStr == "a stringref" + + + "a stringref" == "a stringref" + + + + + stdStr.size() == sr.size() + + + 11 == 11 + + + +
+ +
+
+
+ + + stdStr == "a stringref" + + + "a stringref" == "a stringref" + + + + + stdStr.size() == sr.size() + + + 11 == 11 + + + +
+ +
+
+
+ + + stdStr == "a stringref" + + + "a stringref" == "a stringref" + + + + + stdStr.size() == sr.size() + + + 11 == 11 + + + +
+ +
@@ -8460,7 +8592,7 @@ loose text artifact
- + - + From fa3535e95e79ffc9776cc0b43248a108b173b323 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 14 Aug 2017 08:50:44 +0100 Subject: [PATCH 239/398] Added << ostream overload to StringRef --- include/internal/catch_stringref.cpp | 2 +- include/internal/catch_stringref.h | 5 +- .../Baselines/console.sw.approved.txt | 61 ++++++---------- .../SelfTest/Baselines/junit.sw.approved.txt | 8 ++- .../SelfTest/Baselines/xml.sw.approved.txt | 70 ++++++------------- 5 files changed, 54 insertions(+), 92 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 9a1eaf4c..7d117018 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -173,7 +173,7 @@ namespace Catch { return StringRef( lhs ) + rhs; } - std::ostream& operator << ( std::ostream& os, StringRef const& str ) { + auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { return os << str.c_str(); } diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index cde0667a..1f8412de 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -9,6 +9,7 @@ #include #include +#include namespace Catch { @@ -76,7 +77,9 @@ namespace Catch { auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> String; auto operator + ( StringRef const& lhs, char const* rhs ) -> String; auto operator + ( char const* lhs, StringRef const& rhs ) -> String; - + + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + } // namespace Catch #endif // CATCH_STRINGREF_H_INCLUDED diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index f3d8d63d..3cc191a6 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -4378,7 +4378,7 @@ StringBuilder.tests.cpp:: PASSED: REQUIRE( s == "hello" ) with expansion: - {?} == "hello" + hello == "hello" StringBuilder.tests.cpp:: PASSED: @@ -4397,7 +4397,7 @@ StringBuilder.tests.cpp:: PASSED: REQUIRE( s == "hello world" ) with expansion: - {?} == "hello world" + hello world == "hello world" ------------------------------------------------------------------------------- StringBuilder @@ -4410,7 +4410,7 @@ StringBuilder.tests.cpp:: PASSED: REQUIRE( s == "hello world" ) with expansion: - {?} == "hello world" + hello world == "hello world" ------------------------------------------------------------------------------- StringBuilder @@ -4435,7 +4435,7 @@ StringBuilder.tests.cpp:: PASSED: REQUIRE( s == "hello world" ) with expansion: - {?} == "hello world" + hello world == "hello world" ------------------------------------------------------------------------------- StringBuilder @@ -4449,7 +4449,7 @@ StringBuilder.tests.cpp:: PASSED: REQUIRE( s2 == s ) with expansion: - {?} == {?} + hello == hello StringBuilder.tests.cpp:: PASSED: @@ -4469,7 +4469,7 @@ StringBuilder.tests.cpp:: PASSED: REQUIRE( s2 == "hello" ) with expansion: - {?} == "hello" + hello == "hello" StringBuilder.tests.cpp:: PASSED: @@ -4489,7 +4489,7 @@ StringBuilder.tests.cpp:: PASSED: REQUIRE( s2 == "hello" ) with expansion: - {?} == "hello" + hello == "hello" StringBuilder.tests.cpp:: PASSED: @@ -4589,32 +4589,11 @@ StringRef.tests.cpp: StringRef.tests.cpp:: PASSED: REQUIRE( original == "original" ) -with expansion: - {?} == "original" -StringRef.tests.cpp:: -PASSED: +StringRef.tests.cpp:: FAILED: REQUIRE( isSubstring( original ) ) with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( original ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isSubstring( original ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( original ) ) -with expansion: - true + false ------------------------------------------------------------------------------- StringRef @@ -4646,7 +4625,7 @@ StringRef.tests.cpp:: PASSED: REQUIRE( ss == "hello" ) with expansion: - {?} == "hello" + hello == "hello" ------------------------------------------------------------------------------- StringRef @@ -4757,13 +4736,13 @@ StringRef.tests.cpp:: PASSED: REQUIRE( StringRef("hello") == StringRef("hello") ) with expansion: - {?} == {?} + hello == hello StringRef.tests.cpp:: PASSED: REQUIRE( StringRef("hello") != StringRef("cello") ) with expansion: - {?} != {?} + hello != cello ------------------------------------------------------------------------------- StringRef @@ -4777,13 +4756,13 @@ StringRef.tests.cpp:: PASSED: REQUIRE( copied == "hot potato" ) with expansion: - {?} == "hot potato" + hot potato == "hot potato" StringRef.tests.cpp:: PASSED: REQUIRE( str == "hot potato" ) with expansion: - {?} == "hot potato" + hot potato == "hot potato" StringRef.tests.cpp:: PASSED: @@ -4809,7 +4788,7 @@ StringRef.tests.cpp:: PASSED: REQUIRE( copied == "hot potato" ) with expansion: - {?} == "hot potato" + hot potato == "hot potato" StringRef.tests.cpp:: PASSED: @@ -4841,7 +4820,7 @@ StringRef.tests.cpp:: PASSED: REQUIRE( sr == "a standard string" ) with expansion: - {?} == "a standard string" + a standard string == "a standard string" StringRef.tests.cpp:: PASSED: @@ -4861,7 +4840,7 @@ StringRef.tests.cpp:: PASSED: REQUIRE( sr == "a standard string" ) with expansion: - {?} == "a standard string" + a standard string == "a standard string" StringRef.tests.cpp:: PASSED: @@ -4881,7 +4860,7 @@ StringRef.tests.cpp:: PASSED: REQUIRE( sr == "a standard string" ) with expansion: - {?} == "a standard string" + a standard string == "a standard string" StringRef.tests.cpp:: PASSED: @@ -7758,6 +7737,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 183 | 130 passed | 49 failed | 4 failed as expected -assertions: 913 | 791 passed | 101 failed | 21 failed as expected +test cases: 183 | 129 passed | 50 failed | 4 failed as expected +assertions: 910 | 787 passed | 102 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 390e7297..8cd10426 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -518,7 +518,11 @@ MatchersTests.cpp: - + + +StringRef.tests.cpp: + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 7ad54363..324fbf6b 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -4999,7 +4999,7 @@ Message from section two s == "hello" - {?} == "hello" + hello == "hello"
@@ -5018,7 +5018,7 @@ Message from section two s == "hello world" - {?} == "hello world" + hello world == "hello world" @@ -5029,7 +5029,7 @@ Message from section two s == "hello world" - {?} == "hello world" + hello world == "hello world" @@ -5056,7 +5056,7 @@ Message from section two s == "hello world" - {?} == "hello world" + hello world == "hello world" @@ -5068,7 +5068,7 @@ Message from section two s2 == s - {?} == {?} + hello == hello @@ -5090,7 +5090,7 @@ Message from section two s2 == "hello" - {?} == "hello" + hello == "hello" @@ -5112,7 +5112,7 @@ Message from section two s2 == "hello" - {?} == "hello" + hello == "hello" @@ -5225,42 +5225,18 @@ Message from section two original == "original" - {?} == "original" + original == "original" - + isSubstring( original ) - true + false - - - isOwned( original ) == false - - - false == false - - - - - isSubstring( original ) == false - - - false == false - - - - - isOwned( original ) - - - true - - - +
@@ -5293,7 +5269,7 @@ Message from section two ss == "hello" - {?} == "hello" + hello == "hello" @@ -5418,7 +5394,7 @@ Message from section two StringRef("hello") == StringRef("hello") - {?} == {?} + hello == hello @@ -5426,7 +5402,7 @@ Message from section two StringRef("hello") != StringRef("cello") - {?} != {?} + hello != cello @@ -5438,7 +5414,7 @@ Message from section two copied == "hot potato" - {?} == "hot potato" + hot potato == "hot potato" @@ -5446,7 +5422,7 @@ Message from section two str == "hot potato" - {?} == "hot potato" + hot potato == "hot potato" @@ -5476,7 +5452,7 @@ Message from section two copied == "hot potato" - {?} == "hot potato" + hot potato == "hot potato" @@ -5514,7 +5490,7 @@ Message from section two sr == "a standard string" - {?} == "a standard string" + a standard string == "a standard string" @@ -5536,7 +5512,7 @@ Message from section two sr == "a standard string" - {?} == "a standard string" + a standard string == "a standard string" @@ -5558,7 +5534,7 @@ Message from section two sr == "a standard string" - {?} == "a standard string" + a standard string == "a standard string" @@ -5639,7 +5615,7 @@ Message from section two
- + @@ -8592,7 +8568,7 @@ loose text artifact
- + - + From ece64c3b3aee6256be32f1f860b5d638173e7520 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 14 Aug 2017 08:54:57 +0100 Subject: [PATCH 240/398] Removed redundant .c_str()s from StringRef usages --- include/internal/catch_assertionhandler.cpp | 4 ++-- include/internal/catch_assertionresult.cpp | 19 +++++++++++++------ include/internal/catch_benchmark.h | 2 +- include/internal/catch_capture.hpp | 2 +- include/internal/catch_capture_matchers.h | 2 +- include/internal/catch_decomposer.h | 2 +- .../internal/catch_interfaces_reporter.cpp | 2 +- include/internal/catch_test_registry.cpp | 6 +++--- include/reporters/catch_reporter_console.cpp | 2 +- 9 files changed, 24 insertions(+), 17 deletions(-) diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp index 9e7c8453..0eed7cd9 100644 --- a/include/internal/catch_assertionhandler.cpp +++ b/include/internal/catch_assertionhandler.cpp @@ -79,7 +79,7 @@ namespace Catch { } void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { AssertionResultData data( resultType, LazyExpression( false ) ); - data.message = message.c_str(); + data.message = message; handle( data, nullptr ); } void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { @@ -126,7 +126,7 @@ namespace Catch { } void AssertionHandler::useActiveException() { - handle( ResultWas::ThrewException, Catch::translateActiveException().c_str() ); + handle( ResultWas::ThrewException, Catch::translateActiveException() ); } void AssertionHandler::setExceptionGuard() { diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 04402000..776fdc72 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -52,16 +52,23 @@ namespace Catch { std::string AssertionResult::getExpression() const { if (isFalseTest(m_info.resultDisposition)) - return '!' + std::string(m_info.capturedExpression.c_str()); + return '!' + std::string(m_info.capturedExpression); else - return std::string(m_info.capturedExpression.c_str()); + return m_info.capturedExpression; } std::string AssertionResult::getExpressionInMacro() const { + std::string expr; if( m_info.macroName[0] == 0 ) - return std::string(m_info.capturedExpression.c_str()); - else - return std::string(m_info.macroName.c_str()) + "( " + m_info.capturedExpression.c_str() + " )"; + expr = m_info.capturedExpression; + else { + expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); + expr += m_info.macroName; + expr += "( "; + expr += m_info.capturedExpression; + expr += " )"; + } + return expr; } bool AssertionResult::hasExpandedExpression() const { @@ -83,7 +90,7 @@ namespace Catch { } std::string AssertionResult::getTestMacroName() const { - return m_info.macroName.c_str(); + return m_info.macroName; } } // end namespace Catch diff --git a/include/internal/catch_benchmark.h b/include/internal/catch_benchmark.h index ffb1db78..2e33c163 100644 --- a/include/internal/catch_benchmark.h +++ b/include/internal/catch_benchmark.h @@ -28,7 +28,7 @@ namespace Catch { public: // Keep most of this inline as it's on the code path that is being timed BenchmarkLooper( StringRef name ) - : m_name( name.c_str() ), + : m_name( name ), m_resolution( getResolution() ) { reportStart(); diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 2f631bd3..d5d0ad4e 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -126,7 +126,7 @@ #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ do { \ Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ - catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str().c_str() ); \ + catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) diff --git a/include/internal/catch_capture_matchers.h b/include/internal/catch_capture_matchers.h index e3e43568..f815c14e 100644 --- a/include/internal/catch_capture_matchers.h +++ b/include/internal/catch_capture_matchers.h @@ -35,7 +35,7 @@ namespace Catch { auto matcherAsString = m_matcher.toString(); os << Catch::Detail::stringify( m_arg ) << ' '; if( matcherAsString == Detail::unprintableString ) - os << m_matcherString.c_str(); + os << m_matcherString; else os << matcherAsString; } diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index e1c2f217..6d20be78 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -53,7 +53,7 @@ namespace Catch { BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) : m_result( comparisionResult ), m_lhs( lhs ), - m_op( op.c_str() ), + m_op( op ), m_rhs( rhs ) {} }; diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp index 05117f9e..c7b2e861 100644 --- a/include/internal/catch_interfaces_reporter.cpp +++ b/include/internal/catch_interfaces_reporter.cpp @@ -42,7 +42,7 @@ namespace Catch { if( assertionResult.hasMessage() ) { // Copy message into messages list. // !TBD This should have been done earlier, somewhere - MessageBuilder builder( assertionResult.getTestMacroName().c_str(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); builder << assertionResult.getMessage(); builder.m_info.message = builder.m_stream.str(); diff --git a/include/internal/catch_test_registry.cpp b/include/internal/catch_test_registry.cpp index 2862879c..7a796cce 100644 --- a/include/internal/catch_test_registry.cpp +++ b/include/internal/catch_test_registry.cpp @@ -23,9 +23,9 @@ namespace Catch { .registerTest( makeTestCase( invoker, - extractClassName( classOrMethod.c_str() ), - nameAndTags.name.c_str(), - nameAndTags.tags.c_str(), + extractClassName( classOrMethod ), + nameAndTags.name, + nameAndTags.tags, lineInfo)); } catch (...) { // Do not throw when constructing global objects, instead register the exception to be processed later diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index ca102df6..0922134d 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -85,7 +85,7 @@ namespace { friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { auto colStr = tp.m_oss.str(); // This takes account of utf8 encodings - auto strSize = Catch::StringRef( colStr.c_str(), colStr.size() ).numberOfCharacters(); + auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); tp.m_oss.str(""); tp.open(); if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { From 3772f69f0fbba0620df4c262b1925444a0567b37 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 14 Aug 2017 09:04:14 +0100 Subject: [PATCH 241/398] Removed String and StringBuilder --- CMakeLists.txt | 6 - include/internal/catch_string.cpp | 86 ----- include/internal/catch_string.h | 52 --- include/internal/catch_stringbuilder.cpp | 111 ------- include/internal/catch_stringbuilder.h | 74 ----- include/internal/catch_stringref.cpp | 40 +-- include/internal/catch_stringref.h | 10 +- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 278 +--------------- .../SelfTest/Baselines/junit.sw.approved.txt | 13 +- .../SelfTest/Baselines/xml.sw.approved.txt | 314 +----------------- projects/SelfTest/String.tests.cpp | 22 -- projects/SelfTest/StringBuilder.tests.cpp | 76 ----- projects/SelfTest/StringRef.tests.cpp | 30 +- 14 files changed, 24 insertions(+), 1092 deletions(-) delete mode 100644 include/internal/catch_string.cpp delete mode 100644 include/internal/catch_string.h delete mode 100644 include/internal/catch_stringbuilder.cpp delete mode 100644 include/internal/catch_stringbuilder.h delete mode 100644 projects/SelfTest/String.tests.cpp delete mode 100644 projects/SelfTest/StringBuilder.tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b63eb93..33ec5d1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,8 +76,6 @@ set(TEST_SOURCES ${SELF_TEST_DIR}/TrickyTests.cpp ${SELF_TEST_DIR}/VariadicMacrosTests.cpp ${SELF_TEST_DIR}/MatchersTests.cpp - ${SELF_TEST_DIR}/String.tests.cpp - ${SELF_TEST_DIR}/StringBuilder.tests.cpp ${SELF_TEST_DIR}/StringRef.tests.cpp ) CheckFileList(TEST_SOURCES ${SELF_TEST_DIR}) @@ -172,8 +170,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_startup_exception_registry.h ${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_streambuf.h - ${HEADER_DIR}/internal/catch_string.h - ${HEADER_DIR}/internal/catch_stringbuilder.h ${HEADER_DIR}/internal/catch_stringdata.h ${HEADER_DIR}/internal/catch_stringref.h ${HEADER_DIR}/internal/catch_string_manip.h @@ -226,8 +222,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_section_info.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp ${HEADER_DIR}/internal/catch_stream.cpp - ${HEADER_DIR}/internal/catch_string.cpp - ${HEADER_DIR}/internal/catch_stringbuilder.cpp ${HEADER_DIR}/internal/catch_stringdata.cpp ${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_string_manip.cpp diff --git a/include/internal/catch_string.cpp b/include/internal/catch_string.cpp deleted file mode 100644 index 73d9d77a..00000000 --- a/include/internal/catch_string.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2016 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) - */ - -#include "catch_string.h" -#include "catch_stringref.h" -#include "catch_stringbuilder.h" - -#include "catch_stringdata.h" - -#include - -namespace Catch { - - String::String() - : m_data( StringData::getEmpty() ) - {} - - String::String( StringRef const& stringRef ) - : m_data( StringData::create( stringRef ) ) - {} - - String::String( char const* rawString ) - : String( StringRef( rawString ) ) - {} - - String::String( String const& other ) - : m_data( other.m_data ) - { - m_data->addRef(); - } - String::String( String&& other ) noexcept - : m_data( other.m_data ) - { - other.m_data = StringData::getEmpty(); - } - String::String( StringBuilder&& stringBuf ) - : m_data( stringBuf.m_data ) - { - // const_cast is ok here because we are taking ownership - const_cast( m_data )->size = stringBuf.size(); - stringBuf.m_data = StringData::getEmpty(); - stringBuf.m_size = 0; - } - - - String::~String() noexcept { - m_data->release(); - } - - auto String::operator = ( String const& other ) -> String& { - m_data = other.m_data; - m_data->addRef(); - return *this; - } - - - auto String::empty() const noexcept -> bool { - return m_data->size == 0; - } - auto String::size() const noexcept -> size_type { - return m_data->size; - } - auto String::numberOfCharacters() const noexcept -> size_type { - return StringRef( *this ).numberOfCharacters(); - } - auto String::c_str() const noexcept -> char const* { - return m_data->chars; - } - - auto String::operator == ( StringRef const& other ) const noexcept -> bool { - return other == StringRef( *this ); - } - auto String::operator == ( char const* other ) const noexcept -> bool { - return StringRef( other ) == StringRef( *this ); - } - - std::ostream& operator << ( std::ostream& os, String const& str ) { - os << str.c_str(); - return os; - } - -} // namespace Catch diff --git a/include/internal/catch_string.h b/include/internal/catch_string.h deleted file mode 100644 index 5691be8d..00000000 --- a/include/internal/catch_string.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2016 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) - */ -#ifndef CATCH_STRING_H_INCLUDED -#define CATCH_STRING_H_INCLUDED - -#include - -namespace Catch { - - class StringData; - class StringRef; - class StringBuilder; - - /// An owning, ref-counted, immutable string type. - /// The ref count (not visible here as it is defined in StringData) is atomic - /// so instances should be safe to share across threads - class String { - friend class StringRef; - friend class StringBuilder; - - StringData const* m_data = nullptr; - public: - using size_type = size_t; - - String(); - String( StringRef const& stringRef ); - String( char const* rawString ); - String( String const& other ); - String( String&& other ) noexcept; - String( StringBuilder&& stringBuf ); - - ~String() noexcept; - - auto operator = ( String const& other ) -> String&; - - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator == ( char const* other ) const noexcept -> bool; - - auto empty() const noexcept -> bool; - auto size() const noexcept -> size_type; - auto numberOfCharacters() const noexcept -> size_type; - - auto c_str() const noexcept -> char const*; - }; - -} // namespace Catch - -#endif // CATCH_STRING_H_INCLUDED diff --git a/include/internal/catch_stringbuilder.cpp b/include/internal/catch_stringbuilder.cpp deleted file mode 100644 index 80ba1bbd..00000000 --- a/include/internal/catch_stringbuilder.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2016 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) - */ - -#include "catch_stringbuilder.h" -#include "catch_stringref.h" -#include "catch_stringdata.h" -#include "catch_string.h" - -#include -#include -#include -#include - -namespace Catch { - - static const StringBuilder::size_type s_minimumCapacity = 32; - - StringBuilder::StringBuilder() - : m_data( StringData::getEmpty() ) - {} - - StringBuilder::StringBuilder( size_type initialCapacity ) - : m_size( 0 ), - m_data( StringData::create( StringRef(), initialCapacity ) ) - {} - StringBuilder::StringBuilder( StringRef const& str, size_type initialCapacity ) - : m_size( str.size() ), - m_data( StringData::create( str, initialCapacity ) ) - {} - StringBuilder::StringBuilder( StringBuilder const& other, size_type initialCapacity ) - : StringBuilder( StringRef( other.m_data->chars, other.m_size ), initialCapacity ) - {} - StringBuilder::StringBuilder( StringBuilder&& other ) noexcept - : StringBuilder() - { - swap( other ); - } - StringBuilder::StringBuilder( String&& str ) - : m_size( str.size() ), - m_data( StringData::getEmpty() ) - { - if( str.m_data->isUniquelyOwned() ) - { - std::swap( m_data, const_cast( str.m_data ) ); - } - else - { - size_type initialCapacity = std::min( s_minimumCapacity, m_size ); - m_data = StringData::create( str, initialCapacity ); - } - } - StringBuilder::StringBuilder( String const& other ) - : StringBuilder( StringRef( other ), std::min( s_minimumCapacity, other.size() ) ) - {} - - StringBuilder::~StringBuilder() noexcept { - m_data->release(); - } - - auto StringBuilder::size() const noexcept -> size_type { - return m_size; - } - - void StringBuilder::swap( StringBuilder& other ) noexcept { - std::swap( m_size, other.m_size ); - std::swap( m_data, other.m_data ); - } - void StringBuilder::reserve( size_type minimumCapacity ) { - if( minimumCapacity > capacity() ) { - StringBuilder temp( *this, minimumCapacity ); - swap( temp ); - } - } - void StringBuilder::reserveExponential( size_type minimumCapacity ) { - if( minimumCapacity > capacity() ) { - size_type candidateCapacity = capacity() < s_minimumCapacity ? s_minimumCapacity : capacity()*2; - while( candidateCapacity < minimumCapacity ) - candidateCapacity = candidateCapacity * 3/2; // grow factor of 1.5 - StringBuilder temp( *this, candidateCapacity ); - swap( temp ); - } - } - auto StringBuilder::capacity() const noexcept -> size_type { - return m_data->size; - } - void StringBuilder::writeTo( size_type index, StringRef const& str ) { - assert( index + str.size() < capacity() ); - if( str.size() > 0 ) - std::memcpy( m_data->chars+index, str.data(), str.size() ); - } - void StringBuilder::append( StringRef const& str ) { - reserveExponential( m_size + str.size() + 1 ); - writeTo( m_size, str ); - m_size += str.size(); - m_data->chars[m_size] = '\0'; - } - - auto operator << ( StringBuilder& sb, StringRef sr ) -> StringBuilder& { - sb.append( sr ); - return sb; - } - auto operator << ( StringBuilder&& sb, StringRef sr ) -> StringBuilder&& { - sb.append( sr ); - return std::move( sb ); - } - -} // namespace Catch diff --git a/include/internal/catch_stringbuilder.h b/include/internal/catch_stringbuilder.h deleted file mode 100644 index 2f7d8a2d..00000000 --- a/include/internal/catch_stringbuilder.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2016 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) - */ -#ifndef CATCH_STRINGBUILDER_H_INCLUDED -#define CATCH_STRINGBUILDER_H_INCLUDED - -#include "catch_stringref.h" - -#include - -namespace Catch { - - class String; - class StringData; - - /// A mutable container for string data - /// Use to build up strings before transferring to an immutable String. - /// Construct the String using the rvalue reference constructor (which - /// will usually involve std::move-ing the StringBuilder). This will transfer - /// The underlying buffer without any extra allocations or ref counts. - class StringBuilder { - friend class String; - public: - using size_type = size_t; - - StringBuilder(); - StringBuilder( size_type initialCapacity ); - StringBuilder( StringRef const& str, size_type initialCapacity ); - StringBuilder( StringBuilder const& other, size_type initialCapacity ); - StringBuilder( StringBuilder&& other ) noexcept; - StringBuilder( String&& other ); - StringBuilder( String const& other ); - ~StringBuilder() noexcept; - - void swap( StringBuilder& other ) noexcept; - - auto size() const noexcept -> size_type; - auto capacity() const noexcept -> size_type; - - /// Grows the buffer to exactly the capacity requested, or - /// does nothing if it is already at least as big - void reserve(size_type capacity); - - /// Grows the buffer exponentially (from a baseline of 32 bytes) - /// until it is at least as large as the requested capacity - - /// or does nothing if already large enough - void reserveExponential(size_type capacity); - - /// Writes the string at the current insertion point then moves - /// the insertion point forward by the string length. - /// If the buffer needs to grow to accomodate the string it does so - /// using the exponential strategy - void append( StringRef const& str ); - - friend auto operator << ( StringBuilder& sb, StringRef sr ) -> StringBuilder&; - friend auto operator << ( StringBuilder&& sb, StringRef sr ) -> StringBuilder&&; - - /// Writes the contents of the string ref into the buffer at - /// the indexed location. - /// The bounds are not checked! Use append() to just add to the - /// end of the buffer, extending it if the capacity is not enough. - void writeTo( size_type index, StringRef const& str ); - - private: - size_type m_size = 0; - StringData* m_data; - }; - -} // namespace Catch - -#endif // CATCH_STRINGBUILDER_H_INCLUDED diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 7d117018..61e001bc 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -6,8 +6,6 @@ */ #include "catch_stringref.h" -#include "catch_stringbuilder.h" -#include "catch_string.h" #include "catch_stringdata.h" #include @@ -58,18 +56,6 @@ namespace Catch { m_size = rawSize; } - StringRef::StringRef( String const& other ) noexcept - : m_start( other.c_str() ), - m_size( other.size() ) - {} - - StringRef::StringRef( String&& str ) noexcept - : m_start( str.c_str() ), - m_size( str.size() ), - m_data( str.m_data ) - { - str.m_data = StringData::getEmpty(); - } StringRef::StringRef( std::string const& stdString ) noexcept : m_start( stdString.c_str() ), m_size( stdString.size() ) @@ -112,9 +98,9 @@ namespace Catch { void StringRef::takeOwnership() { if( !isOwned() ) { - StringRef temp = String( *this ); - swap( temp ); - } + m_data = StringData::create( *this ); + m_start = m_data->chars; + } } auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { if( start < m_size ) @@ -159,18 +145,18 @@ namespace Catch { return noChars; } - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> String { - StringBuilder buf; - buf.reserve( lhs.size() + rhs.size() ); - buf.append( lhs ); - buf.append( rhs ); - return String( std::move( buf ) ); + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { + std::string str; + str.reserve( lhs.size() + rhs.size() ); + str += lhs; + str += rhs; + return str; } - auto operator + ( StringRef const& lhs, const char* rhs ) -> String { - return lhs + StringRef( rhs ); + auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); } - auto operator + ( char const* lhs, StringRef const& rhs ) -> String { - return StringRef( lhs ) + rhs; + auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); } auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index 1f8412de..b1f1c41e 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -13,7 +13,6 @@ namespace Catch { - class String; class StringData; /// A non-owning string class (similar to the forthcoming std::string_view) @@ -26,7 +25,6 @@ namespace Catch { class StringRef { friend struct StringRefTestAccess; friend class StringData; - friend class StringBuilder; using size_type = size_t; @@ -43,8 +41,6 @@ namespace Catch { StringRef( StringRef&& other ) noexcept; StringRef( char const* rawChars ) noexcept; StringRef( char const* rawChars, size_type size ) noexcept; - StringRef( String const& other ) noexcept; - StringRef( String&& other ) noexcept; StringRef( std::string const& stdString ) noexcept; ~StringRef() noexcept; @@ -74,9 +70,9 @@ namespace Catch { auto data() const noexcept -> char const*; }; - auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> String; - auto operator + ( StringRef const& lhs, char const* rhs ) -> String; - auto operator + ( char const* lhs, StringRef const& rhs ) -> String; + 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::ostream& os, StringRef const& sr ) -> std::ostream&; diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 2618ba11..4bc5c454 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1020,6 +1020,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 183 | 132 passed | 47 failed | 4 failed as expected -assertions: 908 | 791 passed | 96 failed | 21 failed as expected +test cases: 181 | 130 passed | 47 failed | 4 failed as expected +assertions: 876 | 759 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 3cc191a6..17b876ea 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -4257,50 +4257,6 @@ MatchersTests.cpp:: FAILED: with expansion: "this string contains 'abc' as a substring" starts with: "string" -------------------------------------------------------------------------------- -String - empty string -------------------------------------------------------------------------------- -String.tests.cpp: -............................................................................... - -String.tests.cpp:: -PASSED: - REQUIRE( empty.empty() ) -with expansion: - true - -String.tests.cpp:: -PASSED: - REQUIRE( empty.size() == 0 ) -with expansion: - 0 == 0 - -String.tests.cpp:: -PASSED: - REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ) -with expansion: - 0 == 0 - -------------------------------------------------------------------------------- -String - from literal -------------------------------------------------------------------------------- -String.tests.cpp: -............................................................................... - -String.tests.cpp:: -PASSED: - REQUIRE( s.empty() == false ) -with expansion: - false == false - -String.tests.cpp:: -PASSED: - REQUIRE( s.size() == 5 ) -with expansion: - 5 == 5 - ------------------------------------------------------------------------------- String matchers ------------------------------------------------------------------------------- @@ -4331,172 +4287,6 @@ PASSED: with expansion: "this string contains 'abc' as a substring" ends with: "substring" -------------------------------------------------------------------------------- -StringBuilder - basic -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.capacity() == 0 ) -with expansion: - 0 == 0 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.size() == 0 ) -with expansion: - 0 == 0 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.capacity() == 32 ) -with expansion: - 32 == 32 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.size() == 0 ) -with expansion: - 0 == 0 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.capacity() == 32 ) -with expansion: - 32 == 32 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb.size() == 5 ) -with expansion: - 5 == 5 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello" ) -with expansion: - hello == "hello" - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s.size() == 5 ) -with expansion: - 5 == 5 - -------------------------------------------------------------------------------- -StringBuilder - concatenation -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello world" ) -with expansion: - hello world == "hello world" - -------------------------------------------------------------------------------- -StringBuilder - concat & move -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello world" ) -with expansion: - hello world == "hello world" - -------------------------------------------------------------------------------- -StringBuilder - reserved -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb16.capacity() == 16 ) -with expansion: - 16 == 16 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( sb16.capacity() == 16 ) -with expansion: - 16 == 16 - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s == "hello world" ) -with expansion: - hello world == "hello world" - -------------------------------------------------------------------------------- -StringBuilder - from String - copy -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2 == s ) -with expansion: - hello == hello - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2.c_str() != s.c_str() ) -with expansion: - "hello" != "hello" - -------------------------------------------------------------------------------- -StringBuilder - from String - move from uniquely owned string -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2 == "hello" ) -with expansion: - hello == "hello" - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2.c_str() == originalPointer ) -with expansion: - "hello" == "hello" - -------------------------------------------------------------------------------- -StringBuilder - from String - move from shared string (copies) -------------------------------------------------------------------------------- -StringBuilder.tests.cpp: -............................................................................... - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2 == "hello" ) -with expansion: - hello == "hello" - -StringBuilder.tests.cpp:: -PASSED: - REQUIRE( s2.c_str() != originalPointer ) -with expansion: - "hello" != "hello" - ------------------------------------------------------------------------------- StringRef Empty string @@ -4744,70 +4534,6 @@ PASSED: with expansion: hello != cello -------------------------------------------------------------------------------- -StringRef - From string - Copied -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( copied == "hot potato" ) -with expansion: - hot potato == "hot potato" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( str == "hot potato" ) -with expansion: - hot potato == "hot potato" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( copied ) == false ) -with expansion: - false == false - -StringRef.tests.cpp:: -PASSED: - REQUIRE( data( copied ) == originalPointer ) -with expansion: - "hot potato" == "hot potato" - -------------------------------------------------------------------------------- -StringRef - From string - Moved -------------------------------------------------------------------------------- -StringRef.tests.cpp: -............................................................................... - -StringRef.tests.cpp:: -PASSED: - REQUIRE( copied == "hot potato" ) -with expansion: - hot potato == "hot potato" - -StringRef.tests.cpp:: -PASSED: - REQUIRE( isOwned( copied ) ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( str.empty() ) -with expansion: - true - -StringRef.tests.cpp:: -PASSED: - REQUIRE( data( copied ) == originalPointer ) -with expansion: - "hot potato" == "hot potato" - ------------------------------------------------------------------------------- StringRef from std::string @@ -7737,6 +7463,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 183 | 129 passed | 50 failed | 4 failed as expected -assertions: 910 | 787 passed | 102 failed | 21 failed as expected +test cases: 181 | 127 passed | 50 failed | 4 failed as expected +assertions: 878 | 755 passed | 102 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 8cd10426..88b20529 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -505,16 +505,7 @@ Message from section two MatchersTests.cpp: - - - - - - - - - @@ -529,8 +520,6 @@ StringRef.tests.cpp: - - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 324fbf6b..21c9c9ca 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -4860,55 +4860,6 @@ Message from section two
- -
- - - empty.empty() - - - true - - - - - empty.size() == 0 - - - 0 == 0 - - - - - std::strcmp( empty.c_str(), "" ) == 0 - - - 0 == 0 - - - -
-
- - - s.empty() == false - - - false == false - - - - - s.size() == 5 - - - 5 == 5 - - - -
- -
@@ -4944,191 +4895,6 @@ Message from section two - -
- - - sb.capacity() == 0 - - - 0 == 0 - - - - - sb.size() == 0 - - - 0 == 0 - - - - - sb.capacity() == 32 - - - 32 == 32 - - - - - sb.size() == 0 - - - 0 == 0 - - - - - sb.capacity() == 32 - - - 32 == 32 - - - - - sb.size() == 5 - - - 5 == 5 - - - - - s == "hello" - - - hello == "hello" - - - - - s.size() == 5 - - - 5 == 5 - - - -
-
- - - s == "hello world" - - - hello world == "hello world" - - - -
-
- - - s == "hello world" - - - hello world == "hello world" - - - -
-
- - - sb16.capacity() == 16 - - - 16 == 16 - - - - - sb16.capacity() == 16 - - - 16 == 16 - - - - - s == "hello world" - - - hello world == "hello world" - - - -
-
-
- - - s2 == s - - - hello == hello - - - - - s2.c_str() != s.c_str() - - - "hello" != "hello" - - - -
- -
-
-
- - - s2 == "hello" - - - hello == "hello" - - - - - s2.c_str() == originalPointer - - - "hello" == "hello" - - - -
- -
-
-
- - - s2 == "hello" - - - hello == "hello" - - - - - s2.c_str() != originalPointer - - - "hello" != "hello" - - - -
- -
- -
@@ -5407,82 +5173,6 @@ Message from section two
-
-
- - - copied == "hot potato" - - - hot potato == "hot potato" - - - - - str == "hot potato" - - - hot potato == "hot potato" - - - - - isOwned( copied ) == false - - - false == false - - - - - data( copied ) == originalPointer - - - "hot potato" == "hot potato" - - - -
- -
-
-
- - - copied == "hot potato" - - - hot potato == "hot potato" - - - - - isOwned( copied ) - - - true - - - - - str.empty() - - - true - - - - - data( copied ) == originalPointer - - - "hot potato" == "hot potato" - - - -
- -
@@ -8568,7 +8258,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/String.tests.cpp b/projects/SelfTest/String.tests.cpp deleted file mode 100644 index c27b7508..00000000 --- a/projects/SelfTest/String.tests.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "../include/internal/catch_string.h" - -#include "catch.hpp" - -#include - -TEST_CASE( "String", "[Strings]" ) { - using Catch::String; - - SECTION( "empty string" ) { - String empty; - REQUIRE( empty.empty() ); - REQUIRE( empty.size() == 0 ); - REQUIRE( std::strcmp( empty.c_str(), "" ) == 0 ); - } - SECTION( "from literal" ) { - String s = "hello"; - REQUIRE( s.empty() == false ); - REQUIRE( s.size() == 5 ); - } - -} \ No newline at end of file diff --git a/projects/SelfTest/StringBuilder.tests.cpp b/projects/SelfTest/StringBuilder.tests.cpp deleted file mode 100644 index e91d450d..00000000 --- a/projects/SelfTest/StringBuilder.tests.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "internal/catch_stringbuilder.h" -#include "../include/internal/catch_stringref.h" -#include "../include/internal/catch_string.h" - -#include "catch.hpp" - -TEST_CASE( "StringBuilder", "[Strings]" ) { - - using Catch::StringBuilder; - using Catch::String; - - StringBuilder sb; - - SECTION( "basic" ) { - REQUIRE( sb.capacity() == 0 ); - REQUIRE( sb.size() == 0 ); - - sb.reserve( 32 ); - REQUIRE( sb.capacity() == 32 ); - REQUIRE( sb.size() == 0 ); - - sb.append( "hello" ); - REQUIRE( sb.capacity() == 32 ); - REQUIRE( sb.size() == 5 ); - - String s = std::move( sb ); - REQUIRE( s == "hello" ); - REQUIRE( s.size() == 5 ); - } - - SECTION( "concatenation" ) { - sb << "hello" << " " << "world"; - String s = std::move( sb ); - REQUIRE( s == "hello world" ); - } - - SECTION( "concat & move" ) { - String s = StringBuilder() << "hello" << " " << "world"; - REQUIRE( s == "hello world" ); - } - - SECTION( "reserved" ) { - StringBuilder sb16( 16 ); - REQUIRE( sb16.capacity() == 16 ); - sb16 << "hello" << " " << "world"; - REQUIRE( sb16.capacity() == 16 ); - String s = std::move( sb16 ); - REQUIRE( s == "hello world" ); - } - - SECTION( "from String" ) { - String s = "hello"; - - SECTION( "copy" ) { - StringBuilder sb2 = s; - String s2( std::move(sb2) ); - REQUIRE( s2 == s ); - REQUIRE( s2.c_str() != s.c_str() ); - } - SECTION( "move from uniquely owned string" ) { - auto originalPointer = s.c_str(); - StringBuilder sb2( std::move( s ) ); - String s2( std::move(sb2) ); - REQUIRE( s2 == "hello" ); - REQUIRE( s2.c_str() == originalPointer ); - } - SECTION( "move from shared string (copies)" ) { - auto originalPointer = s.c_str(); - String keepAlive = s; - StringBuilder sb2( std::move( s ) ); - String s2( std::move(sb2) ); - REQUIRE( s2 == "hello" ); - REQUIRE( s2.c_str() != originalPointer ); - } - } -} diff --git a/projects/SelfTest/StringRef.tests.cpp b/projects/SelfTest/StringRef.tests.cpp index 6ebbdb13..d12c79a3 100644 --- a/projects/SelfTest/StringRef.tests.cpp +++ b/projects/SelfTest/StringRef.tests.cpp @@ -1,5 +1,4 @@ #include "../include/internal/catch_stringref.h" -#include "../include/internal/catch_string.h" #include "catch.hpp" @@ -40,8 +39,7 @@ namespace Catch { TEST_CASE( "StringRef", "[Strings]" ) { using Catch::StringRef; - using Catch::String; - + SECTION( "Empty string" ) { StringRef empty; REQUIRE( empty.empty() ); @@ -124,32 +122,6 @@ TEST_CASE( "StringRef", "[Strings]" ) { REQUIRE( StringRef("hello") == StringRef("hello") ); REQUIRE( StringRef("hello") != StringRef("cello") ); } - - SECTION( "From string" ) { - String str = "hot potato"; - auto originalPointer = str.c_str(); - - SECTION( "Copied" ) { - // After a String is "copied" to a StringRef - // It has only copied the pointer and size - // - it does not take ownership - StringRef copied = str; - REQUIRE( copied == "hot potato" ); - REQUIRE( str == "hot potato" ); - REQUIRE( isOwned( copied ) == false ); - REQUIRE( data( copied ) == originalPointer ); - } - SECTION( "Moved" ) { - // After a String is *moved* to a StringRef - // The StringRef takes ownership of the underlying data - // and the String is left in an empty state - StringRef copied = std::move( str ); - REQUIRE( copied == "hot potato" ); - REQUIRE( isOwned( copied ) ); - REQUIRE( str.empty() ); - REQUIRE( data( copied ) == originalPointer ); - } - } SECTION( "from std::string" ) { std::string stdStr = "a standard string"; From 94d347b05939385a827499932f7b02ce7ccc9c45 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 14 Aug 2017 09:14:49 +0100 Subject: [PATCH 242/398] Removed StringData --- CMakeLists.txt | 2 - include/internal/catch_stringdata.cpp | 48 ------------------------ include/internal/catch_stringdata.h | 53 --------------------------- include/internal/catch_stringref.cpp | 18 ++++----- include/internal/catch_stringref.h | 3 +- 5 files changed, 8 insertions(+), 116 deletions(-) delete mode 100644 include/internal/catch_stringdata.cpp delete mode 100644 include/internal/catch_stringdata.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 33ec5d1f..c98c326b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,7 +170,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_startup_exception_registry.h ${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_streambuf.h - ${HEADER_DIR}/internal/catch_stringdata.h ${HEADER_DIR}/internal/catch_stringref.h ${HEADER_DIR}/internal/catch_string_manip.h ${HEADER_DIR}/internal/catch_suppress_warnings.h @@ -222,7 +221,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_section_info.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp ${HEADER_DIR}/internal/catch_stream.cpp - ${HEADER_DIR}/internal/catch_stringdata.cpp ${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_string_manip.cpp ${HEADER_DIR}/internal/catch_tag_alias.cpp diff --git a/include/internal/catch_stringdata.cpp b/include/internal/catch_stringdata.cpp deleted file mode 100644 index 5261739a..00000000 --- a/include/internal/catch_stringdata.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2016 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) - */ - -#include "catch_stringdata.h" -#include "catch_stringref.h" - -#include -#include -#include - -namespace Catch { - - auto StringData::getEmpty() -> StringData* { - static StringData s_empty( 0 ); - return &s_empty; - } - auto StringData::create( StringRef const& stringRef ) -> StringData* { - return create( stringRef, stringRef.size() ); - } - auto StringData::create( StringRef const& stringRef, size_t capacity ) -> StringData* { - if( capacity == 0 ) { - return getEmpty(); - } - else { - assert( stringRef.size() <= capacity ); - auto bufferLen = sizeof(StringData)+capacity; - void* buffer = new char[bufferLen]; - - return new(buffer) StringData( stringRef, capacity ); - } - } - StringData::StringData( unsigned int initialRef ) - : m_refs( initialRef ), - size( 0 ) - {} - StringData::StringData( StringRef const& stringRef, size_t capacity ) - : m_refs( 1 ), - size( capacity) - { - std::memcpy( chars, stringRef.data(), stringRef.size() ); - chars[stringRef.size() ] = 0; - } - -} // namespace Catch \ No newline at end of file diff --git a/include/internal/catch_stringdata.h b/include/internal/catch_stringdata.h deleted file mode 100644 index d4016976..00000000 --- a/include/internal/catch_stringdata.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2016 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) - */ -#ifndef CATCH_STRINGDATA_H_INCLUDED -#define CATCH_STRINGDATA_H_INCLUDED - -#include -#include - -namespace Catch { - - class StringRef; - - class StringData { - mutable std::atomic m_refs; - public: - size_t size; - union { - char chars[1]; - }; - - auto isUniquelyOwned() const noexcept -> bool { - return m_refs == 1; - } - static auto getEmpty() -> StringData*; - static auto create( StringRef const& stringRef ) -> StringData*; - static auto create( StringRef const& stringRef, size_t capacity ) -> StringData*; - - void addRef() const noexcept { - if( m_refs > 0 ) - ++m_refs; - } - void release() const noexcept { - unsigned int refs = m_refs; - if( refs > 1 ) - --m_refs; - else if( refs == 1 ) - delete[] reinterpret_cast( this ); - } - private: - StringData( unsigned int initialRef = 1 ); - StringData( StringRef const& stringRef, size_t capacity ); - - StringData( StringData const& ) = delete; - StringData& operator=( StringData const& ) = delete; - }; - -} // namespace Catch - -#endif // CATCH_STRINGDATA_H_INCLUDED diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index 61e001bc..a6389bd4 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -6,7 +6,6 @@ */ #include "catch_stringref.h" -#include "catch_stringdata.h" #include #include @@ -25,12 +24,8 @@ namespace Catch { StringRef::StringRef( StringRef const& other ) noexcept : m_start( other.m_start ), - m_size( other.m_size ), - m_data( other.m_data ) - { - if( m_data ) - m_data->addRef(); - } + m_size( other.m_size ) + {} StringRef::StringRef( StringRef&& other ) noexcept : m_start( other.m_start ), @@ -62,8 +57,7 @@ namespace Catch { {} StringRef::~StringRef() noexcept { - if( isOwned() ) - m_data->release(); + delete[] m_data; } auto StringRef::operator = ( StringRef other ) noexcept -> StringRef& { @@ -98,8 +92,10 @@ namespace Catch { void StringRef::takeOwnership() { if( !isOwned() ) { - m_data = StringData::create( *this ); - m_start = m_data->chars; + m_data = new char[m_size+1]; + strncpy( m_data, m_start, m_size ); + m_data[m_size] = '\0'; + m_start = m_data; } } auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index b1f1c41e..5870151c 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -24,14 +24,13 @@ namespace Catch { /// threads. class StringRef { friend struct StringRefTestAccess; - friend class StringData; using size_type = size_t; char const* m_start; size_type m_size; - StringData const* m_data = nullptr; + char* m_data = nullptr; void takeOwnership(); From 7be258536ed8b90c307947d11852660666b2f811 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 14 Aug 2017 12:12:28 +0100 Subject: [PATCH 243/398] Suppress strncpy copy warnings on MSVC --- include/internal/catch_stringref.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index a6389bd4..f6a1fc2a 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -11,6 +11,8 @@ #include #include +#define _CRT_SECURE_NO_WARNINGS // Suppress warnings from MSVC about strncpy not being secure + namespace Catch { auto getEmptyStringRef() -> StringRef { From 0aec06f4c31b779756a7e0588fae210a51834aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 10 Aug 2017 16:43:17 +0200 Subject: [PATCH 244/398] Update documentation with changes from 7e4038d --- docs/configuration.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index b7855383..4c236850 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -43,12 +43,13 @@ By default a console width of 80 is assumed but this can be controlled by defini CATCH_CONFIG_NOSTDOUT -Catch does not use ```std::cout``` and ```std::cerr``` directly but gets them from ```Catch::cout()``` and ```Catch::cerr()``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are: +Catch does not use ```std::cout```, ```std::cerr``` and ```std::clog``` directly but gets them from ```Catch::cout()```, ```Catch::cerr()``` and ```Catch::clog``` respectively. If the above identifier is defined these functions are left unimplemented and you must implement them yourself. Their signatures are: std::ostream& cout(); std::ostream& cerr(); + std::ostream& clog(); -This can be useful on certain platforms that do not provide ```std::cout``` and ```std::cerr```, such as certain embedded systems. +This can be useful on certain platforms that do not provide the standard iostreams, such as certain embedded systems. From f06ed856d86ceb3457cb88b167570c01d6566cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 10 Aug 2017 21:38:07 +0200 Subject: [PATCH 245/398] Cherry picked 4f21bb72ff16f82b7fcf7362d683547f412641f4 (Add tests for #961) from master - had to redo the baselines --- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 64 ++++++++++++++++++- .../Baselines/console.swa4.approved.txt | 64 ++++++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 7 +- .../SelfTest/Baselines/xml.sw.approved.txt | 22 ++++++- projects/SelfTest/MiscTests.cpp | 8 +++ 6 files changed, 160 insertions(+), 9 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 4bc5c454..42d62c9c 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1020,6 +1020,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 181 | 130 passed | 47 failed | 4 failed as expected -assertions: 876 | 759 passed | 96 failed | 21 failed as expected +test cases: 182 | 131 passed | 47 failed | 4 failed as expected +assertions: 881 | 764 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 17b876ea..1d228de6 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -137,6 +137,66 @@ with expansion: with message: dummy := 0 +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 0 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 3 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 4 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + ------------------------------------------------------------------------------- 'Not' checks that should fail ------------------------------------------------------------------------------- @@ -7463,6 +7523,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 181 | 127 passed | 50 failed | 4 failed as expected -assertions: 878 | 755 passed | 102 failed | 21 failed as expected +test cases: 182 | 128 passed | 50 failed | 4 failed as expected +assertions: 883 | 760 passed | 102 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index fe22e2b3..bdacd9cb 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -137,6 +137,66 @@ with expansion: with message: dummy := 0 +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 0 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 1 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 2 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 3 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + +------------------------------------------------------------------------------- +#961 -- Dynamically created sections should all be reported + Looped section 4 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: +with message: + Everything is OK + ------------------------------------------------------------------------------- 'Not' checks that should fail ------------------------------------------------------------------------------- @@ -158,6 +218,6 @@ ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) =============================================================================== -test cases: 7 | 4 passed | 1 failed | 2 failed as expected -assertions: 19 | 12 passed | 4 failed | 3 failed as expected +test cases: 8 | 5 passed | 1 failed | 2 failed as expected +assertions: 24 | 17 passed | 4 failed | 3 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 88b20529..6e3607a8 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -26,6 +26,11 @@ MiscTests.cpp: + + + + + ConditionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 21c9c9ca..f290b1de 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -150,6 +150,24 @@ + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
@@ -8258,7 +8276,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 500e876a..e3a9318b 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -358,3 +358,11 @@ TEST_CASE( "#835 -- errno should not be touched by Catch", "[.][failing][!should CHECK(f() == 0); REQUIRE(errno == 1); // Check that f() doesn't touch errno. } + +TEST_CASE( "#961 -- Dynamically created sections should all be reported", "[.]" ) { + for (char i = '0'; i < '5'; ++i) { + SECTION(std::string("Looped section ") + i) { + SUCCEED( "Everything is OK" ); + } + } +} From 917a51da6b9923d385c2e441bef1ebedb96cd123 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 11 Aug 2017 19:55:55 +0100 Subject: [PATCH 246/398] Added libidentify support, including option for waiting for keypress on exit (and/ or start) --- include/catch_session.hpp | 56 +++++++++++++++------- include/internal/catch_commandline.cpp | 18 +++++++ include/internal/catch_config.hpp | 2 + include/internal/catch_interfaces_config.h | 6 +++ 4 files changed, 65 insertions(+), 17 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 61b99049..fb1eb8a5 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace Catch { @@ -121,6 +122,13 @@ namespace Catch { << m_cli << std::endl << "For more detailed usage please see the project docs\n" << std::endl; } + void libIdentify() { + Catch::cout() + << std::left << std::setw(16) << "description: " << "A Catch test executable\n" + << std::left << std::setw(16) << "category: " << "testframework\n" + << std::left << std::setw(16) << "framework: " << "Catch Test\n" + << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; + } int applyCommandLine( int argc, char* argv[] ) { auto result = m_cli.parse( clara::Args( argc, argv ) ); @@ -137,6 +145,8 @@ namespace Catch { if( m_configData.showHelp ) showHelp(); + if( m_configData.libIdentify ) + libIdentify(); m_config.reset(); return 0; } @@ -189,9 +199,36 @@ namespace Catch { return returnCode; } #endif - int run() { - if( m_configData.showHelp ) + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before starting" << std::endl; + std::getchar(); + } + int exitCode = runInternal(); + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; + std::getchar(); + } + return exitCode; + } + + clara::Parser const& cli() const { + return m_cli; + } + void cli( clara::Parser const& newParser ) { + m_cli = newParser; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = std::make_shared( m_configData ); + return *m_config; + } + private: + int runInternal() { + if( m_configData.showHelp || m_configData.libIdentify ) return 0; try @@ -215,21 +252,6 @@ namespace Catch { } } - clara::Parser const& cli() const { - return m_cli; - } - void cli( clara::Parser const& newParser ) { - m_cli = newParser; - } - ConfigData& configData() { - return m_configData; - } - Config& config() { - if( !m_config ) - m_config = std::make_shared( m_configData ); - return *m_config; - } - private: clara::Parser m_cli; ConfigData m_configData; std::shared_ptr m_config; diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index 7342ac42..d92a1c39 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -71,6 +71,18 @@ namespace Catch { return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); return ParserResult::ok( ParseResultType::Matched ); }; + auto const setWaitForKeypress = [&]( std::string const& keypress ) { + auto keypressLc = toLower( keypress ); + if( keypressLc == "start" ) + config.waitForKeypress = WaitForKeypress::BeforeStart; + else if( keypressLc == "exit" ) + config.waitForKeypress = WaitForKeypress::BeforeExit; + else if( keypressLc == "both" ) + config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; + else + return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; auto const setVerbosity = [&]( std::string const& verbosity ) { auto lcVerbosity = toLower( verbosity ); if( lcVerbosity == "quiet" ) @@ -153,6 +165,12 @@ namespace Catch { + Opt( setColourUsage, "yes|no" ) ["--use-colour"] ( "should output be colourised" ) + + Opt( config.libIdentify ) + ["--libidentify"] + ( "report name and version according to libidentify standard" ) + + Opt( setWaitForKeypress, "start|exit|both" ) + ["--wait-for-keypress"] + ( "waits for a keypress before exiting" ) + Opt( config.benchmarkResolutionMultiple, "multiplier" ) ["--benchmark-resolution-multiple"] ( "multiple of clock resolution to run benchmarks" ) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 6bf792b0..61669897 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -35,6 +35,7 @@ namespace Catch { bool showHelp = false; bool showInvisibles = false; bool filenamesAsTags = false; + bool libIdentify = false; int abortAfter = -1; unsigned int rngSeed = 0; @@ -45,6 +46,7 @@ namespace Catch { ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; UseColour::YesOrNo useColour = UseColour::Auto; + WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; std::string outputFilename; std::string name; diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h index 436b80eb..2584ccc0 100644 --- a/include/internal/catch_interfaces_config.h +++ b/include/internal/catch_interfaces_config.h @@ -43,6 +43,12 @@ namespace Catch { Yes, No }; }; + struct WaitForKeypress { enum When { + Never, + BeforeStart = 1, + BeforeExit = 2, + BeforeStartAndExit = BeforeStart | BeforeExit + }; }; class TestSpec; From 74dfd0b1e08861f718bfbe1d9bc0e34a70d8b1f0 Mon Sep 17 00:00:00 2001 From: Monocasual Date: Sun, 13 Aug 2017 16:25:51 +0200 Subject: [PATCH 247/398] Add open-source user --- docs/opensource-users.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/opensource-users.md b/docs/opensource-users.md index ab7a8ae1..2d9949e4 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -63,6 +63,9 @@ A simple header-only C++ argument parser library. ### [ArangoDB](https://github.com/arangodb/arangodb) ArangoDB is a native multi-model database with flexible data models for documents, graphs, and key-values. +### [Giada - Your Hardcore Loop Machine](https://github.com/monocasual/giada) +Minimal, open-source and cross-platform audio tool for live music production. + ### [MAME](https://github.com/mamedev/mame) MAME originally stood for Multiple Arcade Machine Emulator From a988af219c6e02ee494b0bfe2775e027cd8a94ad Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 15 Aug 2017 17:08:32 +0100 Subject: [PATCH 248/398] No longer show full usage in event of error (it obscures the error message) - instead just suggests running with -? to see usage --- include/catch_session.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index fb1eb8a5..1968cb2f 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -138,8 +138,7 @@ namespace Catch { << "\nError(s) in input:\n" << Column( result.errorMessage() ).indent( 2 ) << "\n\n"; - - Catch::cerr() << m_cli << std::endl; + Catch::cerr() << "Run with -? for usage\n" << std::endl; return MaxExitCode; } From 07ded8154118d7a6dd84c296be61c9f7062f1173 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 15 Aug 2017 19:39:26 +0100 Subject: [PATCH 249/398] Added --libidentify and --wait-for-keypress to docs --- docs/command-line.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/command-line.md b/docs/command-line.md index 5afb309d..a0a18be3 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -27,6 +27,8 @@ Click one of the followings links to take you straight to that option - or scrol ` --list-reporters`
` --order`
` --rng-seed`
+ ` --libidentify`
+ ` --wait-for-keypress`

@@ -213,6 +215,20 @@ Alternatively if the keyword ```time``` is provided then the result of calling ` In either case the actual value for the seed is printed as part of Catch's output so if an issue is discovered that is sensitive to test ordering the ordering can be reproduced - even if it was originally seeded from ```std::time(0)```. + +## Identify framework and version according to the libIdentify standard +
--libidentify
+ +See [The LibIdentify repo for more information and examples](https://github.com/janwilmans/LibIdentify). + + +## Wait for key before continuing +
--wait-for-keypress <start|exit|both>
+ +Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing - +either before running any tests, after running all tests - or both, depending on the argument. + + ## Usage
-h, -?, --help
From 699e571400955aa0a9b7bd4212cf5a058bcf550f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 15 Aug 2017 19:51:22 +0100 Subject: [PATCH 250/398] Documented benchmark-resolution-multiple command line option - and increased default to 100 --- docs/command-line.md | 8 ++++++++ include/internal/catch_config.hpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/command-line.md b/docs/command-line.md index a0a18be3..cc944734 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -29,6 +29,7 @@ Click one of the followings links to take you straight to that option - or scrol ` --rng-seed`
` --libidentify`
` --wait-for-keypress`
+ ` --benchmark-resolution-multiple`

@@ -228,6 +229,13 @@ See [The LibIdentify repo for more information and examples](https://github.com/ Will cause the executable to print a message and wait until the return/ enter key is pressed before continuing - either before running any tests, after running all tests - or both, depending on the argument. + +## Specify multiples of clock resolution to run benchmarks for +
--benchmark-resolution-multiple <multiplier>
+ +When running benchmarks the clock resolution is estimated. Benchmarks are then run for exponentially increasing +numbers of iterations until some multiple of the estimated resolution is exceed. By default that multiple is 100, but +it can be overriden here. ## Usage diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 61669897..d2ca6202 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -39,7 +39,7 @@ namespace Catch { int abortAfter = -1; unsigned int rngSeed = 0; - int benchmarkResolutionMultiple = 10; + int benchmarkResolutionMultiple = 100; Verbosity verbosity = Verbosity::Normal; WarnAbout::What warnings = WarnAbout::Nothing; From a36395e2ff9b6cd283fedde1b93da4792740706a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 15 Aug 2017 23:47:52 +0100 Subject: [PATCH 251/398] Changed use of strncpy to memcpy --- include/internal/catch_stringref.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index f6a1fc2a..e22b6c94 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -7,11 +7,9 @@ #include "catch_stringref.h" -#include #include #include - -#define _CRT_SECURE_NO_WARNINGS // Suppress warnings from MSVC about strncpy not being secure +#include namespace Catch { @@ -95,7 +93,7 @@ namespace Catch { void StringRef::takeOwnership() { if( !isOwned() ) { m_data = new char[m_size+1]; - strncpy( m_data, m_start, m_size ); + memcpy( m_data, m_start, m_size ); m_data[m_size] = '\0'; m_start = m_data; } From 8582780f1156e33ee819fdd43eb61d379869adf0 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 16 Aug 2017 14:37:54 +0100 Subject: [PATCH 252/398] Don't include string/ vector matchers if CATCH_CONFIG_MATCHERS defined --- include/catch.hpp | 2 -- include/internal/catch_capture_matchers.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index b58a2354..f04ab7a5 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -36,8 +36,6 @@ #include "internal/catch_benchmark.h" #include "internal/catch_interfaces_exception.h" #include "internal/catch_approx.hpp" -#include "internal/catch_matchers_string.h" -#include "internal/catch_matchers_vector.h" #include "internal/catch_compiler_capabilities.h" #include "internal/catch_interfaces_tag_alias_registry.h" diff --git a/include/internal/catch_capture_matchers.h b/include/internal/catch_capture_matchers.h index f815c14e..80262dbf 100644 --- a/include/internal/catch_capture_matchers.h +++ b/include/internal/catch_capture_matchers.h @@ -11,6 +11,7 @@ #include "catch_capture.hpp" #include "catch_matchers.hpp" #include "catch_matchers_string.h" +#include "catch_matchers_vector.h" namespace Catch { From 8c0a6a43587114811e1b6ae0d148df7c4f528063 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 07:45:12 +0100 Subject: [PATCH 253/398] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..be1a688e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at github@philnash.me. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ From 0b52dbe8bbdc7289d1f025a4906ea4107c1e0446 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 08:28:45 +0100 Subject: [PATCH 254/398] Small doc updates --- README.md | 12 ++++++++---- docs/why-catch.md | 17 ++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 372e2279..b46c6825 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,18 @@ ![catch logo](catch-logo-small.png) [![Github Releases](https://img.shields.io/github/release/philsquared/catch.svg)](https://github.com/philsquared/catch/releases) -[![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch) -[![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master) +[![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=catch2)](https://travis-ci.org/philsquared/Catch?branch=catch2) +[![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/catch2?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/catch2) -The latest, single header, version can be downloaded directly using this link +The latest version of the single header can be downloaded directly using this link ## What's the Catch? -Catch stands for C++ Automated Test Cases in Headers and is a multi-paradigm automated test framework for C++ and Objective-C (and, maybe, C). It is implemented entirely in a set of header files, but is packaged up as a single header for extra convenience. +Catch stands for C++ Automated Test Cases in Headers and is a +multi-paradigm test framework for C++. which also supports Objective-C +and, maybe, C. +It is primarily distributed as a single header file, although certain +extensions may require additional headers. ## How to use it This documentation comprises these three parts: diff --git a/docs/why-catch.md b/docs/why-catch.md index 1dbc43bc..82257d68 100644 --- a/docs/why-catch.md +++ b/docs/why-catch.md @@ -1,12 +1,18 @@ # Why do we need yet another C++ test framework? -Good question. For C++ there are quite a number of established frameworks, including (but not limited to), [CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page), [Google Test](http://code.google.com/p/googletest/), [Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html), [Aeryn](https://launchpad.net/aeryn), [Cute](http://r2.ifs.hsr.ch/cute), [Fructose](http://fructose.sourceforge.net/) and [many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B). Even for Objective-C there are a few, including OCUnit - which now comes bundled with XCode. +Good question. For C++ there are quite a number of established frameworks, +including (but not limited to), +[Google Test](http://code.google.com/p/googletest/), +[Boost.Test](http://www.boost.org/doc/libs/1_49_0/libs/test/doc/html/index.html), +[CppUnit](http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page), +[Cute](http://r2.ifs.hsr.ch/cute), +[many, many more](http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B). So what does Catch bring to the party that differentiates it from these? Apart from a Catchy name, of course. ## Key Features -* Really easy to get started. Just download catch.hpp, `#include` it and you're away. +* Quick and Really easy to get started. Just download catch.hpp, `#include` it and you're away. * No external dependencies. As long as you can compile C++11 and have a C++ standard library available. * Write test cases as, self-registering, functions (or methods, if you prefer). * Divide test cases into sections, each of which is run in isolation (eliminates the need for fixtures). @@ -28,13 +34,6 @@ So what does Catch bring to the party that differentiates it from these? Apart f * Internal and friendly macros are isolated so name clashes can be managed * Matchers -## Objective-C-specific features - -* Automatically detects if you are using it from an Objective-C project -* Works with and without ARC with no additional configuration -* Implement test fixtures using Obj-C classes too (like OCUnit) -* Additional built in matchers that work with Obj-C types (e.g. string matchers) - ## Who else is using Catch? See the list of [open source projects using Catch](opensource-users.md). From 581aaae57ec2a54c60248e0fd98932c649dd5a3c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 08:29:57 +0100 Subject: [PATCH 255/398] Generated single include for develop build --- single_include/catch.hpp | 11539 +++++++++++++++++++++++++++++++++++++ 1 file changed, 11539 insertions(+) create mode 100644 single_include/catch.hpp diff --git a/single_include/catch.hpp b/single_include/catch.hpp new file mode 100644 index 00000000..77035aa9 --- /dev/null +++ b/single_include/catch.hpp @@ -0,0 +1,11539 @@ +/* + * Catch v2.0.0-develop.1 + * Generated: 2017-08-17 08:29:20.059622 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2017 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) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# 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" + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +#endif + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_context.h + +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IConfig; + + using IConfigPtr = std::shared_ptr; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual IConfigPtr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( IConfigPtr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); +} + +// end catch_context.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + +#endif + +#ifdef __clang__ + +# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// 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 + +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// 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 + +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + +// Now set the actual defines based on the above + anything the user has configured + +// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for +// analytics) because, at time of writing, __COUNTER__ is not properly handled by it. +// This does not affect compilation +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_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) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#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 ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +namespace Catch { + + struct IConfig; + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept; + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; + + 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; + }; + + 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(); + + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + + // 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 \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + 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 ); } + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.hpp + +// start catch_interfaces_testcase.h + +#include +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + using ITestCasePtr = std::shared_ptr; + + 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; + }; + + 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 ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include + +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 { + friend struct StringRefTestAccess; + + using size_type = size_t; + + char const* m_start; + size_type m_size; + + char* m_data = nullptr; + + void takeOwnership(); + + 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; + + auto operator = ( StringRef other ) noexcept -> StringRef&; + operator std::string() const; + + 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; + auto size() const noexcept -> size_type; + 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; + + 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& 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::ostream& os, StringRef const& sr ) -> std::ostream&; + +} // namespace Catch + +// end catch_stringref.h +namespace Catch { + +template +class TestInvokerAsMethod : public ITestInvoker { + void (C::*m_testAsMethod)(); +public: + TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( 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 ); +} + +struct NameAndTags { + NameAndTags( StringRef name_ = "", StringRef tags_ = "" ) noexcept; + StringRef name; + StringRef tags; +}; + +struct AutoReg : NonCopyable { + AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; + ~AutoReg() = default; +}; + +} // end namespace Catch + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + static void TestName() + #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, ... ) \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + namespace{ \ + struct TestName : 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_ETD_WARNINGS \ + void TestName::test() + #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, ... ) \ + CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + Catch::AutoReg( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + +// end catch_test_registry.hpp +// start catch_capture.hpp + +// start catch_assertionhandler.h + +// start catch_decomposer.h + +// start catch_tostring.h + +#include +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// start catch_objc_arc.hpp + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +// end catch_objc_arc.hpp +#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 { + + extern const std::string unprintableString; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + 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 + static auto test(...)->std::false_type; + + public: + static const bool value = decltype(test(0))::value; + }; + + } // namespace Detail + + // 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 + static + typename std::enable_if::value, std::string>::type + convert(const Fake&) { + return Detail::unprintableString; + } + }; + + 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); + } + + } // namespace Detail + + // Some predefined specializations + + template<> + struct StringMaker { + static std::string convert(const std::string& str); + }; + template<> + struct StringMaker { + static std::string convert(const std::wstring& wstr); + }; + + 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 + 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 }); + } + }; + + 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"; + } + } + }; + + 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( std::vector const& v ) { + return ::Catch::Detail::rangeToString( v.begin(), v.end() ); + } + }; + + // === Pair === + 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(); + } + }; + + 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 + struct StringMaker> { + static std::string convert(const std::tuple& tuple) { + std::ostringstream os; + os << '{'; + Detail::TupleElementPrinter>::print(tuple, os); + os << " }"; + return os.str(); + } + }; + + template + struct EnumStringMaker { + static std::string convert(const T& t) { + return ::Catch::Detail::stringify(static_cast::type>(t)); + } + }; + +#ifdef __OBJC__ + template<> + struct StringMaker { + static std::string convert(NSString* nsstring); + }; + template<> + struct StringMaker { + static std::string convert(NSString * CATCH_ARC_STRONG nsstring); + }; + template<> + struct StringMaker { + static std::string convert(NSObject* nsObject); + }; +#endif + +} // namespace Catch + +// end catch_tostring.h +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(disable:4018) // more "signed/unsigned mismatch" +#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#endif + +namespace Catch { + + struct ITransientExpression { + virtual auto isBinaryExpression() const -> bool = 0; + virtual auto getResult() const -> bool = 0; + virtual void streamReconstructedExpression( std::ostream &os ) const = 0; + + // We don't actually need a virtual destructore, but many static analysers + // complain if it's not here :-( + virtual ~ITransientExpression() = default; + }; + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); + + template + class BinaryExpr : public ITransientExpression { + bool m_result; + LhsT m_lhs; + std::string m_op; + RhsT m_rhs; + + auto isBinaryExpression() const -> bool override { return true; } + auto getResult() const -> bool override { return m_result; } + + void streamReconstructedExpression( std::ostream &os ) const override { + formatReconstructedExpression + ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); + } + + public: + BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) + : m_result( comparisionResult ), + m_lhs( lhs ), + m_op( op ), + m_rhs( rhs ) + {} + }; + + template + class UnaryExpr : public ITransientExpression { + LhsT m_lhs; + + auto isBinaryExpression() const -> bool override { return false; } + auto getResult() const -> bool override { return m_lhs ? true : false; } + + void streamReconstructedExpression( std::ostream &os ) const override { + os << Catch::Detail::stringify( m_lhs ); + } + + public: + UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {} + }; + + // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) + template + auto compareEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; + template + auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + template + auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + + template + auto compareNotEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; + template + auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + template + auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + + template + class ExprLhs { + LhsT m_lhs; + public: + ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} + + template + auto operator == ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); + } + auto operator == ( bool rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs == rhs, m_lhs, "==", rhs ); + } + + template + auto operator != ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); + } + auto operator != ( bool rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs != rhs, m_lhs, "!=", rhs ); + } + + template + auto operator > ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); + } + template + auto operator < ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); + } + template + auto operator >= ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); + } + template + auto operator <= ( RhsT&& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); + } + + auto makeUnaryExpr() const -> UnaryExpr { + return UnaryExpr( m_lhs ); + } + }; + + void handleExpression( ITransientExpression const& expr ); + + template + void handleExpression( ExprLhs const& expr ) { + handleExpression( expr.makeUnaryExpr() ); + } + + struct Decomposer { + template + auto operator <= ( T& lhs ) -> ExprLhs { + return ExprLhs( lhs ); + } + template + auto operator <= ( T const& lhs ) -> ExprLhs { + return ExprLhs( lhs ); + } + auto operator <=( bool value ) -> ExprLhs { + return ExprLhs( value ); + } + }; + +} // end namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// end catch_decomposer.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 ); + bool isFalseTest( int flags ); + 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 +namespace Catch { + + struct TestFailureException{}; + struct AssertionResultData; + + class LazyExpression { + friend class AssertionHandler; + friend struct AssertionStats; + + ITransientExpression const* m_transientExpression = nullptr; + bool m_isNegated; + public: + LazyExpression( bool isNegated ); + LazyExpression( LazyExpression const& other ); + LazyExpression& operator = ( LazyExpression const& ) = delete; + + explicit operator bool() const; + + friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; + }; + + class AssertionHandler { + AssertionInfo m_assertionInfo; + bool m_shouldDebugBreak = false; + bool m_shouldThrow = false; + bool m_inExceptionGuard = false; + + public: + AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ); + ~AssertionHandler(); + + void handle( ITransientExpression const& expr ); + + template + void handle( ExprLhs const& expr ) { + handle( expr.makeUnaryExpr() ); + } + void handle( ResultWas::OfType resultType ); + void handle( ResultWas::OfType resultType, StringRef const& message ); + void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ); + void handle( AssertionResultData const& resultData, ITransientExpression const* expr ); + + auto shouldDebugBreak() const -> bool; + auto allowThrows() const -> bool; + void reactWithDebugBreak() const; + void reactWithoutDebugBreak() const; + void useActiveException(); + void setExceptionGuard(); + void unsetExceptionGuard(); + }; + + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); + +} // namespace Catch + +// end catch_assertionhandler.h +// start catch_message.h + +#include +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const; + bool operator < ( MessageInfo const& other ) const; + private: + static unsigned int globalCount; + }; + + struct MessageStream { + + template + MessageStream& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + // !TBD reuse a global/ thread-local stream + std::ostringstream m_stream; + }; + + struct MessageBuilder : MessageStream { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ); + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// end catch_message.h +// start catch_interfaces_capture.h + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + struct BenchmarkInfo; + struct BenchmarkStats; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionStarting( AssertionInfo const& info ) = 0; + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + + virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; + virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; + + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + + virtual void exceptionEarlyReported() = 0; + + virtual void handleFatalErrorCondition( std::string const& message ) = 0; + + virtual bool lastAssertionPassed() = 0; + virtual void assertionPassed() = 0; + virtual void assertionRun() = 0; + }; + + IResultCapture& getResultCapture(); +} + +// end catch_interfaces_capture.h +#if defined(CATCH_CONFIG_FAST_COMPILE) +/////////////////////////////////////////////////////////////////////////////// +// We can speedup compilation significantly by breaking into debugger lower in +// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER +// macro in each assertion +#define INTERNAL_CATCH_REACT( handler ) \ + handler.reactWithDebugBreak(); + +/////////////////////////////////////////////////////////////////////////////// +// Another way to speed-up compilation is to omit local try-catch for REQUIRE* +// macros. +// This can potentially cause false negative, if the test code catches +// the exception before it propagates back up to the runner. +#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); +#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard(); + +#else // CATCH_CONFIG_FAST_COMPILE + +// start catch_debugger.h + +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_MAC == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + +#elif defined(CATCH_PLATFORM_LINUX) + // If we can use inline assembler, do it because this allows us to break + // directly at the location of the failing check instead of breaking inside + // raise() called from it, i.e. one stack frame below. + #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) + #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ + #else // Fall back to the generic way. + #include + + #define CATCH_TRAP() raise(SIGTRAP) + #endif +#elif defined(_MSC_VER) + #define CATCH_TRAP() __debugbreak() +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_TRAP() DebugBreak() +#endif + +#ifdef CATCH_TRAP + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } +#else + #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// end catch_debugger.h +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( handler ) \ + if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + handler.reactWithoutDebugBreak(); + +#define INTERNAL_CATCH_TRY( capturer ) try +#define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); } + +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ + CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::isTrue( false && static_cast( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look + // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ + if( Catch::getResultCapture().lastAssertionPassed() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ + if( !Catch::getResultCapture().lastAssertionPassed() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + catchAssertionHandler.useActiveException(); \ + } \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + } \ + else \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(expr); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType const& ) { \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + catchAssertionHandler.useActiveException(); \ + } \ + else \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( macroName, log ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, 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, #__VA_ARGS__ ", " #matcher, resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ + } \ + else \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +// end catch_capture.hpp +// start catch_section.h + +// start catch_section_info.h + +// start catch_totals.hpp + +#include + +namespace Catch { + + struct Counts { + Counts operator - ( Counts const& other ) const; + Counts& operator += ( Counts const& other ); + + std::size_t total() const; + bool allPassed() const; + bool allOk() const; + + std::size_t passed = 0; + std::size_t failed = 0; + std::size_t failedButOk = 0; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const; + Totals& operator += ( Totals const& other ); + + Totals delta( Totals const& prevTotals ) const; + + Counts assertions; + Counts testCases; + }; +} + +// end catch_totals.hpp +#include + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ); + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// end catch_section_info.h +// start catch_timer.h + +#include + +namespace Catch { + + auto getCurrentNanosecondsSinceEpoch() -> uint64_t; + auto getEstimatedClockResolution() -> uint64_t; + + class Timer { + uint64_t m_nanoseconds = 0; + public: + void start(); + auto getElapsedNanoseconds() const -> unsigned int; + auto getElapsedMicroseconds() const -> unsigned int; + auto getElapsedMilliseconds() const -> unsigned int; + auto getElapsedSeconds() const -> double; + }; + +} // namespace Catch + +// end catch_timer.h +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + explicit operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) + +// end catch_section.h +// start catch_benchmark.h + +#include +#include + +namespace Catch { + + class BenchmarkLooper { + + std::string m_name; + size_t m_count = 0; + size_t m_iterationsToRun = 1; + uint64_t m_resolution; + Timer m_timer; + + static auto getResolution() -> uint64_t; + public: + // Keep most of this inline as it's on the code path that is being timed + BenchmarkLooper( StringRef name ) + : m_name( name ), + m_resolution( getResolution() ) + { + reportStart(); + m_timer.start(); + } + + explicit operator bool() { + if( m_count < m_iterationsToRun ) + return true; + return needsMoreIterations(); + } + + void increment() { + ++m_count; + } + + void reportStart(); + auto needsMoreIterations() -> bool; + }; + +} // end namespace Catch + +#define BENCHMARK( name ) \ + for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) + +// end catch_benchmark.h +// start catch_interfaces_exception.h + +#include +#include + +// start catch_interfaces_registry_hub.h + +#include +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + struct ITagAliasRegistry; + class StartupExceptionRegistry; + + using IReporterFactoryPtr = std::shared_ptr; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; + + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; + virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; + virtual void registerStartupException() noexcept = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +// end catch_interfaces_registry_hub.h +namespace Catch { + using exceptionTranslateFunction = std::string(*)(); + + struct IExceptionTranslator; + using ExceptionTranslators = std::vector>; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { + try { + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// end catch_interfaces_exception.h +// start catch_approx.hpp + +#include +#include + +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ); + + static Approx custom(); + + template ::value>::type> + Approx operator()( T const& value ) { + Approx approx( static_cast(value) ); + approx.epsilon( m_epsilon ); + approx.margin( m_margin ); + approx.scale( m_scale ); + return approx; + } + + template ::value>::type> + explicit Approx( T const& value ): Approx(static_cast(value)) + {} + + template ::value>::type> + friend bool operator == ( const T& lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + auto lhs_v = static_cast(lhs); + bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); + if (relativeOK) { + return true; + } + return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; + } + + template ::value>::type> + friend bool operator == ( Approx const& lhs, const T& rhs ) { + return operator==( rhs, lhs ); + } + + template ::value>::type> + friend bool operator != ( T const& lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + template ::value>::type> + friend bool operator != ( Approx const& lhs, T const& rhs ) { + return !operator==( rhs, lhs ); + } + + template ::value>::type> + friend bool operator <= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) < rhs.m_value || lhs == rhs; + } + + template ::value>::type> + friend bool operator <= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value < static_cast(rhs) || lhs == rhs; + } + + template ::value>::type> + friend bool operator >= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) > rhs.m_value || lhs == rhs; + } + + template ::value>::type> + friend bool operator >= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value > static_cast(rhs) || lhs == rhs; + } + + template ::value>::type> + Approx& epsilon( T const& newEpsilon ) { + m_epsilon = static_cast(newEpsilon); + return *this; + } + + template ::value>::type> + Approx& margin( T const& newMargin ) { + m_margin = static_cast(newMargin); + return *this; + } + + template ::value>::type> + Approx& scale( T const& newScale ) { + m_scale = static_cast(newScale); + return *this; + } + + std::string toString() const; + + private: + double m_epsilon; + double m_margin; + double m_scale; + double m_value; + }; +} + +template<> +struct StringMaker { + static std::string convert(Catch::Detail::Approx const& value); +}; + +} // end namespace Catch + +// end catch_approx.hpp +// start catch_interfaces_tag_alias_registry.h + +#include + +namespace Catch { + + struct TagAlias; + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + // Nullptr if not present + virtual TagAlias const* find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// end catch_interfaces_tag_alias_registry.h +#ifndef CATCH_CONFIG_DISABLE_MATCHERS +// start catch_capture_matchers.h + +// start catch_matchers.hpp + +#include +#include + +namespace Catch { +namespace Matchers { + namespace Impl { + + template struct MatchAllOf; + template struct MatchAnyOf; + template struct MatchNotOf; + + class MatcherUntypedBase { + public: + MatcherUntypedBase() = default; + MatcherUntypedBase ( MatcherUntypedBase const& ) = default; + MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; + std::string toString() const; + + protected: + virtual ~MatcherUntypedBase() = default; + virtual std::string describe() const = 0; + mutable std::string m_cachedToString; + }; + + template + struct MatcherMethod { + virtual bool match( ObjectT const& arg ) const = 0; + }; + template + struct MatcherMethod { + virtual bool match( PtrT* arg ) const = 0; + }; + + template + struct MatcherBase : MatcherUntypedBase, MatcherMethod { + + MatchAllOf operator && ( MatcherBase const& other ) const; + MatchAnyOf operator || ( MatcherBase const& other ) const; + MatchNotOf operator ! () const; + }; + + template + struct MatchAllOf : MatcherBase { + bool match( ArgT const& arg ) const override { + for( auto matcher : m_matchers ) { + if (!matcher->match(arg)) + return false; + } + return true; + } + std::string describe() const override { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else + description += " and "; + description += matcher->toString(); + } + description += " )"; + return description; + } + + MatchAllOf& operator && ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + template + struct MatchAnyOf : MatcherBase { + + bool match( ArgT const& arg ) const override { + for( auto matcher : m_matchers ) { + if (matcher->match(arg)) + return true; + } + return false; + } + std::string describe() const override { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else + description += " or "; + description += matcher->toString(); + } + description += " )"; + return description; + } + + MatchAnyOf& operator || ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + + template + struct MatchNotOf : MatcherBase { + + MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} + + bool match( ArgT const& arg ) const override { + return !m_underlyingMatcher.match( arg ); + } + + std::string describe() const override { + return "not " + m_underlyingMatcher.toString(); + } + MatcherBase const& m_underlyingMatcher; + }; + + template + MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { + return MatchAllOf() && *this && other; + } + template + MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { + return MatchAnyOf() || *this || other; + } + template + MatchNotOf MatcherBase::operator ! () const { + return MatchNotOf( *this ); + } + + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + // - deprecated: prefer ||, && and ! + template + Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { + return Impl::MatchNotOf( underlyingMatcher ); + } + template + Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { + return Impl::MatchAllOf() && m1 && m2; + } + template + Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { + return Impl::MatchAllOf() && m1 && m2 && m3; + } + template + Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { + return Impl::MatchAnyOf() || m1 || m2; + } + template + Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { + return Impl::MatchAnyOf() || m1 || m2 || m3; + } + +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch + +// end catch_matchers.hpp +// start catch_matchers_string.h + +#include + +namespace Catch { +namespace Matchers { + + namespace StdString { + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); + std::string adjustString( std::string const& str ) const; + std::string caseSensitivitySuffix() const; + + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct StringMatcherBase : MatcherBase { + StringMatcherBase( std::string const& operation, CasedString const& comparator ); + std::string describe() const override; + + CasedString m_comparator; + std::string m_operation; + }; + + struct EqualsMatcher : StringMatcherBase { + EqualsMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + struct ContainsMatcher : StringMatcherBase { + ContainsMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + struct StartsWithMatcher : StringMatcherBase { + StartsWithMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + struct EndsWithMatcher : StringMatcherBase { + EndsWithMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + + } // namespace StdString + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + + StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_string.h +// start catch_matchers_vector.h + +namespace Catch { +namespace Matchers { + + namespace Vector { + + template + struct ContainsElementMatcher : MatcherBase, T> { + + ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} + + bool match(std::vector const &v) const override { + for (auto const& el : v) { + if (el == m_comparator) { + return true; + } + } + return false; + } + + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); + } + + T const& m_comparator; + }; + + template + struct ContainsMatcher : MatcherBase, std::vector > { + + ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} + + bool match(std::vector const &v) const override { + // !TBD: see note in EqualsMatcher + if (m_comparator.size() > v.size()) + return false; + for (auto const& comparator : m_comparator) { + auto present = false; + for (const auto& el : v) { + if (el == comparator) { + present = true; + break; + } + } + if (!present) { + return false; + } + } + return true; + } + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); + } + + std::vector const& m_comparator; + }; + + template + struct EqualsMatcher : MatcherBase, std::vector > { + + EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} + + bool match(std::vector const &v) const override { + // !TBD: This currently works if all elements can be compared using != + // - a more general approach would be via a compare template that defaults + // to using !=. but could be specialised for, e.g. std::vector etc + // - then just call that directly + if (m_comparator.size() != v.size()) + return false; + for (size_t i = 0; i < v.size(); ++i) + if (m_comparator[i] != v[i]) + return false; + return true; + } + std::string describe() const override { + return "Equals: " + ::Catch::Detail::stringify( m_comparator ); + } + std::vector const& m_comparator; + }; + + } // namespace Vector + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + + template + Vector::ContainsMatcher Contains( std::vector const& comparator ) { + return Vector::ContainsMatcher( comparator ); + } + + template + Vector::ContainsElementMatcher VectorContains( T const& comparator ) { + return Vector::ContainsElementMatcher( comparator ); + } + + template + Vector::EqualsMatcher Equals( std::vector const& comparator ) { + return Vector::EqualsMatcher( comparator ); + } + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_vector.h +namespace Catch { + + template + class MatchExpr : public ITransientExpression { + ArgT const& m_arg; + MatcherT m_matcher; + StringRef m_matcherString; + bool m_result; + public: + MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) + : m_arg( arg ), + m_matcher( matcher ), + m_matcherString( matcherString ), + m_result( matcher.match( arg ) ) + {} + + auto isBinaryExpression() const -> bool override { return true; } + auto getResult() const -> bool override { return m_result; } + + void streamReconstructedExpression( std::ostream &os ) const override { + auto matcherAsString = m_matcher.toString(); + os << Catch::Detail::stringify( m_arg ) << ' '; + if( matcherAsString == Detail::unprintableString ) + os << m_matcherString; + else + os << matcherAsString; + } + }; + + using StringMatcher = Matchers::Impl::MatcherBase; + + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); + + template + auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { + return MatchExpr( arg, matcher, matcherString ); + } + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ + catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__ ); \ + catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType const& ex ) { \ + catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ + } \ + catch( ... ) { \ + catchAssertionHandler.useActiveException(); \ + } \ + else \ + catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( Catch::alwaysFalse() ) + +// end catch_capture_matchers.h +#endif + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// start catch_test_case_info.h + +#include +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestInvoker; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4, + NonPortable = 1 << 5, + Benchmark = 1 << 6 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::vector const& _tags, + SourceLineInfo const& _lineInfo ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::vector tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string tagsAsString() const; + + std::string name; + std::string className; + std::string description; + std::vector tags; + std::vector lcaseTags; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestInvoker* testCase, TestCaseInfo const& info ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + + private: + std::shared_ptr test; + }; + + TestCase makeTestCase( ITestInvoker* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_test_case_info.h +// start catch_interfaces_runner.h + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +// end catch_interfaces_runner.h + +#ifdef __OBJC__ +// start catch_objc.hpp + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public ITestInvoker { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( nullptr, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + struct StringHolder : MatcherBase{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + bool match( NSString* arg ) const override { + return false; + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const override { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + std::string describe() const override { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + std::string describe() const override { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const override { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + std::string describe() const override { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const override { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + std::string describe() const override { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +// end catch_objc.hpp +#endif + +#ifdef CATCH_IMPL +// start catch_impl.hpp + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// start catch_notimplemented_exception.h + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + + virtual ~NotImplementedException() noexcept = default; + + virtual const char* what() const noexcept override; + + private: + std::string m_what; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// end catch_notimplemented_exception.h +// Temporary hack to fix separately provided reporters +// start catch_reporter_bases.hpp + +// start catch_enforce.h + +#include +#include + +#define CATCH_PREPARE_EXCEPTION( type, msg ) \ + type( static_cast( std::ostringstream() << msg ).str() ) +#define CATCH_INTERNAL_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); +#define CATCH_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) +#define CATCH_ENFORCE( condition, msg ) \ + do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) + +// end catch_enforce.h +// start catch_interfaces_reporter.h + +// start catch_config.hpp + +// start catch_test_spec_parser.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// start catch_test_spec.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// start catch_wildcard_pattern.hpp + +#include + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); + virtual ~WildcardPattern() = default; + virtual bool matches( std::string const& str ) const; + + private: + std::string adjustCase( std::string const& str ) const; + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard = NoWildcard; + std::string m_pattern; + }; +} + +// end catch_wildcard_pattern.hpp +#include +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern { + virtual ~Pattern() = default; + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + using PatternPtr = std::shared_ptr; + + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ); + virtual ~NamePattern() = default; + virtual bool matches( TestCaseInfo const& testCase ) const override; + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ); + virtual ~TagPattern() = default; + virtual bool matches( TestCaseInfo const& testCase ) const override; + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( PatternPtr const& underlyingPattern ); + virtual ~ExcludedPattern() = default; + virtual bool matches( TestCaseInfo const& testCase ) const override; + private: + PatternPtr m_underlyingPattern; + }; + + struct Filter { + std::vector m_patterns; + + bool matches( TestCaseInfo const& testCase ) const; + }; + + public: + bool hasFilters() const; + bool matches( TestCaseInfo const& testCase ) const; + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_test_spec.hpp +// start catch_string_manip.h + +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ); + bool startsWith( std::string const& s, char prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool endsWith( std::string const& s, char suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; +} + +// end catch_string_manip.h +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag, EscapedName }; + Mode m_mode = None; + bool m_exclusion = false; + std::size_t m_start = std::string::npos, m_pos = 0; + std::string m_arg; + std::vector m_escapeChars; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases = nullptr; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ); + + TestSpecParser& parse( std::string const& arg ); + TestSpec testSpec(); + + private: + void visitChar( char c ); + void startNewMode( Mode mode, std::size_t start ); + void escape(); + std::string subString() const; + + template + void addPattern() { + std::string token = subString(); + for( size_t i = 0; i < m_escapeChars.size(); ++i ) + token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); + m_escapeChars.clear(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + TestSpec::PatternPtr pattern = std::make_shared( token ); + if( m_exclusion ) + pattern = std::make_shared( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + + void addFilter(); + }; + TestSpec parseTestSpec( std::string const& arg ); + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_test_spec_parser.hpp +// start catch_interfaces_config.h + +#include +#include +#include +#include + +namespace Catch { + + enum class Verbosity { + Quiet = 0, + Normal, + High + }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + struct WaitForKeypress { enum When { + Never, + BeforeStart = 1, + BeforeExit = 2, + BeforeStartAndExit = BeforeStart | BeforeExit + }; }; + + class TestSpec; + + struct IConfig : NonCopyable { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual int benchmarkResolutionMultiple() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + virtual std::vector const& getSectionsToRun() const = 0; + virtual Verbosity verbosity() const = 0; + }; + + using IConfigPtr = std::shared_ptr; +} + +// end catch_interfaces_config.h +// start catch_stream.h + +// start catch_streambuf.h + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() noexcept; + }; +} + +// end catch_streambuf.h +#include +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + std::ostream& clog(); + + struct IStream { + virtual ~IStream() noexcept; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + ~FileStream() noexcept override; + public: // IStream + std::ostream& stream() const override; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + ~CoutStream() noexcept override; + + public: // IStream + std::ostream& stream() const override; + }; + + class DebugOutStream : public IStream { + std::unique_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + ~DebugOutStream() noexcept override; + + public: // IStream + std::ostream& stream() const override; + }; +} + +// end catch_stream.h +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + bool listTests = false; + bool listTags = false; + bool listReporters = false; + bool listTestNamesOnly = false; + + bool showSuccessfulTests = false; + bool shouldDebugBreak = false; + bool noThrow = false; + bool showHelp = false; + bool showInvisibles = false; + bool filenamesAsTags = false; + bool libIdentify = false; + + int abortAfter = -1; + unsigned int rngSeed = 0; + int benchmarkResolutionMultiple = 100; + + Verbosity verbosity = Verbosity::Normal; + WarnAbout::What warnings = WarnAbout::Nothing; + ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; + RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; + UseColour::YesOrNo useColour = UseColour::Auto; + WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; + + std::string outputFilename; + std::string name; + std::string processName; + + std::vector reporterNames; + std::vector testsOrTags; + std::vector sectionsToRun; + }; + + class Config : public IConfig { + virtual void dummy(); + public: + + Config() = default; + Config( ConfigData const& data ); + virtual ~Config() = default; + + std::string const& getFilename() const; + + bool listTests() const; + bool listTestNamesOnly() const; + bool listTags() const; + bool listReporters() const; + + std::string getProcessName() const; + + std::vector const& getReporterNames() const; + std::vector const& getSectionsToRun() const override; + + virtual TestSpec const& testSpec() const override; + + bool showHelp() const; + + // IConfig interface + bool allowThrows() const override; + std::ostream& stream() const override; + std::string name() const override; + bool includeSuccessfulResults() const override; + bool warnAboutMissingAssertions() const override; + ShowDurations::OrNot showDurations() const override; + RunTests::InWhatOrder runOrder() const override; + unsigned int rngSeed() const override; + int benchmarkResolutionMultiple() const override; + UseColour::YesOrNo useColour() const override; + bool shouldDebugBreak() const override; + int abortAfter() const override; + bool showInvisibles() const override; + Verbosity verbosity() const override; + + private: + + IStream const* openStream(); + ConfigData m_data; + + std::unique_ptr m_stream; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// end catch_config.hpp +// start catch_assertionresult.h + +#include + +namespace Catch { + + struct AssertionResultData + { + AssertionResultData() = delete; + + AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ) + : resultType( _resultType ), + lazyExpression( _lazyExpression ) + {} + + ResultWas::OfType resultType = ResultWas::Unknown; + std::string message; + + LazyExpression lazyExpression; + + std::string reconstructExpression() const; + mutable std::string reconstructedExpression; + }; + + class AssertionResult { + public: + AssertionResult() = delete; + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + //protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// end catch_assertionresult.h +// start catch_option.hpp + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( nullptr ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = nullptr; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != nullptr; } + bool none() const { return nullableValue == nullptr; } + + bool operator !() const { return nullableValue == nullptr; } + explicit operator bool() const { + return some(); + } + + private: + T *nullableValue; + alignas(alignof(T)) char storage[sizeof(T)]; + }; + +} // end namespace Catch + +// end catch_option.hpp +#include +#include +#include +#include +#include + +namespace Catch { + + struct ReporterConfig { + explicit ReporterConfig( IConfigPtr const& _fullConfig ); + + ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); + + std::ostream& stream() const; + IConfigPtr fullConfig() const; + + private: + std::ostream* m_stream; + IConfigPtr m_fullConfig; + }; + + struct ReporterPreferences { + bool shouldRedirectStdOut = false; + }; + + template + struct LazyStat : Option { + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used = false; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ); + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ); + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ); + + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; + virtual ~AssertionStats() = default; + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ); + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; + virtual ~SectionStats() = default; + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ); + + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; + virtual ~TestCaseStats() = default; + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ); + TestGroupStats( GroupInfo const& _groupInfo ); + + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; + virtual ~TestGroupStats() = default; + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ); + + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; + virtual ~TestRunStats() = default; + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct BenchmarkInfo { + std::string name; + }; + struct BenchmarkStats { + BenchmarkInfo info; + size_t iterations; + uint64_t elapsedTimeInNanoseconds; + }; + class MultipleReporters; + + struct IStreamingReporter { + virtual ~IStreamingReporter() = default; + + // Implementing class must also provide the following static methods: + // static std::string getDescription(); + // static std::set getSupportedVerbosities() + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + // *** experimental *** + virtual void benchmarkStarting( BenchmarkInfo const& ) {} + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + // *** experimental *** + virtual void benchmarkEnded( BenchmarkStats const& ) {} + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + virtual bool isMulti() const; + }; + using IStreamingReporterPtr = std::unique_ptr; + + struct IReporterFactory { + virtual ~IReporterFactory() = default; + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + using IReporterFactoryPtr = std::shared_ptr; + + struct IReporterRegistry { + using FactoryMap = std::map; + using Listeners = std::vector; + + virtual ~IReporterRegistry() = default; + virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); + +} // end namespace Catch + +// end catch_interfaces_reporter.h +#include +#include +#include +#include +#include +#include + +namespace Catch { + void prepareExpandedExpression(AssertionResult& result); + + // Returns double formatted as %.3f (format expected on output) + std::string getFormattedDuration( double duration ); + + template + struct StreamingReporterBase : IStreamingReporter { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); + } + + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } + + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; + } + + ~StreamingReporterBase() override = default; + + void noMatchingTestCases(std::string const&) override {} + + void testRunStarting(TestRunInfo const& _testRunInfo) override { + currentTestRunInfo = _testRunInfo; + } + void testGroupStarting(GroupInfo const& _groupInfo) override { + currentGroupInfo = _groupInfo; + } + + void testCaseStarting(TestCaseInfo const& _testInfo) override { + currentTestCaseInfo = _testInfo; + } + void sectionStarting(SectionInfo const& _sectionInfo) override { + m_sectionStack.push_back(_sectionInfo); + } + + void sectionEnded(SectionStats const& /* _sectionStats */) override { + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { + currentTestCaseInfo.reset(); + } + void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { + currentGroupInfo.reset(); + } + void testRunEnded(TestRunStats const& /* _testRunStats */) override { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + void skipTest(TestCaseInfo const&) override { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + IConfigPtr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + template + struct CumulativeReporterBase : IStreamingReporter { + template + struct Node { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + using ChildNodes = std::vector>; + T value; + ChildNodes children; + }; + struct SectionNode { + explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} + virtual ~SectionNode() = default; + + bool operator == (SectionNode const& other) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == (std::shared_ptr const& other) const { + return operator==(*other); + } + + SectionStats stats; + using ChildSections = std::vector>; + using Assertions = std::vector; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() (std::shared_ptr const& node) const { + return ((node->stats.sectionInfo.name == m_other.name) && + (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); + } + void operator=(BySectionInfo const&) = delete; + + private: + SectionInfo const& m_other; + }; + + using TestCaseNode = Node; + using TestGroupNode = Node; + using TestRunNode = Node; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); + } + ~CumulativeReporterBase() override = default; + + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } + + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; + } + + void testRunStarting( TestRunInfo const& ) override {} + void testGroupStarting( GroupInfo const& ) override {} + + void testCaseStarting( TestCaseInfo const& ) override {} + + void sectionStarting( SectionInfo const& sectionInfo ) override { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + std::shared_ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = std::make_shared( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + typename SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = std::make_shared( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = std::move(node); + } + + void assertionStarting(AssertionInfo const&) override {} + + bool assertionEnded(AssertionStats const& assertionStats) override { + assert(!m_sectionStack.empty()); + // AssertionResult holds a pointer to a temporary DecomposedExpression, + // which getExpandedExpression() calls to build the expression string. + // Our section stack copy of the assertionResult will likely outlive the + // temporary, so it must be expanded or discarded now to avoid calling + // a destroyed object later. + prepareExpandedExpression(const_cast( assertionStats.assertionResult ) ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back(assertionStats); + return true; + } + void sectionEnded(SectionStats const& sectionStats) override { + assert(!m_sectionStack.empty()); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& testCaseStats) override { + auto node = std::make_shared(testCaseStats); + assert(m_sectionStack.size() == 0); + node->children.push_back(m_rootSection); + m_testCases.push_back(node); + m_rootSection.reset(); + + assert(m_deepestSection); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + void testGroupEnded(TestGroupStats const& testGroupStats) override { + auto node = std::make_shared(testGroupStats); + node->children.swap(m_testCases); + m_testGroups.push_back(node); + } + void testRunEnded(TestRunStats const& testRunStats) override { + auto node = std::make_shared(testRunStats); + node->children.swap(m_testGroups); + m_testRuns.push_back(node); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + void skipTest(TestCaseInfo const&) override {} + + IConfigPtr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector>> m_sections; + std::vector> m_testCases; + std::vector> m_testGroups; + + std::vector> m_testRuns; + + std::shared_ptr m_rootSection; + std::shared_ptr m_deepestSection; + std::vector> m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ); + + void assertionStarting(AssertionInfo const&) override; + bool assertionEnded(AssertionStats const&) override; + }; + +} // end namespace Catch + +// end catch_reporter_bases.hpp +// start catch_reporter_registrars.hpp + +namespace Catch { + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + return std::unique_ptr( new T( config ) ); + } + + virtual std::string getDescription() const override { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, std::make_shared() ); + } + }; + + template + class ListenerRegistrar { + + class ListenerFactory : public IReporterFactory { + + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + return std::make_shared( config ); + } + virtual std::string getDescription() const override { + return std::string(); + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( std::make_shared() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +// Deprecated - use the form without INTERNAL_ +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +#define CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + +// end catch_reporter_registrars.hpp +// + +// start catch_leak_detector.h + +namespace Catch { + + struct LeakDetector { + LeakDetector(); + }; + +} +// end catch_leak_detector.h +// start catch_session.hpp + +// start catch_commandline.hpp + +// start catch_clara.h + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#endif +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 + +// start clara.hpp +// v1.0 +// See https://github.com/philsquared/Clara + + +#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 +#endif + +// ----------- #included from clara_textflow.hpp ----------- + +// TextFlowCpp +// +// A single-header library for wrapping and laying out basic text, by Phil Nash +// +// This work is licensed under the BSD 2-Clause license. +// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause +// +// This project is hosted at https://github.com/philsquared/textflowcpp + + +#include +#include +#include +#include + +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { namespace clara { namespace TextFlow { + + inline auto isWhitespace( char c ) -> bool { + static std::string chars = " \t\n\r"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableBefore( char c ) -> bool { + static std::string chars = "[({<|"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableAfter( char c ) -> bool { + static std::string chars = "])}>.,:;*+-=&/\\"; + return chars.find( c ) != std::string::npos; + } + + class Columns; + + class Column { + std::vector m_strings; + size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; + size_t m_indent = 0; + size_t m_initialIndent = std::string::npos; + + public: + class iterator { + friend Column; + + Column const& m_column; + size_t m_stringIndex = 0; + size_t m_pos = 0; + + size_t m_len = 0; + size_t m_end = 0; + bool m_suffix = false; + + iterator( Column const& column, size_t stringIndex ) + : m_column( column ), + m_stringIndex( stringIndex ) + {} + + auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } + + auto isBoundary( size_t at ) const -> bool { + assert( at > 0 ); + assert( at <= line().size() ); + + return at == line().size() || + ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || + isBreakableBefore( line()[at] ) || + isBreakableAfter( line()[at-1] ); + } + + void calcLength() { + assert( m_stringIndex < m_column.m_strings.size() ); + + m_suffix = false; + auto width = m_column.m_width-indent(); + m_end = m_pos; + while( m_end < line().size() && line()[m_end] != '\n' ) + ++m_end; + + if( m_end < m_pos + width ) { + m_len = m_end - m_pos; + } + else { + size_t len = width; + while (len > 0 && !isBoundary(m_pos + len)) + --len; + while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) + --len; + + if (len > 0) { + m_len = len; + } else { + m_suffix = true; + m_len = width - 1; + } + } + } + + auto indent() const -> size_t { + auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; + return initial == std::string::npos ? m_column.m_indent : initial; + } + + auto addIndentAndSuffix(std::string const &plain) const -> std::string { + return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); + } + + public: + explicit iterator( Column const& column ) : m_column( column ) { + assert( m_column.m_width > m_column.m_indent ); + assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); + calcLength(); + if( m_len == 0 ) + m_stringIndex++; // Empty string + } + + auto operator *() const -> std::string { + assert( m_stringIndex < m_column.m_strings.size() ); + assert( m_pos < m_end ); + if( m_pos + m_column.m_width < m_end ) + return addIndentAndSuffix(line().substr(m_pos, m_len)); + else + return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); + } + + auto operator ++() -> iterator& { + m_pos += m_len; + if( m_pos < line().size() && line()[m_pos] == '\n' ) + m_pos += 1; + else + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) + ++m_pos; + + if( m_pos == line().size() ) { + m_pos = 0; + ++m_stringIndex; + } + if( m_stringIndex < m_column.m_strings.size() ) + calcLength(); + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + + auto operator ==( iterator const& other ) const -> bool { + return + m_pos == other.m_pos && + m_stringIndex == other.m_stringIndex && + &m_column == &other.m_column; + } + auto operator !=( iterator const& other ) const -> bool { + return !operator==( other ); + } + }; + using const_iterator = iterator; + + explicit Column( std::string const& text ) { m_strings.push_back( text ); } + + auto width( size_t newWidth ) -> Column& { + assert( newWidth > 0 ); + m_width = newWidth; + return *this; + } + auto indent( size_t newIndent ) -> Column& { + m_indent = newIndent; + return *this; + } + auto initialIndent( size_t newIndent ) -> Column& { + m_initialIndent = newIndent; + return *this; + } + + auto width() const -> size_t { return m_width; } + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, m_strings.size() }; } + + inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { + bool first = true; + for( auto line : col ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto operator + ( Column const& other ) -> Columns; + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + class Spacer : public Column { + + public: + explicit Spacer( size_t spaceWidth ) : Column( "" ) { + width( spaceWidth ); + } + }; + + class Columns { + std::vector m_columns; + + public: + + class iterator { + friend Columns; + struct EndTag {}; + + std::vector const& m_columns; + std::vector m_iterators; + size_t m_activeIterators; + + iterator( Columns const& columns, EndTag ) + : m_columns( columns.m_columns ), + m_activeIterators( 0 ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.end() ); + } + + public: + explicit iterator( Columns const& columns ) + : m_columns( columns.m_columns ), + m_activeIterators( m_columns.size() ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.begin() ); + } + + auto operator ==( iterator const& other ) const -> bool { + return m_iterators == other.m_iterators; + } + auto operator !=( iterator const& other ) const -> bool { + return m_iterators != other.m_iterators; + } + auto operator *() const -> std::string { + std::string row, padding; + + for( size_t i = 0; i < m_columns.size(); ++i ) { + auto width = m_columns[i].width(); + if( m_iterators[i] != m_columns[i].end() ) { + std::string col = *m_iterators[i]; + row += padding + col; + if( col.size() < width ) + padding = std::string( width - col.size(), ' ' ); + else + padding = ""; + } + else { + padding += std::string( width, ' ' ); + } + } + return row; + } + auto operator ++() -> iterator& { + for( size_t i = 0; i < m_columns.size(); ++i ) { + if (m_iterators[i] != m_columns[i].end()) + ++m_iterators[i]; + } + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + }; + using const_iterator = iterator; + + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, iterator::EndTag() }; } + + auto operator += ( Column const& col ) -> Columns& { + m_columns.push_back( col ); + return *this; + } + auto operator + ( Column const& col ) -> Columns { + Columns combined = *this; + combined += col; + return combined; + } + + inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) { + + bool first = true; + for( auto line : cols ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + inline auto Column::operator + ( Column const& other ) -> Columns { + Columns cols; + cols += *this; + cols += other; + return cols; + } +}}} // namespace Catch::clara::TextFlow + +// ----------- end of #include from clara_textflow.hpp ----------- +// ........... back in clara.hpp + +#include +#include +#include + +#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CLARA_PLATFORM_WINDOWS + +#endif + +namespace Catch { namespace clara { +namespace detail { + + // Traits for extracting arg and return type of lambdas (for single argument lambdas) + template + struct UnaryLambdaTraits : UnaryLambdaTraits {}; + + template + struct UnaryLambdaTraits { + static const bool isValid = false; + }; + + template + struct UnaryLambdaTraits { + static const bool isValid = true; + using ArgType = typename std::remove_const::type>::type;; + using ReturnType = ReturnT; + }; + + class TokenStream; + + // Transport for raw args (copied from main args, or supplied via init list for testing) + class Args { + friend TokenStream; + std::string m_exeName; + std::vector m_args; + + public: + Args(int argc, char *argv[]) { + m_exeName = argv[0]; + for (int i = 1; i < argc; ++i) + m_args.push_back(argv[i]); + } + + Args(std::initializer_list args) + : m_exeName( *args.begin() ), + m_args( args.begin()+1, args.end() ) + {} + + auto exeName() const -> std::string { + return m_exeName; + } + }; + + // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string + // may encode an option + its argument if the : or = form is used + enum class TokenType { + Option, Argument + }; + struct Token { + TokenType type; + std::string token; + }; + + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled + class TokenStream { + using Iterator = std::vector::const_iterator; + Iterator it; + Iterator itEnd; + std::vector m_tokenBuffer; + + void loadBuffer() { + m_tokenBuffer.resize(0); + + // Skip any empty strings + while (it != itEnd && it->empty()) + ++it; + + if (it != itEnd) { + auto const &next = *it; + if (next[0] == '-' || next[0] == '/') { + auto delimiterPos = next.find_first_of(" :="); + if (delimiterPos != std::string::npos) { + m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)}); + m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)}); + } else { + if (next[1] != '-' && next.size() > 2) { + std::string opt = "- "; + for (size_t i = 1; i < next.size(); ++i) { + opt[1] = next[i]; + m_tokenBuffer.push_back({TokenType::Option, opt}); + } + } else { + m_tokenBuffer.push_back({TokenType::Option, next}); + } + } + } else { + m_tokenBuffer.push_back({TokenType::Argument, next}); + } + } + } + + public: + explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} + + TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + loadBuffer(); + } + + explicit operator bool() const { + return !m_tokenBuffer.empty() || it != itEnd; + } + + auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } + + auto operator*() const -> Token { + assert(!m_tokenBuffer.empty()); + return m_tokenBuffer.front(); + } + + auto operator->() const -> Token const * { + assert(!m_tokenBuffer.empty()); + return &m_tokenBuffer.front(); + } + + auto operator++() -> TokenStream & { + if (m_tokenBuffer.size() >= 2) { + m_tokenBuffer.erase(m_tokenBuffer.begin()); + } else { + if (it != itEnd) + ++it; + loadBuffer(); + } + return *this; + } + }; + + class ResultBase { + public: + enum Type { + Ok, LogicError, RuntimeError + }; + + protected: + ResultBase(Type type) : m_type(type) {} + virtual ~ResultBase() = default; + + virtual void enforceOk() const = 0; + + Type m_type; + }; + + template + class ResultValueBase : public ResultBase { + public: + auto value() const -> T const & { + enforceOk(); + return m_value; + } + + protected: + ResultValueBase(Type type) : ResultBase(type) {} + + ResultValueBase(ResultValueBase const &other) : ResultBase(other) { + if (m_type == ResultBase::Ok) + new(&m_value) T(other.m_value); + } + + ResultValueBase(Type, T const &value) : ResultBase(Ok) { + new(&m_value) T(value); + } + + auto operator=(ResultValueBase const &other) -> ResultValueBase & { + if (m_type == ResultBase::Ok) + m_value.~T(); + ResultBase::operator=(other); + if (m_type == ResultBase::Ok) + new(&m_value) T(other.m_value); + return *this; + } + + ~ResultValueBase() { + if (m_type == Ok) + m_value.~T(); + } + + union { + T m_value; + }; + }; + + template<> + class ResultValueBase : public ResultBase { + protected: + using ResultBase::ResultBase; + }; + + template + class BasicResult : public ResultValueBase { + public: + template + explicit BasicResult(BasicResult const &other) + : ResultValueBase(other.type()), + m_errorMessage(other.errorMessage()) { + assert(type() != ResultBase::Ok); + } + + static auto ok() -> BasicResult { return {ResultBase::Ok}; } + + template + static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; } + + static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; } + + static auto runtimeError(std::string const &message) -> BasicResult { + return {ResultBase::RuntimeError, message}; + } + + explicit operator bool() const { return m_type == ResultBase::Ok; } + + auto type() const -> ResultBase::Type { return m_type; } + + auto errorMessage() const -> std::string { return m_errorMessage; } + + protected: + virtual void enforceOk() const { + // !TBD: If no exceptions, std::terminate here or something + switch (m_type) { + case ResultBase::LogicError: + throw std::logic_error(m_errorMessage); + case ResultBase::RuntimeError: + throw std::runtime_error(m_errorMessage); + case ResultBase::Ok: + break; + } + } + + std::string m_errorMessage; // Only populated if resultType is an error + + BasicResult(ResultBase::Type type, std::string const &message) + : ResultValueBase(type), + m_errorMessage(message) { + assert(m_type != ResultBase::Ok); + } + + using ResultValueBase::ResultValueBase; + using ResultBase::m_type; + }; + + enum class ParseResultType { + Matched, NoMatch, ShortCircuitAll, ShortCircuitSame + }; + + class ParseState { + public: + + ParseState(ParseResultType type, TokenStream const &remainingTokens) + : m_type(type), + m_remainingTokens(remainingTokens) {} + + auto type() const -> ParseResultType { return m_type; } + + auto remainingTokens() const -> TokenStream { return m_remainingTokens; } + + private: + ParseResultType m_type; + TokenStream m_remainingTokens; + }; + + using Result = BasicResult; + using ParserResult = BasicResult; + using InternalParseResult = BasicResult; + + struct HelpColumns { + std::string left; + std::string right; + }; + + template + inline auto convertInto(std::string const &source, T& target) -> ParserResult { + std::stringstream ss; + ss << source; + ss >> target; + if (ss.fail()) + return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type"); + else + return ParserResult::ok(ParseResultType::Matched); + } + inline auto convertInto(std::string const &source, std::string& target) -> ParserResult { + target = source; + return ParserResult::ok(ParseResultType::Matched); + } + inline auto convertInto(std::string const &source, bool &target) -> ParserResult { + std::string srcLC = source; + std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast( ::tolower(c) ); } ); + if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") + target = true; + else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") + target = false; + else + return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'"); + return ParserResult::ok(ParseResultType::Matched); + } + + struct BoundRefBase { + BoundRefBase() = default; + + BoundRefBase(BoundRefBase const &) = delete; + + BoundRefBase(BoundRefBase &&) = delete; + + BoundRefBase &operator=(BoundRefBase const &) = delete; + + BoundRefBase &operator=(BoundRefBase &&) = delete; + + virtual ~BoundRefBase() = default; + + virtual auto isFlag() const -> bool = 0; + + virtual auto isContainer() const -> bool { return false; } + + virtual auto setValue(std::string const &arg) -> ParserResult = 0; + + virtual auto setFlag(bool flag) -> ParserResult = 0; + }; + + struct BoundValueRefBase : BoundRefBase { + auto isFlag() const -> bool override { return false; } + + auto setFlag(bool) -> ParserResult override { + return ParserResult::logicError("Flags can only be set on boolean fields"); + } + }; + + struct BoundFlagRefBase : BoundRefBase { + auto isFlag() const -> bool override { return true; } + + auto setValue(std::string const &arg) -> ParserResult override { + bool flag; + auto result = convertInto(arg, flag); + if (result) + setFlag(flag); + return result; + } + }; + + template + struct BoundRef : BoundValueRefBase { + T &m_ref; + + explicit BoundRef(T &ref) : m_ref(ref) {} + + auto setValue(std::string const &arg) -> ParserResult override { + return convertInto(arg, m_ref); + } + }; + + template + struct BoundRef> : BoundValueRefBase { + std::vector &m_ref; + + explicit BoundRef(std::vector &ref) : m_ref(ref) {} + + auto isContainer() const -> bool override { return true; } + + auto setValue(std::string const &arg) -> ParserResult override { + T temp; + auto result = convertInto(arg, temp); + if (result) + m_ref.push_back(temp); + return result; + } + }; + + struct BoundFlagRef : BoundFlagRefBase { + bool &m_ref; + + explicit BoundFlagRef(bool &ref) : m_ref(ref) {} + + auto setFlag(bool flag) -> ParserResult override { + m_ref = flag; + return ParserResult::ok(ParseResultType::Matched); + } + }; + + template + struct LambdaInvoker { + static_assert(std::is_same::value, "Lambda must return void or clara::ParserResult"); + + template + static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { + return lambda(arg); + } + }; + + template<> + struct LambdaInvoker { + template + static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { + lambda(arg); + return ParserResult::ok(ParseResultType::Matched); + } + }; + + template + inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { + ArgType temp; + auto result = convertInto(arg, temp); + return !result + ? result + : LambdaInvoker::ReturnType>::invoke(lambda, temp); + }; + + template + struct BoundLambda : BoundValueRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} + + auto setValue(std::string const &arg) -> ParserResult override { + return invokeLambda::ArgType>(m_lambda, arg); + } + }; + + template + struct BoundFlagLambda : BoundFlagRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); + + explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} + + auto setFlag(bool flag) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke(m_lambda, flag); + } + }; + + enum class Optionality { + Optional, Required + }; + + struct Parser; + + class ParserBase { + public: + virtual ~ParserBase() = default; + virtual auto validate() const -> Result { return Result::ok(); } + virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; + virtual auto cardinality() const -> size_t { return 1; } + + auto parse(Args const &args) const -> InternalParseResult { + return parse( args.exeName(), TokenStream(args)); + } + }; + + template + class ComposableParserImpl : public ParserBase { + public: + template + auto operator+(T const &other) const -> Parser; + }; + + // Common code and state for Args and Opts + template + class ParserRefImpl : public ComposableParserImpl { + protected: + Optionality m_optionality = Optionality::Optional; + std::shared_ptr m_ref; + std::string m_hint; + std::string m_description; + + explicit ParserRefImpl(std::shared_ptr const &ref) : m_ref(ref) {} + + public: + template + ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), m_hint(hint) {} + + template + ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), + m_hint(hint) {} + + auto operator()(std::string const &description) -> DerivedT & { + m_description = description; + return static_cast( *this ); + } + + auto optional() -> DerivedT & { + m_optionality = Optionality::Optional; + return static_cast( *this ); + }; + + auto required() -> DerivedT & { + m_optionality = Optionality::Required; + return static_cast( *this ); + }; + + auto isOptional() const -> bool { + return m_optionality == Optionality::Optional; + } + + auto cardinality() const -> size_t override { + if (m_ref->isContainer()) + return 0; + else + return 1; + } + + auto hint() const -> std::string { return m_hint; } + }; + + class ExeName : public ComposableParserImpl { + std::shared_ptr m_name; + std::shared_ptr m_ref; + + template + static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { + return std::make_shared>(lambda); + } + + public: + ExeName() : m_name(std::make_shared("")) {} + + explicit ExeName(std::string &ref) : ExeName() { + m_ref = std::make_shared>( ref ); + } + + template + explicit ExeName( LambdaT const& lambda ) : ExeName() { + m_ref = std::make_shared>( lambda ); + } + + // The exe name is not parsed out of the normal tokens, but is handled specially + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + } + + auto name() const -> std::string { return *m_name; } + auto set( std::string const& newName ) -> ParserResult { + + auto lastSlash = newName.find_last_of( "\\/" ); + auto filename = (lastSlash == std::string::npos) + ? newName + : newName.substr( lastSlash+1 ); + + *m_name = filename; + if( m_ref ) + return m_ref->setValue( filename ); + else + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + class Arg : public ParserRefImpl { + public: + using ParserRefImpl::ParserRefImpl; + + auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { + auto validationResult = validate(); + if (!validationResult) + return InternalParseResult(validationResult); + + auto remainingTokens = tokens; + auto const &token = *remainingTokens; + if (token.type != TokenType::Argument) + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + + auto result = m_ref->setValue(remainingTokens->token); + if (!result) + return InternalParseResult(result); + else + return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + } + }; + + inline auto normaliseOpt(std::string const &optName) -> std::string { + if (optName[0] == '/') + return "-" + optName.substr(1); + else + return optName; + } + + class Opt : public ParserRefImpl { + protected: + std::vector m_optNames; + + public: + template + explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} + + explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + + template + Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + template + Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + auto operator[](std::string const &optName) -> Opt & { + m_optNames.push_back(optName); + return *this; + } + + auto getHelpColumns() const -> std::vector { + std::ostringstream oss; + bool first = true; + for (auto const &opt : m_optNames) { + if (first) + first = false; + else + oss << ", "; + oss << opt; + } + if (!m_hint.empty()) + oss << " <" << m_hint << ">"; + return {{oss.str(), m_description}}; + } + + auto isMatch(std::string const &optToken) const -> bool { +#ifdef CLARA_PLATFORM_WINDOWS + auto normalisedToken = normaliseOpt( optToken ); +#else + auto const &normalisedToken = optToken; +#endif + for (auto const &name : m_optNames) { + if (normaliseOpt(name) == normalisedToken) + return true; + } + return false; + } + + using ParserBase::parse; + + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + auto validationResult = validate(); + if (!validationResult) + return InternalParseResult(validationResult); + + auto remainingTokens = tokens; + if (remainingTokens && remainingTokens->type == TokenType::Option) { + auto const &token = *remainingTokens; + if (isMatch(token.token)) { + if (m_ref->isFlag()) { + auto result = m_ref->setFlag(true); + if (!result) + return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + } else { + ++remainingTokens; + if (!remainingTokens) + return InternalParseResult::runtimeError("Expected argument following " + token.token); + auto const &argToken = *remainingTokens; + if (argToken.type != TokenType::Argument) + return InternalParseResult::runtimeError("Expected argument following " + token.token); + auto result = m_ref->setValue(argToken.token); + if (!result) + return InternalParseResult(result); + if (result.value() == ParseResultType::ShortCircuitAll) + return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + } + return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + } + } + return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + } + + auto validate() const -> Result override { + if (m_optNames.empty()) + return Result::logicError("No options supplied to Opt"); + for (auto const &name : m_optNames) { + if (name.empty()) + return Result::logicError("Option name cannot be empty"); + if (name[0] != '-' && name[0] != '/') + return Result::logicError("Option name must begin with '-' or '/'"); + } + return ParserRefImpl::validate(); + } + }; + + struct Help : Opt { + Help( bool &showHelpFlag ) + : Opt([&]( bool flag ) { + showHelpFlag = flag; + return ParserResult::ok(ParseResultType::ShortCircuitAll); + }) + { + static_cast(*this) + ("display usage information") + ["-?"]["-h"]["--help"] + .optional(); + } + }; + + struct Parser : ParserBase { + + mutable ExeName m_exeName; + std::vector m_options; + std::vector m_args; + + auto operator+=(ExeName const &exeName) -> Parser & { + m_exeName = exeName; + return *this; + } + + auto operator+=(Arg const &arg) -> Parser & { + m_args.push_back(arg); + return *this; + } + + auto operator+=(Opt const &opt) -> Parser & { + m_options.push_back(opt); + return *this; + } + + auto operator+=(Parser const &other) -> Parser & { + m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); + m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); + return *this; + } + + template + auto operator+(T const &other) const -> Parser { + return Parser(*this) += other; + } + + auto getHelpColumns() const -> std::vector { + std::vector cols; + for (auto const &o : m_options) { + auto childCols = o.getHelpColumns(); + cols.insert(cols.end(), childCols.begin(), childCols.end()); + } + return cols; + } + + void writeToStream(std::ostream &os) const { + if (!m_exeName.name().empty()) { + os << "usage:\n" << " " << m_exeName.name() << " "; + bool required = true, first = true; + for (auto const &arg : m_args) { + if (first) + first = false; + else + os << " "; + if (arg.isOptional() && required) { + os << "["; + required = false; + } + os << "<" << arg.hint() << ">"; + if (arg.cardinality() == 0) + os << " ... "; + } + if (!required) + os << "]"; + if (!m_options.empty()) + os << " options"; + os << "\n\nwhere options are:" << std::endl; + } + + auto rows = getHelpColumns(); + size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; + size_t optWidth = 0; + for (auto const &cols : rows) + optWidth = std::max(optWidth, cols.left.size() + 2); + + for (auto const &cols : rows) { + auto row = + TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Spacer(4) + + TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); + os << row << std::endl; + } + } + + friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { + parser.writeToStream(os); + return os; + } + + auto validate() const -> Result override { + for (auto const &opt : m_options) { + auto result = opt.validate(); + if (!result) + return result; + } + for (auto const &arg : m_args) { + auto result = arg.validate(); + if (!result) + return result; + } + return Result::ok(); + } + + using ParserBase::parse; + + auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override { + std::vector allParsers; + allParsers.reserve(m_args.size() + m_options.size()); + std::set requiredParsers; + + for (auto const &opt : m_options) { + allParsers.push_back(&opt); + if (!opt.isOptional()) + requiredParsers.insert(&opt); + } + + size_t optionalArgs = 0; + for (auto const &arg : m_args) { + allParsers.push_back(&arg); + if (!arg.isOptional()) { + if (optionalArgs > 0) + return InternalParseResult::logicError( + "Required arguments must preceed any optional arguments"); + else + ++optionalArgs; + requiredParsers.insert(&arg); + } + } + + m_exeName.set( exeName ); + + auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + while (result.value().remainingTokens()) { + auto remainingTokenCount = result.value().remainingTokens().count(); + for (auto parser : allParsers) { + result = parser->parse( exeName, result.value().remainingTokens() ); + if (!result || result.value().type() != ParseResultType::NoMatch) { + if (parser->cardinality() == 1) + allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser), + allParsers.end()); + requiredParsers.erase(parser); + break; + } + } + if (!result || remainingTokenCount == result.value().remainingTokens().count()) + return result; + } + // !TBD Check missing required options + return result; + } + }; + + template + template + auto ComposableParserImpl::operator+(T const &other) const -> Parser { + return Parser() + static_cast( *this ) + other; + } +} // namespace detail + +// A Combined parser +using detail::Parser; + +// A parser for options +using detail::Opt; + +// A parser for arguments +using detail::Arg; + +// Wrapper for argc, argv from main() +using detail::Args; + +// Specifies the name of the executable +using detail::ExeName; + +// Convenience wrapper for option parser that specifies the help option +using detail::Help; + +// enum of result types from a parse +using detail::ParseResultType; + +// Result type for parser operation +using detail::ParserResult; + +}} // namespace Catch::clara + +// end clara.hpp +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +// end catch_clara.h +namespace Catch { + + clara::Parser makeCommandLineParser( ConfigData& config ); + +} // end namespace Catch + +// end catch_commandline.hpp +// start catch_console_colour.hpp + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour&& other ) noexcept; + Colour& operator=( Colour&& other ) noexcept; + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved = false; + }; + + std::ostream& operator << ( std::ostream& os, Colour const& ); + +} // end namespace Catch + +// end catch_console_colour.hpp +// start catch_list.h + +#include + +namespace Catch { + + std::size_t listTests( Config const& config ); + + std::size_t listTestsNamesOnly( Config const& config ); + + struct TagInfo { + void add( std::string const& spelling ); + std::string all() const; + + std::set spellings; + std::size_t count = 0; + }; + + std::size_t listTags( Config const& config ); + + std::size_t listReporters( Config const& /*config*/ ); + + Option list( Config const& config ); + +} // end namespace Catch + +// end catch_list.h +// start catch_run_context.hpp + +// start catch_test_case_tracker.hpp + +#include +#include +#include + +CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS + +namespace Catch { +namespace TestCaseTracking { + + struct NameAndLocation { + std::string name; + SourceLineInfo location; + + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); + }; + + struct ITracker; + + using ITrackerPtr = std::shared_ptr; + + struct ITracker { + virtual ~ITracker() = default; + + // static queries + virtual NameAndLocation const& nameAndLocation() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( ITrackerPtr const& child ) = 0; + virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + ITrackerPtr m_rootTracker; + ITracker* m_currentTracker = nullptr; + RunState m_runState = NotStarted; + + public: + + static TrackerContext& instance(); + + ITracker& startRun(); + void endRun(); + + void startCycle(); + void completeCycle(); + + bool completedCycle() const; + ITracker& currentTracker(); + void setCurrentTracker( ITracker* tracker ); + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + + class TrackerHasName { + NameAndLocation m_nameAndLocation; + public: + TrackerHasName( NameAndLocation const& nameAndLocation ); + bool operator ()( ITrackerPtr const& tracker ) const; + }; + + using Children = std::vector; + NameAndLocation m_nameAndLocation; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState = NotStarted; + + public: + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + + NameAndLocation const& nameAndLocation() const override; + bool isComplete() const override; + bool isSuccessfullyCompleted() const override; + bool isOpen() const override; + bool hasChildren() const override; + + void addChild( ITrackerPtr const& child ) override; + + ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; + ITracker& parent() override; + + void openChild() override; + + bool isSectionTracker() const override; + bool isIndexTracker() const override; + + void open(); + + void close() override; + void fail() override; + void markAsNeedingAnotherRun() override; + + private: + void moveToParent(); + void moveToThis(); + }; + + class SectionTracker : public TrackerBase { + std::vector m_filters; + public: + SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + + bool isSectionTracker() const override; + + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); + + void tryOpen(); + + void addInitialFilters( std::vector const& filters ); + void addNextFilters( std::vector const& filters ); + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index = -1; + public: + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); + + bool isIndexTracker() const override; + void close() override; + + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); + + int index() const; + + void moveNext(); + }; + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + +// end catch_test_case_tracker.hpp +// start catch_fatal_condition.h + +#include + +namespace Catch { + + // Report the error condition + void reportFatal( std::string const& message ); + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) +# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +# endif +# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINED_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +// end catch_windows_h_proxy.h + +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + +namespace Catch { + + struct FatalConditionHandler { + + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); + FatalConditionHandler(); + static void reset(); + ~FatalConditionHandler(); + + private: + static bool isSet; + static ULONG guaranteeSize; + static PVOID exceptionHandlerHandle; + }; + +} // namespace Catch + +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct FatalConditionHandler { + + static bool isSet; + static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; + static stack_t oldSigStack; + static char altStackMem[]; + + static void handleSignal( int sig ); + + FatalConditionHandler(); + ~FatalConditionHandler(); + static void reset(); + }; + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows + +// end catch_fatal_condition.h +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect(std::ostream& stream, std::string& targetString); + + ~StreamRedirect(); + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + // StdErr has two constituent streams in C++, std::cerr and std::clog + // This means that we need to redirect 2 streams into 1 to keep proper + // order of writes and cannot use StreamRedirect on its own + class StdErrRedirect { + public: + StdErrRedirect(std::string& targetString); + ~StdErrRedirect(); + private: + std::streambuf* m_cerrBuf; + std::streambuf* m_clogBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + public: + RunContext( RunContext const& ) = delete; + RunContext& operator =( RunContext const& ) = delete; + + explicit RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter); + + virtual ~RunContext(); + + void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount); + void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount); + + Totals runTest(TestCase const& testCase); + + IConfigPtr config() const; + IStreamingReporter& reporter() const; + + private: // IResultCapture + + void assertionStarting(AssertionInfo const& info) override; + void assertionEnded(AssertionResult const& result) override; + + bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; + bool testForMissingAssertions(Counts& assertions); + + void sectionEnded(SectionEndInfo const& endInfo) override; + void sectionEndedEarly(SectionEndInfo const& endInfo) override; + + void benchmarkStarting( BenchmarkInfo const& info ) override; + void benchmarkEnded( BenchmarkStats const& stats ) override; + + void pushScopedMessage(MessageInfo const& message) override; + void popScopedMessage(MessageInfo const& message) override; + + std::string getCurrentTestName() const override; + + const AssertionResult* getLastResult() const override; + + void exceptionEarlyReported() override; + + void handleFatalErrorCondition(std::string const& message) override; + + bool lastAssertionPassed() override; + + void assertionPassed() override; + + void assertionRun() override; + + public: + // !TBD We need to do this another way! + bool aborting() const override; + + private: + + void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); + void invokeActiveTestCase(); + + private: + + void handleUnfinishedSections(); + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase = nullptr; + ITracker* m_testCaseTracker; + Option m_lastResult; + + IConfigPtr m_config; + Totals m_totals; + IStreamingReporterPtr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + size_t m_prevPassed = 0; + bool m_shouldReportUnexpected = true; + }; + + IResultCapture& getResultCapture(); + +} // end namespace Catch + +// end catch_run_context.hpp +// start catch_version.h + +#include + +namespace Catch { + + // Versioning information + struct Version { + Version( Version const& ) = delete; + Version& operator=( Version const& ) = delete; + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + char const * const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + }; + + Version const& libraryVersion(); +} + +// end catch_version.h +// start catch_startup_exception_registry.h + +#include +#include + +namespace Catch { + + class StartupExceptionRegistry { + public: + void add(std::exception_ptr const& exception) noexcept; + std::vector const& getExceptions() const noexcept; + private: + std::vector m_exceptions; + }; + +} // end namespace Catch + +// end catch_startup_exception_registry.h +// start catch_text.h + +namespace Catch { + using namespace clara::TextFlow; +} + +// end catch_text.h +#include +#include +#include +#include + +namespace Catch { + + IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { + auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); + CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); + + return reporter; + } + +#ifndef CATCH_CONFIG_DEFAULT_REPORTER +#define CATCH_CONFIG_DEFAULT_REPORTER "console" +#endif + + IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { + auto const& reporterNames = config->getReporterNames(); + if( reporterNames.empty() ) + return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config ); + + IStreamingReporterPtr reporter; + for( auto const& name : reporterNames ) + addReporter( reporter, createReporter( name, config ) ); + return reporter; + } + void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) { + auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( auto const& listener : listeners ) + addReporter(reporters, listener->create( ReporterConfig( config ) ) ); + } + + Totals runTests( std::shared_ptr const& config ) { + + IStreamingReporterPtr reporter = makeReporter( config ); + addListeners( reporter, config ); + + RunContext context( config, std::move( reporter ) ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *config ); + for( auto const& testCase : allTestCases ) { + if( !context.aborting() && matchTest( testCase, testSpec, *config ) ) + totals += context.runTest( testCase ); + else + context.reporter().skipTest( testCase ); + } + + context.testGroupEnded( config->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + auto& tests = const_cast&>( getAllTestCasesSorted( config ) ); + for( auto& testCase : tests ) { + auto tags = testCase.tags; + + std::string filename = testCase.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( '.' ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.push_back( '#' + filename ); + setTags( testCase, tags ); + } + } + + class Session : NonCopyable { + static const int MaxExitCode; + public: + + Session() { + static bool alreadyInstantiated = false; + if( alreadyInstantiated ) + CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); + alreadyInstantiated = true; + m_cli = makeCommandLineParser( m_configData ); + } + ~Session() override { + Catch::cleanUp(); + } + + void showHelp() const { + Catch::cout() + << "\nCatch v" << libraryVersion() << "\n" + << m_cli << std::endl + << "For more detailed usage please see the project docs\n" << std::endl; + } + void libIdentify() { + Catch::cout() + << std::left << std::setw(16) << "description: " << "A Catch test executable\n" + << std::left << std::setw(16) << "category: " << "testframework\n" + << std::left << std::setw(16) << "framework: " << "Catch Test\n" + << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; + } + + int applyCommandLine( int argc, char* argv[] ) { + auto result = m_cli.parse( clara::Args( argc, argv ) ); + if( !result ) { + Catch::cerr() + << Colour( Colour::Red ) + << "\nError(s) in input:\n" + << Column( result.errorMessage() ).indent( 2 ) + << "\n\n"; + Catch::cerr() << "Run with -? for usage\n" << std::endl; + return MaxExitCode; + } + + if( m_configData.showHelp ) + showHelp(); + if( m_configData.libIdentify ) + libIdentify(); + m_config.reset(); + return 0; + } + + void useConfigData( ConfigData const& configData ) { + m_configData = configData; + m_config.reset(); + } + + int run( int argc, char* argv[] ) { + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + Catch::cerr() << "Errors occured during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << ex.what() << '\n'; + } + } + return 1; + } + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + #if defined(WIN32) && defined(UNICODE) + int run( int argc, wchar_t* const argv[] ) { + + char **utf8Argv = new char *[ argc ]; + + for ( int i = 0; i < argc; ++i ) { + int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + + utf8Argv[ i ] = new char[ bufSize ]; + + WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); + } + + int returnCode = run( argc, utf8Argv ); + + for ( int i = 0; i < argc; ++i ) + delete [] utf8Argv[ i ]; + + delete [] utf8Argv; + + return returnCode; + } + #endif + int run() { + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before starting" << std::endl; + std::getchar(); + } + int exitCode = runInternal(); + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; + std::getchar(); + } + return exitCode; + } + + clara::Parser const& cli() const { + return m_cli; + } + void cli( clara::Parser const& newParser ) { + m_cli = newParser; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = std::make_shared( m_configData ); + return *m_config; + } + private: + int runInternal() { + if( m_configData.showHelp || m_configData.libIdentify ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return MaxExitCode; + } + } + + clara::Parser m_cli; + ConfigData m_configData; + std::shared_ptr m_config; + }; + + const int Session::MaxExitCode = 255; + +} // end namespace Catch + +// end catch_session.hpp +// Cpp files will be included in the single-header file here +// start catch_approx.cpp + +#include + +namespace Catch { +namespace Detail { + + Approx::Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_margin( 0.0 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx Approx::custom() { + return Approx( 0 ); + } + + std::string Approx::toString() const { + std::ostringstream oss; + oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; + return oss.str(); + } + +} // end namespace Detail + +std::string StringMaker::convert(Catch::Detail::Approx const& value) { + return value.toString(); +} + +} // end namespace Catch +// end catch_approx.cpp +// start catch_assertionhandler.cpp + +#include + +namespace Catch { + + auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { + expr.streamReconstructedExpression( os ); + return os; + } + + LazyExpression::LazyExpression( bool isNegated ) + : m_isNegated( isNegated ) + {} + + LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} + + LazyExpression::operator bool() const { + return m_transientExpression != nullptr; + } + + auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { + if( lazyExpr.m_isNegated ) + os << "!"; + + if( lazyExpr ) { + if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) + os << "(" << *lazyExpr.m_transientExpression << ")"; + else + os << *lazyExpr.m_transientExpression; + } + else { + os << "{** error - unchecked empty expression requested **}"; + } + return os; + } + + AssertionHandler::AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } + { + getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); + } + AssertionHandler::~AssertionHandler() { + if ( m_inExceptionGuard ) { + handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ); + getCurrentContext().getResultCapture()->exceptionEarlyReported(); + } + } + + void AssertionHandler::handle( ITransientExpression const& expr ) { + + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + bool result = expr.getResult() != negated; + + handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); + } + void AssertionHandler::handle( ResultWas::OfType resultType ) { + handle( resultType, nullptr, false ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { + AssertionResultData data( resultType, LazyExpression( false ) ); + data.message = message; + handle( data, nullptr ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { + AssertionResultData data( resultType, LazyExpression( negated ) ); + handle( data, expr ); + } + void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) { + + getResultCapture().assertionRun(); + + AssertionResult assertionResult{ m_assertionInfo, resultData }; + assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; + + getResultCapture().assertionEnded( assertionResult ); + + if( !assertionResult.isOk() ) { + m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); + m_shouldThrow = + getCurrentContext().getRunner()->aborting() || + (m_assertionInfo.resultDisposition & ResultDisposition::Normal); + } + } + + auto AssertionHandler::allowThrows() const -> bool { + return getCurrentContext().getConfig()->allowThrows(); + } + + auto AssertionHandler::shouldDebugBreak() const -> bool { + return m_shouldDebugBreak; + } + void AssertionHandler::reactWithDebugBreak() const { + if (m_shouldDebugBreak) { + /////////////////////////////////////////////////////////////////// + // To inspect the state during test, you need to go one level up the callstack + // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call + /////////////////////////////////////////////////////////////////// + CATCH_BREAK_INTO_DEBUGGER(); + } + reactWithoutDebugBreak(); + } + void AssertionHandler::reactWithoutDebugBreak() const { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + void AssertionHandler::useActiveException() { + handle( ResultWas::ThrewException, Catch::translateActiveException() ); + } + + void AssertionHandler::setExceptionGuard() { + assert( m_inExceptionGuard == false ); + m_inExceptionGuard = true; + } + void AssertionHandler::unsetExceptionGuard() { + assert( m_inExceptionGuard == true ); + m_inExceptionGuard = false; + } + + // 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 ) { + handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); + } + +} // namespace Catch +// end catch_assertionhandler.cpp +// start catch_assertionresult.cpp + +namespace Catch { + + std::string AssertionResultData::reconstructExpression() const { + + if( reconstructedExpression.empty() ) { + if( lazyExpression ) { + // !TBD Use stringstream for now, but rework above to pass stream in + std::ostringstream oss; + oss << lazyExpression; + reconstructedExpression = oss.str(); + } + } + return reconstructedExpression; + } + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return m_info.capturedExpression[0] != 0; + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if (isFalseTest(m_info.resultDisposition)) + return '!' + std::string(m_info.capturedExpression); + else + return m_info.capturedExpression; + } + + std::string AssertionResult::getExpressionInMacro() const { + std::string expr; + if( m_info.macroName[0] == 0 ) + expr = m_info.capturedExpression; + else { + expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); + expr += m_info.macroName; + expr += "( "; + expr += m_info.capturedExpression; + expr += " )"; + } + return expr; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + std::string expr = m_resultData.reconstructExpression(); + return expr.empty() + ? getExpression() + : expr; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch +// end catch_assertionresult.cpp +// start catch_benchmark.cpp + +namespace Catch { + + auto BenchmarkLooper::getResolution() -> uint64_t { + return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); + } + + void BenchmarkLooper::reportStart() { + getResultCapture().benchmarkStarting( { m_name } ); + } + auto BenchmarkLooper::needsMoreIterations() -> bool { + auto elapsed = m_timer.getElapsedNanoseconds(); + + // Exponentially increasing iterations until we're confident in our timer resolution + if( elapsed < m_resolution ) { + m_iterationsToRun *= 10; + return true; + } + + getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); + return false; + } + +} // end namespace Catch +// end catch_benchmark.cpp +// start catch_capture_matchers.cpp + +namespace Catch { + + using StringMatcher = Matchers::Impl::MatcherBase; + + // This is the general overload that takes a any string matcher + // There is another overload, in catch_assertinhandler.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 ) { + MatchExpr expr( Catch::translateActiveException(), matcher, matcherString ); + handler.handle( expr ); + } + +} // namespace Catch +// end catch_capture_matchers.cpp +// start catch_commandline.cpp + +#include +#include + +namespace Catch { + + clara::Parser makeCommandLineParser( ConfigData& config ) { + + using namespace clara; + + auto const setWarning = [&]( std::string const& warning ) { + if( warning != "NoAssertions" ) + return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const loadTestNamesFromFile = [&]( std::string const& filename ) { + std::ifstream f( filename.c_str() ); + if( !f.is_open() ) + return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, '#' ) ) { + if( !startsWith( line, '"' ) ) + line = '"' + line + '"'; + config.testsOrTags.push_back( line + ',' ); + } + } + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setTestOrder = [&]( std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setRngSeed = [&]( std::string const& seed ) { + if( seed != "time" ) + return clara::detail::convertInto( seed, config.rngSeed ); + config.rngSeed = static_cast( std::time(nullptr) ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setColourUsage = [&]( std::string const& useColour ) { + auto mode = toLower( useColour ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setWaitForKeypress = [&]( std::string const& keypress ) { + auto keypressLc = toLower( keypress ); + if( keypressLc == "start" ) + config.waitForKeypress = WaitForKeypress::BeforeStart; + else if( keypressLc == "exit" ) + config.waitForKeypress = WaitForKeypress::BeforeExit; + else if( keypressLc == "both" ) + config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; + else + return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setVerbosity = [&]( std::string const& verbosity ) { + auto lcVerbosity = toLower( verbosity ); + if( lcVerbosity == "quiet" ) + config.verbosity = Verbosity::Quiet; + else if( lcVerbosity == "normal" ) + config.verbosity = Verbosity::Normal; + else if( lcVerbosity == "high" ) + config.verbosity = Verbosity::High; + else + return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + + auto cli + = ExeName( config.processName ) + + Help( config.showHelp ) + + Opt( config.listTests ) + ["-l"]["--list-tests"] + ( "list all/matching test cases" ) + + Opt( config.listTags ) + ["-t"]["--list-tags"] + ( "list all/matching tags" ) + + Opt( config.showSuccessfulTests ) + ["-s"]["--success"] + ( "include successful tests in output" ) + + Opt( config.shouldDebugBreak ) + ["-b"]["--break"] + ( "break into debugger on failure" ) + + Opt( config.noThrow ) + ["-e"]["--nothrow"] + ( "skip exception tests" ) + + Opt( config.showInvisibles ) + ["-i"]["--invisibles"] + ( "show invisibles (tabs, newlines)" ) + + Opt( config.outputFilename, "filename" ) + ["-o"]["--out"] + ( "output filename" ) + + Opt( config.reporterNames, "name" ) + ["-r"]["--reporter"] + ( "reporter to use (defaults to console)" ) + + Opt( config.name, "name" ) + ["-n"]["--name"] + ( "suite name" ) + + Opt( [&]( bool ){ config.abortAfter = 1; } ) + ["-a"]["--abort"] + ( "abort at first failure" ) + + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + ["-x"]["--abortx"] + ( "abort after x failures" ) + + Opt( setWarning, "warning name" ) + ["-w"]["--warn"] + ( "enable warnings" ) + + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) + ["-d"]["--durations"] + ( "show test durations" ) + + Opt( loadTestNamesFromFile, "filename" ) + ["-f"]["--input-file"] + ( "load test names to run from a file" ) + + Opt( config.filenamesAsTags ) + ["-#"]["--filenames-as-tags"] + ( "adds a tag for the filename" ) + + Opt( config.sectionsToRun, "section name" ) + ["-c"]["--section"] + ( "specify section to run" ) + + Opt( setVerbosity, "quiet|normal|high" ) + ["-v"]["--verbosity"] + ( "set output verbosity" ) + + Opt( config.listTestNamesOnly ) + ["--list-test-names-only"] + ( "list all/matching test cases names only" ) + + Opt( config.listReporters ) + ["--list-reporters"] + ( "list all reporters" ) + + Opt( setTestOrder, "decl|lex|rand" ) + ["--order"] + ( "test case order (defaults to decl)" ) + + Opt( setRngSeed, "'time'|number" ) + ["--rng-seed"] + ( "set a specific seed for random numbers" ) + + Opt( setColourUsage, "yes|no" ) + ["--use-colour"] + ( "should output be colourised" ) + + Opt( config.libIdentify ) + ["--libidentify"] + ( "report name and version according to libidentify standard" ) + + Opt( setWaitForKeypress, "start|exit|both" ) + ["--wait-for-keypress"] + ( "waits for a keypress before exiting" ) + + Opt( config.benchmarkResolutionMultiple, "multiplier" ) + ["--benchmark-resolution-multiple"] + ( "multiple of clock resolution to run benchmarks" ) + + + Arg( config.testsOrTags, "test name|pattern|tags" ) + ( "which test or tests to use" ); + + return cli; + } + +} // end namespace Catch +// end catch_commandline.cpp +// start catch_common.cpp + +#include +#include + +namespace Catch { + + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + bool SourceLineInfo::empty() const noexcept { + return file[0] == '\0'; + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { + 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)); + } + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << '(' << info.line << ')'; +#else + os << info.file << ':' << info.line; +#endif + return os; + } + + bool isTrue( bool value ){ return value; } + bool alwaysTrue() { return true; } + bool alwaysFalse() { return false; } + + std::string StreamEndStop::operator+() const { + return std::string(); + } + +} +// end catch_common.cpp +// start catch_config.cpp + +namespace Catch { + + Config::Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( auto const& testOrTags : data.testsOrTags ) + parser.parse( testOrTags ); + m_testSpec = parser.testSpec(); + } + } + + std::string const& Config::getFilename() const { + return m_data.outputFilename ; + } + + bool Config::listTests() const { return m_data.listTests; } + bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool Config::listTags() const { return m_data.listTags; } + bool Config::listReporters() const { return m_data.listReporters; } + + std::string Config::getProcessName() const { return m_data.processName; } + + std::vector const& Config::getReporterNames() const { return m_data.reporterNames; } + std::vector const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } + + TestSpec const& Config::testSpec() const { return m_testSpec; } + + bool Config::showHelp() const { return m_data.showHelp; } + + // IConfig interface + bool Config::allowThrows() const { return !m_data.noThrow; } + std::ostream& Config::stream() const { return m_stream->stream(); } + std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + bool Config::warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } + RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } + unsigned int Config::rngSeed() const { return m_data.rngSeed; } + int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; } + UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } + bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } + int Config::abortAfter() const { return m_data.abortAfter; } + bool Config::showInvisibles() const { return m_data.showInvisibles; } + Verbosity Config::verbosity() const { return m_data.verbosity; } + + IStream const* Config::openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" ); + } + else + return new FileStream( m_data.outputFilename ); + } + +} // end namespace Catch +// end catch_config.cpp +// start catch_console_colour.cpp + +// start catch_errno_guard.h + +namespace Catch { + + class ErrnoGuard { + public: + ErrnoGuard(); + ~ErrnoGuard(); + private: + int m_oldErrno; + }; + +} + +// end catch_errno_guard.h +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() = default; + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) override { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + IConfigPtr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = UseColour::Yes; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) override { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0;34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + IColourImpl* platformColourInstance() { + ErrnoGuard guard; + IConfigPtr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = isatty(STDOUT_FILENO) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) { use( _colourCode ); } + Colour::Colour( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + } + Colour& Colour::operator=( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + return *this; + } + + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + + std::ostream& operator << ( std::ostream& os, Colour const& ) { + return os; + } + +} // end namespace Catch +// end catch_console_colour.cpp +// start catch_context.cpp + +namespace Catch { + + class Context : public IMutableContext, NonCopyable { + + public: // IContext + virtual IResultCapture* getResultCapture() override { + return m_resultCapture; + } + virtual IRunner* getRunner() override { + return m_runner; + } + + virtual IConfigPtr getConfig() const override { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) override { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) override { + m_runner = runner; + } + virtual void setConfig( IConfigPtr const& config ) override { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IConfigPtr m_config; + IRunner* m_runner = nullptr; + IResultCapture* m_resultCapture = nullptr; + }; + + namespace { + Context* currentContext = nullptr; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + void cleanUpContext() { + delete currentContext; + currentContext = nullptr; + } +} +// end catch_context.cpp +// start catch_debugger.cpp + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(CATCH_PLATFORM_LINUX) + #include + #include + + namespace Catch{ + // The standard POSIX way of detecting a debugger is to attempt to + // ptrace() the process, but this needs to be done from a child and not + // this process itself to still allow attaching to this process later + // if wanted, so is rather heavy. Under Linux we have the PID of the + // "debugger" (which doesn't need to be gdb, of course, it could also + // be strace, for example) in /proc/$PID/status, so just get it from + // there instead. + bool isDebuggerActive(){ + // Libstdc++ has a bug, where std::ifstream sets errno to 0 + // This way our users can properly assert over errno values + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for( std::string line; std::getline(in, line); ) { + static const int PREFIX_LEN = 11; + if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { + // We're traced if the PID is not 0 and no other PID starts + // with 0 digit, so it's enough to check for just a single + // character. + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + + return false; + } + } // namespace Catch +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform +// end catch_debugger.cpp +// start catch_decomposer.cpp + +namespace Catch { + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) { + if( lhs.size() + rhs.size() < 40 && + lhs.find('\n') == std::string::npos && + rhs.find('\n') == std::string::npos ) + os << lhs << " " << op << " " << rhs; + else + os << lhs << "\n" << op << "\n" << rhs; + } +} +// end catch_decomposer.cpp +// start catch_errno_guard.cpp + +#include + +namespace Catch { + ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} + ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } +} +// end catch_errno_guard.cpp +// start catch_exception_translator_registry.cpp + +// start catch_exception_translator_registry.h + +#include +#include +#include + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry(); + virtual void registerTranslator( const IExceptionTranslator* translator ); + virtual std::string translateActiveException() const override; + std::string tryTranslators() const; + + private: + std::vector> m_translators; + }; +} + +// end catch_exception_translator_registry.h +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { + } + + void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( std::unique_ptr( translator ) ); + } + + std::string ExceptionTranslatorRegistry::translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::toString( [exception description] ); + } +#else + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string ExceptionTranslatorRegistry::tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } +} +// end catch_exception_translator_registry.cpp +// start catch_fatal_condition.cpp + +namespace Catch { + + // Report the error condition + void reportFatal( std::string const& message ) { + IContext& context = Catch::getCurrentContext(); + IResultCapture* resultCapture = context.getResultCapture(); + resultCapture->handleFatalErrorCondition( message ); + } + +} // namespace Catch + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + void FatalConditionHandler::reset() {} +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + +namespace Catch { + struct SignalDefs { DWORD id; const char* name; }; + + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + SignalDefs signalDefs[] = { + { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, + { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, + { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, + { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, + }; + + LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + } + } + // If its not an exception we care about, pass it along. + // This stops us from eating debugger breaks etc. + return EXCEPTION_CONTINUE_SEARCH; + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + // 32k seems enough for Catch to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + exceptionHandlerHandle = nullptr; + // Register as first handler in current chain + exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + } + + void FatalConditionHandler::reset() { + if (isSet) { + // Unregister handler and restore the old guarantee + RemoveVectoredExceptionHandler(exceptionHandlerHandle); + SetThreadStackGuarantee(&guaranteeSize); + exceptionHandlerHandle = nullptr; + isSet = false; + } + } + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + +bool FatalConditionHandler::isSet = false; +ULONG FatalConditionHandler::guaranteeSize = 0; +PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; + +} // namespace Catch + +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + void FatalConditionHandler::reset() {} +} + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct SignalDefs { + int id; + const char* name; + }; + SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + void FatalConditionHandler::handleSignal( int sig ) { + std::string name = ""; + for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { + SignalDefs &def = signalDefs[i]; + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise( sig ); + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = SIGSTKSZ; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = { }; + + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + + void FatalConditionHandler::reset() { + if( isSet ) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows +// end catch_fatal_condition.cpp +// start catch_interfaces_reporter.cpp + +// start catch_reporter_multi.h + +namespace Catch { + + class MultipleReporters : public IStreamingReporter { + using Reporters = std::vector; + Reporters m_reporters; + + public: + void add( IStreamingReporterPtr&& reporter ); + + public: // IStreamingReporter + + ReporterPreferences getPreferences() const override; + + void noMatchingTestCases( std::string const& spec ) override; + + static std::set getSupportedVerbosities(); + + void testRunStarting( TestRunInfo const& testRunInfo ) override; + void testGroupStarting( GroupInfo const& groupInfo ) override; + void testCaseStarting( TestCaseInfo const& testInfo ) override; + void sectionStarting( SectionInfo const& sectionInfo ) override; + void assertionStarting( AssertionInfo const& assertionInfo ) override; + + // The return value indicates if the messages buffer should be cleared: + bool assertionEnded( AssertionStats const& assertionStats ) override; + void sectionEnded( SectionStats const& sectionStats ) override; + void testCaseEnded( TestCaseStats const& testCaseStats ) override; + void testGroupEnded( TestGroupStats const& testGroupStats ) override; + void testRunEnded( TestRunStats const& testRunStats ) override; + + void skipTest( TestCaseInfo const& testInfo ) override; + bool isMulti() const override; + + }; + +} // end namespace Catch +// end catch_reporter_multi.h +namespace Catch { + + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& ReporterConfig::stream() const { return *m_stream; } + IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } + + TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} + + GroupInfo::GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + AssertionStats::AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; + + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + + SectionStats::SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + + TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + + TestRunStats::TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + bool IStreamingReporter::isMulti() const { return false; } + + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { + + if( !existingReporter ) { + existingReporter = std::move( additionalReporter ); + return; + } + + MultipleReporters* multi = nullptr; + + if( existingReporter->isMulti() ) { + multi = static_cast( existingReporter.get() ); + } + else { + auto newMulti = std::unique_ptr( new MultipleReporters ); + newMulti->add( std::move( existingReporter ) ); + multi = newMulti.get(); + existingReporter = std::move( newMulti ); + } + multi->add( std::move( additionalReporter ) ); + } + +} // end namespace Catch +// end catch_interfaces_reporter.cpp +// start catch_leak_detector.cpp + +namespace Catch { + +#ifdef CATCH_CONFIG_WINDOWS_CRTDBG +#include + + LeakDetector::LeakDetector() { + int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flag |= _CRTDBG_LEAK_CHECK_DF; + flag |= _CRTDBG_ALLOC_MEM_DF; + _CrtSetDbgFlag(flag); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + // Change this to leaking allocation's number to break there + _CrtSetBreakAlloc(-1); + } + +#else + + LeakDetector::LeakDetector(){} + +#endif + +} +// end catch_leak_detector.cpp +// start catch_list.cpp + +#include +#include +#include + +namespace Catch { + + std::size_t listTests( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCaseInfo : matchedTestCases ) { + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; + if( config.verbosity() >= Verbosity::High ) { + Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; + std::string description = testCaseInfo.description; + if( description.empty() ) + description = "(NO DESCRIPTION)"; + Catch::cout() << Column( description ).indent(4) << std::endl; + } + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; + } + + if( !config.testSpec().hasFilters() ) + Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; + else + Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; + return matchedTestCases.size(); + } + + std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCaseInfo : matchedTestCases ) { + matchedTests++; + if( startsWith( testCaseInfo.name, '#' ) ) + Catch::cout() << '"' << testCaseInfo.name << '"'; + else + Catch::cout() << testCaseInfo.name; + if ( config.verbosity() >= Verbosity::High ) + Catch::cout() << "\t@" << testCaseInfo.lineInfo; + Catch::cout() << std::endl; + } + return matchedTests; + } + + void TagInfo::add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + + std::string TagInfo::all() const { + std::string out; + for( auto const& spelling : spellings ) + out += "[" + spelling + "]"; + return out; + } + + std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCase : matchedTestCases ) { + for( auto const& tagName : testCase.getTestCaseInfo().tags ) { + std::string lcaseTagName = toLower( tagName ); + auto countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( auto const& tagCount : tagCounts ) { + std::ostringstream oss; + oss << " " << std::setw(2) << tagCount.second.count << " "; + auto wrapper = Column( tagCount.second.all() ) + .initialIndent( 0 ) + .indent( oss.str().size() ) + .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); + Catch::cout() << oss.str() << wrapper << '\n'; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; + return tagCounts.size(); + } + + std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + std::size_t maxNameLen = 0; + for( auto const& factoryKvp : factories ) + maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); + + for( auto const& factoryKvp : factories ) { + Catch::cout() + << Column( factoryKvp.first + ":" ) + .indent(2) + .width( 5+maxNameLen ) + + Column( factoryKvp.second->getDescription() ) + .initialIndent(0) + .indent(2) + .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) + << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch +// end catch_list.cpp +// start catch_matchers.cpp + +namespace Catch { +namespace Matchers { + namespace Impl { + + std::string MatcherUntypedBase::toString() const { + if( m_cachedToString.empty() ) + m_cachedToString = describe(); + return m_cachedToString; + } + + } // namespace Impl +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch +// end catch_matchers.cpp +// start catch_matchers_string.cpp + +namespace Catch { +namespace Matchers { + + namespace StdString { + + CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string CasedString::adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + } + std::string CasedString::caseSensitivitySuffix() const { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : std::string(); + } + + StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) + : m_comparator( comparator ), + m_operation( operation ) { + } + + std::string StringMatcherBase::describe() const { + std::string description; + description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + + m_comparator.caseSensitivitySuffix().size()); + description += m_operation; + description += ": \""; + description += m_comparator.m_str; + description += "\""; + description += m_comparator.caseSensitivitySuffix(); + return description; + } + + EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} + + bool EqualsMatcher::match( std::string const& source ) const { + return m_comparator.adjustString( source ) == m_comparator.m_str; + } + + ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} + + bool ContainsMatcher::match( std::string const& source ) const { + return contains( m_comparator.adjustString( source ), m_comparator.m_str ); + } + + StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} + + bool StartsWithMatcher::match( std::string const& source ) const { + return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); + } + + EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} + + bool EndsWithMatcher::match( std::string const& source ) const { + return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); + } + + } // namespace StdString + + StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); + } + StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); + } + StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); + } + StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); + } + +} // namespace Matchers +} // namespace Catch +// end catch_matchers_string.cpp +// start catch_message.cpp + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + bool MessageInfo::operator==( MessageInfo const& other ) const { + return sequence == other.sequence; + } + + bool MessageInfo::operator<( MessageInfo const& other ) const { + return sequence < other.sequence; + } + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + Catch::MessageBuilder::MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + :m_info(macroName, lineInfo, type) {} + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + + ScopedMessage::~ScopedMessage() { + if ( !std::uncaught_exception() ){ + getResultCapture().popScopedMessage(m_info); + } + } + +} // end namespace Catch +// end catch_message.cpp +// start catch_notimplemented_exception.cpp + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const noexcept { + return m_what.c_str(); + } + +} // end namespace Catch +// end catch_notimplemented_exception.cpp +// start catch_registry_hub.cpp + +// start catch_test_case_registry_impl.hpp + +#include +#include +#include +#include + +namespace Catch { + + class TestCase; + struct IConfig; + + struct RandomNumberGenerator { + using result_type = std::ptrdiff_t; + + result_type operator()( result_type n ) const; + + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return 1000000; } + result_type operator()() const; + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; + std::shuffle( vector.begin(), vector.end(), rng ); + } + }; + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + + void enforceNoDuplicateTestCases( std::vector const& functions ); + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + + class TestRegistry : public ITestCaseRegistry { + public: + virtual ~TestRegistry() = default; + + virtual void registerTest( TestCase const& testCase ); + + std::vector const& getAllTests() const override; + std::vector const& getAllTestsSorted( IConfig const& config ) const override; + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; + mutable std::vector m_sortedFunctions; + size_t m_unnamedCount = 0; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class TestInvokerAsFunction : public ITestInvoker { + void(*m_testAsFunction)(); + public: + TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; + + void invoke() const override; + }; + + std::string extractClassName( std::string const& classOrQualifiedMethodName ); + + /////////////////////////////////////////////////////////////////////////// + +} // end namespace Catch + +// end catch_test_case_registry_impl.hpp +// start catch_reporter_registry.hpp + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + ~ReporterRegistry() override {} + + IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return nullptr; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { + m_factories.insert( { name, factory } ); + } + void registerListener( IReporterFactoryPtr const& factory ) { + m_listeners.push_back( factory ); + } + + FactoryMap const& getFactories() const override { + return m_factories; + } + Listeners const& getListeners() const override { + return m_listeners; + } + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// end catch_reporter_registry.hpp +// start catch_tag_alias_registry.h + +// start catch_tag_alias.h + +#include + +namespace Catch { + + struct TagAlias { + TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); + + std::string tag; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// end catch_tag_alias.h +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + ~TagAliasRegistry() override; + TagAlias const* find( std::string const& alias ) const override; + std::string expandAliases( std::string const& unexpandedTestSpec ) const override; + void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +// end catch_tag_alias_registry.h +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub, + private NonCopyable { + + public: // IRegistryHub + RegistryHub() { + } + IReporterRegistry const& getReporterRegistry() const override { + return m_reporterRegistry; + } + ITestCaseRegistry const& getTestCaseRegistry() const override { + return m_testCaseRegistry; + } + IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { + return m_exceptionTranslatorRegistry; + } + ITagAliasRegistry const& getTagAliasRegistry() const override { + return m_tagAliasRegistry; + } + StartupExceptionRegistry const& getStartupExceptionRegistry() const override { + return m_exceptionRegistry; + } + + public: // IMutableRegistryHub + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { + m_reporterRegistry.registerReporter( name, factory ); + } + void registerListener( IReporterFactoryPtr const& factory ) override { + m_reporterRegistry.registerListener( factory ); + } + void registerTest( TestCase const& testInfo ) override { + m_testCaseRegistry.registerTest( testInfo ); + } + void registerTranslator( const IExceptionTranslator* translator ) override { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { + m_tagAliasRegistry.add( alias, tag, lineInfo ); + } + void registerStartupException() noexcept override { + m_exceptionRegistry.add(std::current_exception()); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + TagAliasRegistry m_tagAliasRegistry; + StartupExceptionRegistry m_exceptionRegistry; + }; + + // Single, global, instance + RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = nullptr; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = nullptr; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch +// end catch_registry_hub.cpp +// start catch_result_type.cpp + +namespace Catch { + + bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch +// end catch_result_type.cpp +// start catch_run_context.cpp + +#include +#include + +namespace Catch { + + StreamRedirect::StreamRedirect(std::ostream& stream, std::string& targetString) + : m_stream(stream), + m_prevBuf(stream.rdbuf()), + m_targetString(targetString) { + stream.rdbuf(m_oss.rdbuf()); + } + + StreamRedirect::~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf(m_prevBuf); + } + + StdErrRedirect::StdErrRedirect(std::string & targetString) + :m_cerrBuf(cerr().rdbuf()), m_clogBuf(clog().rdbuf()), + m_targetString(targetString) { + cerr().rdbuf(m_oss.rdbuf()); + clog().rdbuf(m_oss.rdbuf()); + } + + StdErrRedirect::~StdErrRedirect() { + m_targetString += m_oss.str(); + cerr().rdbuf(m_cerrBuf); + clog().rdbuf(m_clogBuf); + } + + RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) + : m_runInfo(_config->name()), + m_context(getCurrentMutableContext()), + m_config(_config), + m_reporter(std::move(reporter)), + m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal } + { + m_context.setRunner(this); + m_context.setConfig(m_config); + m_context.setResultCapture(this); + m_reporter->testRunStarting(m_runInfo); + } + + RunContext::~RunContext() { + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); + } + + void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { + m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); + } + + void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { + m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); + } + + Totals RunContext::runTest(TestCase const& testCase) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting(testInfo); + + m_activeTestCase = &testCase; + + ITracker& rootTracker = m_trackerContext.startRun(); + assert(rootTracker.isSectionTracker()); + static_cast(rootTracker).addInitialFilters(m_config->getSectionsToRun()); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); + runCurrentTest(redirectedCout, redirectedCerr); + } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); + + Totals deltaTotals = m_totals.delta(prevTotals); + if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting())); + + m_activeTestCase = nullptr; + m_testCaseTracker = nullptr; + + return deltaTotals; + } + + IConfigPtr RunContext::config() const { + return m_config; + } + + IStreamingReporter& RunContext::reporter() const { + return *m_reporter; + } + + void RunContext::assertionStarting(AssertionInfo const& info) { + m_reporter->assertionStarting( info ); + } + void RunContext::assertionEnded(AssertionResult const & result) { + if (result.getResultType() == ResultWas::Ok) { + m_totals.assertions.passed++; + } else if (!result.isOk()) { + m_totals.assertions.failed++; + } + + // We have no use for the return value (whether messages should be cleared), because messages were made scoped + // and should be let to clear themselves out. + static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); + + // Reset working state + m_lastAssertionInfo = { "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition }; + m_lastResult = result; + } + + bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { + ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); + if (!sectionTracker.isOpen()) + return false; + m_activeSections.push_back(§ionTracker); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting(sectionInfo); + + assertions = m_totals.assertions; + + return true; + } + + bool RunContext::testForMissingAssertions(Counts& assertions) { + if (assertions.total() != 0) + return false; + if (!m_config->warnAboutMissingAssertions()) + return false; + if (m_trackerContext.currentTracker().hasChildren()) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + void RunContext::sectionEnded(SectionEndInfo const & endInfo) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + if (!m_activeSections.empty()) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); + m_messages.clear(); + } + + void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { + if (m_unfinishedSections.empty()) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back(endInfo); + } + void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { + m_reporter->benchmarkStarting( info ); + } + void RunContext::benchmarkEnded( BenchmarkStats const& stats ) { + m_reporter->benchmarkEnded( stats ); + } + + void RunContext::pushScopedMessage(MessageInfo const & message) { + m_messages.push_back(message); + } + + void RunContext::popScopedMessage(MessageInfo const & message) { + m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); + } + + std::string RunContext::getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : std::string(); + } + + const AssertionResult * RunContext::getLastResult() const { + return &(*m_lastResult); + } + + void RunContext::exceptionEarlyReported() { + m_shouldReportUnexpected = false; + } + + void RunContext::handleFatalErrorCondition(std::string const & message) { + // Don't rebuild the result -- the stringification itself can cause more fatal errors + // Instead, fake a result data. + AssertionResultData tempResult( ResultWas::Unknown, { false } ); + tempResult.resultType = ResultWas::FatalErrorCondition; + tempResult.message = message; + AssertionResult result(m_lastAssertionInfo, tempResult); + + getResultCapture().assertionEnded(result); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); + m_reporter->sectionEnded(testCaseSectionStats); + + TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + deltaTotals.assertions.failed = 1; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + std::string(), + std::string(), + false)); + m_totals.testCases.failed++; + testGroupEnded(std::string(), m_totals, 1, 1); + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); + } + + bool RunContext::lastAssertionPassed() { + return m_totals.assertions.passed == (m_prevPassed + 1); + } + + void RunContext::assertionPassed() { + ++m_totals.assertions.passed; + m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; + m_lastAssertionInfo.macroName = ""; + } + + void RunContext::assertionRun() { + m_prevPassed = m_totals.assertions.passed; + } + + bool RunContext::aborting() const { + return m_totals.assertions.failed == static_cast(m_config->abortAfter()); + } + + void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); + m_reporter->sectionStarting(testCaseSection); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + m_shouldReportUnexpected = true; + try { + m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal }; + + seedRng(*m_config); + + Timer timer; + timer.start(); + if (m_reporter->getPreferences().shouldRedirectStdOut) { + StreamRedirect coutRedir(cout(), redirectedCout); + StdErrRedirect errRedir(redirectedCerr); + invokeActiveTestCase(); + } else { + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } catch (TestFailureException&) { + // This just means the test was aborted due to failure + } catch (...) { + // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions + // are reported without translation at the point of origin. + if (m_shouldReportUnexpected) { + AssertionHandler + ( m_lastAssertionInfo.macroName, + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression, + m_lastAssertionInfo.resultDisposition ).useActiveException(); + } + } + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + if (testCaseInfo.okToFail()) { + std::swap(assertions.failedButOk, assertions.failed); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); + m_reporter->sectionEnded(testCaseSectionStats); + } + + void RunContext::invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + void RunContext::handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for (auto it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it) + sectionEnded(*it); + m_unfinishedSections.clear(); + } + + IResultCapture& getResultCapture() { + if (IResultCapture* capture = getCurrentContext().getResultCapture()) + return *capture; + else + CATCH_INTERNAL_ERROR("No result capture instance"); + } +} +// end catch_run_context.cpp +// start catch_section.cpp + +namespace Catch { + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 +#endif + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch +// end catch_section.cpp +// start catch_section_info.cpp + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + +} // end namespace Catch +// end catch_section_info.cpp +// start catch_startup_exception_registry.cpp + +namespace Catch { + void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { + try { + m_exceptions.push_back(exception); + } + catch(...) { + // If we run out of memory during start-up there's really not a lot more we can do about it + std::terminate(); + } + } + + std::vector const& StartupExceptionRegistry::getExceptions() const noexcept { + return m_exceptions; + } + +} // end namespace Catch +// end catch_startup_exception_registry.cpp +// start catch_stream.cpp + +#include +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() noexcept { + StreamBufImpl::sync(); + } + + private: + int overflow( int c ) override { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() override { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + + std::ostream& CoutStream::stream() const { + return m_os; + } + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { + return std::cout; + } + std::ostream& cerr() { + return std::cerr; + } + std::ostream& clog() { + return std::clog; + } +#endif +} +// end catch_stream.cpp +// start catch_string_manip.cpp + +#include +#include +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); + } + bool startsWith( std::string const& s, char prefix ) { + return !s.empty() && s[0] == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); + } + bool endsWith( std::string const& s, char suffix ) { + return !s.empty() && s[s.size()-1] == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << 's'; + return os; + } + +} +// end catch_string_manip.cpp +// start catch_stringref.cpp + +#include +#include +#include + +namespace Catch { + + auto getEmptyStringRef() -> StringRef { + static StringRef s_emptyStringRef(""); + return s_emptyStringRef; + } + + StringRef::StringRef() noexcept + : StringRef( getEmptyStringRef() ) + {} + + StringRef::StringRef( StringRef const& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ) + {} + + StringRef::StringRef( StringRef&& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ), + m_data( other.m_data ) + { + other.m_data = nullptr; + } + + StringRef::StringRef( char const* rawChars ) noexcept + : m_start( rawChars ), + m_size( static_cast( std::strlen( rawChars ) ) ) + { + assert( rawChars != nullptr ); + } + + StringRef::StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + { + size_type rawSize = rawChars == nullptr ? 0 : static_cast( std::strlen( rawChars ) ); + if( rawSize < size ) + m_size = rawSize; + } + + StringRef::StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + StringRef::~StringRef() noexcept { + delete[] m_data; + } + + auto StringRef::operator = ( StringRef other ) noexcept -> StringRef& { + swap( other ); + return *this; + } + StringRef::operator std::string() const { + return std::string( m_start, m_size ); + } + + void StringRef::swap( StringRef& other ) noexcept { + std::swap( m_start, other.m_start ); + std::swap( m_size, other.m_size ); + std::swap( m_data, other.m_data ); + } + + auto StringRef::c_str() const -> char const* { + if( isSubstring() ) + const_cast( this )->takeOwnership(); + return m_start; + } + auto StringRef::data() const noexcept -> char const* { + return m_start; + } + + auto StringRef::isOwned() const noexcept -> bool { + return m_data != nullptr; + } + auto StringRef::isSubstring() const noexcept -> bool { + return m_start[m_size] != '\0'; + } + + void StringRef::takeOwnership() { + if( !isOwned() ) { + m_data = new char[m_size+1]; + memcpy( m_data, m_start, m_size ); + m_data[m_size] = '\0'; + m_start = m_data; + } + } + auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { + if( start < m_size ) + return StringRef( m_start+start, size ); + else + return StringRef(); + } + auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { + return + size() == other.size() && + (std::strncmp( m_start, other.m_start, size() ) == 0); + } + auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { + return !operator==( other ); + } + + auto StringRef::operator[](size_type index) const noexcept -> char { + return m_start[index]; + } + + auto StringRef::empty() const noexcept -> bool { + return m_size == 0; + } + + auto StringRef::size() const noexcept -> size_type { + return m_size; + } + auto StringRef::numberOfCharacters() const noexcept -> size_type { + size_type noChars = m_size; + // Make adjustments for uft encodings + for( size_type i=0; i < m_size; ++i ) { + char c = m_start[i]; + if( ( c & 0b11000000 ) == 0b11000000 ) { + if( ( c & 0b11100000 ) == 0b11000000 ) + noChars--; + else if( ( c & 0b11110000 ) == 0b11100000 ) + noChars-=2; + else if( ( c & 0b11111000 ) == 0b11110000 ) + noChars-=3; + } + } + return noChars; + } + + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { + std::string str; + str.reserve( lhs.size() + rhs.size() ); + str += lhs; + str += rhs; + return str; + } + auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); + } + auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); + } + + auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { + return os << str.c_str(); + } + +} // namespace Catch +// end catch_stringref.cpp +// start catch_tag_alias.cpp + +namespace Catch { + TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} +} +// end catch_tag_alias.cpp +// start catch_tag_alias_autoregistrar.cpp + +namespace Catch { + + RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { + try { + getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(); + } + } + +} +// end catch_tag_alias_autoregistrar.cpp +// start catch_tag_alias_registry.cpp + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { + auto it = m_registry.find( alias ); + if( it != m_registry.end() ) + return &(it->second); + else + return nullptr; + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( auto const& registryKvp : m_registry ) { + std::size_t pos = expandedTestSpec.find( registryKvp.first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + registryKvp.second.tag + + expandedTestSpec.substr( pos + registryKvp.first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { + CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), + "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); + + CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, + "error: tag alias, '" << alias << "' already registered.\n" + << "\tFirst seen at: " << find(alias)->lineInfo << "\n" + << "\tRedefined at: " << lineInfo ); + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + + ITagAliasRegistry const& ITagAliasRegistry::get() { + return getRegistryHub().getTagAliasRegistry(); + } + +} // end namespace Catch +// end catch_tag_alias_registry.cpp +// start catch_test_case_info.cpp + +#include +#include +#include + +namespace Catch { + + TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, '.' ) || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else if( tag == "!nonportable" ) + return TestCaseInfo::NonPortable; + else if( tag == "!benchmark" ) + return static_cast( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); + else + return TestCaseInfo::None; + } + bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); + } + void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + CATCH_ENFORCE( !isReservedTag(tag), + "Tag name: [" << tag << "] is not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n" + << _lineInfo ); + } + + TestCase makeTestCase( ITestInvoker* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::vector tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( ( prop & TestCaseInfo::IsHidden ) != 0 ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.push_back( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.push_back( "hide" ); + tags.push_back( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::vector tags ) { + std::sort(begin(tags), end(tags)); + tags.erase(std::unique(begin(tags), end(tags)), end(tags)); + testCaseInfo.lcaseTags.clear(); + + for( auto const& tag : tags ) { + std::string lcaseTag = toLower( tag ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.push_back( lcaseTag ); + } + testCaseInfo.tags = std::move(tags); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::vector const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + std::string TestCaseInfo::tagsAsString() const { + std::string ret; + // '[' and ']' per tag + size_t full_size = 2 * tags.size(); + for (const auto& tag : tags) { + full_size += tag.size(); + } + ret.reserve(full_size); + for (const auto& tag : tags) { + ret.push_back('['); + ret.append(tag); + ret.push_back(']'); + } + + return ret; + } + + TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch +// end catch_test_case_info.cpp +// start catch_test_case_registry_impl.cpp + +#include + +namespace Catch { + + RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { return std::rand() % n; } + RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { return std::rand() % max(); } + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end() ); + break; + case RunTests::InRandomOrder: + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( auto const& function : functions ) { + auto prev = seenFunctions.insert( function ); + CATCH_ENFORCE( prev.second, + "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( auto const& testCase : testCases ) + if( matchTest( testCase, testSpec, config ) ) + filtered.push_back( testCase ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + void TestRegistry::registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name.empty() ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + m_functions.push_back( testCase ); + } + + std::vector const& TestRegistry::getAllTests() const { + return m_functions; + } + std::vector const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + /////////////////////////////////////////////////////////////////////////// + TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} + + void TestInvokerAsFunction::invoke() const { + m_testAsFunction(); + } + + std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, '&' ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + +} // end namespace Catch +// end catch_test_case_registry_impl.cpp +// start catch_test_case_tracker.cpp + +#include +#include +#include +#include + +CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS + +namespace Catch { +namespace TestCaseTracking { + + NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) + : name( _name ), + location( _location ) + {} + + TrackerContext& TrackerContext::instance() { + static TrackerContext s_instance; + return s_instance; + } + + ITracker& TrackerContext::startRun() { + m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); + m_currentTracker = nullptr; + m_runState = Executing; + return *m_rootTracker; + } + + void TrackerContext::endRun() { + m_rootTracker.reset(); + m_currentTracker = nullptr; + m_runState = NotStarted; + } + + void TrackerContext::startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void TrackerContext::completeCycle() { + m_runState = CompletedCycle; + } + + bool TrackerContext::completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& TrackerContext::currentTracker() { + return *m_currentTracker; + } + void TrackerContext::setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + + TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} + bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const { + return + tracker->nameAndLocation().name == m_nameAndLocation.name && + tracker->nameAndLocation().location == m_nameAndLocation.location; + } + + TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : m_nameAndLocation( nameAndLocation ), + m_ctx( ctx ), + m_parent( parent ) + {} + + NameAndLocation const& TrackerBase::nameAndLocation() const { + return m_nameAndLocation; + } + bool TrackerBase::isComplete() const { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + bool TrackerBase::isSuccessfullyCompleted() const { + return m_runState == CompletedSuccessfully; + } + bool TrackerBase::isOpen() const { + return m_runState != NotStarted && !isComplete(); + } + bool TrackerBase::hasChildren() const { + return !m_children.empty(); + } + + void TrackerBase::addChild( ITrackerPtr const& child ) { + m_children.push_back( child ); + } + + ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { + auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); + return( it != m_children.end() ) + ? *it + : nullptr; + } + ITracker& TrackerBase::parent() { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + void TrackerBase::openChild() { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + bool TrackerBase::isSectionTracker() const { return false; } + bool TrackerBase::isIndexTracker() const { return false; } + + void TrackerBase::open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + void TrackerBase::close() { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NeedsAnotherRun: + break; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + case NotStarted: + case CompletedSuccessfully: + case Failed: + CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); + + default: + CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); + } + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::fail() { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::markAsNeedingAnotherRun() { + m_runState = NeedsAnotherRun; + } + + void TrackerBase::moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void TrackerBase::moveToThis() { + m_ctx.setCurrentTracker( this ); + } + + SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( nameAndLocation, ctx, parent ) + { + if( parent ) { + while( !parent->isSectionTracker() ) + parent = &parent->parent(); + + SectionTracker& parentSection = static_cast( *parent ); + addNextFilters( parentSection.m_filters ); + } + } + + bool SectionTracker::isSectionTracker() const { return true; } + + SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { + std::shared_ptr section; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = std::static_pointer_cast( childTracker ); + } + else { + section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() ) + section->tryOpen(); + return *section; + } + + void SectionTracker::tryOpen() { + if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) + open(); + } + + void SectionTracker::addInitialFilters( std::vector const& filters ) { + if( !filters.empty() ) { + m_filters.push_back(""); // Root - should never be consulted + m_filters.push_back(""); // Test Case - not a section filter + m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); + } + } + void SectionTracker::addNextFilters( std::vector const& filters ) { + if( filters.size() > 1 ) + m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); + } + + IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_size( size ) + {} + + bool IndexTracker::isIndexTracker() const { return true; } + + IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { + std::shared_ptr tracker; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = std::static_pointer_cast( childTracker ); + } + else { + tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int IndexTracker::index() const { return m_index; } + + void IndexTracker::moveNext() { + m_index++; + m_children.clear(); + } + + void IndexTracker::close() { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +// end catch_test_case_tracker.cpp +// start catch_test_registry.cpp + +namespace Catch { + + auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); + } + + NameAndTags::NameAndTags( StringRef name_ , StringRef tags_ ) noexcept : name( name_ ), tags( tags_ ) {} + + AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept { + try { + getMutableRegistryHub() + .registerTest( + makeTestCase( + invoker, + extractClassName( classOrMethod ), + nameAndTags.name, + nameAndTags.tags, + lineInfo)); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(); + } + } +} +// end catch_test_registry.cpp +// start catch_test_spec.cpp + +#include +#include +#include +#include + +namespace Catch { + + TestSpec::NamePattern::NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + + TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { + return std::find(begin(testCase.lcaseTags), + end(testCase.lcaseTags), + m_tag) != end(testCase.lcaseTags); + } + + TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + + bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( auto const& pattern : m_patterns ) { + if( !pattern->matches( testCase ) ) + return false; + } + return true; + } + + bool TestSpec::hasFilters() const { + return !m_filters.empty(); + } + bool TestSpec::matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( auto const& filter : m_filters ) + if( filter.matches( testCase ) ) + return true; + return false; + } +} +// end catch_test_spec.cpp +// start catch_test_spec_parser.cpp + +namespace Catch { + + TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& TestSpecParser::parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + m_escapeChars.clear(); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec TestSpecParser::testSpec() { + addFilter(); + return m_testSpec; + } + + void TestSpecParser::visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + case '\\': return escape(); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + else if( c == '\\' ) + escape(); + } + else if( m_mode == EscapedName ) + m_mode = Name; + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + void TestSpecParser::escape() { + if( m_mode == None ) + m_start = m_pos; + m_mode = EscapedName; + m_escapeChars.push_back( m_pos ); + } + std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + + void TestSpecParser::addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + + TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch +// end catch_test_spec_parser.cpp +// start catch_timer.cpp + +#include + +namespace Catch { + + auto getCurrentNanosecondsSinceEpoch() -> uint64_t { + return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); + } + + auto estimateClockResolution() -> uint64_t { + uint64_t sum = 0; + static const uint64_t iterations = 1000000; + + for( size_t i = 0; i < iterations; ++i ) { + + uint64_t ticks; + uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); + do { + ticks = getCurrentNanosecondsSinceEpoch(); + } + while( ticks == baseTicks ); + + auto delta = ticks - baseTicks; + sum += delta; + } + + // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers + // - and potentially do more iterations if there's a high variance. + return sum/iterations; + } + auto getEstimatedClockResolution() -> uint64_t { + static auto s_resolution = estimateClockResolution(); + return s_resolution; + } + + void Timer::start() { + m_nanoseconds = getCurrentNanosecondsSinceEpoch(); + } + auto Timer::getElapsedNanoseconds() const -> unsigned int { + return static_cast(getCurrentNanosecondsSinceEpoch() - m_nanoseconds); + } + auto Timer::getElapsedMicroseconds() const -> unsigned int { + return static_cast(getElapsedNanoseconds()/1000); + } + auto Timer::getElapsedMilliseconds() const -> unsigned int { + return static_cast(getElapsedMicroseconds()/1000); + } + auto Timer::getElapsedSeconds() const -> double { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch +// end catch_timer.cpp +// start catch_tostring.cpp + +#include + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +//// ======================================================= //// +// +// Out-of-line defs for full specialization of StringMaker +// +//// ======================================================= //// + +std::string StringMaker::convert(const std::string& str) { + if (!getCurrentContext().getConfig()->showInvisibles()) { + return '"' + str + '"'; + } + + std::string s("\""); + for (char c : str) { + switch (c) { + case '\n': + s.append("\\n"); + break; + case '\t': + s.append("\\t"); + break; + default: + s.push_back(c); + break; + } + } + s.append("\""); + return s; +} + +std::string StringMaker::convert(const std::wstring& wstr) { + std::string s; + s.reserve(wstr.size()); + for (auto c : wstr) { + s += (c <= 0xff) ? static_cast(c) : '?'; + } + return ::Catch::Detail::stringify(s); +} + +std::string StringMaker::convert(char const* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(char* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(wchar_t const * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(wchar_t * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} + +std::string StringMaker::convert(int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(long long value) { + std::ostringstream oss; + oss << value; + if (value > Detail::hexThreshold) { + oss << " (0x" << std::hex << value << ')'; + } + return oss.str(); +} + +std::string StringMaker::convert(unsigned int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(unsigned long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(unsigned long long value) { + std::ostringstream oss; + oss << value; + if (value > Detail::hexThreshold) { + oss << " (0x" << std::hex << value << ')'; + } + return oss.str(); +} + +std::string StringMaker::convert(bool b) { + return b ? "true" : "false"; +} + +std::string StringMaker::convert(char value) { + if (value == '\r') { + return "'\\r'"; + } else if (value == '\f') { + return "'\\f'"; + } else if (value == '\n') { + return "'\\n'"; + } else if (value == '\t') { + return "'\\t'"; + } else if ('\0' <= value && value < ' ') { + return ::Catch::Detail::stringify(static_cast(value)); + } else { + char chstr[] = "' '"; + chstr[1] = value; + return chstr; + } +} +std::string StringMaker::convert(signed char c) { + return ::Catch::Detail::stringify(static_cast(c)); +} +std::string StringMaker::convert(unsigned char c) { + return ::Catch::Detail::stringify(static_cast(c)); +} + +std::string StringMaker::convert(std::nullptr_t) { + return "nullptr"; +} + +std::string StringMaker::convert(float value) { + return fpToString(value, 5) + 'f'; +} +std::string StringMaker::convert(double value) { + return fpToString(value, 10); +} + +#ifdef __OBJC__ +std::string StringMaker::convert(NSString* nsstring) { + if (!nsstring) + return "nil"; + return "@" + toString([nsstring UTF8String]); +} +std::string StringMaker::convert(NSString* CATCH_ARC_STRONG nsstring) { + if (!nsstring) + return "nil"; + return "@" + toString([nsstring UTF8String]); +} +std::string StringMaker::convert(NSObject* nsObject) { + return ::Catch::Detail::stringify([nsObject description]); +} +#endif + +} // end namespace Catch +// end catch_tostring.cpp +// start catch_totals.cpp + +namespace Catch { + + Counts Counts::operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + + Counts& Counts::operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t Counts::total() const { + return passed + failed + failedButOk; + } + bool Counts::allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool Counts::allOk() const { + return failed == 0; + } + + Totals Totals::operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals& Totals::operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Totals Totals::delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + +} +// end catch_totals.cpp +// start catch_version.cpp + +#include + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << '.' + << version.minorVersion << '.' + << version.patchNumber; + // branchName is never null -> 0th char is \0 if it is empty + if (version.branchName[0]) { + os << '-' << version.branchName + << '.' << version.buildNumber; + } + return os; + } + + Version const& libraryVersion() { + static Version version( 2, 0, 0, "develop", 1 ); + return version; + } + +} +// end catch_version.cpp +// start catch_wildcard_pattern.cpp + +namespace Catch { + + WildcardPattern::WildcardPattern( std::string const& pattern, + CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + + bool WildcardPattern::matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + default: + CATCH_INTERNAL_ERROR( "Unknown enum" ); + } + } + + std::string WildcardPattern::adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } +} +// end catch_wildcard_pattern.cpp +// start catch_xmlwriter.cpp + +// start catch_xmlwriter.hpp + +#include +#include + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); + + void encodeTo( std::ostream& os ) const; + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ); + + ScopedElement( ScopedElement&& other ) noexcept; + ScopedElement& operator=( ScopedElement&& other ) noexcept; + + ~ScopedElement(); + + ScopedElement& writeText( std::string const& text, bool indent = true ); + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer = nullptr; + }; + + XmlWriter( std::ostream& os = Catch::cout() ); + ~XmlWriter(); + + XmlWriter( XmlWriter const& ) = delete; + XmlWriter& operator=( XmlWriter const& ) = delete; + + XmlWriter& startElement( std::string const& name ); + + ScopedElement scopedElement( std::string const& name ); + + XmlWriter& endElement(); + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); + + XmlWriter& writeAttribute( std::string const& name, bool attribute ); + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + m_oss.clear(); + m_oss.str(std::string()); + m_oss << attribute; + return writeAttribute( name, m_oss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ); + + XmlWriter& writeComment( std::string const& text ); + + void writeStylesheetRef( std::string const& url ); + + XmlWriter& writeBlankLine(); + + void ensureTagClosed(); + + private: + + void writeDeclaration(); + + void newlineIfNecessary(); + + bool m_tagIsOpen = false; + bool m_needsNewline = false; + std::vector m_tags; + std::string m_indent; + std::ostream& m_os; + std::ostringstream m_oss; + }; + +} + +// end catch_xmlwriter.hpp +#include + +namespace Catch { + + XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void XmlEncode::encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 and + // by @mrpi PR #588 + if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { + // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast( c ); + } + else + os << c; + } + } + } + + std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept + : m_writer( other.m_writer ){ + other.m_writer = nullptr; + } + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { + if ( m_writer ) { + m_writer->endElement(); + } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; + } + + XmlWriter::ScopedElement::~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { + m_writer->writeText( text, indent ); + return *this; + } + + XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) + { + writeDeclaration(); + } + + XmlWriter::~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& XmlWriter::startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { + m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& XmlWriter::writeComment( std::string const& text ) { + ensureTagClosed(); + m_os << m_indent << ""; + m_needsNewline = true; + return *this; + } + + void XmlWriter::writeStylesheetRef( std::string const& url ) { + m_os << "\n"; + } + + XmlWriter& XmlWriter::writeBlankLine() { + ensureTagClosed(); + m_os << '\n'; + return *this; + } + + void XmlWriter::ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + void XmlWriter::writeDeclaration() { + m_os << "\n"; + } + + void XmlWriter::newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } +} +// end catch_xmlwriter.cpp +// start catch_reporter_bases.cpp + +#include +#include +#include +#include +#include + +namespace Catch { + void prepareExpandedExpression(AssertionResult& result) { + result.getExpandedExpression(); + } + + // Because formatting using c++ streams is stateful, drop down to C is required + // Alternatively we could use stringstream, but its performance is... not good. + std::string getFormattedDuration( double duration ) { + // Max exponent + 1 is required to represent the whole part + // + 1 for decimal point + // + 3 for the 3 decimal places + // + 1 for null terminator + const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + char buffer[maxDoubleSize]; + + // Save previous errno, to prevent sprintf from overwriting it + ErrnoGuard guard; +#ifdef _MSC_VER + sprintf_s(buffer, "%.3f", duration); +#else + sprintf(buffer, "%.3f", duration); +#endif + return std::string(buffer); + } + + TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) + :StreamingReporterBase(_config) {} + + void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} + + bool TestEventListenerBase::assertionEnded(AssertionStats const &) { + return false; + } + +} // end namespace Catch +// end catch_reporter_bases.cpp +// start catch_reporter_compact.cpp + +namespace { + +#ifdef CATCH_PLATFORM_MAC + const char* failedString() { return "FAILED"; } + const char* passedString() { return "PASSED"; } +#else + const char* failedString() { return "failed"; } + const char* passedString() { return "passed"; } +#endif + + // Colour::LightGrey + Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } + + std::string bothOrAll( std::size_t count ) { + return count == 1 ? std::string() : + count == 2 ? "both " : "all " ; + } +} + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + using StreamingReporterBase::StreamingReporterBase; + + ~CompactReporter() override; + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + ReporterPreferences getPreferences() const override { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + void noMatchingTestCases( std::string const& spec ) override { + stream << "No test cases matched '" << spec << '\'' << std::endl; + } + + void assertionStarting( AssertionInfo const& ) override {} + + bool assertionEnded( AssertionStats const& _assertionStats ) override { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + void sectionEnded(SectionStats const& _sectionStats) override { + if (m_config->showDurations() == ShowDurations::Always) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + } + } + + void testRunEnded( TestRunStats const& _testRunStats ) override { + printTotals( _testRunStats.totals ); + stream << '\n' << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + public: + AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; + AssertionPrinter( AssertionPrinter const& ) = delete; + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType( Colour::Error, failedString() ); + printIssue( "fatal error condition with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ':'; + } + + void printResultType( Colour::Code colour, std::string const& passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << ' ' << passOrFail; + } + stream << ':'; + } + } + + void printIssue( std::string const& issue ) const { + stream << ' ' << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ';'; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << ' ' << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << '\''; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields (or auto) compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ':'; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << '\''; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : std::string(); + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << '.'; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << '.'; + } + } + }; + + CompactReporter::~CompactReporter() {} + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch +// end catch_reporter_compact.cpp +// start catch_reporter_console.cpp + +#include +#include + +namespace { + std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + + std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + struct ColumnInfo { + enum Justification { Left, Right }; + std::string name; + int width; + Justification justification; + }; + struct ColumnBreak {}; + struct RowBreak {}; + + class TablePrinter { + std::ostream& m_os; + std::vector m_columnInfos; + std::ostringstream m_oss; + int m_currentColumn = -1; + bool m_isOpen = false; + + public: + TablePrinter( std::ostream& os, std::vector const& columnInfos ) + : m_os( os ), + m_columnInfos( columnInfos ) + {} + + auto columnInfos() const -> std::vector const& { + return m_columnInfos; + } + + void open() { + if( !m_isOpen ) { + m_isOpen = true; + *this << RowBreak(); + for( auto const& info : m_columnInfos ) + *this << info.name << ColumnBreak(); + *this << RowBreak(); + m_os << Catch::getLineOfChars<'-'>() << "\n"; + } + } + void close() { + if( m_isOpen ) { + *this << RowBreak(); + m_os << std::endl; + m_isOpen = false; + } + } + + template + friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { + tp.m_oss << value; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { + auto colStr = tp.m_oss.str(); + // This takes account of utf8 encodings + auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); + tp.m_oss.str(""); + tp.open(); + if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { + tp.m_currentColumn = -1; + tp.m_os << "\n"; + } + tp.m_currentColumn++; + + auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; + auto padding = ( strSize+2 < static_cast( colInfo.width ) ) + ? std::string( colInfo.width-(strSize+2), ' ' ) + : std::string(); + if( colInfo.justification == ColumnInfo::Left ) + tp.m_os << colStr << padding << " "; + else + tp.m_os << padding << colStr << " "; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { + if( tp.m_currentColumn > 0 ) { + tp.m_os << "\n"; + tp.m_currentColumn = -1; + } + return tp; + } + }; + + class Duration { + enum class Unit { + Auto, + Nanoseconds, + Microseconds, + Milliseconds, + Seconds, + Minutes + }; + static const uint64_t s_nanosecondsInAMicrosecond = 1000; + static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; + static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; + static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; + + uint64_t m_inNanoseconds; + Unit m_units; + + public: + Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) + : m_inNanoseconds( inNanoseconds ), + m_units( units ) + { + if( m_units == Unit::Auto ) { + if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) + m_units = Unit::Nanoseconds; + else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) + m_units = Unit::Microseconds; + else if( m_inNanoseconds < s_nanosecondsInASecond ) + m_units = Unit::Milliseconds; + else if( m_inNanoseconds < s_nanosecondsInAMinute ) + m_units = Unit::Seconds; + else + m_units = Unit::Minutes; + } + + } + + auto value() const -> double { + switch( m_units ) { + case Unit::Microseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); + case Unit::Milliseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); + case Unit::Seconds: + return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); + case Unit::Minutes: + return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); + default: + return static_cast( m_inNanoseconds ); + } + } + auto unitsAsString() const -> std::string { + switch( m_units ) { + case Unit::Nanoseconds: + return "ns"; + case Unit::Microseconds: + return "µs"; + case Unit::Milliseconds: + return "ms"; + case Unit::Seconds: + return "s"; + case Unit::Minutes: + return "m"; + default: + return "** internal error **"; + } + + } + friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { + return os << duration.value() << " " << duration.unitsAsString(); + } + }; +} + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + TablePrinter m_tablePrinter; + + ConsoleReporter( ReporterConfig const& config ) + : StreamingReporterBase( config ), + m_tablePrinter( config.stream(), + { + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH-32, ColumnInfo::Left }, + { "iters", 8, ColumnInfo::Right }, + { "elapsed ns", 14, ColumnInfo::Right }, + { "average", 14, ColumnInfo::Right } + } ) + {} + ~ConsoleReporter() override; + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + + void noMatchingTestCases( std::string const& spec ) override { + stream << "No test cases matched '" << spec << '\'' << std::endl; + } + + void assertionStarting( AssertionInfo const& ) override { + } + + bool assertionEnded( AssertionStats const& _assertionStats ) override { + AssertionResult const& result = _assertionStats.assertionResult; + + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + + // Drop out if result was successful but we're not printing them. + if( !includeResults && result.getResultType() != ResultWas::Warning ) + return false; + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, includeResults ); + printer.print(); + stream << std::endl; + return true; + } + + void sectionStarting( SectionInfo const& _sectionInfo ) override { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + void sectionEnded( SectionStats const& _sectionStats ) override { + m_tablePrinter.close(); + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_config->showDurations() == ShowDurations::Always ) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + } + if( m_headerPrinted ) { + m_headerPrinted = false; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + void benchmarkStarting( BenchmarkInfo const& info ) override { + lazyPrintWithoutClosingBenchmarkTable(); + + auto nameCol = Column( info.name ).width( m_tablePrinter.columnInfos()[0].width-2 ); + + bool firstLine = true; + for( auto line : nameCol ) { + if( !firstLine ) + m_tablePrinter << ColumnBreak() << ColumnBreak() << ColumnBreak(); + else + firstLine = false; + + m_tablePrinter << line << ColumnBreak(); + } + } + void benchmarkEnded( BenchmarkStats const& stats ) override { + Duration average( stats.elapsedTimeInNanoseconds/stats.iterations ); + m_tablePrinter + << stats.iterations << ColumnBreak() + << stats.elapsedTimeInNanoseconds << ColumnBreak() + << average << ColumnBreak(); + } + + void testCaseEnded( TestCaseStats const& _testCaseStats ) override { + m_tablePrinter.close(); + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + void testGroupEnded( TestGroupStats const& _testGroupStats ) override { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << '\n' << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + void testRunEnded( TestRunStats const& _testRunStats ) override { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + public: + AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; + AssertionPrinter( AssertionPrinter const& ) = delete; + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with "; + if (_stats.infoMessages.size() == 1) + messageLabel += "message"; + if (_stats.infoMessages.size() > 1) + messageLabel += "messages"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << '\n'; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << '\n'; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << '\n'; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Column( result.getExpandedExpression() ).indent(2) << '\n'; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ':' << '\n'; + for( auto const& msg : messages ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || msg.type != ResultWas::Info ) + stream << Column( msg.message ).indent(2) << '\n'; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + m_tablePrinter.close(); + lazyPrintWithoutClosingBenchmarkTable(); + } + + void lazyPrintWithoutClosingBenchmarkTable() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << '\n' << getLineOfChars<'~'>() << '\n'; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion() << " host application.\n" + << "Run with -? for options\n\n"; + + if( m_config->rngSeed() != 0 ) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + auto + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << '\n'; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << '\n'; + } + stream << getLineOfChars<'.'>() << '\n' << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << '\n'; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << '\n'; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Column( _string ).indent( indent+i ).initialIndent( indent ) << '\n'; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( auto& oldRow : rows ) { + while( oldRow.size() < row.size() ) + oldRow = ' ' + oldRow; + while( oldRow.size() > row.size() ) + row = ' ' + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ')' + << '\n'; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( auto col : cols ) { + std::string value = col.rows[row]; + if( col.label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( col.colour ) + << value << ' ' << col.label; + } + } + stream << '\n'; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << '\n'; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << '\n'; + } + + private: + bool m_headerPrinted = false; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + + ConsoleReporter::~ConsoleReporter() {} + +} // end namespace Catch +// end catch_reporter_console.cpp +// start catch_reporter_junit.cpp + +#include + +#include +#include + +namespace Catch { + + namespace { + std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); + +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &rawtime); +#else + std::tm* timeInfo; + timeInfo = std::gmtime(&rawtime); +#endif + + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } + + std::string fileNameTag(const std::vector &tags) { + auto it = std::find_if(begin(tags), + end(tags), + [] (std::string const& tag) {return tag.front() == '#'; }); + if (it != tags.end()) + return it->substr(1); + return std::string(); + } + } + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + ~JunitReporter() override; + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + void noMatchingTestCases( std::string const& /*spec*/ ) override {} + + void testRunStarting( TestRunInfo const& runInfo ) override { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + void testGroupStarting( GroupInfo const& groupInfo ) override { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + void testCaseStarting( TestCaseInfo const& testCaseInfo ) override { + m_okToFail = testCaseInfo.okToFail(); + } + bool assertionEnded( AssertionStats const& assertionStats ) override { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + void testCaseEnded( TestCaseStats const& testCaseStats ) override { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + void testGroupEnded( TestGroupStats const& testGroupStats ) override { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + void testRunEndedCumulative() override { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", getCurrentTimestamp() ); + + // Write test cases + for( auto const& child : groupNode.children ) + writeTestCase( *child ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + className = fileNameTag(stats.testInfo.tags); + if ( className.empty() ) + className = "global"; + } + + if ( !m_config->name().empty() ) + className = m_config->name() + "." + className; + + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + '/' + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( auto const& childNode : sectionNode.childSections ) + if( className.empty() ) + writeSection( name, "", *childNode ); + else + writeSection( className, name, *childNode ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( auto const& assertion : sectionNode.assertions ) + writeAssertion( assertion ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << '\n'; + for( auto const& msg : stats.infoMessages ) + if( msg.type == ResultWas::Info ) + oss << msg.message << '\n'; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions = 0; + bool m_okToFail = false; + }; + + JunitReporter::~JunitReporter() {} + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch +// end catch_reporter_junit.cpp +// start catch_reporter_multi.cpp + +namespace Catch { + + void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { + m_reporters.push_back( std::move( reporter ) ); + } + + ReporterPreferences MultipleReporters::getPreferences() const { + return m_reporters[0]->getPreferences(); + } + + std::set MultipleReporters::getSupportedVerbosities() { + return { }; + } + + void MultipleReporters::noMatchingTestCases( std::string const& spec ) { + for( auto const& reporter : m_reporters ) + reporter->noMatchingTestCases( spec ); + } + + void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { + for( auto const& reporter : m_reporters ) + reporter->testRunStarting( testRunInfo ); + } + + void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) { + for( auto const& reporter : m_reporters ) + reporter->testGroupStarting( groupInfo ); + } + + void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) { + for( auto const& reporter : m_reporters ) + reporter->testCaseStarting( testInfo ); + } + + void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) { + for( auto const& reporter : m_reporters ) + reporter->sectionStarting( sectionInfo ); + } + + void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) { + for( auto const& reporter : m_reporters ) + reporter->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) { + bool clearBuffer = false; + for( auto const& reporter : m_reporters ) + clearBuffer |= reporter->assertionEnded( assertionStats ); + return clearBuffer; + } + + void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) { + for( auto const& reporter : m_reporters ) + reporter->sectionEnded( sectionStats ); + } + + void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) { + for( auto const& reporter : m_reporters ) + reporter->testCaseEnded( testCaseStats ); + } + + void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) { + for( auto const& reporter : m_reporters ) + reporter->testGroupEnded( testGroupStats ); + } + + void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) { + for( auto const& reporter : m_reporters ) + reporter->testRunEnded( testRunStats ); + } + + void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) { + for( auto const& reporter : m_reporters ) + reporter->skipTest( testInfo ); + } + + bool MultipleReporters::isMulti() const { + return true; + } + +} // end namespace Catch +// end catch_reporter_multi.cpp +// start catch_reporter_xml.cpp + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_xml(_config.stream()) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + ~XmlReporter() override; + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + + virtual std::string getStylesheetRef() const { + return std::string(); + } + + void writeSourceInfo( SourceLineInfo const& sourceInfo ) { + m_xml + .writeAttribute( "filename", sourceInfo.file ) + .writeAttribute( "line", sourceInfo.line ); + } + + public: // StreamingReporterBase + + void noMatchingTestCases( std::string const& s ) override { + StreamingReporterBase::noMatchingTestCases( s ); + } + + void testRunStarting( TestRunInfo const& testInfo ) override { + StreamingReporterBase::testRunStarting( testInfo ); + std::string stylesheetRef = getStylesheetRef(); + if( !stylesheetRef.empty() ) + m_xml.writeStylesheetRef( stylesheetRef ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + void testGroupStarting( GroupInfo const& groupInfo ) override { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + void testCaseStarting( TestCaseInfo const& testInfo ) override { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ) + .writeAttribute( "name", trim( testInfo.name ) ) + .writeAttribute( "description", testInfo.description ) + .writeAttribute( "tags", testInfo.tagsAsString() ); + + writeSourceInfo( testInfo.lineInfo ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + m_xml.ensureTagClosed(); + } + + void sectionStarting( SectionInfo const& sectionInfo ) override { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + writeSourceInfo( sectionInfo.lineInfo ); + m_xml.ensureTagClosed(); + } + } + + void assertionStarting( AssertionInfo const& ) override { } + + bool assertionEnded( AssertionStats const& assertionStats ) override { + + AssertionResult const& result = assertionStats.assertionResult; + + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + + if( includeResults ) { + // Print any info messages in tags. + for( auto const& msg : assertionStats.infoMessages ) { + if( msg.type == ResultWas::Info ) { + m_xml.scopedElement( "Info" ) + .writeText( msg.message ); + } else if ( msg.type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( msg.message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !includeResults && result.getResultType() != ResultWas::Warning ) + return true; + + // Print the expression if there is one. + if( result.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", result.succeeded() ) + .writeAttribute( "type", result.getTestMacroName() ); + + writeSourceInfo( result.getSourceInfo() ); + + m_xml.scopedElement( "Original" ) + .writeText( result.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( result.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( result.getResultType() ) { + case ResultWas::ThrewException: + m_xml.startElement( "Exception" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::FatalErrorCondition: + m_xml.startElement( "FatalErrorCondition" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( result.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.startElement( "Failure" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + default: + break; + } + + if( result.hasExpression() ) + m_xml.endElement(); + + return true; + } + + void sectionEnded( SectionStats const& sectionStats ) override { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + void testCaseEnded( TestCaseStats const& testCaseStats ) override { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + if( !testCaseStats.stdOut.empty() ) + m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); + if( !testCaseStats.stdErr.empty() ) + m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); + + m_xml.endElement(); + } + + void testGroupEnded( TestGroupStats const& testGroupStats ) override { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + void testRunEnded( TestRunStats const& testRunStats ) override { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth = 0; + }; + + XmlReporter::~XmlReporter() {} + INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch +// end catch_reporter_xml.cpp +// ~*~* CATCH_CPP_STITCH_PLACE *~*~ + +namespace Catch { + LeakDetector leakDetector; + + // These are all here to avoid warnings about not having any out of line + // virtual methods + NonCopyable::~NonCopyable() {} + IStream::~IStream() noexcept {} + FileStream::~FileStream() noexcept {} + CoutStream::~CoutStream() noexcept {} + DebugOutStream::~DebugOutStream() noexcept {} + StreamBufBase::~StreamBufBase() noexcept {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestInvoker::~ITestInvoker() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + + void Config::dummy() {} +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_impl.hpp +#endif + +#ifdef CATCH_CONFIG_MAIN +// start catch_default_main.hpp + +#ifndef __OBJC__ + +#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) +// Standard C/C++ Win32 Unicode wmain entry point +extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { +#else +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { +#endif + + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +// end catch_default_main.hpp +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + +#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif// CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + +#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + +#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) + +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) + +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) +#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) + +// "BDD-style" convenience wrappers +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + +#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + +#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + +#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) + +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) +#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) + +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) +#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) +#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) + +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc ) + +using Catch::Detail::Approx; + +// start catch_reenable_warnings.h + + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + +// end catch_reenable_warnings.h +// end catch.hpp +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + From e6ffbb732a538c5ada1a2e8cdd1dbcc3ed4f15d3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 08:40:58 +0100 Subject: [PATCH 256/398] Updated conan files to use version number --- conanfile.py | 2 +- test_package/conanfile.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conanfile.py b/conanfile.py index 81e9c708..3565eb6d 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "1.9.6" + version = "2.0.0-develop.1" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 9444b737..56665718 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/1.9.5@%s/%s" % (username, channel) + requires = "Catch/2.0.0-develop.1@%s/%s" % (username, channel) def build(self): cmake = CMake(self) From ff9aaf3afebe0281fbae28a16e444ac95756b6e6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 10:48:53 +0100 Subject: [PATCH 257/398] Added Clara and TextFlowCpp to open source users --- docs/opensource-users.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/opensource-users.md b/docs/opensource-users.md index 2d9949e4..f1e1806a 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -25,6 +25,9 @@ The core part of the Chakra Javascript engine that powers Microsoft Edge ### [ChaiScript](https://github.com/ChaiScript/ChaiScript) A, header-only, embedded scripting language designed from the ground up to directly target C++ and take advantage of modern C++ development techniques +### [Clara](https://github.com/philsquared/Clara) +A, single-header-only, type-safe, command line parser - which also prints formatted usage strings. + ### [Couchbase-lite-core](https://github.com/couchbase/couchbase-lite-core) The next-generation core storage and query engine for Couchbase Lite/ @@ -52,6 +55,9 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an ### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp) A library of algorithms for values-distributed-in-time +### [TextFlowCpp](https://github.com/philsquared/textflowcpp) +A small, single-header-only, library for wrapping and composing columns of text + ### [Trompeloeil](https://github.com/rollbear/trompeloeil) A thread safe header only mocking framework for C++14 From aaedae60b41121da6c2d0e362f8a6bba2b420e00 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 16:46:05 +0100 Subject: [PATCH 258/398] Fixed issue with comparing non-copyable values --- include/internal/catch_decomposer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 6d20be78..8cb4c1d4 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -76,14 +76,14 @@ namespace Catch { // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template - auto compareEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; + auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) == rhs; }; template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; template auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; template - auto compareNotEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; + auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) != rhs; }; template auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; template From b8f482b9aa4f274bdc7f4e840283db05a5ebfe2e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 16:48:46 +0100 Subject: [PATCH 259/398] Added test comparing non-copyable values --- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 16 +- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 15 +- .../SelfTest/Baselines/xml.sw.unapproved.txt | 8293 +++++++++++++++++ projects/SelfTest/TrickyTests.cpp | 6 + 6 files changed, 8330 insertions(+), 7 deletions(-) create mode 100644 projects/SelfTest/Baselines/xml.sw.unapproved.txt diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 42d62c9c..50991312 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1020,6 +1020,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 182 | 131 passed | 47 failed | 4 failed as expected -assertions: 881 | 764 passed | 96 failed | 21 failed as expected +test cases: 183 | 132 passed | 47 failed | 4 failed as expected +assertions: 882 | 765 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 1d228de6..ae2f6928 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -6672,6 +6672,18 @@ PASSED: with expansion: "7" == "7" +------------------------------------------------------------------------------- +non-copyable objects +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + CHECK( ti == typeid(int) ) +with expansion: + {?} == {?} + ------------------------------------------------------------------------------- not allowed ------------------------------------------------------------------------------- @@ -7523,6 +7535,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 182 | 128 passed | 50 failed | 4 failed as expected -assertions: 883 | 760 passed | 102 failed | 21 failed as expected +test cases: 183 | 129 passed | 50 failed | 4 failed as expected +assertions: 884 | 761 passed | 102 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 6e3607a8..e49e19e4 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -725,6 +725,7 @@ MiscTests.cpp: + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index f290b1de..685e21bc 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -7433,6 +7433,17 @@ loose text artifact + + + + ti == typeid(int) + + + {?} == {?} + + + + @@ -8276,7 +8287,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/Baselines/xml.sw.unapproved.txt b/projects/SelfTest/Baselines/xml.sw.unapproved.txt new file mode 100644 index 00000000..edabc05e --- /dev/null +++ b/projects/SelfTest/Baselines/xml.sw.unapproved.txt @@ -0,0 +1,8293 @@ + + + + + + + +
+ + answer := 42 + + + expected exception + + +
+
+ + answer := 42 + + + + thisThrows() + + + thisThrows() + + + expected exception + + + +
+
+ + answer := 42 + + + + thisThrows() + + + thisThrows() + + + +
+ +
+ + + + 42 == f + + + 42 == {?} + + + + + + + + a == t + + + 3 == 3 + + + + + a == t + + + 3 == 3 + + + + + throws_int(true) + + + throws_int(true) + + + + + throws_int(true), int + + + throws_int(true), int + + + + + throws_int(false) + + + throws_int(false) + + + + + "aaa", Catch::EndsWith("aaa") + + + "aaa" ends with: "aaa" + + + + + templated_tests<int>(3) + + + true + + + + + + + + f() == 0 + + + 1 == 0 + + + + + errno == 1 + + + 1 == 1 + + + + + + + dummy := 0 + + + + x == 4 + + + {?} == 4 + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+ + + + false != false + + + false != false + + + + + true != true + + + true != true + + + + + !true + + + false + + + + + !true + + + !true + + + + + !trueValue + + + false + + + + + !trueValue + + + !true + + + + + !(1 == 1) + + + false + + + + + !1 == 1 + + + !(1 == 1) + + + + + + + + false == false + + + false == false + + + + + true == true + + + true == true + + + + + !false + + + true + + + + + !false + + + !false + + + + + !falseValue + + + true + + + + + !falseValue + + + !false + + + + + !(1 == 2) + + + true + + + + + !1 == 2 + + + !(1 == 2) + + + + + +
+ + + is_true<true>::value == true + + + true == true + + + + + true == is_true<true>::value + + + true == true + + + +
+
+ + + is_true<false>::value == false + + + false == false + + + + + false == is_true<false>::value + + + false == false + + + +
+
+ + + !is_true<false>::value + + + true + + + +
+
+ + + !!is_true<true>::value + + + true + + + +
+
+ + + is_true<true>::value + + + true + + + + + !is_true<false>::value + + + !false + + + +
+ +
+ + + + s == "world" + + + "hello" == "world" + + + + + + + + s == "hello" + + + "hello" == "hello" + + + + + + + + m_a == 2 + + + 1 == 2 + + + + + + + + m_a == 1 + + + 1 == 1 + + + + + +
+
+ +
+ +
+ + to infinity and beyond + + +
+ + + + &o1 == &o2 + + + 0x == 0x + + + + + o1 == o2 + + + {?} == {?} + + + + + + + + 104.0 != Approx(100.0) + + + 104.0 != Approx( 100.0 ) + + + + + 104.0 == Approx(100.0).margin(5) + + + 104.0 == Approx( 100.0 ) + + + + + 104.0 != Approx(100.0).margin(3) + + + 104.0 != Approx( 100.0 ) + + + + + 100.3 != Approx(100.0) + + + 100.3 != Approx( 100.0 ) + + + + + 100.3 == Approx(100.0).margin(0.5) + + + 100.3 == Approx( 100.0 ) + + + + + + + + testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) + + + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) + + + + + + + + + + + i++ == 7 + + + 7 == 7 + + + + + i++ == 8 + + + 8 == 8 + + + + + + + + 1 == 1 + + + 1 == 1 + + + + + {Unknown expression after the reported line} + + + {Unknown expression after the reported line} + + + unexpected exception + + + + + + + + + + + testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) + + + "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) + + + + + testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) + + + "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) + + + + + + + + divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) + + + 3.1428571429 == Approx( 3.141 ) + + + + + divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) + + + 3.1428571429 != Approx( 3.141 ) + + + + + + + + d != Approx( 1.231 ) + + + 1.23 != Approx( 1.231 ) + + + + + d == Approx( 1.231 ).epsilon( 0.1 ) + + + 1.23 == Approx( 1.231 ) + + + + + + + + 1.23f == Approx( 1.23f ) + + + 1.23f == Approx( 1.2300000191 ) + + + + + 0.0f == Approx( 0.0f ) + + + 0.0f == Approx( 0.0 ) + + + + + + + + 1 == Approx( 1 ) + + + 1 == Approx( 1.0 ) + + + + + 0 == Approx( 0 ) + + + 0 == Approx( 0.0 ) + + + + + + + + 1.0f == Approx( 1 ) + + + 1.0f == Approx( 1.0 ) + + + + + 0 == Approx( dZero) + + + 0 == Approx( 0.0 ) + + + + + 0 == Approx( dSmall ).epsilon( 0.001 ) + + + 0 == Approx( 0.00001 ) + + + + + 1.234f == Approx( dMedium ) + + + 1.234f == Approx( 1.234 ) + + + + + dMedium == Approx( 1.234f ) + + + 1.234 == Approx( 1.2339999676 ) + + + + + + + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + + +
+ +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + +
+ + + Catch::alwaysTrue() + + + true + + + +
+ +
+ +
+ +
+ + i := 2 + + + + true + + + true + + + +
+
+ + 3 + + + + true + + + true + + + +
+ +
+ +
+ + + tab == '\t' + + + '\t' == '\t' + + + + + newline == '\n' + + + '\n' == '\n' + + + + + carr_return == '\r' + + + '\r' == '\r' + + + + + form_feed == '\f' + + + '\f' == '\f' + + + +
+
+ + + space == ' ' + + + ' ' == ' ' + + + + + c == chars[i] + + + 'a' == 'a' + + + + + c == chars[i] + + + 'z' == 'z' + + + + + c == chars[i] + + + 'A' == 'A' + + + + + c == chars[i] + + + 'Z' == 'Z' + + + +
+
+ + + null_terminator == '\0' + + + 0 == 0 + + + + + c == i + + + 2 == 2 + + + + + c == i + + + 3 == 3 + + + + + c == i + + + 4 == 4 + + + + + c == i + + + 5 == 5 + + + +
+ +
+ + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} + + + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + + + !({ 1, 2 } == { 1, 2, 3 }) + + + + + !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + + + !({ 1, 2 } == { 1, 2, 3 }) + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + true + + + true + + + + + std::vector<int>{1, 2} == std::vector<int>{1, 2} + + + { 1, 2 } == { 1, 2 } + + + + + + + + a + + + 0x + + + + + a == &foo + + + 0x == 0x + + + + + + + + m == &S::f + + + 0x +== +0x + + + + + + + + td == Approx(10.0) + + + StrongDoubleTypedef(10) == Approx( 10.0 ) + + + + + Approx(10.0) == td + + + Approx( 10.0 ) == StrongDoubleTypedef(10) + + + + + td != Approx(11.0) + + + StrongDoubleTypedef(10) != Approx( 11.0 ) + + + + + Approx(11.0) != td + + + Approx( 11.0 ) != StrongDoubleTypedef(10) + + + + + td <= Approx(10.0) + + + StrongDoubleTypedef(10) <= Approx( 10.0 ) + + + + + td <= Approx(11.0) + + + StrongDoubleTypedef(10) <= Approx( 11.0 ) + + + + + Approx(10.0) <= td + + + Approx( 10.0 ) <= StrongDoubleTypedef(10) + + + + + Approx(9.0) <= td + + + Approx( 9.0 ) <= StrongDoubleTypedef(10) + + + + + td >= Approx(9.0) + + + StrongDoubleTypedef(10) >= Approx( 9.0 ) + + + + + td >= Approx(10.0) + + + StrongDoubleTypedef(10) >= Approx( 10.0 ) + + + + + Approx(10.0) >= td + + + Approx( 10.0 ) >= StrongDoubleTypedef(10) + + + + + Approx(11.0) >= td + + + Approx( 11.0 ) >= StrongDoubleTypedef(10) + + + + + + + + 54 == 6*9 + + + 54 == 54 + + + + + + + + ( -1 > 2u ) + + + true + + + + + -1 > 2u + + + -1 > 2 + + + + + ( 2u < -1 ) + + + true + + + + + 2u < -1 + + + 2 < -1 + + + + + ( minInt > 2u ) + + + true + + + + + minInt > 2u + + + -2147483648 > 2 + + + + + + + + i == 1 + + + 1 == 1 + + + + + ui == 2 + + + 2 == 2 + + + + + l == 3 + + + 3 == 3 + + + + + ul == 4 + + + 4 == 4 + + + + + c == 5 + + + 5 == 5 + + + + + uc == 6 + + + 6 == 6 + + + + + 1 == i + + + 1 == 1 + + + + + 2 == ui + + + 2 == 2 + + + + + 3 == l + + + 3 == 3 + + + + + 4 == ul + + + 4 == 4 + + + + + 5 == c + + + 5 == 5 + + + + + 6 == uc + + + 6 == 6 + + + + + (std::numeric_limits<unsigned long>::max)() > ul + + + 18446744073709551615 (0x) +> +4 + + + + + + + + testStringForMatching(), Contains( "not there" ) + + + "this string contains 'abc' as a substring" contains: "not there" + + + + + + + + throwCustom() + + + throwCustom() + + + custom exception - not std + + + + + + + + throwCustom(), std::exception + + + throwCustom(), std::exception + + + custom exception - not std + + + + + + + custom std exception + + + + + + + t == 1u + + + {?} == 1 + + + + + + + + testStringForMatching(), EndsWith( "this" ) + + + "this string contains 'abc' as a substring" ends with: "this" + + + + + + + + data.int_seven == 6 + + + 7 == 6 + + + + + data.int_seven == 8 + + + 7 == 8 + + + + + data.int_seven == 0 + + + 7 == 0 + + + + + data.float_nine_point_one == Approx( 9.11f ) + + + 9.1f == Approx( 9.1099996567 ) + + + + + data.float_nine_point_one == Approx( 9.0f ) + + + 9.1f == Approx( 9.0 ) + + + + + data.float_nine_point_one == Approx( 1 ) + + + 9.1f == Approx( 1.0 ) + + + + + data.float_nine_point_one == Approx( 0 ) + + + 9.1f == Approx( 0.0 ) + + + + + data.double_pi == Approx( 3.1415 ) + + + 3.1415926535 == Approx( 3.1415 ) + + + + + data.str_hello == "goodbye" + + + "hello" == "goodbye" + + + + + data.str_hello == "hell" + + + "hello" == "hell" + + + + + data.str_hello == "hello1" + + + "hello" == "hello1" + + + + + data.str_hello.size() == 6 + + + 5 == 6 + + + + + x == Approx( 1.301 ) + + + 1.3 == Approx( 1.301 ) + + + + + + + + data.int_seven == 7 + + + 7 == 7 + + + + + data.float_nine_point_one == Approx( 9.1f ) + + + 9.1f == Approx( 9.1000003815 ) + + + + + data.double_pi == Approx( 3.1415926535 ) + + + 3.1415926535 == Approx( 3.1415926535 ) + + + + + data.str_hello == "hello" + + + "hello" == "hello" + + + + + "hello" == data.str_hello + + + "hello" == "hello" + + + + + data.str_hello.size() == 5 + + + 5 == 5 + + + + + x == Approx( 1.3 ) + + + 1.3 == Approx( 1.3 ) + + + + + + + + testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) + + + "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" + + + + + + + + testStringForMatching(), Equals( "something else" ) + + + "this string contains 'abc' as a substring" equals: "something else" + + + + + +
+ + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } + + + +
+
+ + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + Unknown exception + + + + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } + + + Unknown exception + + + +
+
+ + + throws(3), SpecialException, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + + + throws(4), SpecialException, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + +
+ +
+ + + + throws(1), SpecialException, ExceptionMatcher{ 1 } + + + {?} special exception has value of 1 + + + + + throws(2), SpecialException, ExceptionMatcher{ 2 } + + + {?} special exception has value of 2 + + + + + +
+ + + thisThrows(), "expected exception" + + + "expected exception" equals: "expected exception" + + + +
+
+ + + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + + + "expected exception" equals: "expected exception" (case insensitive) + + + +
+
+ + + thisThrows(), StartsWith( "expected" ) + + + "expected exception" starts with: "expected" + + + + + thisThrows(), EndsWith( "exception" ) + + + "expected exception" ends with: "exception" + + + + + thisThrows(), Contains( "except" ) + + + "expected exception" contains: "except" + + + + + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + + + "expected exception" contains: "except" (case insensitive) + + + +
+ +
+ + + + thisThrows(), std::string + + + thisThrows(), std::string + + + expected exception + + + + + thisDoesntThrow(), std::domain_error + + + thisDoesntThrow(), std::domain_error + + + + + thisThrows() + + + thisThrows() + + + expected exception + + + + + + + This is a failure + + + + + + + + + + This is a failure + + + This message appears in the output + + + + + + + Factorial(0) == 1 + + + 1 == 1 + + + + + Factorial(1) == 1 + + + 1 == 1 + + + + + Factorial(2) == 2 + + + 2 == 2 + + + + + Factorial(3) == 6 + + + 6 == 6 + + + + + Factorial(10) == 3628800 + + + 3628800 (0x) == 3628800 (0x) + + + + + + + + d >= Approx( 1.22 ) + + + 1.23 >= Approx( 1.22 ) + + + + + d >= Approx( 1.23 ) + + + 1.23 >= Approx( 1.23 ) + + + + + !d >= Approx( 1.24 ) + + + !(1.23 >= Approx( 1.24 )) + + + + + d >= Approx( 1.24 ).epsilon(0.1) + + + 1.23 >= Approx( 1.24 ) + + + + + + + this is a message + + + this is a warning + + + + + + this message should be logged + + + so should this + + + + a == 1 + + + 2 == 1 + + + + + + + this message may be logged later + + + + a == 2 + + + 2 == 2 + + + + this message may be logged later + + + this message should be logged + + + + a == 1 + + + 2 == 1 + + + + this message may be logged later + + + this message should be logged + + + and this, but later + + + + a == 0 + + + 2 == 0 + + + + this message may be logged later + + + this message should be logged + + + and this, but later + + + but not this + + + + a == 2 + + + 2 == 2 + + + + + + + current counter 0 + + + i := 0 + + + + i < 10 + + + 0 < 10 + + + + current counter 1 + + + i := 1 + + + + i < 10 + + + 1 < 10 + + + + current counter 2 + + + i := 2 + + + + i < 10 + + + 2 < 10 + + + + current counter 3 + + + i := 3 + + + + i < 10 + + + 3 < 10 + + + + current counter 4 + + + i := 4 + + + + i < 10 + + + 4 < 10 + + + + current counter 5 + + + i := 5 + + + + i < 10 + + + 5 < 10 + + + + current counter 6 + + + i := 6 + + + + i < 10 + + + 6 < 10 + + + + current counter 7 + + + i := 7 + + + + i < 10 + + + 7 < 10 + + + + current counter 8 + + + i := 8 + + + + i < 10 + + + 8 < 10 + + + + current counter 9 + + + i := 9 + + + + i < 10 + + + 9 < 10 + + + + current counter 10 + + + i := 10 + + + + i < 10 + + + 10 < 10 + + + + + + + + data.int_seven != 7 + + + 7 != 7 + + + + + data.float_nine_point_one != Approx( 9.1f ) + + + 9.1f != Approx( 9.1000003815 ) + + + + + data.double_pi != Approx( 3.1415926535 ) + + + 3.1415926535 != Approx( 3.1415926535 ) + + + + + data.str_hello != "hello" + + + "hello" != "hello" + + + + + data.str_hello.size() != 5 + + + 5 != 5 + + + + + + + + data.int_seven != 6 + + + 7 != 6 + + + + + data.int_seven != 8 + + + 7 != 8 + + + + + data.float_nine_point_one != Approx( 9.11f ) + + + 9.1f != Approx( 9.1099996567 ) + + + + + data.float_nine_point_one != Approx( 9.0f ) + + + 9.1f != Approx( 9.0 ) + + + + + data.float_nine_point_one != Approx( 1 ) + + + 9.1f != Approx( 1.0 ) + + + + + data.float_nine_point_one != Approx( 0 ) + + + 9.1f != Approx( 0.0 ) + + + + + data.double_pi != Approx( 3.1415 ) + + + 3.1415926535 != Approx( 3.1415 ) + + + + + data.str_hello != "goodbye" + + + "hello" != "goodbye" + + + + + data.str_hello != "hell" + + + "hello" != "hell" + + + + + data.str_hello != "hello1" + + + "hello" != "hello1" + + + + + data.str_hello.size() != 6 + + + 5 != 6 + + + + + + + + d <= Approx( 1.24 ) + + + 1.23 <= Approx( 1.24 ) + + + + + d <= Approx( 1.23 ) + + + 1.23 <= Approx( 1.23 ) + + + + + !d <= Approx( 1.22 ) + + + !(1.23 <= Approx( 1.22 )) + + + + + d <= Approx( 1.22 ).epsilon(0.1) + + + 1.23 <= Approx( 1.22 ) + + + + + + + + + + + testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) + + + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" ) + + + + + + + + testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + + + + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" ) + + + + + + + + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) + + + + + + + + testStringForMatching(), !Contains( "different" ) + + + "this string contains 'abc' as a substring" not contains: "different" + + + + + + + + testStringForMatching(), !Contains( "substring" ) + + + "this string contains 'abc' as a substring" not contains: "substring" + + + + + + + + thisThrows(), "expected exception" + + + "expected exception" equals: "expected exception" + + + + + thisThrows(), "should fail" + + + "expected exception" equals: "should fail" + + + + + + + This one ran + + + + + + custom exception + + + + + + + True + + + {?} + + + + + !False + + + true + + + + + !False + + + !{?} + + + + + + + + 0x == o + + + 3221225472 (0x) == {?} + + + + + + + + data.int_seven > 7 + + + 7 > 7 + + + + + data.int_seven < 7 + + + 7 < 7 + + + + + data.int_seven > 8 + + + 7 > 8 + + + + + data.int_seven < 6 + + + 7 < 6 + + + + + data.int_seven < 0 + + + 7 < 0 + + + + + data.int_seven < -1 + + + 7 < -1 + + + + + data.int_seven >= 8 + + + 7 >= 8 + + + + + data.int_seven <= 6 + + + 7 <= 6 + + + + + data.float_nine_point_one < 9 + + + 9.1f < 9 + + + + + data.float_nine_point_one > 10 + + + 9.1f > 10 + + + + + data.float_nine_point_one > 9.2 + + + 9.1f > 9.2 + + + + + data.str_hello > "hello" + + + "hello" > "hello" + + + + + data.str_hello < "hello" + + + "hello" < "hello" + + + + + data.str_hello > "hellp" + + + "hello" > "hellp" + + + + + data.str_hello > "z" + + + "hello" > "z" + + + + + data.str_hello < "hellm" + + + "hello" < "hellm" + + + + + data.str_hello < "a" + + + "hello" < "a" + + + + + data.str_hello >= "z" + + + "hello" >= "z" + + + + + data.str_hello <= "a" + + + "hello" <= "a" + + + + + + + + data.int_seven < 8 + + + 7 < 8 + + + + + data.int_seven > 6 + + + 7 > 6 + + + + + data.int_seven > 0 + + + 7 > 0 + + + + + data.int_seven > -1 + + + 7 > -1 + + + + + data.int_seven >= 7 + + + 7 >= 7 + + + + + data.int_seven >= 6 + + + 7 >= 6 + + + + + data.int_seven <= 7 + + + 7 <= 7 + + + + + data.int_seven <= 8 + + + 7 <= 8 + + + + + data.float_nine_point_one > 9 + + + 9.1f > 9 + + + + + data.float_nine_point_one < 10 + + + 9.1f < 10 + + + + + data.float_nine_point_one < 9.2 + + + 9.1f < 9.2 + + + + + data.str_hello <= "hello" + + + "hello" <= "hello" + + + + + data.str_hello >= "hello" + + + "hello" >= "hello" + + + + + data.str_hello < "hellp" + + + "hello" < "hellp" + + + + + data.str_hello < "zebra" + + + "hello" < "zebra" + + + + + data.str_hello > "hellm" + + + "hello" > "hellm" + + + + + data.str_hello > "a" + + + "hello" > "a" + + + + + +
+ + Message from section one + + +
+
+ + Message from section two + + +
+ +
+ +
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches(tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + + + parseTestSpec( "*a" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + + + parseTestSpec( "a*" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + + + parseTestSpec( "*a*" ).matches( tcA ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == true + + + true == true + + + + + spec.matches( tcB ) == true + + + true == true + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == true + + + true == true + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == false + + + false == false + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == false + + + false == false + + + +
+
+ + + spec.hasFilters() == true + + + true == true + + + + + spec.matches( tcA ) == false + + + false == false + + + + + spec.matches( tcB ) == false + + + false == false + + + + + spec.matches( tcC ) == false + + + false == false + + + + + spec.matches( tcD ) == true + + + true == true + + + +
+ +
+ + + + (std::pair<int, int>( 1, 2 )) == aNicePair + + + { 1, 2 } == { 1, 2 } + + + + + + + + p == 0 + + + 0 == 0 + + + + + p == pNULL + + + 0 == 0 + + + + + p != 0 + + + 0x != 0 + + + + + cp != 0 + + + 0x != 0 + + + + + cpc != 0 + + + 0x != 0 + + + + + returnsNull() == 0 + + + {null string} == 0 + + + + + returnsConstNull() == 0 + + + {null string} == 0 + + + + + 0 != p + + + 0 != 0x + + + + + + + actual address of p: 0x + + + toString(p): 0x + + + + +
+ + + result + + + {?} + + + + + config.processName == "" + + + "" == "" + + + +
+
+ + + result + + + {?} + + + + + config.processName == "test" + + + "test" == "test" + + + + + config.shouldDebugBreak == false + + + false == false + + + + + config.abortAfter == -1 + + + -1 == -1 + + + + + config.noThrow == false + + + false == false + + + + + config.reporterNames.empty() + + + true + + + +
+
+
+ + + result + + + {?} + + + + + cfg.testSpec().matches(fakeTestCase("notIncluded")) == false + + + false == false + + + + + cfg.testSpec().matches(fakeTestCase("test1")) + + + true + + + +
+ +
+
+
+ + + result + + + {?} + + + + + cfg.testSpec().matches(fakeTestCase("test1")) == false + + + false == false + + + + + cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) + + + true + + + +
+ +
+
+
+ + + result + + + {?} + + + + + cfg.testSpec().matches(fakeTestCase("test1")) == false + + + false == false + + + + + cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "-r", "console"}) + + + {?} + + + + + config.reporterNames[0] == "console" + + + "console" == "console" + + + +
+ +
+
+
+ + + cli.parse({"test", "-r", "xml"}) + + + {?} + + + + + config.reporterNames[0] == "xml" + + + "xml" == "xml" + + + +
+ +
+
+
+ + + cli.parse({"test", "-r", "xml", "-r", "junit"}) + + + {?} + + + + + config.reporterNames.size() == 2 + + + 2 == 2 + + + + + config.reporterNames[0] == "xml" + + + "xml" == "xml" + + + + + config.reporterNames[1] == "junit" + + + "junit" == "junit" + + + +
+ +
+
+
+ + + cli.parse({"test", "--reporter", "junit"}) + + + {?} + + + + + config.reporterNames[0] == "junit" + + + "junit" == "junit" + + + +
+ +
+
+
+ + + cli.parse({"test", "-b"}) + + + {?} + + + + + config.shouldDebugBreak == true + + + true == true + + + +
+ +
+
+
+ + + cli.parse({"test", "--break"}) + + + {?} + + + + + config.shouldDebugBreak + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "-a"}) + + + {?} + + + + + config.abortAfter == 1 + + + 1 == 1 + + + +
+ +
+
+
+ + + cli.parse({"test", "-x", "2"}) + + + {?} + + + + + config.abortAfter == 2 + + + 2 == 2 + + + +
+ +
+
+
+ + + !result + + + true + + + + + result.errorMessage(), Contains("convert") && Contains("oops") + + + "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" ) + + + +
+ +
+
+
+ + + cli.parse({"test", "-e"}) + + + {?} + + + + + config.noThrow + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "--nothrow"}) + + + {?} + + + + + config.noThrow + + + true + + + +
+ +
+
+
+ + + cli.parse({"test", "-o", "filename.ext"}) + + + {?} + + + + + config.outputFilename == "filename.ext" + + + "filename.ext" == "filename.ext" + + + +
+ +
+
+
+ + + cli.parse({"test", "--out", "filename.ext"}) + + + {?} + + + + + config.outputFilename == "filename.ext" + + + "filename.ext" == "filename.ext" + + + +
+ +
+
+
+ + + cli.parse({"test", "-abe"}) + + + {?} + + + + + config.abortAfter == 1 + + + 1 == 1 + + + + + config.shouldDebugBreak + + + true + + + + + config.noThrow == true + + + true == true + + + +
+ +
+
+
+ + + cli.parse({"test"}) + + + {?} + + + + + config.useColour == UseColour::Auto + + + 0 == 0 + + + +
+ +
+
+
+ + + cli.parse({"test", "--use-colour", "auto"}) + + + {?} + + + + + config.useColour == UseColour::Auto + + + 0 == 0 + + + +
+ +
+
+
+ + + cli.parse({"test", "--use-colour", "yes"}) + + + {?} + + + + + config.useColour == UseColour::Yes + + + 1 == 1 + + + +
+ +
+
+
+ + + cli.parse({"test", "--use-colour", "no"}) + + + {?} + + + + + config.useColour == UseColour::No + + + 2 == 2 + + + +
+ +
+
+
+ + + !result + + + true + + + + + result.errorMessage(), Contains( "colour mode must be one of" ) + + + "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" + + + +
+ +
+ +
+ + + + truthy(false) + + + Hey, its truthy! + + + + + + + + + + + +
+ + + before == 0 + + + 0 == 0 + + +
+
+ + + after > before + + + 1 > 0 + + + +
+ +
+ +
+ +
+ +
+
+
+ + + itDoesThis() + + + true + + +
+ + + itDoesThat() + + + true + + + +
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+ +
+ +
+ +
+ +
+ + + v.size() == 0 + + + 0 == 0 + + +
+
+ + + v.size() == 10 + + + 10 == 10 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + +
+
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ +
+ +
+ +
+ +
+
+ + + v.size() == 0 + + + 0 == 0 + + +
+
+ + + v.capacity() >= 10 + + + 10 >= 10 + + + + + v.size() == 0 + + + 0 == 0 + + + +
+ +
+ +
+ +
+ + + +A string sent directly to stdout + + +A string sent directly to stderr + + + + + + + d == Approx( 1.23 ) + + + 1.23 == Approx( 1.23 ) + + + + + d != Approx( 1.22 ) + + + 1.23 != Approx( 1.22 ) + + + + + d != Approx( 1.24 ) + + + 1.23 != Approx( 1.24 ) + + + + + Approx( d ) == 1.23 + + + Approx( 1.23 ) == 1.23 + + + + + Approx( d ) != 1.22 + + + Approx( 1.23 ) != 1.22 + + + + + Approx( d ) != 1.24 + + + Approx( 1.23 ) != 1.24 + + + + + +
+ +
+
+ +
+
+ +
+ + +Write to std::cerr +Write to std::clog +Interleaved writes to error streams + + +
+ +
+ +
+
+ +
+ + +Message from section one +Message from section two + + +
+ + + + testStringForMatching(), StartsWith( "string" ) + + + "this string contains 'abc' as a substring" starts with: "string" + + + + + + + + testStringForMatching(), Contains( "string" ) + + + "this string contains 'abc' as a substring" contains: "string" + + + + + testStringForMatching(), Contains( "abc" ) + + + "this string contains 'abc' as a substring" contains: "abc" + + + + + testStringForMatching(), StartsWith( "this" ) + + + "this string contains 'abc' as a substring" starts with: "this" + + + + + testStringForMatching(), EndsWith( "substring" ) + + + "this string contains 'abc' as a substring" ends with: "substring" + + + + + +
+ + + empty.empty() + + + true + + + + + empty.size() == 0 + + + 0 == 0 + + + + + std::strcmp( empty.c_str(), "" ) == 0 + + + 0 == 0 + + + +
+
+ + + s.empty() == false + + + false == false + + + + + s.size() == 5 + + + 5 == 5 + + + + + isSubstring( s ) == false + + + false == false + + + + + std::strcmp( rawChars, "hello" ) == 0 + + + 0 == 0 + + +
+ + + isOwned( s ) == false + + + false == false + + + + + s.c_str() == rawChars + + + "hello" == "hello" + + + + + isOwned( s ) == false + + + false == false + + + +
+ +
+
+ + + original == "original" + + + original == "original" + + + + + isSubstring( original ) + + + false + + + +
+
+
+ + + ss.empty() == false + + + false == false + + + + + ss.size() == 5 + + + 5 == 5 + + + + + std::strcmp( ss.c_str(), "hello" ) == 0 + + + 0 == 0 + + + + + ss == "hello" + + + hello == "hello" + + + +
+ +
+
+
+ + + isSubstring( ss ) + + + true + + + + + isOwned( ss ) == false + + + false == false + + + + + rawChars == data( s ) + + + "hello world!" == "hello world!" + + + + + ss.c_str() != rawChars + + + "hello" != "hello world!" + + + + + isSubstring( ss ) == false + + + false == false + + + + + isOwned( ss ) + + + true + + + + + data( ss ) != data( s ) + + + "hello" != "hello world!" + + + +
+ +
+
+
+ + + ss.size() == 6 + + + 6 == 6 + + + + + std::strcmp( ss.c_str(), "world!" ) == 0 + + + 0 == 0 + + + +
+ +
+
+
+ + + s.c_str() == s2.c_str() + + + "hello world!" == "hello world!" + + + +
+ +
+
+
+ + + s.c_str() != ss.c_str() + + + "hello world!" != "hello" + + + +
+ +
+
+ + + StringRef("hello") == StringRef("hello") + + + hello == hello + + + + + StringRef("hello") != StringRef("cello") + + + hello != cello + + + +
+
+
+ + + sr == "a standard string" + + + a standard string == "a standard string" + + + + + sr.size() == stdStr.size() + + + 17 == 17 + + + +
+ +
+
+
+ + + sr == "a standard string" + + + a standard string == "a standard string" + + + + + sr.size() == stdStr.size() + + + 17 == 17 + + + +
+ +
+
+
+ + + sr == "a standard string" + + + a standard string == "a standard string" + + + + + sr.size() == stdStr.size() + + + 17 == 17 + + + +
+ +
+
+
+ + + stdStr == "a stringref" + + + "a stringref" == "a stringref" + + + + + stdStr.size() == sr.size() + + + 11 == 11 + + + +
+ +
+
+
+ + + stdStr == "a stringref" + + + "a stringref" == "a stringref" + + + + + stdStr.size() == sr.size() + + + 11 == 11 + + + +
+ +
+
+
+ + + stdStr == "a stringref" + + + "a stringref" == "a stringref" + + + + + stdStr.size() == sr.size() + + + 11 == 11 + + + +
+ +
+ +
+ + + + s1 == s2 + + + "if ($b == 10) { + $a = 20; +}" +== +"if ($b == 10) { + $a = 20; +} +" + + + + + +
+ + + what, Contains( "[@zzz]" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "[@zzz]" + + + + + what, Contains( "file" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "file" + + + + + what, Contains( "2" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "2" + + + + + what, Contains( "10" ) + + + "error: tag alias, '[@zzz]' already registered. + First seen at: file:2 + Redefined at: file:10" contains: "10" + + + +
+
+ + + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + + + + + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + + + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + + + +
+ +
+ + + + + + + 0x == bit30and31 + + + 3221225472 (0x) == 3221225472 + + + + + + + + 1 == 2 + + + 1 == 2 + + + + + + + + + + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isSuccessfullyCompleted() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2.isOpen() + + + true + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isSuccessfullyCompleted() + + + true + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isComplete() + + + true + + + + + s2b.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() == false + + + false == false + + + + + s2c.isOpen() == false + + + false == false + + + + + testCase3.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + s1.isComplete() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + testCase.isComplete() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s1.isComplete() == false + + + false == false + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s1.isComplete() == false + + + false == false + + + + + s1b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s2b.isOpen() + + + true + + + + + s2b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + s1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s2.isSuccessfullyCompleted() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 0 + + + 0 == 0 + + + + + s2b.isOpen() == false + + + false == false + + + + + g1b.isComplete() == false + + + false == false + + + + + s1b.isComplete() == false + + + false == false + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() + + + true + + + + + g1c.isOpen() + + + true + + + + + g1c.index() == 1 + + + 1 == 1 + + + + + s2c.isOpen() + + + true + + + + + s2c.isComplete() + + + true + + + + + g1c.isComplete() + + + true + + + + + s1c.isComplete() + + + true + + + + + testCase3.isComplete() + + + true + + + +
+ +
+ +
+ +
+ + + 3.14 + + + + + + + d == approx( 1.23 ) + + + 1.23 == Approx( 1.23 ) + + + + + d == approx( 1.22 ) + + + 1.23 == Approx( 1.22 ) + + + + + d == approx( 1.24 ) + + + 1.23 == Approx( 1.24 ) + + + + + d != approx( 1.25 ) + + + 1.23 != Approx( 1.25 ) + + + + + approx( d ) == 1.23 + + + Approx( 1.23 ) == 1.23 + + + + + approx( d ) == 1.22 + + + Approx( 1.23 ) == 1.22 + + + + + approx( d ) == 1.24 + + + Approx( 1.23 ) == 1.24 + + + + + approx( d ) != 1.25 + + + Approx( 1.23 ) != 1.25 + + + + + +
+ +
+ +
+ +
+ + + v, VectorContains( 1 ) + + + { 1, 2, 3 } Contains: 1 + + + + + v, VectorContains( 2 ) + + + { 1, 2, 3 } Contains: 2 + + + +
+
+ + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2 } + + + + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2, 3 } + + + + + v, Contains( empty) + + + { 1, 2, 3 } Contains: { } + + + + + empty, Contains( empty) + + + { } Contains: { } + + + +
+
+ + + v, Equals( v ) + + + { 1, 2, 3 } Equals: { 1, 2, 3 } + + + + + empty, Equals( empty ) + + + { } Equals: { } + + + + + v, Equals( v2 ) + + + { 1, 2, 3 } Equals: { 1, 2, 3 } + + + +
+ +
+ +
+ + + v, VectorContains( -1 ) + + + { 1, 2, 3 } Contains: -1 + + + + + empty, VectorContains( 1 ) + + + { } Contains: 1 + + + +
+
+ + + empty, Contains( v) + + + { } Contains: { 1, 2, 3 } + + + + + v, Contains( v2 ) + + + { 1, 2, 3 } Contains: { 1, 2, 4 } + + + +
+
+ + + v, Equals( v2 ) + + + { 1, 2, 3 } Equals: { 1, 2 } + + + + + v2, Equals( v ) + + + { 1, 2 } Equals: { 1, 2, 3 } + + + + + empty, Equals( v ) + + + { } Equals: { 1, 2, 3 } + + + + + v, Equals( empty ) + + + { 1, 2, 3 } Equals: { } + + + +
+ +
+ + + + thisThrows(), std::domain_error + + + thisThrows(), std::domain_error + + + + + thisDoesntThrow() + + + thisDoesntThrow() + + + + + thisThrows() + + + thisThrows() + + + + + + + unexpected exception + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + + + + thisThrows() == 0 + + + thisThrows() == 0 + + + expected exception + + + + + +
+ + unexpected exception + + +
+ +
+ + + + + + Uncomment the code in this test to check that it gives a sensible compiler error + + + + + + Uncomment the code in this test to check that it gives a sensible compiler error + + + + + + + + + + + + + + + + +
+ + + encode( "normal string" ) == "normal string" + + + "normal string" == "normal string" + + + +
+
+ + + encode( "" ) == "" + + + "" == "" + + + +
+
+ + + encode( "smith & jones" ) == "smith &amp; jones" + + + "smith &amp; jones" == "smith &amp; jones" + + + +
+
+ + + encode( "smith < jones" ) == "smith &lt; jones" + + + "smith &lt; jones" == "smith &lt; jones" + + + +
+
+ + + encode( "smith > jones" ) == "smith > jones" + + + "smith > jones" == "smith > jones" + + + + + encode( "smith ]]> jones" ) == "smith ]]&gt; jones" + + + "smith ]]&gt; jones" +== +"smith ]]&gt; jones" + + + +
+
+ + + encode( stringWithQuotes ) == stringWithQuotes + + + "don't "quote" me on that" +== +"don't "quote" me on that" + + + + + encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" + + + "don't &quot;quote&quot; me on that" +== +"don't &quot;quote&quot; me on that" + + + +
+
+ + + encode( "[\x01]" ) == "[\\x01]" + + + "[\x01]" == "[\x01]" + + + +
+
+ + + encode( "[\x7F]" ) == "[\\x7F]" + + + "[\x7F]" == "[\x7F]" + + + +
+ +
+ + + + + + + x == 0 + + + 0 == 0 + + + + + + + + obj.prop != 0 + + + 0x != 0 + + + + + + + + flag + + + true + + + + + testCheckedElse( true ) + + + true + + + + + + + + flag + + + false + + + + + testCheckedElse( false ) + + + false + + + + + + + + flag + + + true + + + + + testCheckedIf( true ) + + + true + + + + + + + + flag + + + false + + + + + testCheckedIf( false ) + + + false + + + + + + + + unsigned_char_var == 1 + + + 1 == 1 + + + + + unsigned_short_var == 1 + + + 1 == 1 + + + + + unsigned_int_var == 1 + + + 1 == 1 + + + + + unsigned_long_var == 1 + + + 1 == 1 + + + + + + + + long_var == unsigned_char_var + + + 1 == 1 + + + + + long_var == unsigned_short_var + + + 1 == 1 + + + + + long_var == unsigned_int_var + + + 1 == 1 + + + + + long_var == unsigned_long_var + + + 1 == 1 + + + + + +
+
+ +
+ +
+
+
+ +
+ +
+
+ +
+ +
+ + + + +loose text artifact + + + + + Previous info should not be seen + + + + + + + + + + l == std::numeric_limits<long long>::max() + + + 9223372036854775807 (0x) +== +9223372036854775807 (0x) + + + + + +
+ + + b > a + + + 0 > 1 + + + +
+ +
+ + + Testing if fib[0] (1) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[1] (1) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[2] (2) is even + + + + ( fib[i] % 2 ) == 0 + + + 0 == 0 + + + + Testing if fib[3] (3) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[4] (5) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[5] (8) is even + + + + ( fib[i] % 2 ) == 0 + + + 0 == 0 + + + + Testing if fib[6] (13) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + Testing if fib[7] (21) is even + + + + ( fib[i] % 2 ) == 0 + + + 1 == 0 + + + + + +
+
+ + + a == b + + + 1 == 2 + + + +
+ +
+
+
+ + + a != b + + + 1 != 2 + + + +
+ +
+
+
+ + + a < b + + + 1 < 2 + + + +
+ +
+ +
+ +
+ + + a != b + + + 1 != 2 + + + + + b != a + + + 2 != 1 + + +
+ + + a != b + + + 1 != 2 + + + +
+ +
+ +
+ + + + s == "7" + + + "7" == "7" + + + + + + + + ti == typeid(int) + + + {?} == {?} + + + + + + + + + + + makeString( false ) != static_cast<char*>(0) + + + "valid string" != {null string} + + + + + makeString( true ) == static_cast<char*>(0) + + + {null string} == {null string} + + + + + + + + ptr.get() == 0 + + + 0 == 0 + + + + + + + + ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" + + + "{ { 42, "Arthur" }, { "Ford", 24 } }" +== +"{ { 42, "Arthur" }, { "Ford", 24 } }" + + + + + + + + p == 0 + + + 0 == 0 + + + + + +
+ + + a != b + + + 1 != 2 + + + + + b != a + + + 2 != 1 + + + +
+
+ + + a != b + + + 1 != 2 + + + +
+ +
+ +
+ + + Catch::replaceInPlace( letters, "b", "z" ) + + + true + + + + + letters == "azcdefcg" + + + "azcdefcg" == "azcdefcg" + + + +
+
+ + + Catch::replaceInPlace( letters, "c", "z" ) + + + true + + + + + letters == "abzdefzg" + + + "abzdefzg" == "abzdefzg" + + + +
+
+ + + Catch::replaceInPlace( letters, "a", "z" ) + + + true + + + + + letters == "zbcdefcg" + + + "zbcdefcg" == "zbcdefcg" + + + +
+
+ + + Catch::replaceInPlace( letters, "g", "z" ) + + + true + + + + + letters == "abcdefcz" + + + "abcdefcz" == "abcdefcz" + + + +
+
+ + + Catch::replaceInPlace( letters, letters, "replaced" ) + + + true + + + + + letters == "replaced" + + + "replaced" == "replaced" + + + +
+
+ + + !Catch::replaceInPlace( letters, "x", "z" ) + + + !false + + + + + letters == letters + + + "abcdefcg" == "abcdefcg" + + + +
+
+ + + Catch::replaceInPlace( s, "'", "|'" ) + + + true + + + + + s == "didn|'t" + + + "didn|'t" == "didn|'t" + + + +
+ +
+ + + + + + 3 + + + + false + + + false + + + + + + + hi + + + i := 7 + + + + false + + + false + + + + + + + + ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" + + + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + + + + + + + + ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" + + + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + + + + + + + + ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" + + + "{ { "green", 55 } }" +== +"{ { "green", 55 } }" + + + + + + + + std::string( "first" ) == "second" + + + "first" == "second" + + + + + + + + ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" + + + "StringMaker<has_maker>" +== +"StringMaker<has_maker>" + + + + + + + + ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" + + + "StringMaker<has_maker_and_operator>" +== +"StringMaker<has_maker_and_operator>" + + + + + + + + ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" + + + "operator<<( has_operator )" +== +"operator<<( has_operator )" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + result == "\"wide load\"" + + + ""wide load"" == ""wide load"" + + + + + + + + ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" + + + "{ StringMaker<has_maker> }" +== +"{ StringMaker<has_maker> }" + + + + + + + + ::Catch::Detail::stringify(e0) == "E2/V0" + + + "E2/V0" == "E2/V0" + + + + + ::Catch::Detail::stringify(e1) == "E2/V1" + + + "E2/V1" == "E2/V1" + + + + + ::Catch::Detail::stringify(e3) == "Unknown enum value 10" + + + "Unknown enum value 10" +== +"Unknown enum value 10" + + + + + + + + ::Catch::Detail::stringify(e0) == "0" + + + "{?}" == "0" + + + + + ::Catch::Detail::stringify(e1) == "1" + + + "{?}" == "1" + + + + + + + + ::Catch::Detail::stringify(e0) == "E2{0}" + + + "E2{0}" == "E2{0}" + + + + + ::Catch::Detail::stringify(e1) == "E2{1}" + + + "E2{1}" == "E2{1}" + + + + + + + + ::Catch::Detail::stringify(e0) == "0" + + + "0" == "0" + + + + + ::Catch::Detail::stringify(e1) == "1" + + + "1" == "1" + + + + + + + + "{ }" == ::Catch::Detail::stringify(type{}) + + + "{ }" == "{ }" + + + + + "{ }" == ::Catch::Detail::stringify(value) + + + "{ }" == "{ }" + + + + + + + + "1.2f" == ::Catch::Detail::stringify(float(1.2)) + + + "1.2f" == "1.2f" + + + + + "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) + + + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + + + + + + + + "{ 0 }" == ::Catch::Detail::stringify(type{0}) + + + "{ 0 }" == "{ 0 }" + + + + + + + + "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) + + + "{ 0, 42, "Catch me" }" +== +"{ 0, 42, "Catch me" }" + + + + + + + + "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) + + + "{ "hello", "world" }" +== +"{ "hello", "world" }" + + + + + + + + "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) + + + "{ { 42 }, { }, 1.2f }" +== +"{ { 42 }, { }, 1.2f }" + + + + + + + + ::Catch::Detail::stringify(v) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" + + + "{ { "hello" }, { "world" } }" +== +"{ { "hello" }, { "world" } }" + + + + + + + + ::Catch::Detail::stringify(vv) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42 }" + + + "{ 42 }" == "{ 42 }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42, 250 }" + + + "{ 42, 250 }" == "{ 42, 250 }" + + + + + + + + ::Catch::Detail::stringify(vv) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42 }" + + + "{ 42 }" == "{ 42 }" + + + + + ::Catch::Detail::stringify(vv) == "{ 42, 250 }" + + + "{ 42, 250 }" == "{ 42, 250 }" + + + + + + + + ::Catch::Detail::stringify(vv) == "{ }" + + + "{ }" == "{ }" + + + + + ::Catch::Detail::stringify(vv) == "{ \"hello\" }" + + + "{ "hello" }" == "{ "hello" }" + + + + + ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" + + + "{ "hello", "world" }" +== +"{ "hello", "world" }" + + + + + + + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 10 + + + 10 == 10 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 0 + + + 0 == 0 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.capacity() == 0 + + + 0 == 0 + + + +
+ +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 10 + + + 10 >= 10 + + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + +
+ + + v.size() == 5 + + + 5 == 5 + + + + + v.capacity() >= 5 + + + 5 >= 5 + + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index a03b21ff..8d15c6a4 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -435,3 +435,9 @@ TEST_CASE( "null deref", "[.][failing][!nonportable]" ) { int *x = NULL; *x = 1; } + +TEST_CASE( "non-copyable objects", "[.]" ) { + // Thanks to Agustin Bergé (@k-ballo on the cpplang Slack) for raising this + std::type_info const& ti = typeid(int); + CHECK( ti == typeid(int) ); +} From 632e023ff491e4d3f45d3408194b30247a43f1a7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 16:55:35 +0100 Subject: [PATCH 260/398] Added non-copyable test to [failing] set --- .../SelfTest/Baselines/xml.sw.approved.txt | 2 +- .../SelfTest/Baselines/xml.sw.unapproved.txt | 8293 ----------------- projects/SelfTest/TrickyTests.cpp | 2 +- 3 files changed, 2 insertions(+), 8295 deletions(-) delete mode 100644 projects/SelfTest/Baselines/xml.sw.unapproved.txt diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 685e21bc..edabc05e 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -7433,7 +7433,7 @@ loose text artifact
- + ti == typeid(int) diff --git a/projects/SelfTest/Baselines/xml.sw.unapproved.txt b/projects/SelfTest/Baselines/xml.sw.unapproved.txt deleted file mode 100644 index edabc05e..00000000 --- a/projects/SelfTest/Baselines/xml.sw.unapproved.txt +++ /dev/null @@ -1,8293 +0,0 @@ - - - - - - - -
- - answer := 42 - - - expected exception - - -
-
- - answer := 42 - - - - thisThrows() - - - thisThrows() - - - expected exception - - - -
-
- - answer := 42 - - - - thisThrows() - - - thisThrows() - - - -
- -
- - - - 42 == f - - - 42 == {?} - - - - - - - - a == t - - - 3 == 3 - - - - - a == t - - - 3 == 3 - - - - - throws_int(true) - - - throws_int(true) - - - - - throws_int(true), int - - - throws_int(true), int - - - - - throws_int(false) - - - throws_int(false) - - - - - "aaa", Catch::EndsWith("aaa") - - - "aaa" ends with: "aaa" - - - - - templated_tests<int>(3) - - - true - - - - - - - - f() == 0 - - - 1 == 0 - - - - - errno == 1 - - - 1 == 1 - - - - - - - dummy := 0 - - - - x == 4 - - - {?} == 4 - - - - - -
- -
-
- -
-
- -
-
- -
-
- -
- -
- - - - false != false - - - false != false - - - - - true != true - - - true != true - - - - - !true - - - false - - - - - !true - - - !true - - - - - !trueValue - - - false - - - - - !trueValue - - - !true - - - - - !(1 == 1) - - - false - - - - - !1 == 1 - - - !(1 == 1) - - - - - - - - false == false - - - false == false - - - - - true == true - - - true == true - - - - - !false - - - true - - - - - !false - - - !false - - - - - !falseValue - - - true - - - - - !falseValue - - - !false - - - - - !(1 == 2) - - - true - - - - - !1 == 2 - - - !(1 == 2) - - - - - -
- - - is_true<true>::value == true - - - true == true - - - - - true == is_true<true>::value - - - true == true - - - -
-
- - - is_true<false>::value == false - - - false == false - - - - - false == is_true<false>::value - - - false == false - - - -
-
- - - !is_true<false>::value - - - true - - - -
-
- - - !!is_true<true>::value - - - true - - - -
-
- - - is_true<true>::value - - - true - - - - - !is_true<false>::value - - - !false - - - -
- -
- - - - s == "world" - - - "hello" == "world" - - - - - - - - s == "hello" - - - "hello" == "hello" - - - - - - - - m_a == 2 - - - 1 == 2 - - - - - - - - m_a == 1 - - - 1 == 1 - - - - - -
-
- -
- -
- - to infinity and beyond - - -
- - - - &o1 == &o2 - - - 0x == 0x - - - - - o1 == o2 - - - {?} == {?} - - - - - - - - 104.0 != Approx(100.0) - - - 104.0 != Approx( 100.0 ) - - - - - 104.0 == Approx(100.0).margin(5) - - - 104.0 == Approx( 100.0 ) - - - - - 104.0 != Approx(100.0).margin(3) - - - 104.0 != Approx( 100.0 ) - - - - - 100.3 != Approx(100.0) - - - 100.3 != Approx( 100.0 ) - - - - - 100.3 == Approx(100.0).margin(0.5) - - - 100.3 == Approx( 100.0 ) - - - - - - - - testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) - - - "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) - - - - - - - - - - - i++ == 7 - - - 7 == 7 - - - - - i++ == 8 - - - 8 == 8 - - - - - - - - 1 == 1 - - - 1 == 1 - - - - - {Unknown expression after the reported line} - - - {Unknown expression after the reported line} - - - unexpected exception - - - - - - - - - - - testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) - - - "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) - - - - - testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) - - - "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) - - - - - - - - divide( 22, 7 ) == Approx( 3.141 ).epsilon( 0.001 ) - - - 3.1428571429 == Approx( 3.141 ) - - - - - divide( 22, 7 ) != Approx( 3.141 ).epsilon( 0.0001 ) - - - 3.1428571429 != Approx( 3.141 ) - - - - - - - - d != Approx( 1.231 ) - - - 1.23 != Approx( 1.231 ) - - - - - d == Approx( 1.231 ).epsilon( 0.1 ) - - - 1.23 == Approx( 1.231 ) - - - - - - - - 1.23f == Approx( 1.23f ) - - - 1.23f == Approx( 1.2300000191 ) - - - - - 0.0f == Approx( 0.0f ) - - - 0.0f == Approx( 0.0 ) - - - - - - - - 1 == Approx( 1 ) - - - 1 == Approx( 1.0 ) - - - - - 0 == Approx( 0 ) - - - 0 == Approx( 0.0 ) - - - - - - - - 1.0f == Approx( 1 ) - - - 1.0f == Approx( 1.0 ) - - - - - 0 == Approx( dZero) - - - 0 == Approx( 0.0 ) - - - - - 0 == Approx( dSmall ).epsilon( 0.001 ) - - - 0 == Approx( 0.00001 ) - - - - - 1.234f == Approx( dMedium ) - - - 1.234f == Approx( 1.234 ) - - - - - dMedium == Approx( 1.234f ) - - - 1.234 == Approx( 1.2339999676 ) - - - - - - - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - - -
- -
- - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - -
- - - Catch::alwaysTrue() - - - true - - - -
- -
- -
- -
- - i := 2 - - - - true - - - true - - - -
-
- - 3 - - - - true - - - true - - - -
- -
- -
- - - tab == '\t' - - - '\t' == '\t' - - - - - newline == '\n' - - - '\n' == '\n' - - - - - carr_return == '\r' - - - '\r' == '\r' - - - - - form_feed == '\f' - - - '\f' == '\f' - - - -
-
- - - space == ' ' - - - ' ' == ' ' - - - - - c == chars[i] - - - 'a' == 'a' - - - - - c == chars[i] - - - 'z' == 'z' - - - - - c == chars[i] - - - 'A' == 'A' - - - - - c == chars[i] - - - 'Z' == 'Z' - - - -
-
- - - null_terminator == '\0' - - - 0 == 0 - - - - - c == i - - - 2 == 2 - - - - - c == i - - - 3 == 3 - - - - - c == i - - - 4 == 4 - - - - - c == i - - - 5 == 5 - - - -
- -
- - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - std::vector<constructor_throws>{constructor_throws{}, constructor_throws{}} - - - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - std::vector<int>{1, 2, 3} == std::vector<int>{1, 2, 3} - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} - - - !({ 1, 2 } == { 1, 2, 3 }) - - - - - !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} - - - !({ 1, 2 } == { 1, 2, 3 }) - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - true - - - true - - - - - std::vector<int>{1, 2} == std::vector<int>{1, 2} - - - { 1, 2 } == { 1, 2 } - - - - - - - - a - - - 0x - - - - - a == &foo - - - 0x == 0x - - - - - - - - m == &S::f - - - 0x -== -0x - - - - - - - - td == Approx(10.0) - - - StrongDoubleTypedef(10) == Approx( 10.0 ) - - - - - Approx(10.0) == td - - - Approx( 10.0 ) == StrongDoubleTypedef(10) - - - - - td != Approx(11.0) - - - StrongDoubleTypedef(10) != Approx( 11.0 ) - - - - - Approx(11.0) != td - - - Approx( 11.0 ) != StrongDoubleTypedef(10) - - - - - td <= Approx(10.0) - - - StrongDoubleTypedef(10) <= Approx( 10.0 ) - - - - - td <= Approx(11.0) - - - StrongDoubleTypedef(10) <= Approx( 11.0 ) - - - - - Approx(10.0) <= td - - - Approx( 10.0 ) <= StrongDoubleTypedef(10) - - - - - Approx(9.0) <= td - - - Approx( 9.0 ) <= StrongDoubleTypedef(10) - - - - - td >= Approx(9.0) - - - StrongDoubleTypedef(10) >= Approx( 9.0 ) - - - - - td >= Approx(10.0) - - - StrongDoubleTypedef(10) >= Approx( 10.0 ) - - - - - Approx(10.0) >= td - - - Approx( 10.0 ) >= StrongDoubleTypedef(10) - - - - - Approx(11.0) >= td - - - Approx( 11.0 ) >= StrongDoubleTypedef(10) - - - - - - - - 54 == 6*9 - - - 54 == 54 - - - - - - - - ( -1 > 2u ) - - - true - - - - - -1 > 2u - - - -1 > 2 - - - - - ( 2u < -1 ) - - - true - - - - - 2u < -1 - - - 2 < -1 - - - - - ( minInt > 2u ) - - - true - - - - - minInt > 2u - - - -2147483648 > 2 - - - - - - - - i == 1 - - - 1 == 1 - - - - - ui == 2 - - - 2 == 2 - - - - - l == 3 - - - 3 == 3 - - - - - ul == 4 - - - 4 == 4 - - - - - c == 5 - - - 5 == 5 - - - - - uc == 6 - - - 6 == 6 - - - - - 1 == i - - - 1 == 1 - - - - - 2 == ui - - - 2 == 2 - - - - - 3 == l - - - 3 == 3 - - - - - 4 == ul - - - 4 == 4 - - - - - 5 == c - - - 5 == 5 - - - - - 6 == uc - - - 6 == 6 - - - - - (std::numeric_limits<unsigned long>::max)() > ul - - - 18446744073709551615 (0x) -> -4 - - - - - - - - testStringForMatching(), Contains( "not there" ) - - - "this string contains 'abc' as a substring" contains: "not there" - - - - - - - - throwCustom() - - - throwCustom() - - - custom exception - not std - - - - - - - - throwCustom(), std::exception - - - throwCustom(), std::exception - - - custom exception - not std - - - - - - - custom std exception - - - - - - - t == 1u - - - {?} == 1 - - - - - - - - testStringForMatching(), EndsWith( "this" ) - - - "this string contains 'abc' as a substring" ends with: "this" - - - - - - - - data.int_seven == 6 - - - 7 == 6 - - - - - data.int_seven == 8 - - - 7 == 8 - - - - - data.int_seven == 0 - - - 7 == 0 - - - - - data.float_nine_point_one == Approx( 9.11f ) - - - 9.1f == Approx( 9.1099996567 ) - - - - - data.float_nine_point_one == Approx( 9.0f ) - - - 9.1f == Approx( 9.0 ) - - - - - data.float_nine_point_one == Approx( 1 ) - - - 9.1f == Approx( 1.0 ) - - - - - data.float_nine_point_one == Approx( 0 ) - - - 9.1f == Approx( 0.0 ) - - - - - data.double_pi == Approx( 3.1415 ) - - - 3.1415926535 == Approx( 3.1415 ) - - - - - data.str_hello == "goodbye" - - - "hello" == "goodbye" - - - - - data.str_hello == "hell" - - - "hello" == "hell" - - - - - data.str_hello == "hello1" - - - "hello" == "hello1" - - - - - data.str_hello.size() == 6 - - - 5 == 6 - - - - - x == Approx( 1.301 ) - - - 1.3 == Approx( 1.301 ) - - - - - - - - data.int_seven == 7 - - - 7 == 7 - - - - - data.float_nine_point_one == Approx( 9.1f ) - - - 9.1f == Approx( 9.1000003815 ) - - - - - data.double_pi == Approx( 3.1415926535 ) - - - 3.1415926535 == Approx( 3.1415926535 ) - - - - - data.str_hello == "hello" - - - "hello" == "hello" - - - - - "hello" == data.str_hello - - - "hello" == "hello" - - - - - data.str_hello.size() == 5 - - - 5 == 5 - - - - - x == Approx( 1.3 ) - - - 1.3 == Approx( 1.3 ) - - - - - - - - testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) - - - "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" - - - - - - - - testStringForMatching(), Equals( "something else" ) - - - "this string contains 'abc' as a substring" equals: "something else" - - - - - -
- - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } - - - -
-
- - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - Unknown exception - - - - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - throwsAsInt(1), SpecialException, ExceptionMatcher{ 1 } - - - Unknown exception - - - -
-
- - - throws(3), SpecialException, ExceptionMatcher{ 1 } - - - {?} special exception has value of 1 - - - - - throws(4), SpecialException, ExceptionMatcher{ 1 } - - - {?} special exception has value of 1 - - - -
- -
- - - - throws(1), SpecialException, ExceptionMatcher{ 1 } - - - {?} special exception has value of 1 - - - - - throws(2), SpecialException, ExceptionMatcher{ 2 } - - - {?} special exception has value of 2 - - - - - -
- - - thisThrows(), "expected exception" - - - "expected exception" equals: "expected exception" - - - -
-
- - - thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) - - - "expected exception" equals: "expected exception" (case insensitive) - - - -
-
- - - thisThrows(), StartsWith( "expected" ) - - - "expected exception" starts with: "expected" - - - - - thisThrows(), EndsWith( "exception" ) - - - "expected exception" ends with: "exception" - - - - - thisThrows(), Contains( "except" ) - - - "expected exception" contains: "except" - - - - - thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) - - - "expected exception" contains: "except" (case insensitive) - - - -
- -
- - - - thisThrows(), std::string - - - thisThrows(), std::string - - - expected exception - - - - - thisDoesntThrow(), std::domain_error - - - thisDoesntThrow(), std::domain_error - - - - - thisThrows() - - - thisThrows() - - - expected exception - - - - - - - This is a failure - - - - - - - - - - This is a failure - - - This message appears in the output - - - - - - - Factorial(0) == 1 - - - 1 == 1 - - - - - Factorial(1) == 1 - - - 1 == 1 - - - - - Factorial(2) == 2 - - - 2 == 2 - - - - - Factorial(3) == 6 - - - 6 == 6 - - - - - Factorial(10) == 3628800 - - - 3628800 (0x) == 3628800 (0x) - - - - - - - - d >= Approx( 1.22 ) - - - 1.23 >= Approx( 1.22 ) - - - - - d >= Approx( 1.23 ) - - - 1.23 >= Approx( 1.23 ) - - - - - !d >= Approx( 1.24 ) - - - !(1.23 >= Approx( 1.24 )) - - - - - d >= Approx( 1.24 ).epsilon(0.1) - - - 1.23 >= Approx( 1.24 ) - - - - - - - this is a message - - - this is a warning - - - - - - this message should be logged - - - so should this - - - - a == 1 - - - 2 == 1 - - - - - - - this message may be logged later - - - - a == 2 - - - 2 == 2 - - - - this message may be logged later - - - this message should be logged - - - - a == 1 - - - 2 == 1 - - - - this message may be logged later - - - this message should be logged - - - and this, but later - - - - a == 0 - - - 2 == 0 - - - - this message may be logged later - - - this message should be logged - - - and this, but later - - - but not this - - - - a == 2 - - - 2 == 2 - - - - - - - current counter 0 - - - i := 0 - - - - i < 10 - - - 0 < 10 - - - - current counter 1 - - - i := 1 - - - - i < 10 - - - 1 < 10 - - - - current counter 2 - - - i := 2 - - - - i < 10 - - - 2 < 10 - - - - current counter 3 - - - i := 3 - - - - i < 10 - - - 3 < 10 - - - - current counter 4 - - - i := 4 - - - - i < 10 - - - 4 < 10 - - - - current counter 5 - - - i := 5 - - - - i < 10 - - - 5 < 10 - - - - current counter 6 - - - i := 6 - - - - i < 10 - - - 6 < 10 - - - - current counter 7 - - - i := 7 - - - - i < 10 - - - 7 < 10 - - - - current counter 8 - - - i := 8 - - - - i < 10 - - - 8 < 10 - - - - current counter 9 - - - i := 9 - - - - i < 10 - - - 9 < 10 - - - - current counter 10 - - - i := 10 - - - - i < 10 - - - 10 < 10 - - - - - - - - data.int_seven != 7 - - - 7 != 7 - - - - - data.float_nine_point_one != Approx( 9.1f ) - - - 9.1f != Approx( 9.1000003815 ) - - - - - data.double_pi != Approx( 3.1415926535 ) - - - 3.1415926535 != Approx( 3.1415926535 ) - - - - - data.str_hello != "hello" - - - "hello" != "hello" - - - - - data.str_hello.size() != 5 - - - 5 != 5 - - - - - - - - data.int_seven != 6 - - - 7 != 6 - - - - - data.int_seven != 8 - - - 7 != 8 - - - - - data.float_nine_point_one != Approx( 9.11f ) - - - 9.1f != Approx( 9.1099996567 ) - - - - - data.float_nine_point_one != Approx( 9.0f ) - - - 9.1f != Approx( 9.0 ) - - - - - data.float_nine_point_one != Approx( 1 ) - - - 9.1f != Approx( 1.0 ) - - - - - data.float_nine_point_one != Approx( 0 ) - - - 9.1f != Approx( 0.0 ) - - - - - data.double_pi != Approx( 3.1415 ) - - - 3.1415926535 != Approx( 3.1415 ) - - - - - data.str_hello != "goodbye" - - - "hello" != "goodbye" - - - - - data.str_hello != "hell" - - - "hello" != "hell" - - - - - data.str_hello != "hello1" - - - "hello" != "hello1" - - - - - data.str_hello.size() != 6 - - - 5 != 6 - - - - - - - - d <= Approx( 1.24 ) - - - 1.23 <= Approx( 1.24 ) - - - - - d <= Approx( 1.23 ) - - - 1.23 <= Approx( 1.23 ) - - - - - !d <= Approx( 1.22 ) - - - !(1.23 <= Approx( 1.22 )) - - - - - d <= Approx( 1.22 ).epsilon(0.1) - - - 1.23 <= Approx( 1.22 ) - - - - - - - - - - - testStringForMatching(), Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) - - - "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" ) - - - - - - - - testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) - - - "this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" ) - - - - - testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) - - - "some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" ) - - - - - - - - testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) - - - "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" ) - - - - - - - - testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) - - - "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) - - - - - - - - testStringForMatching(), !Contains( "different" ) - - - "this string contains 'abc' as a substring" not contains: "different" - - - - - - - - testStringForMatching(), !Contains( "substring" ) - - - "this string contains 'abc' as a substring" not contains: "substring" - - - - - - - - thisThrows(), "expected exception" - - - "expected exception" equals: "expected exception" - - - - - thisThrows(), "should fail" - - - "expected exception" equals: "should fail" - - - - - - - This one ran - - - - - - custom exception - - - - - - - True - - - {?} - - - - - !False - - - true - - - - - !False - - - !{?} - - - - - - - - 0x == o - - - 3221225472 (0x) == {?} - - - - - - - - data.int_seven > 7 - - - 7 > 7 - - - - - data.int_seven < 7 - - - 7 < 7 - - - - - data.int_seven > 8 - - - 7 > 8 - - - - - data.int_seven < 6 - - - 7 < 6 - - - - - data.int_seven < 0 - - - 7 < 0 - - - - - data.int_seven < -1 - - - 7 < -1 - - - - - data.int_seven >= 8 - - - 7 >= 8 - - - - - data.int_seven <= 6 - - - 7 <= 6 - - - - - data.float_nine_point_one < 9 - - - 9.1f < 9 - - - - - data.float_nine_point_one > 10 - - - 9.1f > 10 - - - - - data.float_nine_point_one > 9.2 - - - 9.1f > 9.2 - - - - - data.str_hello > "hello" - - - "hello" > "hello" - - - - - data.str_hello < "hello" - - - "hello" < "hello" - - - - - data.str_hello > "hellp" - - - "hello" > "hellp" - - - - - data.str_hello > "z" - - - "hello" > "z" - - - - - data.str_hello < "hellm" - - - "hello" < "hellm" - - - - - data.str_hello < "a" - - - "hello" < "a" - - - - - data.str_hello >= "z" - - - "hello" >= "z" - - - - - data.str_hello <= "a" - - - "hello" <= "a" - - - - - - - - data.int_seven < 8 - - - 7 < 8 - - - - - data.int_seven > 6 - - - 7 > 6 - - - - - data.int_seven > 0 - - - 7 > 0 - - - - - data.int_seven > -1 - - - 7 > -1 - - - - - data.int_seven >= 7 - - - 7 >= 7 - - - - - data.int_seven >= 6 - - - 7 >= 6 - - - - - data.int_seven <= 7 - - - 7 <= 7 - - - - - data.int_seven <= 8 - - - 7 <= 8 - - - - - data.float_nine_point_one > 9 - - - 9.1f > 9 - - - - - data.float_nine_point_one < 10 - - - 9.1f < 10 - - - - - data.float_nine_point_one < 9.2 - - - 9.1f < 9.2 - - - - - data.str_hello <= "hello" - - - "hello" <= "hello" - - - - - data.str_hello >= "hello" - - - "hello" >= "hello" - - - - - data.str_hello < "hellp" - - - "hello" < "hellp" - - - - - data.str_hello < "zebra" - - - "hello" < "zebra" - - - - - data.str_hello > "hellm" - - - "hello" > "hellm" - - - - - data.str_hello > "a" - - - "hello" > "a" - - - - - -
- - Message from section one - - -
-
- - Message from section two - - -
- -
- -
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches(tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - - - parseTestSpec( "*a" ).matches( tcA ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - - - parseTestSpec( "a*" ).matches( tcA ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - - - parseTestSpec( "*a*" ).matches( tcA ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == true - - - true == true - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == true - - - true == true - - - - - spec.matches( tcB ) == true - - - true == true - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == true - - - true == true - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == false - - - false == false - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == false - - - false == false - - - -
-
- - - spec.hasFilters() == true - - - true == true - - - - - spec.matches( tcA ) == false - - - false == false - - - - - spec.matches( tcB ) == false - - - false == false - - - - - spec.matches( tcC ) == false - - - false == false - - - - - spec.matches( tcD ) == true - - - true == true - - - -
- -
- - - - (std::pair<int, int>( 1, 2 )) == aNicePair - - - { 1, 2 } == { 1, 2 } - - - - - - - - p == 0 - - - 0 == 0 - - - - - p == pNULL - - - 0 == 0 - - - - - p != 0 - - - 0x != 0 - - - - - cp != 0 - - - 0x != 0 - - - - - cpc != 0 - - - 0x != 0 - - - - - returnsNull() == 0 - - - {null string} == 0 - - - - - returnsConstNull() == 0 - - - {null string} == 0 - - - - - 0 != p - - - 0 != 0x - - - - - - - actual address of p: 0x - - - toString(p): 0x - - - - -
- - - result - - - {?} - - - - - config.processName == "" - - - "" == "" - - - -
-
- - - result - - - {?} - - - - - config.processName == "test" - - - "test" == "test" - - - - - config.shouldDebugBreak == false - - - false == false - - - - - config.abortAfter == -1 - - - -1 == -1 - - - - - config.noThrow == false - - - false == false - - - - - config.reporterNames.empty() - - - true - - - -
-
-
- - - result - - - {?} - - - - - cfg.testSpec().matches(fakeTestCase("notIncluded")) == false - - - false == false - - - - - cfg.testSpec().matches(fakeTestCase("test1")) - - - true - - - -
- -
-
-
- - - result - - - {?} - - - - - cfg.testSpec().matches(fakeTestCase("test1")) == false - - - false == false - - - - - cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) - - - true - - - -
- -
-
-
- - - result - - - {?} - - - - - cfg.testSpec().matches(fakeTestCase("test1")) == false - - - false == false - - - - - cfg.testSpec().matches(fakeTestCase("alwaysIncluded")) - - - true - - - -
- -
-
-
- - - cli.parse({"test", "-r", "console"}) - - - {?} - - - - - config.reporterNames[0] == "console" - - - "console" == "console" - - - -
- -
-
-
- - - cli.parse({"test", "-r", "xml"}) - - - {?} - - - - - config.reporterNames[0] == "xml" - - - "xml" == "xml" - - - -
- -
-
-
- - - cli.parse({"test", "-r", "xml", "-r", "junit"}) - - - {?} - - - - - config.reporterNames.size() == 2 - - - 2 == 2 - - - - - config.reporterNames[0] == "xml" - - - "xml" == "xml" - - - - - config.reporterNames[1] == "junit" - - - "junit" == "junit" - - - -
- -
-
-
- - - cli.parse({"test", "--reporter", "junit"}) - - - {?} - - - - - config.reporterNames[0] == "junit" - - - "junit" == "junit" - - - -
- -
-
-
- - - cli.parse({"test", "-b"}) - - - {?} - - - - - config.shouldDebugBreak == true - - - true == true - - - -
- -
-
-
- - - cli.parse({"test", "--break"}) - - - {?} - - - - - config.shouldDebugBreak - - - true - - - -
- -
-
-
- - - cli.parse({"test", "-a"}) - - - {?} - - - - - config.abortAfter == 1 - - - 1 == 1 - - - -
- -
-
-
- - - cli.parse({"test", "-x", "2"}) - - - {?} - - - - - config.abortAfter == 2 - - - 2 == 2 - - - -
- -
-
-
- - - !result - - - true - - - - - result.errorMessage(), Contains("convert") && Contains("oops") - - - "Unable to convert 'oops' to destination type" ( contains: "convert" and contains: "oops" ) - - - -
- -
-
-
- - - cli.parse({"test", "-e"}) - - - {?} - - - - - config.noThrow - - - true - - - -
- -
-
-
- - - cli.parse({"test", "--nothrow"}) - - - {?} - - - - - config.noThrow - - - true - - - -
- -
-
-
- - - cli.parse({"test", "-o", "filename.ext"}) - - - {?} - - - - - config.outputFilename == "filename.ext" - - - "filename.ext" == "filename.ext" - - - -
- -
-
-
- - - cli.parse({"test", "--out", "filename.ext"}) - - - {?} - - - - - config.outputFilename == "filename.ext" - - - "filename.ext" == "filename.ext" - - - -
- -
-
-
- - - cli.parse({"test", "-abe"}) - - - {?} - - - - - config.abortAfter == 1 - - - 1 == 1 - - - - - config.shouldDebugBreak - - - true - - - - - config.noThrow == true - - - true == true - - - -
- -
-
-
- - - cli.parse({"test"}) - - - {?} - - - - - config.useColour == UseColour::Auto - - - 0 == 0 - - - -
- -
-
-
- - - cli.parse({"test", "--use-colour", "auto"}) - - - {?} - - - - - config.useColour == UseColour::Auto - - - 0 == 0 - - - -
- -
-
-
- - - cli.parse({"test", "--use-colour", "yes"}) - - - {?} - - - - - config.useColour == UseColour::Yes - - - 1 == 1 - - - -
- -
-
-
- - - cli.parse({"test", "--use-colour", "no"}) - - - {?} - - - - - config.useColour == UseColour::No - - - 2 == 2 - - - -
- -
-
-
- - - !result - - - true - - - - - result.errorMessage(), Contains( "colour mode must be one of" ) - - - "colour mode must be one of: auto, yes or no. 'wrong' not recognised" contains: "colour mode must be one of" - - - -
- -
- -
- - - - truthy(false) - - - Hey, its truthy! - - - - - - - - - - - -
- - - before == 0 - - - 0 == 0 - - -
-
- - - after > before - - - 1 > 0 - - - -
- -
- -
- -
- -
-
-
- - - itDoesThis() - - - true - - -
- - - itDoesThat() - - - true - - - -
- -
- -
- -
- -
- -
-
-
- -
- -
- -
- -
- -
- - - v.size() == 0 - - - 0 == 0 - - -
-
- - - v.size() == 10 - - - 10 == 10 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - -
-
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - - -
- -
- -
- -
- -
-
- - - v.size() == 0 - - - 0 == 0 - - -
-
- - - v.capacity() >= 10 - - - 10 >= 10 - - - - - v.size() == 0 - - - 0 == 0 - - - -
- -
- -
- -
- - - -A string sent directly to stdout - - -A string sent directly to stderr - - - - - - - d == Approx( 1.23 ) - - - 1.23 == Approx( 1.23 ) - - - - - d != Approx( 1.22 ) - - - 1.23 != Approx( 1.22 ) - - - - - d != Approx( 1.24 ) - - - 1.23 != Approx( 1.24 ) - - - - - Approx( d ) == 1.23 - - - Approx( 1.23 ) == 1.23 - - - - - Approx( d ) != 1.22 - - - Approx( 1.23 ) != 1.22 - - - - - Approx( d ) != 1.24 - - - Approx( 1.23 ) != 1.24 - - - - - -
- -
-
- -
-
- -
- - -Write to std::cerr -Write to std::clog -Interleaved writes to error streams - - -
- -
- -
-
- -
- - -Message from section one -Message from section two - - -
- - - - testStringForMatching(), StartsWith( "string" ) - - - "this string contains 'abc' as a substring" starts with: "string" - - - - - - - - testStringForMatching(), Contains( "string" ) - - - "this string contains 'abc' as a substring" contains: "string" - - - - - testStringForMatching(), Contains( "abc" ) - - - "this string contains 'abc' as a substring" contains: "abc" - - - - - testStringForMatching(), StartsWith( "this" ) - - - "this string contains 'abc' as a substring" starts with: "this" - - - - - testStringForMatching(), EndsWith( "substring" ) - - - "this string contains 'abc' as a substring" ends with: "substring" - - - - - -
- - - empty.empty() - - - true - - - - - empty.size() == 0 - - - 0 == 0 - - - - - std::strcmp( empty.c_str(), "" ) == 0 - - - 0 == 0 - - - -
-
- - - s.empty() == false - - - false == false - - - - - s.size() == 5 - - - 5 == 5 - - - - - isSubstring( s ) == false - - - false == false - - - - - std::strcmp( rawChars, "hello" ) == 0 - - - 0 == 0 - - -
- - - isOwned( s ) == false - - - false == false - - - - - s.c_str() == rawChars - - - "hello" == "hello" - - - - - isOwned( s ) == false - - - false == false - - - -
- -
-
- - - original == "original" - - - original == "original" - - - - - isSubstring( original ) - - - false - - - -
-
-
- - - ss.empty() == false - - - false == false - - - - - ss.size() == 5 - - - 5 == 5 - - - - - std::strcmp( ss.c_str(), "hello" ) == 0 - - - 0 == 0 - - - - - ss == "hello" - - - hello == "hello" - - - -
- -
-
-
- - - isSubstring( ss ) - - - true - - - - - isOwned( ss ) == false - - - false == false - - - - - rawChars == data( s ) - - - "hello world!" == "hello world!" - - - - - ss.c_str() != rawChars - - - "hello" != "hello world!" - - - - - isSubstring( ss ) == false - - - false == false - - - - - isOwned( ss ) - - - true - - - - - data( ss ) != data( s ) - - - "hello" != "hello world!" - - - -
- -
-
-
- - - ss.size() == 6 - - - 6 == 6 - - - - - std::strcmp( ss.c_str(), "world!" ) == 0 - - - 0 == 0 - - - -
- -
-
-
- - - s.c_str() == s2.c_str() - - - "hello world!" == "hello world!" - - - -
- -
-
-
- - - s.c_str() != ss.c_str() - - - "hello world!" != "hello" - - - -
- -
-
- - - StringRef("hello") == StringRef("hello") - - - hello == hello - - - - - StringRef("hello") != StringRef("cello") - - - hello != cello - - - -
-
-
- - - sr == "a standard string" - - - a standard string == "a standard string" - - - - - sr.size() == stdStr.size() - - - 17 == 17 - - - -
- -
-
-
- - - sr == "a standard string" - - - a standard string == "a standard string" - - - - - sr.size() == stdStr.size() - - - 17 == 17 - - - -
- -
-
-
- - - sr == "a standard string" - - - a standard string == "a standard string" - - - - - sr.size() == stdStr.size() - - - 17 == 17 - - - -
- -
-
-
- - - stdStr == "a stringref" - - - "a stringref" == "a stringref" - - - - - stdStr.size() == sr.size() - - - 11 == 11 - - - -
- -
-
-
- - - stdStr == "a stringref" - - - "a stringref" == "a stringref" - - - - - stdStr.size() == sr.size() - - - 11 == 11 - - - -
- -
-
-
- - - stdStr == "a stringref" - - - "a stringref" == "a stringref" - - - - - stdStr.size() == sr.size() - - - 11 == 11 - - - -
- -
- -
- - - - s1 == s2 - - - "if ($b == 10) { - $a = 20; -}" -== -"if ($b == 10) { - $a = 20; -} -" - - - - - -
- - - what, Contains( "[@zzz]" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "[@zzz]" - - - - - what, Contains( "file" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "file" - - - - - what, Contains( "2" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "2" - - - - - what, Contains( "10" ) - - - "error: tag alias, '[@zzz]' already registered. - First seen at: file:2 - Redefined at: file:10" contains: "10" - - - -
-
- - - registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - - - registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - - - registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) - - - - - registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) - - - registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) - - - -
- -
- - - - - - - 0x == bit30and31 - - - 3221225472 (0x) == 3221225472 - - - - - - - - 1 == 2 - - - 1 == 2 - - - - - - - - - - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s1.isSuccessfullyCompleted() - - - true - - - - - testCase.isComplete() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isSuccessfullyCompleted() - - - true - - - -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s1.isComplete() - - - true - - - - - s1.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isSuccessfullyCompleted() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isComplete() - - - true - - - - - testCase.isSuccessfullyCompleted() - - - true - - - -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s1.isComplete() - - - true - - - - - s1.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - - - - ctx.completedCycle() - - - true - - - - - testCase.isSuccessfullyCompleted() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - s2.isOpen() - - - true - - - - - ctx.completedCycle() - - - true - - - - - testCase.isComplete() - - - true - - - - - testCase.isSuccessfullyCompleted() - - - true - - - -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s2.isOpen() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - s2b.isOpen() - - - true - - - - - ctx.completedCycle() == false - - - false == false - - -
- - - ctx.completedCycle() - - - true - - - - - s2b.isSuccessfullyCompleted() - - - true - - - - - testCase2.isComplete() == false - - - false == false - - - - - testCase2.isSuccessfullyCompleted() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s2.isOpen() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() == false - - - false == false - - - - - s2b.isOpen() - - - true - - - - - ctx.completedCycle() == false - - - false == false - - -
- - - ctx.completedCycle() - - - true - - - - - s2b.isComplete() - - - true - - - - - s2b.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase2.isSuccessfullyCompleted() == false - - - false == false - - - - - testCase3.isOpen() - - - true - - - - - s1c.isOpen() == false - - - false == false - - - - - s2c.isOpen() == false - - - false == false - - - - - testCase3.isSuccessfullyCompleted() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - s2.isOpen() - - - true - - - - - s2.isComplete() - - - true - - - - - s1.isComplete() == false - - - false == false - - - - - s1.isComplete() - - - true - - - - - testCase.isComplete() == false - - - false == false - - - - - testCase.isComplete() - - - true - - - -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - g1.isOpen() - - - true - - - - - g1.index() == 0 - - - 0 == 0 - - - - - g1.isComplete() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - -
- - - s1.isComplete() == false - - - false == false - - - - - testCase.isSuccessfullyCompleted() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() - - - true - - - - - g1b.isOpen() - - - true - - - - - g1b.index() == 1 - - - 1 == 1 - - - - - s1.isComplete() == false - - - false == false - - - - - s1b.isComplete() - - - true - - - - - g1b.isComplete() - - - true - - - - - testCase2.isComplete() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - g1.isOpen() - - - true - - - - - g1.index() == 0 - - - 0 == 0 - - - - - g1.isComplete() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - -
- - - s2.isOpen() - - - true - - - - - s2.isComplete() - - - true - - - - - s1.isComplete() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() - - - true - - - - - g1b.isOpen() - - - true - - - - - g1b.index() == 1 - - - 1 == 1 - - - - - s2b.isOpen() - - - true - - - - - s2b.isComplete() - - - true - - - - - g1b.isComplete() - - - true - - - - - s1b.isComplete() - - - true - - - - - testCase2.isComplete() - - - true - - - -
- -
- -
- - - testCase.isOpen() - - - true - - - - - s1.isOpen() - - - true - - -
- - - g1.isOpen() - - - true - - - - - g1.index() == 0 - - - 0 == 0 - - - - - g1.isComplete() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - -
- - - s2.isOpen() - - - true - - - - - s2.isComplete() - - - true - - - - - s2.isSuccessfullyCompleted() == false - - - false == false - - - - - s1.isComplete() == false - - - false == false - - - - - testCase.isComplete() == false - - - false == false - - -
- - - testCase2.isOpen() - - - true - - - - - s1b.isOpen() - - - true - - - - - g1b.isOpen() - - - true - - - - - g1b.index() == 0 - - - 0 == 0 - - - - - s2b.isOpen() == false - - - false == false - - - - - g1b.isComplete() == false - - - false == false - - - - - s1b.isComplete() == false - - - false == false - - - - - testCase2.isComplete() == false - - - false == false - - - - - testCase3.isOpen() - - - true - - - - - s1c.isOpen() - - - true - - - - - g1c.isOpen() - - - true - - - - - g1c.index() == 1 - - - 1 == 1 - - - - - s2c.isOpen() - - - true - - - - - s2c.isComplete() - - - true - - - - - g1c.isComplete() - - - true - - - - - s1c.isComplete() - - - true - - - - - testCase3.isComplete() - - - true - - - -
- -
- -
- -
- - - 3.14 - - - - - - - d == approx( 1.23 ) - - - 1.23 == Approx( 1.23 ) - - - - - d == approx( 1.22 ) - - - 1.23 == Approx( 1.22 ) - - - - - d == approx( 1.24 ) - - - 1.23 == Approx( 1.24 ) - - - - - d != approx( 1.25 ) - - - 1.23 != Approx( 1.25 ) - - - - - approx( d ) == 1.23 - - - Approx( 1.23 ) == 1.23 - - - - - approx( d ) == 1.22 - - - Approx( 1.23 ) == 1.22 - - - - - approx( d ) == 1.24 - - - Approx( 1.23 ) == 1.24 - - - - - approx( d ) != 1.25 - - - Approx( 1.23 ) != 1.25 - - - - - -
- -
- -
- -
- - - v, VectorContains( 1 ) - - - { 1, 2, 3 } Contains: 1 - - - - - v, VectorContains( 2 ) - - - { 1, 2, 3 } Contains: 2 - - - -
-
- - - v, Contains( v2 ) - - - { 1, 2, 3 } Contains: { 1, 2 } - - - - - v, Contains( v2 ) - - - { 1, 2, 3 } Contains: { 1, 2, 3 } - - - - - v, Contains( empty) - - - { 1, 2, 3 } Contains: { } - - - - - empty, Contains( empty) - - - { } Contains: { } - - - -
-
- - - v, Equals( v ) - - - { 1, 2, 3 } Equals: { 1, 2, 3 } - - - - - empty, Equals( empty ) - - - { } Equals: { } - - - - - v, Equals( v2 ) - - - { 1, 2, 3 } Equals: { 1, 2, 3 } - - - -
- -
- -
- - - v, VectorContains( -1 ) - - - { 1, 2, 3 } Contains: -1 - - - - - empty, VectorContains( 1 ) - - - { } Contains: 1 - - - -
-
- - - empty, Contains( v) - - - { } Contains: { 1, 2, 3 } - - - - - v, Contains( v2 ) - - - { 1, 2, 3 } Contains: { 1, 2, 4 } - - - -
-
- - - v, Equals( v2 ) - - - { 1, 2, 3 } Equals: { 1, 2 } - - - - - v2, Equals( v ) - - - { 1, 2 } Equals: { 1, 2, 3 } - - - - - empty, Equals( v ) - - - { } Equals: { 1, 2, 3 } - - - - - v, Equals( empty ) - - - { 1, 2, 3 } Equals: { } - - - -
- -
- - - - thisThrows(), std::domain_error - - - thisThrows(), std::domain_error - - - - - thisDoesntThrow() - - - thisDoesntThrow() - - - - - thisThrows() - - - thisThrows() - - - - - - - unexpected exception - - - - - - - thisThrows() == 0 - - - thisThrows() == 0 - - - expected exception - - - - - - - - thisThrows() == 0 - - - thisThrows() == 0 - - - expected exception - - - - - - - - thisThrows() == 0 - - - thisThrows() == 0 - - - expected exception - - - - - -
- - unexpected exception - - -
- -
- - - - - - Uncomment the code in this test to check that it gives a sensible compiler error - - - - - - Uncomment the code in this test to check that it gives a sensible compiler error - - - - - - - - - - - - - - - - -
- - - encode( "normal string" ) == "normal string" - - - "normal string" == "normal string" - - - -
-
- - - encode( "" ) == "" - - - "" == "" - - - -
-
- - - encode( "smith & jones" ) == "smith &amp; jones" - - - "smith &amp; jones" == "smith &amp; jones" - - - -
-
- - - encode( "smith < jones" ) == "smith &lt; jones" - - - "smith &lt; jones" == "smith &lt; jones" - - - -
-
- - - encode( "smith > jones" ) == "smith > jones" - - - "smith > jones" == "smith > jones" - - - - - encode( "smith ]]> jones" ) == "smith ]]&gt; jones" - - - "smith ]]&gt; jones" -== -"smith ]]&gt; jones" - - - -
-
- - - encode( stringWithQuotes ) == stringWithQuotes - - - "don't "quote" me on that" -== -"don't "quote" me on that" - - - - - encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" - - - "don't &quot;quote&quot; me on that" -== -"don't &quot;quote&quot; me on that" - - - -
-
- - - encode( "[\x01]" ) == "[\\x01]" - - - "[\x01]" == "[\x01]" - - - -
-
- - - encode( "[\x7F]" ) == "[\\x7F]" - - - "[\x7F]" == "[\x7F]" - - - -
- -
- - - - - - - x == 0 - - - 0 == 0 - - - - - - - - obj.prop != 0 - - - 0x != 0 - - - - - - - - flag - - - true - - - - - testCheckedElse( true ) - - - true - - - - - - - - flag - - - false - - - - - testCheckedElse( false ) - - - false - - - - - - - - flag - - - true - - - - - testCheckedIf( true ) - - - true - - - - - - - - flag - - - false - - - - - testCheckedIf( false ) - - - false - - - - - - - - unsigned_char_var == 1 - - - 1 == 1 - - - - - unsigned_short_var == 1 - - - 1 == 1 - - - - - unsigned_int_var == 1 - - - 1 == 1 - - - - - unsigned_long_var == 1 - - - 1 == 1 - - - - - - - - long_var == unsigned_char_var - - - 1 == 1 - - - - - long_var == unsigned_short_var - - - 1 == 1 - - - - - long_var == unsigned_int_var - - - 1 == 1 - - - - - long_var == unsigned_long_var - - - 1 == 1 - - - - - -
-
- -
- -
-
-
- -
- -
-
- -
- -
- - - - -loose text artifact - - - - - Previous info should not be seen - - - - - - - - - - l == std::numeric_limits<long long>::max() - - - 9223372036854775807 (0x) -== -9223372036854775807 (0x) - - - - - -
- - - b > a - - - 0 > 1 - - - -
- -
- - - Testing if fib[0] (1) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[1] (1) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[2] (2) is even - - - - ( fib[i] % 2 ) == 0 - - - 0 == 0 - - - - Testing if fib[3] (3) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[4] (5) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[5] (8) is even - - - - ( fib[i] % 2 ) == 0 - - - 0 == 0 - - - - Testing if fib[6] (13) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - Testing if fib[7] (21) is even - - - - ( fib[i] % 2 ) == 0 - - - 1 == 0 - - - - - -
-
- - - a == b - - - 1 == 2 - - - -
- -
-
-
- - - a != b - - - 1 != 2 - - - -
- -
-
-
- - - a < b - - - 1 < 2 - - - -
- -
- -
- -
- - - a != b - - - 1 != 2 - - - - - b != a - - - 2 != 1 - - -
- - - a != b - - - 1 != 2 - - - -
- -
- -
- - - - s == "7" - - - "7" == "7" - - - - - - - - ti == typeid(int) - - - {?} == {?} - - - - - - - - - - - makeString( false ) != static_cast<char*>(0) - - - "valid string" != {null string} - - - - - makeString( true ) == static_cast<char*>(0) - - - {null string} == {null string} - - - - - - - - ptr.get() == 0 - - - 0 == 0 - - - - - - - - ::Catch::Detail::stringify( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" - - - "{ { 42, "Arthur" }, { "Ford", 24 } }" -== -"{ { 42, "Arthur" }, { "Ford", 24 } }" - - - - - - - - p == 0 - - - 0 == 0 - - - - - -
- - - a != b - - - 1 != 2 - - - - - b != a - - - 2 != 1 - - - -
-
- - - a != b - - - 1 != 2 - - - -
- -
- -
- - - Catch::replaceInPlace( letters, "b", "z" ) - - - true - - - - - letters == "azcdefcg" - - - "azcdefcg" == "azcdefcg" - - - -
-
- - - Catch::replaceInPlace( letters, "c", "z" ) - - - true - - - - - letters == "abzdefzg" - - - "abzdefzg" == "abzdefzg" - - - -
-
- - - Catch::replaceInPlace( letters, "a", "z" ) - - - true - - - - - letters == "zbcdefcg" - - - "zbcdefcg" == "zbcdefcg" - - - -
-
- - - Catch::replaceInPlace( letters, "g", "z" ) - - - true - - - - - letters == "abcdefcz" - - - "abcdefcz" == "abcdefcz" - - - -
-
- - - Catch::replaceInPlace( letters, letters, "replaced" ) - - - true - - - - - letters == "replaced" - - - "replaced" == "replaced" - - - -
-
- - - !Catch::replaceInPlace( letters, "x", "z" ) - - - !false - - - - - letters == letters - - - "abcdefcg" == "abcdefcg" - - - -
-
- - - Catch::replaceInPlace( s, "'", "|'" ) - - - true - - - - - s == "didn|'t" - - - "didn|'t" == "didn|'t" - - - -
- -
- - - - - - 3 - - - - false - - - false - - - - - - - hi - - - i := 7 - - - - false - - - false - - - - - - - - ::Catch::Detail::stringify(value) == "{ 34, \"xyzzy\" }" - - - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" - - - - - - - - ::Catch::Detail::stringify( value ) == "{ 34, \"xyzzy\" }" - - - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" - - - - - - - - ::Catch::Detail::stringify( pr ) == "{ { \"green\", 55 } }" - - - "{ { "green", 55 } }" -== -"{ { "green", 55 } }" - - - - - - - - std::string( "first" ) == "second" - - - "first" == "second" - - - - - - - - ::Catch::Detail::stringify( item ) == "StringMaker<has_maker>" - - - "StringMaker<has_maker>" -== -"StringMaker<has_maker>" - - - - - - - - ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" - - - "StringMaker<has_maker_and_operator>" -== -"StringMaker<has_maker_and_operator>" - - - - - - - - ::Catch::Detail::stringify( item ) == "operator<<( has_operator )" - - - "operator<<( has_operator )" -== -"operator<<( has_operator )" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - result == "\"wide load\"" - - - ""wide load"" == ""wide load"" - - - - - - - - ::Catch::Detail::stringify( v ) == "{ StringMaker<has_maker> }" - - - "{ StringMaker<has_maker> }" -== -"{ StringMaker<has_maker> }" - - - - - - - - ::Catch::Detail::stringify(e0) == "E2/V0" - - - "E2/V0" == "E2/V0" - - - - - ::Catch::Detail::stringify(e1) == "E2/V1" - - - "E2/V1" == "E2/V1" - - - - - ::Catch::Detail::stringify(e3) == "Unknown enum value 10" - - - "Unknown enum value 10" -== -"Unknown enum value 10" - - - - - - - - ::Catch::Detail::stringify(e0) == "0" - - - "{?}" == "0" - - - - - ::Catch::Detail::stringify(e1) == "1" - - - "{?}" == "1" - - - - - - - - ::Catch::Detail::stringify(e0) == "E2{0}" - - - "E2{0}" == "E2{0}" - - - - - ::Catch::Detail::stringify(e1) == "E2{1}" - - - "E2{1}" == "E2{1}" - - - - - - - - ::Catch::Detail::stringify(e0) == "0" - - - "0" == "0" - - - - - ::Catch::Detail::stringify(e1) == "1" - - - "1" == "1" - - - - - - - - "{ }" == ::Catch::Detail::stringify(type{}) - - - "{ }" == "{ }" - - - - - "{ }" == ::Catch::Detail::stringify(value) - - - "{ }" == "{ }" - - - - - - - - "1.2f" == ::Catch::Detail::stringify(float(1.2)) - - - "1.2f" == "1.2f" - - - - - "{ 1.2f, 0 }" == ::Catch::Detail::stringify(type{1.2f,0}) - - - "{ 1.2f, 0 }" == "{ 1.2f, 0 }" - - - - - - - - "{ 0 }" == ::Catch::Detail::stringify(type{0}) - - - "{ 0 }" == "{ 0 }" - - - - - - - - "{ 0, 42, \"Catch me\" }" == ::Catch::Detail::stringify(value) - - - "{ 0, 42, "Catch me" }" -== -"{ 0, 42, "Catch me" }" - - - - - - - - "{ \"hello\", \"world\" }" == ::Catch::Detail::stringify(type{"hello","world"}) - - - "{ "hello", "world" }" -== -"{ "hello", "world" }" - - - - - - - - "{ { 42 }, { }, 1.2f }" == ::Catch::Detail::stringify(value) - - - "{ { 42 }, { }, 1.2f }" -== -"{ { 42 }, { }, 1.2f }" - - - - - - - - ::Catch::Detail::stringify(v) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(v) == "{ { \"hello\" }, { \"world\" } }" - - - "{ { "hello" }, { "world" } }" -== -"{ { "hello" }, { "world" } }" - - - - - - - - ::Catch::Detail::stringify(vv) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42 }" - - - "{ 42 }" == "{ 42 }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42, 250 }" - - - "{ 42, 250 }" == "{ 42, 250 }" - - - - - - - - ::Catch::Detail::stringify(vv) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42 }" - - - "{ 42 }" == "{ 42 }" - - - - - ::Catch::Detail::stringify(vv) == "{ 42, 250 }" - - - "{ 42, 250 }" == "{ 42, 250 }" - - - - - - - - ::Catch::Detail::stringify(vv) == "{ }" - - - "{ }" == "{ }" - - - - - ::Catch::Detail::stringify(vv) == "{ \"hello\" }" - - - "{ "hello" }" == "{ "hello" }" - - - - - ::Catch::Detail::stringify(vv) == "{ \"hello\", \"world\" }" - - - "{ "hello", "world" }" -== -"{ "hello", "world" }" - - - - - - - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 10 - - - 10 == 10 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 0 - - - 0 == 0 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.capacity() == 0 - - - 0 == 0 - - - -
- -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 10 - - - 10 >= 10 - - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - -
- - - v.size() == 5 - - - 5 == 5 - - - - - v.capacity() >= 5 - - - 5 >= 5 - - - -
- -
- -
- -
-
- -
- -
- -
- -
diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 8d15c6a4..f551d3bf 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -436,7 +436,7 @@ TEST_CASE( "null deref", "[.][failing][!nonportable]" ) { *x = 1; } -TEST_CASE( "non-copyable objects", "[.]" ) { +TEST_CASE( "non-copyable objects", "[.][failing]" ) { // Thanks to Agustin Bergé (@k-ballo on the cpplang Slack) for raising this std::type_info const& ti = typeid(int); CHECK( ti == typeid(int) ); From 185573e701ed06ced6bf89e1761399735e495ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 16:00:53 +0200 Subject: [PATCH 261/398] Do not include c++ stitch marking in final single header --- scripts/generateSingleHeader.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index acc1720d..d4be7404 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -71,6 +71,7 @@ def parseFile( path, filename ): for line in f: if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line: insertCpps() + continue elif ifParser.match( line ): ifdefs = ifdefs + 1 elif endIfParser.match( line ): From 8e6641c19be469d062ac5c36df8f466db44651a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 16:13:28 +0200 Subject: [PATCH 262/398] Replace stdint.h include with cstdint include Just small unification of includes --- include/internal/catch_timer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_timer.h b/include/internal/catch_timer.h index e01a1cb7..28e1f9db 100644 --- a/include/internal/catch_timer.h +++ b/include/internal/catch_timer.h @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_TIMER_H_INCLUDED #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED -#include +#include namespace Catch { From 9a18ba042f137deddd9c655f57664e02c1c98a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 17:21:54 +0200 Subject: [PATCH 263/398] Remove deprecated listener registration macro --- include/internal/catch_reporter_registrars.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index f10c493c..483003fe 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -57,10 +57,6 @@ namespace Catch { #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } -// Deprecated - use the form without INTERNAL_ -#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - #define CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } From f99f5111550ff55545e8a68713c9ea4a740e083a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 18:07:24 +0200 Subject: [PATCH 264/398] Removed *_REGISTER_REPORTER from main path Also simplified them to single macro: CATCH_REGISTER_REPORTER --- include/catch.hpp | 4 ---- include/internal/catch_reporter_registrars.hpp | 2 +- include/reporters/catch_reporter_automake.hpp | 2 +- include/reporters/catch_reporter_compact.cpp | 2 +- include/reporters/catch_reporter_console.cpp | 2 +- include/reporters/catch_reporter_junit.cpp | 2 +- include/reporters/catch_reporter_tap.hpp | 2 +- include/reporters/catch_reporter_teamcity.hpp | 2 +- include/reporters/catch_reporter_xml.cpp | 2 +- 9 files changed, 8 insertions(+), 12 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index f04ab7a5..4b149b4e 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -115,8 +115,6 @@ #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) - // "BDD-style" convenience wrappers #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) @@ -175,8 +173,6 @@ #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) - #endif #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 483003fe..74ee494e 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -54,7 +54,7 @@ namespace Catch { }; } -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ +#define CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } #define CATCH_REGISTER_LISTENER( listenerType ) \ diff --git a/include/reporters/catch_reporter_automake.hpp b/include/reporters/catch_reporter_automake.hpp index 86eb0325..dbebe975 100644 --- a/include/reporters/catch_reporter_automake.hpp +++ b/include/reporters/catch_reporter_automake.hpp @@ -55,7 +55,7 @@ namespace Catch { AutomakeReporter::~AutomakeReporter() {} #endif - INTERNAL_CATCH_REGISTER_REPORTER( "automake", AutomakeReporter) + CATCH_REGISTER_REPORTER( "automake", AutomakeReporter) } // end namespace Catch diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp index a1bb108f..80f3767d 100644 --- a/include/reporters/catch_reporter_compact.cpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -299,6 +299,6 @@ namespace Catch { CompactReporter::~CompactReporter() {} - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 0922134d..63fad69a 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -634,7 +634,7 @@ namespace Catch { bool m_headerPrinted = false; }; - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) ConsoleReporter::~ConsoleReporter() {} diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp index ae3ea384..b40e9619 100644 --- a/include/reporters/catch_reporter_junit.cpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -251,6 +251,6 @@ namespace Catch { }; JunitReporter::~JunitReporter() {} - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + CATCH_REGISTER_REPORTER( "junit", JunitReporter ) } // end namespace Catch diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index 1d1093b8..47661598 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -248,7 +248,7 @@ namespace Catch { TAPReporter::~TAPReporter() {} #endif - INTERNAL_CATCH_REGISTER_REPORTER( "tap", TAPReporter ) + CATCH_REGISTER_REPORTER( "tap", TAPReporter ) } // end namespace Catch diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 15cfc016..3fcbbd4e 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -206,7 +206,7 @@ namespace Catch { TeamCityReporter::~TeamCityReporter() {} #endif - INTERNAL_CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter ) + CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter ) } // end namespace Catch diff --git a/include/reporters/catch_reporter_xml.cpp b/include/reporters/catch_reporter_xml.cpp index 128899a9..0033b310 100644 --- a/include/reporters/catch_reporter_xml.cpp +++ b/include/reporters/catch_reporter_xml.cpp @@ -220,6 +220,6 @@ namespace Catch { }; XmlReporter::~XmlReporter() {} - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch From 597fca3c8971500fe541417c7434e85d9a41b8c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 15:34:00 +0200 Subject: [PATCH 265/398] Remove header from the common path It was only used for std::max within Approx, so we now have ::Catch::Detail::max(double, double) that is used instead. --- include/internal/catch_approx.cpp | 7 +++++++ include/internal/catch_approx.hpp | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp index 98fc7bce..419a9cd6 100644 --- a/include/internal/catch_approx.cpp +++ b/include/internal/catch_approx.cpp @@ -13,6 +13,13 @@ namespace Catch { namespace Detail { + double max(double lhs, double rhs) { + if (lhs < rhs) { + return rhs; + } + return lhs; + } + Approx::Approx ( double value ) : m_epsilon( std::numeric_limits::epsilon()*100 ), m_margin( 0.0 ), diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.hpp index 590c8f5b..2185b8f6 100644 --- a/include/internal/catch_approx.hpp +++ b/include/internal/catch_approx.hpp @@ -10,7 +10,6 @@ #include "catch_tostring.h" -#include #include #include @@ -18,6 +17,8 @@ namespace Catch { namespace Detail { + double max(double lhs, double rhs); + class Approx { public: explicit Approx ( double value ); @@ -42,7 +43,7 @@ namespace Detail { friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula auto lhs_v = static_cast(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); + bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); if (relativeOK) { return true; } From ee75b324e7d88faa7d6b4e41bd7daf9c483b07fa Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 19:18:54 +0100 Subject: [PATCH 266/398] Rebased with missing [failing] tag --- projects/SelfTest/Baselines/xml.sw.approved.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index edabc05e..8f52326e 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -7433,7 +7433,7 @@ loose text artifact
- + ti == typeid(int) From 0545de0a31c0691f978f858f3b5b875c6469fb35 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 19:19:17 +0100 Subject: [PATCH 267/398] Hold translated exception in local string while matching --- include/internal/catch_capture_matchers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_capture_matchers.cpp b/include/internal/catch_capture_matchers.cpp index 8c30a154..758177e9 100644 --- a/include/internal/catch_capture_matchers.cpp +++ b/include/internal/catch_capture_matchers.cpp @@ -16,7 +16,8 @@ namespace Catch { // There is another overload, in catch_assertinhandler.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 ) { - MatchExpr expr( Catch::translateActiveException(), matcher, matcherString ); + std::string exceptionMessage = Catch::translateActiveException(); + MatchExpr expr( exceptionMessage, matcher, matcherString ); handler.handle( expr ); } From 24af32f37871bbd3856c6f3021ba3639cb301b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 20:21:06 +0200 Subject: [PATCH 268/398] Add define that pulls in reporter and listeners interfaces This allows users to define reporters and listeners in files different from the main file. Related to #991, #986 --- CMakeLists.txt | 1 + include/catch.hpp | 5 +++++ include/internal/catch_external_interfaces.h | 13 +++++++++++++ include/internal/catch_reporter_registrars.hpp | 3 ++- 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 include/internal/catch_external_interfaces.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c98c326b..b538f5d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -138,6 +138,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_enforce.h ${HEADER_DIR}/internal/catch_errno_guard.h ${HEADER_DIR}/internal/catch_exception_translator_registry.h + ${HEADER_DIR}/internal/catch_external_interfaces.h ${HEADER_DIR}/internal/catch_fatal_condition.h ${HEADER_DIR}/internal/catch_impl.hpp ${HEADER_DIR}/internal/catch_interfaces_capture.h diff --git a/include/catch.hpp b/include/catch.hpp index 4b149b4e..db1f366c 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -19,6 +19,7 @@ #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL +# define CATCH_CONFIG_EXTERNAL_INTERFACES #endif #ifdef CATCH_IMPL @@ -52,6 +53,10 @@ #include "internal/catch_objc.hpp" #endif +#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES +#include "internal/catch_external_interfaces.h" +#endif + #ifdef CATCH_IMPL #include "internal/catch_impl.hpp" #endif diff --git a/include/internal/catch_external_interfaces.h b/include/internal/catch_external_interfaces.h new file mode 100644 index 00000000..7243ed7b --- /dev/null +++ b/include/internal/catch_external_interfaces.h @@ -0,0 +1,13 @@ +/* + * Created by Martin on 17/08/2017. + * + * 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) + */ +#ifndef TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H +#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H + +#include "../reporters/catch_reporter_bases.hpp" +#include "catch_reporter_registrars.hpp" + +#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 74ee494e..e0db392b 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -1,3 +1,4 @@ + /* * Created by Phil on 31/12/2010. * Copyright 2010 Two Blue Cubes Ltd. All rights reserved. @@ -39,7 +40,7 @@ namespace Catch { class ListenerFactory : public IReporterFactory { virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { - return std::make_shared( config ); + return std::unique_ptr( new T( config ) ); } virtual std::string getDescription() const override { return std::string(); From 28f11a714948d28812d3867d3f5f3e9b35a3e86e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 17 Aug 2017 19:40:39 +0100 Subject: [PATCH 269/398] Added dummy listener registration --- projects/SelfTest/TestMain.cpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index c3b1f29b..cdb13c52 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -24,25 +24,11 @@ CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" ) # pragma clang diagnostic ignored "-Wc++98-compat" #endif +struct TestListener : Catch::TestEventListenerBase { + using TestEventListenerBase::TestEventListenerBase; // inherit constructor +}; +CATCH_REGISTER_LISTENER( TestListener ); -//template -//void parseIntoConfig( const char * (&argv)[size], Catch::ConfigData& config ) { -// auto parser = Catch::makeCommandLineParser(); -// parser.parseInto( Catch::Clara::argsToVector( size, argv ), config ); -//} -// -//template -//std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::ConfigData& config ) { -// try { -// parseIntoConfig( argv, config ); -// FAIL( "expected exception" ); -// } -// catch( std::exception& ex ) { -// return ex.what(); -// } -// return ""; -//} -// inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( nullptr, "", name, desc, CATCH_INTERNAL_LINEINFO ); } TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { From 3bc03cd617eedaa4d0fd4de5811fd22503888f46 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 18 Aug 2017 15:53:10 +0100 Subject: [PATCH 270/398] Went back to Catch 1.x behaviour for -d -d takes "yes" or "no", rather than being a standalone flag option. The default is "defaultForReporter" so the previous change actually dropped some control. --- include/internal/catch_commandline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index d92a1c39..1410baa4 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -135,7 +135,7 @@ namespace Catch { + Opt( setWarning, "warning name" ) ["-w"]["--warn"] ( "enable warnings" ) - + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) + + Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) ["-d"]["--durations"] ( "show test durations" ) + Opt( loadTestNamesFromFile, "filename" ) From 5d6c1f4dd04a9794c16850261b57a56101e2bfae Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 18 Aug 2017 15:58:00 +0100 Subject: [PATCH 271/398] Dev build 2 --- conanfile.py | 2 +- include/internal/catch_version.cpp | 2 +- single_include/catch.hpp | 133 ++++++++++++++++------------- test_package/conanfile.py | 2 +- 4 files changed, 75 insertions(+), 64 deletions(-) diff --git a/conanfile.py b/conanfile.py index 3565eb6d..4b7990a6 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.0.0-develop.1" + version = "2.0.0-develop.2" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index 6f13d8a5..96e66d5a 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 1 ); + static Version version( 2, 0, 0, "develop", 2 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 77035aa9..2b440890 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.0.0-develop.1 - * Generated: 2017-08-17 08:29:20.059622 + * Catch v2.0.0-develop.2 + * Generated: 2017-08-18 15:57:31.231591 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. @@ -46,6 +46,7 @@ // end catch_suppress_warnings.h #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL +# define CATCH_CONFIG_EXTERNAL_INTERFACES #endif #ifdef CATCH_IMPL @@ -914,14 +915,14 @@ namespace Catch { // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template - auto compareEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; + auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) == rhs; }; template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; template auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; template - auto compareNotEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; + auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) != rhs; }; template auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; template @@ -1493,7 +1494,7 @@ namespace Catch { // end catch_section_info.h // start catch_timer.h -#include +#include namespace Catch { @@ -1701,7 +1702,6 @@ namespace Catch { // end catch_interfaces_exception.h // start catch_approx.hpp -#include #include #include @@ -1709,6 +1709,8 @@ namespace Catch { namespace Catch { namespace Detail { + double max(double lhs, double rhs); + class Approx { public: explicit Approx ( double value ); @@ -1732,7 +1734,7 @@ namespace Detail { friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula auto lhs_v = static_cast(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); + bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); if (relativeOK) { return true; } @@ -2536,43 +2538,11 @@ return @ desc; \ // end catch_objc.hpp #endif -#ifdef CATCH_IMPL -// start catch_impl.hpp +#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES +// start catch_external_interfaces.h +#ifndef TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H +#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wweak-vtables" -#endif - -// start catch_notimplemented_exception.h - -#include - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - - virtual ~NotImplementedException() noexcept = default; - - virtual const char* what() const noexcept override; - - private: - std::string m_what; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -// end catch_notimplemented_exception.h -// Temporary hack to fix separately provided reporters // start catch_reporter_bases.hpp // start catch_enforce.h @@ -3596,6 +3566,7 @@ namespace Catch { // end catch_reporter_bases.hpp // start catch_reporter_registrars.hpp + namespace Catch { template @@ -3625,7 +3596,7 @@ namespace Catch { class ListenerFactory : public IReporterFactory { virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { - return std::make_shared( config ); + return std::unique_ptr( new T( config ) ); } virtual std::string getDescription() const override { return std::string(); @@ -3640,17 +3611,54 @@ namespace Catch { }; } -#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ +#define CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } -// Deprecated - use the form without INTERNAL_ -#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - #define CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } // end catch_reporter_registrars.hpp +#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H +// end catch_external_interfaces.h +#endif + +#ifdef CATCH_IMPL +// start catch_impl.hpp + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// start catch_notimplemented_exception.h + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + + virtual ~NotImplementedException() noexcept = default; + + virtual const char* what() const noexcept override; + + private: + std::string m_what; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// end catch_notimplemented_exception.h +// Temporary hack to fix separately provided reporters // // start catch_leak_detector.h @@ -5696,6 +5704,13 @@ namespace Catch { namespace Catch { namespace Detail { + double max(double lhs, double rhs) { + if (lhs < rhs) { + return rhs; + } + return lhs; + } + Approx::Approx ( double value ) : m_epsilon( std::numeric_limits::epsilon()*100 ), m_margin( 0.0 ), @@ -5978,7 +5993,8 @@ namespace Catch { // There is another overload, in catch_assertinhandler.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 ) { - MatchExpr expr( Catch::translateActiveException(), matcher, matcherString ); + std::string exceptionMessage = Catch::translateActiveException(); + MatchExpr expr( exceptionMessage, matcher, matcherString ); handler.handle( expr ); } @@ -6111,7 +6127,7 @@ namespace Catch { + Opt( setWarning, "warning name" ) ["-w"]["--warn"] ( "enable warnings" ) - + Opt( [&]( bool ) { config.showDurations = ShowDurations::Always; } ) + + Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) ["-d"]["--durations"] ( "show test durations" ) + Opt( loadTestNamesFromFile, "filename" ) @@ -9484,7 +9500,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 1 ); + static Version version( 2, 0, 0, "develop", 2 ); return version; } @@ -10143,7 +10159,7 @@ namespace Catch { CompactReporter::~CompactReporter() {} - INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch // end catch_reporter_compact.cpp @@ -10768,7 +10784,7 @@ namespace Catch { bool m_headerPrinted = false; }; - INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) ConsoleReporter::~ConsoleReporter() {} @@ -11014,7 +11030,7 @@ namespace Catch { }; JunitReporter::~JunitReporter() {} - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + CATCH_REGISTER_REPORTER( "junit", JunitReporter ) } // end namespace Catch // end catch_reporter_junit.cpp @@ -11311,11 +11327,10 @@ namespace Catch { }; XmlReporter::~XmlReporter() {} - INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch // end catch_reporter_xml.cpp -// ~*~* CATCH_CPP_STITCH_PLACE *~*~ namespace Catch { LeakDetector leakDetector; @@ -11443,8 +11458,6 @@ int main (int argc, char * const argv[]) { #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() -#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) - // "BDD-style" convenience wrappers #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) @@ -11502,8 +11515,6 @@ int main (int argc, char * const argv[]) { #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() -#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) - #endif #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 56665718..c96cf111 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.0.0-develop.1@%s/%s" % (username, channel) + requires = "Catch/2.0.0-develop.2@%s/%s" % (username, channel) def build(self): cmake = CMake(self) From 626b1d39361ac644bc1025bef28b9592315cf0ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 22:25:06 +0200 Subject: [PATCH 272/398] Add problems with `SECTION`s in loops to documentations --- docs/limitations.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/limitations.md b/docs/limitations.md index bee4a296..60ea0de2 100644 --- a/docs/limitations.md +++ b/docs/limitations.md @@ -2,6 +2,20 @@ Catch has some known limitations, that we are not planning to change. Some of these are caused by our desire to support C++98 compilers, some of these are caused by our desire to keep Catch crossplatform, some exist because their priority is seen as low compared to the development effort they would need and some other yet are compiler/runtime bugs. +## Implementation limits +### Sections nested in loops + +If you are using `SECTION`s inside loops, you have to create them with different name per loop's iteration. The recommended way to do so is to incorporate the loop's counter into section's name, like so +```cpp +TEST_CASE( "Looped section" ) { + for (char i = '0'; i < '5'; ++i) { + SECTION(std::string("Looped section ") + i) { + SUCCEED( "Everything is OK" ); + } + } +} +``` + ## Features This section outlines some missing features, what is their status and their possible workarounds. From 3dc4de817337e755c07b5f67c1a3d58a1c2f6cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 22:29:04 +0200 Subject: [PATCH 273/398] Document implementation of listeners in non-main files Closes #991 --- docs/configuration.md | 8 ++++++++ docs/event-listeners.md | 7 ++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 4c236850..59712020 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -9,6 +9,14 @@ Nonetheless there are still some occasions where finer control is needed. For th Although Catch is header only it still, internally, maintains a distinction between interface headers and headers that contain implementation. Only one source file in your test project should compile the implementation headers and this is controlled through the use of one of these macros - one of these identifiers should be defined before including Catch in *exactly one implementation file in your project*. +# Reporter / Listener interfaces + + CATCH_CONFIG_EXTERNAL_INTERFACES // Brings in neccessary headers for Reporter/Listener implementation + +Brings in various parts of Catch that are required for user defined Reporters and Listeners. This means that new Reporters and Listeners can be defined in this file as well as in the main file. + +Implied by both `CATCH_CONFIG_MAIN` and `CATCH_CONFIG_RUNNER`. + # Prefixing Catch macros CATCH_CONFIG_PREFIX_ALL diff --git a/docs/event-listeners.md b/docs/event-listeners.md index ab057444..58c2d8db 100644 --- a/docs/event-listeners.md +++ b/docs/event-listeners.md @@ -12,10 +12,11 @@ so you are not forced to implement events you're not interested in. ## Implementing a Listener +Simply derive a class from `Catch::TestEventListenerBase` and implement the methods you are interested in, either in +the main source file (i.e. the one that defines `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`), or in a +file that defines `CATCH_CONFIG_EXTERNAL_INTERFACES`. -In your main source file (i.e. the one that has the `#define` for `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`), -simply derive a class from `Catch::TestEventListenerBase` and implement the methods you are interested in. -Then register it using `INTERNAL_CATCH_REGISTER_LISTENER`. +Then register it using `CATCH_REGISTER_LISTENER`. For example: From c7da5b51281421674d3074e883835d82b779a92c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 22:42:35 +0200 Subject: [PATCH 274/398] Remove obsolete note from reporter documentation --- docs/reporters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reporters.md b/docs/reporters.md index 92710622..4ae0ce71 100644 --- a/docs/reporters.md +++ b/docs/reporters.md @@ -17,7 +17,7 @@ There are four reporters built in to the single include: * `console` writes as lines of text, formatted to a typical terminal width, with colours if a capable terminal is detected. * `compact` similar to `console` but optimised for minimal output - each entry on one line -* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. If you are using Jenkins with Catch 1.x, you can improve quality of output by applying changes in [#923](https://github.com/philsquared/Catch/pull/923). +* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. Because of the way the junit format is structured the run must complete before anything is written. * `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively. From 489b63958711fa72ec6831092a4e19e3cc47faf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 17 Aug 2017 23:23:04 +0200 Subject: [PATCH 275/398] Change include guards in catch_external_interfaces.h Previously they weren't recognized by the generateSingleHeader.py script and weren't removed during stitching --- include/internal/catch_external_interfaces.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_external_interfaces.h b/include/internal/catch_external_interfaces.h index 7243ed7b..dffd5187 100644 --- a/include/internal/catch_external_interfaces.h +++ b/include/internal/catch_external_interfaces.h @@ -4,10 +4,10 @@ * 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) */ -#ifndef TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H -#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H +#ifndef TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED +#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED #include "../reporters/catch_reporter_bases.hpp" #include "catch_reporter_registrars.hpp" -#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H +#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED From 49f5919c4130762df35571a7f39edf6aa29d0286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 18 Aug 2017 20:15:00 +0200 Subject: [PATCH 276/398] Add partial release notes for 2.0.0 --- docs/release-notes.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 2c510c3c..c6c91ce1 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,3 +1,45 @@ +# 2.0.0 (in progress) + +## Breaking changes +* Removed C++98 support +* Removed legacy reporter support +* Removed legacy generator support + * Generator support will come back later, reworked +* Removed `Catch::toString` support + * The new stringification machinery uses `Catch::StringMaker` specializations first and `operator<<` overloads second. +* Removed legacy `SCOPED_MSG` and `SCOPED_INFO` macros +* Output into debugger is now colourized +* `*_THROWS_AS(expr, exception_type)` now unconditionally appends `const&` to the exception type. +* `CATCH_CONFIG_FAST_COMPILE` now affects the `CHECK_` family of assertions as well as `REQUIRE_` family of assertions + * This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section. + +## Improvements +* Reporters and Listeners can be defined in files different from the main file + * The file has to define `CATCH_CONFIG_EXTERNAL_INTERFACES` before including catch.hpp. +* Errors that happen during set up before main are now caught and properly reported once main is entered + * If you are providing your own main, you can access and use these as well. +* New assertion macros, *_THROWS_WITH(expr, exception_type, matcher) are provided + * As the arguments suggest, these allow you to assert that an expression throws desired type of exception and pass the exception to a matcher. +* JUnit reporter no longer has significantly different output for test cases with and without sections +* Most assertions now support expressions containing commas (ie `REQUIRE(foo() == std::vector{1, 2, 3});`) +* Catch now contains experimental micro benchmarking support + * See `projects/SelfTest/Benchmark.tests.cpp` for examples + * The support being experiment means that it can be changed without prior notice +* Catch uses new CLI parsing library (Clara) + * Users can now easily add new command line options to the final executable + * This also leads to some changes in `Catch::Session` interface + +## Fixes + + +## Internal changes +* The development version now uses .cpp files instead of header files containing implementation. + * This makes partial rebuilds much faster during development +* The expression decomposition layer has been rewritten +* The evaluation layer has been rewritten +* New library (TextFlow) is used for formatting text to output + + # 1.9.6 ### Improvements From cb2fceb1198252d718ae9613b73d4146bf4f204a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 21 Aug 2017 14:58:50 +0200 Subject: [PATCH 277/398] Force include catch_platform.h before any if-defs Closes #994 --- include/catch.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/catch.hpp b/include/catch.hpp index db1f366c..c1099264 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -22,6 +22,8 @@ # define CATCH_CONFIG_EXTERNAL_INTERFACES #endif +#include "internal/catch_platform.h" + #ifdef CATCH_IMPL # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED From a7a9be59ff9998afc3eff06300fba34cc89d4c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 22 Aug 2017 22:00:52 +0200 Subject: [PATCH 278/398] Ignore return value of getchar when waiting for keypress Previously this was causing warnings under MSVC for ignored return value. --- include/catch_session.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 1968cb2f..a423a3be 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -201,12 +201,12 @@ namespace Catch { int run() { if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { Catch::cout() << "...waiting for enter/ return before starting" << std::endl; - std::getchar(); + static_cast(std::getchar()); } int exitCode = runInternal(); if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; - std::getchar(); + static_cast(std::getchar()); } return exitCode; } From e8225052f18773960c04b8db253144c03e70c3fb Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Thu, 24 Aug 2017 15:21:36 +0200 Subject: [PATCH 279/398] Add html anchor 'top' --- README.md | 1 + docs/Readme.md | 1 + docs/assertions.md | 3 ++- docs/build-systems.md | 1 + docs/command-line.md | 1 + docs/commercial-users.md | 1 + docs/configuration.md | 1 + docs/contributing.md | 3 ++- docs/event-listeners.md | 1 + docs/limitations.md | 1 + docs/logging.md | 3 ++- docs/matchers.md | 3 ++- docs/opensource-users.md | 1 + docs/own-main.md | 1 + docs/release-notes.md | 1 + docs/release-process.md | 1 + docs/reporters.md | 3 ++- docs/slow-compiles.md | 3 ++- docs/test-cases-and-sections.md | 1 + docs/test-fixtures.md | 1 + docs/tostring.md | 1 + docs/tutorial.md | 1 + docs/why-catch.md | 3 ++- 23 files changed, 30 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b46c6825..f9ac378a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + ![catch logo](catch-logo-small.png) [![Github Releases](https://img.shields.io/github/release/philsquared/catch.svg)](https://github.com/philsquared/catch/releases) diff --git a/docs/Readme.md b/docs/Readme.md index 36048ff8..27aaedb4 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -1,3 +1,4 @@ + To get the most out of Catch, start with the [tutorial](tutorial.md). Once you're up and running consider the following reference material. diff --git a/docs/assertions.md b/docs/assertions.md index 6f390448..d6699eef 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -1,3 +1,4 @@ + # Assertion Macros Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc). @@ -145,4 +146,4 @@ For more details, along with workarounds, see the section on [the limitations pa --- -[Home](Readme.md) \ No newline at end of file +[Home](Readme.md) diff --git a/docs/build-systems.md b/docs/build-systems.md index b9644e53..30d99c14 100644 --- a/docs/build-systems.md +++ b/docs/build-systems.md @@ -1,3 +1,4 @@ + # CI and build system integration Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both. diff --git a/docs/command-line.md b/docs/command-line.md index cc944734..8b546126 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -1,3 +1,4 @@ + Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available. Click one of the followings links to take you straight to that option - or scroll on to browse the available options. diff --git a/docs/commercial-users.md b/docs/commercial-users.md index 424eb22c..60101441 100644 --- a/docs/commercial-users.md +++ b/docs/commercial-users.md @@ -1,3 +1,4 @@ + # Commercial users of Catch As well as [Open Source](opensource-users.md) users Catch is widely used within proprietary code bases too. diff --git a/docs/configuration.md b/docs/configuration.md index 59712020..d2003065 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,3 +1,4 @@ + Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a set of macros for configuring how it is built. diff --git a/docs/contributing.md b/docs/contributing.md index 1bcef99b..ab831d4c 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,3 +1,4 @@ + # Contributing to Catch So you want to contribute something to Catch? That's great! Whether it's a bug fix, a new feature, support for @@ -57,4 +58,4 @@ be fairly self-explanatory. --- -[Home](Readme.md) \ No newline at end of file +[Home](Readme.md) diff --git a/docs/event-listeners.md b/docs/event-listeners.md index 58c2d8db..a63b3ba2 100644 --- a/docs/event-listeners.md +++ b/docs/event-listeners.md @@ -1,3 +1,4 @@ + # Event Listeners A `Listener` is a class you can register with Catch that will then be passed events, diff --git a/docs/limitations.md b/docs/limitations.md index 60ea0de2..8c192320 100644 --- a/docs/limitations.md +++ b/docs/limitations.md @@ -1,3 +1,4 @@ + # Known limitations Catch has some known limitations, that we are not planning to change. Some of these are caused by our desire to support C++98 compilers, some of these are caused by our desire to keep Catch crossplatform, some exist because their priority is seen as low compared to the development effort they would need and some other yet are compiler/runtime bugs. diff --git a/docs/logging.md b/docs/logging.md index afbfd224..88adfc8b 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -1,3 +1,4 @@ + # Logging macros Additional messages can be logged during a test case. Note that the messages are scoped and thus will not be reported if failure occurs in scope preceding the message declaration. An example: @@ -79,4 +80,4 @@ These macros are now deprecated and are just aliases for INFO and CAPTURE (which --- -[Home](Readme.md) \ No newline at end of file +[Home](Readme.md) diff --git a/docs/matchers.md b/docs/matchers.md index 5daf68d7..acbcbb85 100644 --- a/docs/matchers.md +++ b/docs/matchers.md @@ -1,3 +1,4 @@ + # Matchers Matchers are an alternative way to do assertions which are easily extensible and composable. @@ -101,4 +102,4 @@ with expansion: --- -[Home](Readme.md) \ No newline at end of file +[Home](Readme.md) diff --git a/docs/opensource-users.md b/docs/opensource-users.md index f1e1806a..c1e93d0f 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -1,3 +1,4 @@ + # Open Source projects using Catch Catch is great for open source. With it's [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution diff --git a/docs/own-main.md b/docs/own-main.md index 8ab0077e..2b6d032e 100644 --- a/docs/own-main.md +++ b/docs/own-main.md @@ -1,3 +1,4 @@ + # Supplying main() yourself The easiest way to use Catch is to let it supply ```main()``` for you and handle configuring itself from the command line. diff --git a/docs/release-notes.md b/docs/release-notes.md index c6c91ce1..d9c658fd 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,3 +1,4 @@ + # 2.0.0 (in progress) ## Breaking changes diff --git a/docs/release-process.md b/docs/release-process.md index 725779ea..34002ae6 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -1,3 +1,4 @@ + # How to release When enough changes have accumulated, it is time to release new version of Catch. This document describes the proces in doing so, that no steps are forgotten. Note that all referenced scripts can be found in the `scripts/` directory. diff --git a/docs/reporters.md b/docs/reporters.md index 4ae0ce71..7c8e4204 100644 --- a/docs/reporters.md +++ b/docs/reporters.md @@ -1,3 +1,4 @@ + # Reporters Catch has a modular reporting system and comes bundled with a handful of useful reporters built in. @@ -42,4 +43,4 @@ but do keep in mind upcoming changes (these will be minor, simplifying, changes --- -[Home](Readme.md) \ No newline at end of file +[Home](Readme.md) diff --git a/docs/slow-compiles.md b/docs/slow-compiles.md index a12d0867..0b609f68 100644 --- a/docs/slow-compiles.md +++ b/docs/slow-compiles.md @@ -1,3 +1,4 @@ + # Why do my tests take so long to compile? Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that? @@ -61,4 +62,4 @@ You can also opt to sacrifice some features in order to speed-up Catch's compila --- -[Home](Readme.md) \ No newline at end of file +[Home](Readme.md) diff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md index 4e53c35c..45269044 100644 --- a/docs/test-cases-and-sections.md +++ b/docs/test-cases-and-sections.md @@ -1,3 +1,4 @@ + # Test cases and sections While Catch fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style. diff --git a/docs/test-fixtures.md b/docs/test-fixtures.md index fc546b39..bfbd0aa3 100644 --- a/docs/test-fixtures.md +++ b/docs/test-fixtures.md @@ -1,3 +1,4 @@ + Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure: ```c++ diff --git a/docs/tostring.md b/docs/tostring.md index 05a6b79b..8a2939e5 100644 --- a/docs/tostring.md +++ b/docs/tostring.md @@ -1,3 +1,4 @@ + # String conversions Catch needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes). diff --git a/docs/tutorial.md b/docs/tutorial.md index 600ba3ba..833d3a02 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -1,3 +1,4 @@ + # Getting Catch The simplest way to get Catch is to download the latest [single header version](https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. diff --git a/docs/why-catch.md b/docs/why-catch.md index 82257d68..fce02bcd 100644 --- a/docs/why-catch.md +++ b/docs/why-catch.md @@ -1,3 +1,4 @@ + # Why do we need yet another C++ test framework? Good question. For C++ there are quite a number of established frameworks, @@ -42,4 +43,4 @@ See the [tutorial](tutorial.md) to get more of a taste of using Catch in practic --- -[Home](Readme.md) \ No newline at end of file +[Home](Readme.md) From 6c09b45a2076552131c73d1a70da164bcc138c69 Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Thu, 24 Aug 2017 15:33:38 +0200 Subject: [PATCH 280/398] Let toplevel links to .md files link to .md#top --- README.md | 8 +++---- docs/Readme.md | 38 ++++++++++++++++----------------- docs/assertions.md | 4 ++-- docs/build-systems.md | 2 +- docs/command-line.md | 2 +- docs/commercial-users.md | 2 +- docs/configuration.md | 2 +- docs/contributing.md | 2 +- docs/event-listeners.md | 2 +- docs/logging.md | 2 +- docs/matchers.md | 2 +- docs/opensource-users.md | 2 +- docs/own-main.md | 2 +- docs/release-notes.md | 16 +++++++------- docs/reporters.md | 2 +- docs/slow-compiles.md | 4 ++-- docs/test-cases-and-sections.md | 4 ++-- docs/test-fixtures.md | 2 +- docs/tostring.md | 2 +- docs/tutorial.md | 16 +++++++------- docs/why-catch.md | 6 +++--- 21 files changed, 61 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index f9ac378a..523cb791 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,11 @@ extensions may require additional headers. ## How to use it This documentation comprises these three parts: -* [Why do we need yet another C++ Test Framework?](docs/why-catch.md) -* [Tutorial](docs/tutorial.md) - getting started -* [Reference section](docs/Readme.md) - all the details +* [Why do we need yet another C++ Test Framework?](docs/why-catch.md#top) +* [Tutorial](docs/tutorial.md#top) - getting started +* [Reference section](docs/Readme.md#top) - all the details ## More * Issues and bugs can be raised on the [Issue tracker on GitHub](https://github.com/philsquared/Catch/issues) * For discussion or questions please use [the dedicated Google Groups forum](https://groups.google.com/forum/?fromgroups#!forum/catch-forum) -* See [who else is using Catch](docs/opensource-users.md) +* See [who else is using Catch](docs/opensource-users.md#top) diff --git a/docs/Readme.md b/docs/Readme.md index 27aaedb4..b1623626 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -1,31 +1,31 @@ -To get the most out of Catch, start with the [tutorial](tutorial.md). +To get the most out of Catch, start with the [tutorial](tutorial.md#top). Once you're up and running consider the following reference material. Writing tests: -* [Assertion macros](assertions.md) -* [Matchers](matchers.md) -* [Logging macros](logging.md) -* [Test cases and sections](test-cases-and-sections.md) -* [Test fixtures](test-fixtures.md) -* [Reporters](reporters.md) -* [Event Listeners](event-listeners.md) +* [Assertion macros](assertions.md#top) +* [Matchers](matchers.md#top) +* [Logging macros](logging.md#top) +* [Test cases and sections](test-cases-and-sections.md#top) +* [Test fixtures](test-fixtures.md#top) +* [Reporters](reporters.md#top) +* [Event Listeners](event-listeners.md#top) Fine tuning: -* [Supplying your own main()](own-main.md) -* [Compile-time configuration](configuration.md) -* [String Conversions](tostring.md) +* [Supplying your own main()](own-main.md#top) +* [Compile-time configuration](configuration.md#top) +* [String Conversions](tostring.md#top) Running: -* [Command line](command-line.md) -* [CI and Build system integration](build-systems.md) +* [Command line](command-line.md#top) +* [CI and Build system integration](build-systems.md#top) FAQ: -* [Why are my tests slow to compile?](slow-compiles.md) -* [Known limitations](limitations.md) +* [Why are my tests slow to compile?](slow-compiles.md#top) +* [Known limitations](limitations.md#top) Other: -* [Why Catch?](why-catch.md) -* [Open Source Projects using Catch](opensource-users.md) -* [Contributing](contributing.md) -* [Release Notes](release-notes.md) +* [Why Catch?](why-catch.md#top) +* [Open Source Projects using Catch](opensource-users.md#top) +* [Contributing](contributing.md#top) +* [Release Notes](release-notes.md#top) diff --git a/docs/assertions.md b/docs/assertions.md index d6699eef..3150b584 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -132,7 +132,7 @@ REQUIRE_NOTHROW([&](){ ## Matcher expressions -To support Matchers a slightly different form is used. Matchers have [their own documentation](matchers.md). +To support Matchers a slightly different form is used. Matchers have [their own documentation](matchers.md#top). * **REQUIRE_THAT(** _lhs_, _matcher expression_ **)** and * **CHECK_THAT(** _lhs_, _matcher expression_ **)** @@ -146,4 +146,4 @@ For more details, along with workarounds, see the section on [the limitations pa --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/build-systems.md b/docs/build-systems.md index 30d99c14..1033490d 100644 --- a/docs/build-systems.md +++ b/docs/build-systems.md @@ -141,4 +141,4 @@ If you are using GCOV tool to get testing coverage of your code, and are not sur --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/command-line.md b/docs/command-line.md index 8b546126..0e1a7af8 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -299,4 +299,4 @@ So, for example, tests within the file `~\Dev\MyProject\Ferrets.cpp` would be t --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/commercial-users.md b/docs/commercial-users.md index 60101441..e4d789f1 100644 --- a/docs/commercial-users.md +++ b/docs/commercial-users.md @@ -1,7 +1,7 @@ # Commercial users of Catch -As well as [Open Source](opensource-users.md) users Catch is widely used within proprietary code bases too. +As well as [Open Source](opensource-users.md#top) users Catch is widely used within proprietary code bases too. Many organisations like to keep this information internal, and that's fine, but if you're more open it would be great if we could list the names of as many organisations as possible that use Catch somewhere in their codebase. diff --git a/docs/configuration.md b/docs/configuration.md index d2003065..35809ab4 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -102,4 +102,4 @@ On Windows Catch includes `windows.h`. To minimize global namespace clutter in t --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/contributing.md b/docs/contributing.md index ab831d4c..b6150375 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -58,4 +58,4 @@ be fairly self-explanatory. --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/event-listeners.md b/docs/event-listeners.md index a63b3ba2..b9331b49 100644 --- a/docs/event-listeners.md +++ b/docs/event-listeners.md @@ -72,4 +72,4 @@ just look in the source code to see what fields are available. --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/logging.md b/docs/logging.md index 88adfc8b..7ae54aab 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -80,4 +80,4 @@ These macros are now deprecated and are just aliases for INFO and CAPTURE (which --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/matchers.md b/docs/matchers.md index acbcbb85..647ec64f 100644 --- a/docs/matchers.md +++ b/docs/matchers.md @@ -102,4 +102,4 @@ with expansion: --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/opensource-users.md b/docs/opensource-users.md index c1e93d0f..d23f4140 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -84,4 +84,4 @@ Standardese aims to be a nextgen Doxygen --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/own-main.md b/docs/own-main.md index 2b6d032e..23f472e2 100644 --- a/docs/own-main.md +++ b/docs/own-main.md @@ -84,4 +84,4 @@ Catch embeds a powerful command line parser which you can also use to parse your --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/release-notes.md b/docs/release-notes.md index d9c658fd..2c4765fe 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -153,7 +153,7 @@ * This means it reports `INFO` messages on success, if output on success (`-s`) is enabled. * Previously it only reported `INFO` messages on failure. * `CAPTURE(expr)` now stringifies `expr` in the same way assertion macros do (#639) -* Listeners are now finally [documented](event-listeners.md). +* Listeners are now finally [documented](event-listeners.md#top). * Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion. @@ -192,7 +192,7 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough * Matchers have new, simpler (and documented) interface. * Catch provides string and vector matchers. - * For details see [Matchers documentation](matchers.md). + * For details see [Matchers documentation](matchers.md#top). * Changed console reporter test duration reporting format (#322) * Old format: `Some simple comparisons between doubles completed in 0.000123s` * New format: `xxx.123s: Some simple comparisons between doubles` _(There will always be exactly 3 decimal places)_ @@ -203,10 +203,10 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough * _More changes are coming_ * Added [TAP (Test Anything Protocol)](https://testanything.org/) and [Automake](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html#Log-files-generation-and-test-results-recording) reporters. * These are not present in the default single-include header and need to be downloaded from GitHub separately. - * For details see [documentation about integrating with build systems](build-systems.md). + * For details see [documentation about integrating with build systems](build-systems.md#top). * XML reporter now reports filename as part of the `Section` and `TestCase` tags. * `Approx` now supports an optional margin of absolute error - * It has also received [new documentation](assertions.md). + * It has also received [new documentation](assertions.md#top). ### Fixes * Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer. @@ -249,7 +249,7 @@ Other: ### Fixes: * Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`. * Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC. - * For specifics, look into the [documentation](configuration.md). + * For specifics, look into the [documentation](configuration.md#top). * Fixed compilation error under MinGW caused by improper compiler detection. * Fixed XML reporter sometimes leaving an empty output file when a test ends with signal/structured exception. * Fixed XML reporter not reporting captured stdout/stderr. @@ -263,7 +263,7 @@ Other: * Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s. * Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s. * Catch can now run specific sections within test cases. - * For now the support is only basic (no wildcards or tags), for details see the [documentation](command-line.md). + * For now the support is only basic (no wildcards or tags), for details see the [documentation](command-line.md#top). * Catch now supports SEH on Windows as well as signals on Linux. * After receiving a signal, Catch reports failing assertion and then passes the signal onto the previous handler. * Approx can be used to compare values against strong typedefs (available in C++11 mode only). @@ -300,7 +300,7 @@ Other: * Approval tests can now be run on Windows * CMake will now warn if a file is present in the `include` folder but not is not enumerated as part of the project * Catch now defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including `windows.h` - * This can be disabled if needed, see [documentation](configuration.md) for details. + * This can be disabled if needed, see [documentation](configuration.md#top) for details. ## 1.6.0 @@ -329,4 +329,4 @@ Release notes were not maintained prior to v1.6.0, but you should be able to wor --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/reporters.md b/docs/reporters.md index 7c8e4204..78e78ee9 100644 --- a/docs/reporters.md +++ b/docs/reporters.md @@ -43,4 +43,4 @@ but do keep in mind upcoming changes (these will be minor, simplifying, changes --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/slow-compiles.md b/docs/slow-compiles.md index 0b609f68..d1806d03 100644 --- a/docs/slow-compiles.md +++ b/docs/slow-compiles.md @@ -19,7 +19,7 @@ Because Catch is implemented *entirely* in headers you might think that the whol As a result the main source file *does* compile the whole of Catch every time! So it makes sense to dedicate this file to *only* ```#define```-ing the identifier and ```#include```-ing Catch (and implementing the runner code, if you're doing that). Keep all your test cases in other files. This way you won't pay the recompilation cost for the whole of Catch ## Practical example -Assume you have the `Factorial` function from the [tutorial](tutorial.md) in `factorial.cpp` (with forward declaration in `factorial.h`) and want to test it and keep the compile times down when adding new tests. Then you should have 2 files, `tests-main.cpp` and `tests-factorial.cpp`: +Assume you have the `Factorial` function from the [tutorial](tutorial.md#top) in `factorial.cpp` (with forward declaration in `factorial.h`) and want to test it and keep the compile times down when adding new tests. Then you should have 2 files, `tests-main.cpp` and `tests-factorial.cpp`: ```cpp // tests-main.cpp @@ -62,4 +62,4 @@ You can also opt to sacrifice some features in order to speed-up Catch's compila --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md index 45269044..7d26226e 100644 --- a/docs/test-cases-and-sections.md +++ b/docs/test-cases-and-sections.md @@ -12,7 +12,7 @@ Test cases and sections are very easy to use in practice: _test name_ and _section name_ are free form, quoted, strings. The optional _tags_ argument is a quoted string containing one or more tags enclosed in square brackets. Tags are discussed below. Test names must be unique within the Catch executable. -For examples see the [Tutorial](tutorial.md) +For examples see the [Tutorial](tutorial.md#top) ## Tags @@ -86,4 +86,4 @@ Other than the additional prefixes and the formatting in the console reporter th --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/test-fixtures.md b/docs/test-fixtures.md index bfbd0aa3..c887ce26 100644 --- a/docs/test-fixtures.md +++ b/docs/test-fixtures.md @@ -30,4 +30,4 @@ The two test cases here will create uniquely-named derived classes of UniqueTest --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/tostring.md b/docs/tostring.md index 8a2939e5..cfca0533 100644 --- a/docs/tostring.md +++ b/docs/tostring.md @@ -45,4 +45,4 @@ CATCH_TRANSLATE_EXCEPTION( MyType& ex ) { --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/tutorial.md b/docs/tutorial.md index 833d3a02..f4bcb07d 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -40,7 +40,7 @@ TEST_CASE( "Factorials are computed", "[factorial]" ) { } ``` -This will compile to a complete executable which responds to [command line arguments](command-line.md). If you just run it with no arguments it will execute all test cases (in this case there is just one), report any failures, report a summary of how many tests passed and failed and return the number of failed tests (useful for if you just want a yes/ no answer to: "did it work"). +This will compile to a complete executable which responds to [command line arguments](command-line.md#top). If you just run it with no arguments it will execute all test cases (in this case there is just one), report any failures, report a summary of how many tests passed and failed and return the number of failed tests (useful for if you just want a yes/ no answer to: "did it work"). If you run this as written it will pass. Everything is good. Right? Well, there is still a bug here. In fact the first version of this tutorial I posted here genuinely had the bug in! So it's not completely contrived (thanks to Daryle Walker (```@CTMacUser```) for pointing this out). @@ -87,8 +87,8 @@ Of course there are still more issues to deal with. For example we'll hit proble Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on. -1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md)). -2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see Test cases and Sections, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md) for more information on running tests. +1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md#top). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md#top)). +2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see Test cases and Sections, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md#top) for more information on running tests. 3. The name and tags arguments are just strings. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you, and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names. 4. We write our individual test assertions using the ```REQUIRE``` macro. Rather than a separate macro for each type of condition we express the condition naturally using C/C++ syntax. Behind the scenes a simple set of expression templates captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. As we'll see later there _are_ other assertion macros - but because of this technique the number of them is drastically reduced. @@ -162,7 +162,7 @@ Sections can be nested to an arbitrary depth (limited only by your stack size). ## BDD-Style -If you name your test cases and sections appropriately you can achieve a BDD-style specification structure. This became such a useful way of working that first class support has been added to Catch. Scenarios can be specified using ```SCENARIO```, ```GIVEN```, ```WHEN``` and ```THEN``` macros, which map on to ```TEST_CASE```s and ```SECTION```s, respectively. For more details see [Test cases and sections](test-cases-and-sections.md). +If you name your test cases and sections appropriately you can achieve a BDD-style specification structure. This became such a useful way of working that first class support has been added to Catch. Scenarios can be specified using ```SCENARIO```, ```GIVEN```, ```WHEN``` and ```THEN``` macros, which map on to ```TEST_CASE```s and ```SECTION```s, respectively. For more details see [Test cases and sections](test-cases-and-sections.md#top). The vector example can be adjusted to use these macros like so: @@ -225,7 +225,7 @@ Scenario: vectors can be sized and resized To keep the tutorial simple we put all our code in a single file. This is fine to get started - and makes jumping into Catch even quicker and easier. As you write more real-world tests, though, this is not really the best approach. -The requirement is that the following block of code ([or equivalent](own-main.md)): +The requirement is that the following block of code ([or equivalent](own-main.md#top)): ```c++ #define CATCH_CONFIG_MAIN @@ -234,7 +234,7 @@ The requirement is that the following block of code ([or equivalent](own-main.md appears in _exactly one_ source file. Use as many additional cpp files (or whatever you call your implementation files) as you need for your tests, partitioned however makes most sense for your way of working. Each additional file need only ```#include "catch.hpp"``` - do not repeat the ```#define```! -In fact it is usually a good idea to put the block with the ```#define``` [in its own source file](slow-compiles.md). +In fact it is usually a good idea to put the block with the ```#define``` [in its own source file](slow-compiles.md#top). Do not write your tests in header files! @@ -243,8 +243,8 @@ Do not write your tests in header files! This has been a brief introduction to get you up and running with Catch, and to point out some of the key differences between Catch and other frameworks you may already be familiar with. This will get you going quite far already and you are now in a position to dive in and write some tests. -Of course there is more to learn - most of which you should be able to page-fault in as you go. Please see the ever-growing [Reference section](Readme.md) for what's available. +Of course there is more to learn - most of which you should be able to page-fault in as you go. Please see the ever-growing [Reference section](Readme.md#top) for what's available. --- -[Home](Readme.md) +[Home](Readme.md#top) diff --git a/docs/why-catch.md b/docs/why-catch.md index fce02bcd..45f58a6a 100644 --- a/docs/why-catch.md +++ b/docs/why-catch.md @@ -37,10 +37,10 @@ So what does Catch bring to the party that differentiates it from these? Apart f ## Who else is using Catch? -See the list of [open source projects using Catch](opensource-users.md). +See the list of [open source projects using Catch](opensource-users.md#top). -See the [tutorial](tutorial.md) to get more of a taste of using Catch in practice +See the [tutorial](tutorial.md#top) to get more of a taste of using Catch in practice --- -[Home](Readme.md) +[Home](Readme.md#top) From dee61df274ff33ac6da962cdc0743d0199d71bb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 24 Aug 2017 21:59:06 +0200 Subject: [PATCH 281/398] Refactor release scripts, automatically update Wandbox on release --- scripts/generateSingleHeader.py | 210 ++++++++++++++++---------------- scripts/majorRelease.py | 9 +- scripts/minorRelease.py | 9 +- scripts/patchRelease.py | 9 +- scripts/releaseCommon.py | 93 ++++++++------ scripts/updateWandbox.py | 47 +++++++ 6 files changed, 217 insertions(+), 160 deletions(-) create mode 100644 scripts/updateWandbox.py diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index d4be7404..1b9b10e7 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -10,117 +10,119 @@ import string from glob import glob from scriptCommon import catchPath -from releaseCommon import Version +def generate(v): + includesParser = re.compile( r'\s*#\s*include\s*"(.*)"' ) + guardParser = re.compile( r'\s*#.*(TWOBLUECUBES_)?CATCH_.*_INCLUDED') + defineParser = re.compile( r'\s*#define\s+(TWOBLUECUBES_)?CATCH_.*_INCLUDED') + ifParser = re.compile( r'\s*#ifndef (TWOBLUECUBES_)?CATCH_.*_INCLUDED') + endIfParser = re.compile( r'\s*#endif // (TWOBLUECUBES_)?CATCH_.*_INCLUDED') + ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' ) + commentParser1 = re.compile( r'^\s*/\*') + commentParser2 = re.compile( r'^ \*') + blankParser = re.compile( r'^\s*$') -includesParser = re.compile( r'\s*#\s*include\s*"(.*)"' ) -guardParser = re.compile( r'\s*#.*(TWOBLUECUBES_)?CATCH_.*_INCLUDED') -defineParser = re.compile( r'\s*#define\s+(TWOBLUECUBES_)?CATCH_.*_INCLUDED') -ifParser = re.compile( r'\s*#ifndef (TWOBLUECUBES_)?CATCH_.*_INCLUDED') -endIfParser = re.compile( r'\s*#endif // (TWOBLUECUBES_)?CATCH_.*_INCLUDED') -ifImplParser = re.compile( r'\s*#ifdef CATCH_CONFIG_RUNNER' ) -commentParser1 = re.compile( r'^\s*/\*') -commentParser2 = re.compile( r'^ \*') -blankParser = re.compile( r'^\s*$') + seenHeaders = set([]) + rootPath = os.path.join( catchPath, 'include/' ) + outputPath = os.path.join( catchPath, 'single_include/catch.hpp' ) -seenHeaders = set([]) -rootPath = os.path.join( catchPath, 'include/' ) -outputPath = os.path.join( catchPath, 'single_include/catch.hpp' ) + globals = { + 'includeImpl' : True, + 'ifdefs' : 0, + 'implIfDefs' : -1 + } -includeImpl = True - -for arg in sys.argv[1:]: - arg = string.lower(arg) - if arg == "noimpl": - includeImpl = False - print( "Not including impl code" ) - else: - print( "\n** Unrecognised argument: " + arg + " **\n" ) - exit(1) - - -# ensure that the output directory exists (hopefully no races) -outDir = os.path.dirname(outputPath) -if not os.path.exists(outDir): - os.makedirs(outDir) -out = open( outputPath, 'w' ) -ifdefs = 0 -implIfDefs = -1 - -def write( line ): - if includeImpl or implIfDefs == -1: - out.write( line ) - -def insertCpps(): - dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters']] - cppFiles = [] - for dir in dirs: - cppFiles += glob(os.path.join(dir, '*.cpp')) - for fname in cppFiles: - dir, name = fname.rsplit(os.path.sep, 1) - dir += os.path.sep - parseFile(dir, name) - -def parseFile( path, filename ): - global ifdefs - global implIfDefs - - f = open( os.path.join(path, filename), 'r' ) - blanks = 0 - write( "// start {0}\n".format( filename ) ) - for line in f: - if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line: - insertCpps() - continue - elif ifParser.match( line ): - ifdefs = ifdefs + 1 - elif endIfParser.match( line ): - ifdefs = ifdefs - 1 - if ifdefs == implIfDefs: - implIfDefs = -1 - m = includesParser.match( line ) - if m: - header = m.group(1) - headerPath, sep, headerFile = header.rpartition( "/" ) - if not headerFile in seenHeaders: - if headerFile != "tbc_text_format.h" and headerFile != "clara.h": - seenHeaders.add( headerFile ) - if headerPath == "internal" and path.endswith("internal/"): - headerPath = "" - sep = "" - if os.path.exists( path + headerPath + sep + headerFile ): - parseFile( path + headerPath + sep, headerFile ) - else: - parseFile( rootPath + headerPath + sep, headerFile ) + for arg in sys.argv[1:]: + arg = string.lower(arg) + if arg == "noimpl": + globals['includeImpl'] = False + print( "Not including impl code" ) else: - if ifImplParser.match(line): - implIfDefs = ifdefs - if (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ): - if blankParser.match( line ): - blanks = blanks + 1 - else: - blanks = 0 - if blanks < 2 and not defineParser.match(line): - write( line.rstrip() + "\n" ) - write( '// end {}\n'.format(filename) ) + print( "\n** Unrecognised argument: " + arg + " **\n" ) + exit(1) -v = Version() -out.write( "/*\n" ) -out.write( " * Catch v{0}\n".format( v.getVersionString() ) ) -out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) ) -out.write( " * ----------------------------------------------------------\n" ) -out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" ) -out.write( " * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) ) -out.write( " *\n" ) -out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" ) -out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" ) -out.write( " */\n" ) -out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) -out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) + # ensure that the output directory exists (hopefully no races) + outDir = os.path.dirname(outputPath) + if not os.path.exists(outDir): + os.makedirs(outDir) + out = open( outputPath, 'w' ) -parseFile( rootPath, 'catch.hpp' ) + def write( line ): + if globals['includeImpl'] or globals['implIfDefs'] == -1: + out.write( line ) -out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" ) + def insertCpps(): + dirs = [os.path.join( rootPath, s) for s in ['', 'internal', 'reporters']] + cppFiles = [] + for dir in dirs: + cppFiles += glob(os.path.join(dir, '*.cpp')) + for fname in cppFiles: + dir, name = fname.rsplit(os.path.sep, 1) + dir += os.path.sep + parseFile(dir, name) -print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) ) + def parseFile( path, filename ): + f = open( os.path.join(path, filename), 'r' ) + blanks = 0 + write( "// start {0}\n".format( filename ) ) + for line in f: + if '// ~*~* CATCH_CPP_STITCH_PLACE *~*~' in line: + insertCpps() + continue + elif ifParser.match( line ): + globals['ifdefs'] += 1 + elif endIfParser.match( line ): + globals['ifdefs'] -= 1 + if globals['ifdefs'] == globals['implIfDefs']: + globals['implIfDefs'] = -1 + m = includesParser.match( line ) + if m: + header = m.group(1) + headerPath, sep, headerFile = header.rpartition( "/" ) + if not headerFile in seenHeaders: + if headerFile != "tbc_text_format.h" and headerFile != "clara.h": + seenHeaders.add( headerFile ) + if headerPath == "internal" and path.endswith("internal/"): + headerPath = "" + sep = "" + if os.path.exists( path + headerPath + sep + headerFile ): + parseFile( path + headerPath + sep, headerFile ) + else: + parseFile( rootPath + headerPath + sep, headerFile ) + else: + if ifImplParser.match(line): + globals['implIfDefs'] = globals['ifdefs'] + if (not guardParser.match( line ) or defineParser.match( line ) ) and not commentParser1.match( line )and not commentParser2.match( line ): + if blankParser.match( line ): + blanks = blanks + 1 + else: + blanks = 0 + if blanks < 2 and not defineParser.match(line): + write( line.rstrip() + "\n" ) + write( '// end {}\n'.format(filename) ) + + + out.write( "/*\n" ) + out.write( " * Catch v{0}\n".format( v.getVersionString() ) ) + out.write( " * Generated: {0}\n".format( datetime.datetime.now() ) ) + out.write( " * ----------------------------------------------------------\n" ) + out.write( " * This file has been merged from multiple headers. Please don't edit it directly\n" ) + out.write( " * Copyright (c) {} Two Blue Cubes Ltd. All rights reserved.\n".format( datetime.date.today().year ) ) + out.write( " *\n" ) + out.write( " * Distributed under the Boost Software License, Version 1.0. (See accompanying\n" ) + out.write( " * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)\n" ) + out.write( " */\n" ) + out.write( "#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) + out.write( "#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n" ) + + parseFile( rootPath, 'catch.hpp' ) + + out.write( "#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED\n\n" ) + out.close() + print ("Generated single include for Catch v{0}\n".format( v.getVersionString() ) ) + + +if __name__ == '__main__': + from releaseCommon import Version + generate(Version()) diff --git a/scripts/majorRelease.py b/scripts/majorRelease.py index e8116d3b..8da34066 100755 --- a/scripts/majorRelease.py +++ b/scripts/majorRelease.py @@ -1,13 +1,10 @@ #!/usr/bin/env python from __future__ import print_function -from releaseCommon import Version +import releaseCommon -v = Version() +v = releaseCommon.Version() v.incrementMajorVersion() -v.updateVersionFile() -v.updateReadmeFile() -v.updateConanFile() -v.updateConanTestFile() +releaseCommon.performUpdates(v) print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) ) diff --git a/scripts/minorRelease.py b/scripts/minorRelease.py index dff2d8c8..6e71cd80 100755 --- a/scripts/minorRelease.py +++ b/scripts/minorRelease.py @@ -1,13 +1,10 @@ #!/usr/bin/env python from __future__ import print_function -from releaseCommon import Version +import releaseCommon -v = Version() +v = releaseCommon.Version() v.incrementMinorVersion() -v.updateVersionFile() -v.updateReadmeFile() -v.updateConanFile() -v.updateConanTestFile() +releaseCommon.performUpdates(v) print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) ) diff --git a/scripts/patchRelease.py b/scripts/patchRelease.py index e33e4064..14176420 100755 --- a/scripts/patchRelease.py +++ b/scripts/patchRelease.py @@ -1,13 +1,10 @@ #!/usr/bin/env python from __future__ import print_function -from releaseCommon import Version +import releaseCommon -v = Version() +v = releaseCommon.Version() v.incrementPatchNumber() -v.updateVersionFile() -v.updateReadmeFile() -v.updateConanFile() -v.updateConanTestFile() +releaseCommon.performUpdates(v) print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) ) diff --git a/scripts/releaseCommon.py b/scripts/releaseCommon.py index 6737f13b..6ec175f6 100644 --- a/scripts/releaseCommon.py +++ b/scripts/releaseCommon.py @@ -6,6 +6,8 @@ import re import string from scriptCommon import catchPath +import generateSingleHeader +import updateWandbox versionParser = re.compile( r'(\s*static\sVersion\sversion)\s*\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*\"(.*)\"\s*,\s*(.*)\s*\).*' ) rootPath = os.path.join( catchPath, 'include/' ) @@ -76,44 +78,59 @@ class Version: for line in lines: f.write( line + "\n" ) - def updateReadmeFile(self): - downloadParser = re.compile( r'' ) - f = open( readmePath, 'r' ) - lines = [] - for line in f: +def updateReadmeFile(version): + downloadParser = re.compile( r'' ) + success, wandboxLink = updateWandbox.uploadFiles() + if not success: + print('Error when uploading to wandbox: {}'.format(wandboxLink)) + exit(1) + f = open( readmePath, 'r' ) + lines = [] + for line in f: + lines.append( line.rstrip() ) + f.close() + f = open( readmePath, 'w' ) + for line in lines: + line = downloadParser.sub( r''.format(version.getVersionString()) , line) + if '[![Try online](https://img.shields.io/badge/try-online-blue.svg)]' in line: + line = '[![Try online](https://img.shields.io/badge/try-online-blue.svg)]({0})'.format(wandboxLink) + f.write( line + "\n" ) + +def updateConanFile(version): + conanParser = re.compile( r' version = "\d+\.\d+\.\d+.*"') + f = open( conanPath, 'r' ) + lines = [] + for line in f: + m = conanParser.match( line ) + if m: + lines.append( ' version = "{0}"'.format(format(version.getVersionString())) ) + else: lines.append( line.rstrip() ) - f.close() - f = open( readmePath, 'w' ) - for line in lines: - line = downloadParser.sub( r''.format(self.getVersionString()) , line) - f.write( line + "\n" ) + f.close() + f = open( conanPath, 'w' ) + for line in lines: + f.write( line + "\n" ) - def updateConanFile(self): - conanParser = re.compile( r' version = "\d+\.\d+\.\d+.*"') - f = open( conanPath, 'r' ) - lines = [] - for line in f: - m = conanParser.match( line ) - if m: - lines.append( ' version = "{0}"'.format(format(self.getVersionString())) ) - else: - lines.append( line.rstrip() ) - f.close() - f = open( conanPath, 'w' ) - for line in lines: - f.write( line + "\n" ) +def updateConanTestFile(version): + conanParser = re.compile( r' requires = \"Catch\/\d+\.\d+\.\d+.*@%s\/%s\" % \(username, channel\)') + f = open( conanTestPath, 'r' ) + lines = [] + for line in f: + m = conanParser.match( line ) + if m: + lines.append( ' requires = "Catch/{0}@%s/%s" % (username, channel)'.format(format(version.getVersionString())) ) + else: + lines.append( line.rstrip() ) + f.close() + f = open( conanTestPath, 'w' ) + for line in lines: + f.write( line + "\n" ) - def updateConanTestFile(self): - conanParser = re.compile( r' requires = \"Catch\/\d+\.\d+\.\d+.*@%s\/%s\" % \(username, channel\)') - f = open( conanTestPath, 'r' ) - lines = [] - for line in f: - m = conanParser.match( line ) - if m: - lines.append( ' requires = "Catch/{0}@%s/%s" % (username, channel)'.format(format(self.getVersionString())) ) - else: - lines.append( line.rstrip() ) - f.close() - f = open( conanTestPath, 'w' ) - for line in lines: - f.write( line + "\n" ) +def performUpdates(version): + # First update version file, so we can regenerate single header and + # have it ready for upload to wandbox, when updating readme + version.updateVersionFile() + generateSingleHeader.generate(version) + updateReadmeFile(version) + updateConanFile(version) + updateConanTestFile(version) diff --git a/scripts/updateWandbox.py b/scripts/updateWandbox.py new file mode 100644 index 00000000..25a74631 --- /dev/null +++ b/scripts/updateWandbox.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import json +import os +import urllib2 + +from scriptCommon import catchPath + +def upload(options): + request = urllib2.Request('http://melpon.org/wandbox/api/compile.json') + request.add_header('Content-Type', 'application/json') + response = urllib2.urlopen(request, json.dumps(options)) + return json.loads(response.read()) + +main_file = ''' +#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file +#include "catch.hpp" + +unsigned int Factorial( unsigned int number ) { + return number <= 1 ? number : Factorial(number-1)*number; +} + +TEST_CASE( "Factorials are computed", "[factorial]" ) { + REQUIRE( Factorial(1) == 1 ); + REQUIRE( Factorial(2) == 2 ); + REQUIRE( Factorial(3) == 6 ); + REQUIRE( Factorial(10) == 3628800 ); +} +''' + +def uploadFiles(): + response = upload({ + 'compiler': 'gcc-head', + 'code': main_file, + 'codes': [{ + 'file': 'catch.hpp', + 'code': open(os.path.join(catchPath, 'single_include', 'catch.hpp')).read() + }], + 'options': 'c++11,cpp-no-pedantic,boost-nothing', + 'compiler-option-raw': '-DCATCH_CONFIG_FAST_COMPILE', + 'save': True + }) + + if 'status' in response and not 'compiler_error' in response: + return True, response['url'] + else: + return False, response From 071f49b12b62f70ead40b84073620529ba9fc487 Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Thu, 24 Aug 2017 22:21:54 +0200 Subject: [PATCH 282/398] Add page titles --- docs/Readme.md | 2 ++ docs/command-line.md | 2 ++ docs/configuration.md | 2 ++ docs/test-fixtures.md | 2 ++ docs/tutorial.md | 8 +++++--- 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/Readme.md b/docs/Readme.md index b1623626..e7815671 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -1,4 +1,6 @@ +# Reference + To get the most out of Catch, start with the [tutorial](tutorial.md#top). Once you're up and running consider the following reference material. diff --git a/docs/command-line.md b/docs/command-line.md index 0e1a7af8..12517bcc 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -1,4 +1,6 @@ +# Command line + Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available. Click one of the followings links to take you straight to that option - or scroll on to browse the available options. diff --git a/docs/configuration.md b/docs/configuration.md index 35809ab4..82edc55c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,4 +1,6 @@ +# Compile-time configuration + Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a set of macros for configuring how it is built. diff --git a/docs/test-fixtures.md b/docs/test-fixtures.md index c887ce26..1dc7baba 100644 --- a/docs/test-fixtures.md +++ b/docs/test-fixtures.md @@ -1,4 +1,6 @@ +# Test fixtures + Although Catch allows you to group tests together as sections within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. Catch fully supports this too. You define the test fixture as a simple structure: ```c++ diff --git a/docs/tutorial.md b/docs/tutorial.md index f4bcb07d..80465ba2 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -1,5 +1,7 @@ -# Getting Catch +# Tutorial + +## Getting Catch The simplest way to get Catch is to download the latest [single header version](https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. @@ -12,7 +14,7 @@ Catch is header only. All you need to do is drop the file(s) somewhere reachable The rest of this tutorial will assume that the Catch single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary. -# Writing tests +## Writing tests Let's start with a really simple example. Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now). @@ -83,7 +85,7 @@ Now all the tests pass. Of course there are still more issues to deal with. For example we'll hit problems when the return value starts to exceed the range of an unsigned int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here. -## What did we do here? +### What did we do here? Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on. From b1d008579604b08217857863c8276bcfc6865c67 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 25 Aug 2017 11:33:29 +0100 Subject: [PATCH 283/398] Tweaked how failedButOk assertions are recorded - fixes issue where sections in !shouldfail or !mayfail test cases that have failing assertions where marked as failed instead of failedButOk --- include/internal/catch_run_context.cpp | 12 ++++-------- projects/SelfTest/Baselines/xml.sw.approved.txt | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index d29ef54d..d5b69ae5 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -112,7 +112,10 @@ namespace Catch { if (result.getResultType() == ResultWas::Ok) { m_totals.assertions.passed++; } else if (!result.isOk()) { - m_totals.assertions.failed++; + if( m_activeTestCase->getTestCaseInfo().okToFail() ) + m_totals.assertions.failedButOk++; + else + m_totals.assertions.failed++; } // We have no use for the return value (whether messages should be cleared), because messages were made scoped @@ -297,13 +300,6 @@ namespace Catch { Counts assertions = m_totals.assertions - prevAssertions; bool missingAssertions = testForMissingAssertions(assertions); - - if (testCaseInfo.okToFail()) { - std::swap(assertions.failedButOk, assertions.failed); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); m_reporter->sectionEnded(testCaseSectionStats); } diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 8f52326e..61870985 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -12,7 +12,7 @@ expected exception - +
@@ -29,7 +29,7 @@ expected exception - +
From 67dc654c7087992f6179f8a9d0d590b571493b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 27 Aug 2017 11:43:55 +0200 Subject: [PATCH 284/398] Fix updateVcpkgPackage --- scripts/updateVcpkgPackage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/updateVcpkgPackage.py b/scripts/updateVcpkgPackage.py index 4d20d11c..43f5bb4f 100644 --- a/scripts/updateVcpkgPackage.py +++ b/scripts/updateVcpkgPackage.py @@ -65,7 +65,7 @@ def update_portfile(path, header_hash, licence_hash): for line in lines: # Update the version if 'set(CATCH_VERSION' in line: - line = 'set(CATCH_VERSION v{})'.format(v.getVersionString()) + line = 'set(CATCH_VERSION v{})\n'.format(v.getVersionString()) # Determine which file we are updating if 'vcpkg_download_distfile' in line: From e8d3be3621241531a146571d55d7e181b1251e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 26 Aug 2017 15:14:27 +0200 Subject: [PATCH 285/398] Workaround raw string literal bug in VS2017 --- docs/configuration.md | 4 ++- docs/limitations.md | 32 +++++++++++++++++++++++ include/internal/catch_capture.hpp | 15 +++++++---- include/internal/catch_capture_matchers.h | 4 +-- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 82edc55c..ff5811d9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -72,6 +72,7 @@ This can be useful on certain platforms that do not provide the standard iostrea CATCH_CONFIG_DISABLE_MATCHERS // Do not compile Matchers in this compilation unit CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap + CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support. @@ -88,12 +89,13 @@ Defining this flag speeds up compilation of test files by ~20%, by making 2 chan `CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable. - ## `CATCH_CONFIG_DISABLE_MATCHERS` When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU. _Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._ +## `CATCH_CONFIG_DISABLE_STRINGIFICATION` +This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#Visual Studio 2017 -- raw string literal in assert fails to compile) # Windows header clutter diff --git a/docs/limitations.md b/docs/limitations.md index 8c192320..c6ef640e 100644 --- a/docs/limitations.md +++ b/docs/limitations.md @@ -65,6 +65,38 @@ Both of these solutions have their problems, but should let you wring parallelis ## 3rd party bugs This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes). +### Visual Studio 2017 -- raw string literal in assert fails to compile +There is a known bug in Visual Studio 2017 (VC 15), that causes compilation error when preprocessor attempts to stringize a raw string literal (`#` preprocessor is applied to it). This snippet is sufficient to trigger the compilation error: +```cpp +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +TEST_CASE("test") { + CHECK(std::string(R"("\)") == "\"\\"); +} +``` + +Catch provides a workaround, it is possible to disable stringification of original expressions by defining `CATCH_CONFIG_DISABLE_STRINGIFICATION`: +```cpp +#define CATCH_CONFIG_FAST_COMPILE +#define CATCH_CONFIG_DISABLE_STRINGIFICATION +#include "catch.hpp" + +TEST_CASE("test") { + CHECK(std::string(R"("\)") == "\"\\"); +} +``` + +_Do note that this changes the output somewhat_ +``` +catchwork\test1.cpp(6): +PASSED: + CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION ) +with expansion: + ""\" == ""\" +``` + + ### Visual Studio 2013 -- do-while loop withing range based for fails to compile (C2059) There is a known bug in Visual Studio 2013 (VC 12), that causes compilation error if range based for is followed by an assertion macro, without enclosing the block in braces. This snippet is sufficient to trigger the error ```cpp diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index d5d0ad4e..bfa18bfd 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -12,6 +12,11 @@ #include "catch_message.h" #include "catch_interfaces_capture.h" +#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) + #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ +#else + #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" +#endif #if defined(CATCH_CONFIG_FAST_COMPILE) /////////////////////////////////////////////////////////////////////////////// @@ -50,7 +55,7 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ @@ -73,7 +78,7 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ try { \ static_cast(__VA_ARGS__); \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ @@ -87,7 +92,7 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__); \ @@ -104,7 +109,7 @@ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(expr); \ @@ -138,7 +143,7 @@ // 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, #__VA_ARGS__ ", " #matcher, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__); \ diff --git a/include/internal/catch_capture_matchers.h b/include/internal/catch_capture_matchers.h index 80262dbf..3520ad2e 100644 --- a/include/internal/catch_capture_matchers.h +++ b/include/internal/catch_capture_matchers.h @@ -57,7 +57,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ @@ -68,7 +68,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__ ); \ From 8f6d6a4a2daa7f7157dda2032e39bdd30dabe58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 27 Aug 2017 16:45:53 +0200 Subject: [PATCH 286/398] Remove legacy [hide] tag Also removed even legacier "./" prefix for test case name... --- docs/test-cases-and-sections.md | 2 +- include/internal/catch_test_case_info.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md index 7d26226e..56600759 100644 --- a/docs/test-cases-and-sections.md +++ b/docs/test-cases-and-sections.md @@ -35,7 +35,7 @@ Tag names are not case sensitive and can contain any ASCII characters. This mean All tag names beginning with non-alphanumeric characters are reserved by Catch. Catch defines a number of "special" tags, which have meaning to the test runner itself. These special tags all begin with a symbol character. Following is a list of currently defined special tags and their meanings. -* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (i.e. when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them. +* `[!hide]` or `[.]` - causes test cases to be skipped from the default list (i.e. when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them. * `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`. diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index a811f1df..d97b5996 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -20,7 +20,6 @@ namespace Catch { TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { if( startsWith( tag, '.' ) || - tag == "hide" || tag == "!hide" ) return TestCaseInfo::IsHidden; else if( tag == "!throws" ) @@ -52,7 +51,7 @@ namespace Catch { std::string const& _descOrTags, SourceLineInfo const& _lineInfo ) { - bool isHidden( startsWith( _name, "./" ) ); // Legacy support + bool isHidden = false; // Parse out tags std::vector tags; @@ -83,7 +82,6 @@ namespace Catch { } } if( isHidden ) { - tags.push_back( "hide" ); tags.push_back( "." ); } From a0988dabf62137d972236dcd2c5771152d7bbf11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 27 Aug 2017 16:47:25 +0200 Subject: [PATCH 287/398] Add the experimental benchmark feature in documentation --- docs/test-cases-and-sections.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md index 56600759..0e5cc466 100644 --- a/docs/test-cases-and-sections.md +++ b/docs/test-cases-and-sections.md @@ -49,6 +49,8 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch. * `[@]` - tag aliases all begin with `@` (see below). +* `[!benchmark]` - this test case is actually a benchmark. This is an experimental feature, and currently has no documentation. If you want to try it out, look at `projects/SelfTest/Benchmark.tests.cpp` for details. + ## Tag aliases Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form: From 2a13593885f400c5ab89143c9d768f0d4a184db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 27 Aug 2017 16:48:15 +0200 Subject: [PATCH 288/398] Update CATCH_CONFIG_FAST_COMPILE documentation Now it mentions that CHECK family of macros is affected as well --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index ff5811d9..28397e25 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -85,7 +85,7 @@ These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CO ## `CATCH_CONFIG_FAST_COMPILE` Defining this flag speeds up compilation of test files by ~20%, by making 2 changes: * The `-b` (`--break`) flag no longer makes Catch break into debugger in the same stack frame as the failed test, but rather in a stack frame *below*. -* The `REQUIRE` family of macros (`REQUIRE`, `REQUIRE_FALSE` and `REQUIRE_THAT`) no longer uses local try-catch block. This disables exception translation, but should not lead to false negatives. +* Non-exception family of macros ({`REQUIRE`,`CHECK`}{`_`,`_FALSE`, `_FALSE`}, no longer use local try-cache block. This disables exception translation, but should not lead to false negatives. `CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable. From 053c29a2b844b42e569d757c9353cb5997ca0723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 27 Aug 2017 17:03:32 +0200 Subject: [PATCH 289/398] Add partial implementation of CATCH_CONFIG_DISABLE * Assertions are defined into (void)(0) no-op * SECTIONs are defined away (leaving {} as scope) * TEST_CASEs and TEST_CASE_METHODs are not registered. * REGISTER_TEST_CASE is defined into (void)(0) no-op * METHOD_AS_TEST_CASE is defined away --- docs/configuration.md | 8 ++ docs/release-notes.md | 12 +++ include/catch.hpp | 129 +++++++++++++++++++++++ include/internal/catch_capture.hpp | 3 + include/internal/catch_test_registry.hpp | 13 +++ 5 files changed, 165 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index 28397e25..2e5fc6f9 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -73,6 +73,7 @@ This can be useful on certain platforms that do not provide the standard iostrea CATCH_CONFIG_POSIX_SIGNALS // Enable handling POSIX signals CATCH_CONFIG_WINDOWS_CRTDBG // Enable leak checking using Windows's CRT Debug Heap CATCH_CONFIG_DISABLE_STRINGIFICATION // Disable stringifying the original expression + CATCH_CONFIG_DISABLE // Disables assertions and test case registration Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support. @@ -97,6 +98,13 @@ _Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's ## `CATCH_CONFIG_DISABLE_STRINGIFICATION` This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#Visual Studio 2017 -- raw string literal in assert fails to compile) +## `CATCH_CONFIG_DISABLE` +This toggle removes most of Catch from given file. This means that `TEST_CASE`s are not registered and assertions are turned into no-ops. Useful for keeping tests within implementation files (ie for functions with internal linkage), instead of in external files. + +This feature is considered experimental and might change at any point. + +_Inspired by Doctest's `DOCTEST_CONFIG_DISABLE`_ + # Windows header clutter On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros: diff --git a/docs/release-notes.md b/docs/release-notes.md index 2c4765fe..d076c8b3 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -9,6 +9,10 @@ * Removed `Catch::toString` support * The new stringification machinery uses `Catch::StringMaker` specializations first and `operator<<` overloads second. * Removed legacy `SCOPED_MSG` and `SCOPED_INFO` macros +* Removed `INTERNAL_CATCH_REGISTER_REPORTER` + * `CATCH_REGISTER_REPORTER` should be used to register reporters +* Removed legacy `[hide]` tag + * `[.]`, `[.foo]` and `[!hide]` are still supported * Output into debugger is now colourized * `*_THROWS_AS(expr, exception_type)` now unconditionally appends `const&` to the exception type. * `CATCH_CONFIG_FAST_COMPILE` now affects the `CHECK_` family of assertions as well as `REQUIRE_` family of assertions @@ -29,6 +33,14 @@ * Catch uses new CLI parsing library (Clara) * Users can now easily add new command line options to the final executable * This also leads to some changes in `Catch::Session` interface +* All parts of matchers can be removed from a TU by defining `CATCH_CONFIG_DISABLE_MATCHERS` + * This can be used to somewhat speed up compilation times +* An experimental implementation of `CATCH_CONFIG_DISABLE` has been added + * Speeds up compilation by removing away Catch tests + * Currently removes all assertions and prevents `TEST_CASE` registrations + * Useful for implementing tests in source files + * ie for functions in anonymous namespaces + * Inspired by Doctest's `DOCTEST_CONFIG_DISABLE` ## Fixes diff --git a/include/catch.hpp b/include/catch.hpp index c1099264..956c4b30 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -72,6 +72,7 @@ # undef CLARA_CONFIG_MAIN #endif +#if !defined(CATCH_CONFIG_DISABLE) ////// // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL @@ -196,6 +197,134 @@ using Catch::Detail::Approx; +#else +////// +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( ... ) (void)(0) +#define CATCH_REQUIRE_FALSE( ... ) (void)(0) + +#define CATCH_REQUIRE_THROWS( ... ) (void)(0) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif// CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) + +#define CATCH_CHECK( ... ) (void)(0) +#define CATCH_CHECK_FALSE( ... ) (void)(0) +#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) +#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CATCH_CHECK_NOFAIL( ... ) (void)(0) + +#define CATCH_CHECK_THROWS( ... ) (void)(0) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW( ... ) (void)(0) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THAT( arg, matcher ) (void)(0) + +#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define CATCH_INFO( msg ) (void)(0) +#define CATCH_WARN( msg ) (void)(0) +#define CATCH_CAPTURE( msg ) (void)(0) + +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define CATCH_SECTION( ... ) +#define CATCH_FAIL( ... ) (void)(0) +#define CATCH_FAIL_CHECK( ... ) (void)(0) +#define CATCH_SUCCEED( ... ) (void)(0) + +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +// "BDD-style" convenience wrappers +#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define CATCH_GIVEN( desc ) +#define CATCH_WHEN( desc ) +#define CATCH_AND_WHEN( desc ) +#define CATCH_THEN( desc ) +#define CATCH_AND_THEN( desc ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( ... ) (void)(0) +#define REQUIRE_FALSE( ... ) (void)(0) + +#define REQUIRE_THROWS( ... ) (void)(0) +#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW( ... ) (void)(0) + +#define CHECK( ... ) (void)(0) +#define CHECK_FALSE( ... ) (void)(0) +#define CHECKED_IF( ... ) if (__VA_ARGS__) +#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CHECK_NOFAIL( ... ) (void)(0) + +#define CHECK_THROWS( ... ) (void)(0) +#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW( ... ) (void)(0) + + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THAT( arg, matcher ) (void)(0) + +#define REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define INFO( msg ) (void)(0) +#define WARN( msg ) (void)(0) +#define CAPTURE( msg ) (void)(0) + +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define METHOD_AS_TEST_CASE( method, ... ) +#define REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define SECTION( ... ) +#define FAIL( ... ) (void)(0) +#define FAIL_CHECK( ... ) (void)(0) +#define SUCCEED( ... ) (void)(0) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) + +#define GIVEN( desc ) +#define WHEN( desc ) +#define AND_WHEN( desc ) +#define THEN( desc ) +#define AND_THEN( desc ) + +using Catch::Detail::Approx; + + +#endif + #include "internal/catch_reenable_warnings.h" #endif // TWOBLUECUBES_CATCH_HPP_INCLUDED diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index bfa18bfd..c914bffe 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -12,6 +12,8 @@ #include "catch_message.h" #include "catch_interfaces_capture.h" +#if !defined(CATCH_CONFIG_DISABLE) + #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ #else @@ -157,5 +159,6 @@ INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) +#endif // CATCH_CONFIG_DISABLE #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index 07334c34..374da734 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -47,6 +47,19 @@ struct AutoReg : NonCopyable { } // end namespace Catch +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ + static void TestName() + #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ + namespace{ \ + struct TestName : ClassName { \ + void test(); \ + }; \ + } \ + void TestName::test() + +#endif + /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ From 05b6f03f3e8e1e3a51814e61f8b4d1edc12e4cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 09:48:52 +0200 Subject: [PATCH 290/398] Disable reporter/listener registration with CATCH_CONFIG_DISABLE --- include/internal/catch_reporter_registrars.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index e0db392b..6d30a833 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -55,10 +55,19 @@ namespace Catch { }; } +#if !defined(CATCH_CONFIG_DISABLE) + #define CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } #define CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } +#else // CATCH_CONFIG_DISABLE + +#define CATCH_REGISTER_REPORTER(name, reporterType) +#define CATCH_REGISTER_LISTENER(listenerType) + +#endif // CATCH_CONFIG_DISABLE + #endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED From 75f143835e1320f4bb5970e52505482ec9c7a1c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 09:52:25 +0200 Subject: [PATCH 291/398] Prevent exception translator registration with CATCH_CONFIG_DISABLE --- include/catch.hpp | 2 +- include/internal/catch_interfaces_exception.h | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 956c4b30..d49c7461 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -308,7 +308,7 @@ using Catch::Detail::Approx; #endif -#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // "BDD-style" convenience wrappers #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index 43e4fbf4..40b7e59b 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -8,11 +8,16 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED +#include "catch_interfaces_registry_hub.h" + +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ + static std::string translatorName( signature ) +#endif + #include #include -#include "catch_interfaces_registry_hub.h" - namespace Catch { using exceptionTranslateFunction = std::string(*)(); From 3b8b25c59d7425c66d350cdb21155438f7b071d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 09:52:58 +0200 Subject: [PATCH 292/398] Make REGISTER_TEST_CASE auto registering This also means it can be used in global scope --- include/internal/catch_test_registry.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index 374da734..19f08c2a 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -93,7 +93,7 @@ struct AutoReg : NonCopyable { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( 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::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS From faead531518a8e9dee4eb1a516bc6ea9072bbb74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 13:48:20 +0200 Subject: [PATCH 293/398] Update approval test baselines after removing [hide] tag --- .../SelfTest/Baselines/xml.sw.approved.txt | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 61870985..68607f0b 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -4,7 +4,7 @@ - +
answer := 42 @@ -117,7 +117,7 @@ - + f() == 0 @@ -150,7 +150,7 @@ - +
@@ -168,7 +168,7 @@
- + false != false @@ -384,7 +384,7 @@
- + s == "world" @@ -406,7 +406,7 @@ - + m_a == 2 @@ -428,7 +428,7 @@ - +
@@ -440,7 +440,7 @@ - + &o1 == &o2 @@ -535,7 +535,7 @@ - + 1 == 1 @@ -1317,7 +1317,7 @@ - + testStringForMatching(), Contains( "not there" ) @@ -1328,7 +1328,7 @@ - + throwCustom() @@ -1342,7 +1342,7 @@ - + throwCustom(), std::exception @@ -1356,7 +1356,7 @@ - + custom std exception @@ -1373,7 +1373,7 @@ - + testStringForMatching(), EndsWith( "this" ) @@ -1384,7 +1384,7 @@ - + data.int_seven == 6 @@ -1561,7 +1561,7 @@ - + testStringForMatching(), Equals( "something else" ) @@ -1572,7 +1572,7 @@ - +
@@ -1717,7 +1717,7 @@
- + thisThrows(), std::string @@ -1750,17 +1750,17 @@ - + This is a failure - + - + This is a failure @@ -1847,7 +1847,7 @@ - + this is a message @@ -1856,7 +1856,7 @@ - + this message should be logged @@ -1873,7 +1873,7 @@ - + this message may be logged later @@ -1938,7 +1938,7 @@ - + current counter 0 @@ -2095,7 +2095,7 @@ - + data.int_seven != 7 @@ -2308,7 +2308,7 @@ - + testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) @@ -2330,7 +2330,7 @@ - + testStringForMatching(), !Contains( "substring" ) @@ -2341,7 +2341,7 @@ - + thisThrows(), "expected exception" @@ -2360,13 +2360,13 @@ - + This one ran - + custom exception @@ -2410,7 +2410,7 @@ - + data.int_seven > 7 @@ -2704,7 +2704,7 @@ - +
Message from section one @@ -3973,7 +3973,7 @@ - + actual address of p: 0x @@ -4595,7 +4595,7 @@
- + truthy(false) @@ -4609,7 +4609,7 @@ - + @@ -4774,7 +4774,7 @@
- + A string sent directly to stdout @@ -4835,7 +4835,7 @@ A string sent directly to stderr - +
@@ -4853,7 +4853,7 @@ Interleaved writes to error streams
- +
@@ -4867,7 +4867,7 @@ Message from section two
- + testStringForMatching(), StartsWith( "string" ) @@ -5325,7 +5325,7 @@ Message from section two
- + s1 == s2 @@ -5449,7 +5449,7 @@ Message from section two - + @@ -6558,7 +6558,7 @@ Message from section two
- + 3.14 @@ -6721,7 +6721,7 @@ Message from section two
- +
@@ -6824,13 +6824,13 @@ Message from section two - + unexpected exception - + thisThrows() == 0 @@ -6844,7 +6844,7 @@ Message from section two - + thisThrows() == 0 @@ -6858,7 +6858,7 @@ Message from section two - + thisThrows() == 0 @@ -6872,7 +6872,7 @@ Message from section two - +
unexpected exception @@ -6884,13 +6884,13 @@ Message from section two - + Uncomment the code in this test to check that it gives a sensible compiler error - + Uncomment the code in this test to check that it gives a sensible compiler error @@ -7065,7 +7065,7 @@ Message from section two - + flag @@ -7103,7 +7103,7 @@ Message from section two - + flag @@ -7217,7 +7217,7 @@ Message from section two loose text artifact - + Previous info should not be seen @@ -7239,7 +7239,7 @@ loose text artifact - +
@@ -7253,7 +7253,7 @@ loose text artifact
- + Testing if fib[0] (1) is even @@ -7344,7 +7344,7 @@ loose text artifact - +
@@ -7389,7 +7389,7 @@ loose text artifact
- +
@@ -7433,7 +7433,7 @@ loose text artifact - + ti == typeid(int) @@ -7501,7 +7501,7 @@ loose text artifact - +
@@ -7673,7 +7673,7 @@ loose text artifact - + 3 @@ -7687,7 +7687,7 @@ loose text artifact - + hi @@ -7739,7 +7739,7 @@ loose text artifact - + std::string( "first" ) == "second" @@ -7763,7 +7763,7 @@ loose text artifact - + ::Catch::Detail::stringify( item ) == "StringMaker<has_maker_and_operator>" @@ -7875,7 +7875,7 @@ loose text artifact - + ::Catch::Detail::stringify(e0) == "0" From 5932576f534ef08a3d13b0cd99464999dbe7b50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 13:51:55 +0200 Subject: [PATCH 294/398] Split writeToDebugConsole out of main path --- CMakeLists.txt | 2 ++ include/internal/catch_debug_console.cpp | 29 ++++++++++++++++++++++++ include/internal/catch_debug_console.h | 17 ++++++++++++++ include/internal/catch_debugger.cpp | 18 --------------- include/internal/catch_debugger.h | 6 +---- include/internal/catch_stream.cpp | 2 +- 6 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 include/internal/catch_debug_console.cpp create mode 100644 include/internal/catch_debug_console.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b538f5d7..8248ed99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_config.hpp ${HEADER_DIR}/internal/catch_console_colour.hpp ${HEADER_DIR}/internal/catch_context.h + ${HEADER_DIR}/internal/catch_debug_console.h ${HEADER_DIR}/internal/catch_debugger.h ${HEADER_DIR}/internal/catch_decomposer.h ${HEADER_DIR}/internal/catch_default_main.hpp @@ -203,6 +204,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_config.cpp ${HEADER_DIR}/internal/catch_console_colour.cpp ${HEADER_DIR}/internal/catch_context.cpp + ${HEADER_DIR}/internal/catch_debug_console.cpp ${HEADER_DIR}/internal/catch_debugger.cpp ${HEADER_DIR}/internal/catch_decomposer.cpp ${HEADER_DIR}/internal/catch_errno_guard.cpp diff --git a/include/internal/catch_debug_console.cpp b/include/internal/catch_debug_console.cpp new file mode 100644 index 00000000..d817c561 --- /dev/null +++ b/include/internal/catch_debug_console.cpp @@ -0,0 +1,29 @@ +/* + * Created by Martin on 29/08/2017. + * + * 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) + * + */ + +#include "catch_debug_console.h" +#include "catch_stream.h" +#include "catch_platform.h" + +#ifdef CATCH_PLATFORM_WINDOWS + +#include "catch_windows_h_proxy.h" + + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform diff --git a/include/internal/catch_debug_console.h b/include/internal/catch_debug_console.h new file mode 100644 index 00000000..2c229a83 --- /dev/null +++ b/include/internal/catch_debug_console.h @@ -0,0 +1,17 @@ +/* + * Created by Martin on 29/08/2017. + * + * 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) + * + */ +#ifndef TWOBLUECUBES_CATCH_DEBUG_CONSOLE_H_INCLUDED +#define TWOBLUECUBES_CATCH_DEBUG_CONSOLE_H_INCLUDED + +#include + +namespace Catch { + void writeToDebugConsole( std::string const& text ); +} + +#endif // TWOBLUECUBES_CATCH_DEBUG_CONSOLE_H_INCLUDED diff --git a/include/internal/catch_debugger.cpp b/include/internal/catch_debugger.cpp index 4d05c85a..a467e9fd 100644 --- a/include/internal/catch_debugger.cpp +++ b/include/internal/catch_debugger.cpp @@ -109,21 +109,3 @@ bool isDebuggerActive() { return false; } } #endif // Platform - -#ifdef CATCH_PLATFORM_WINDOWS - -#include "catch_windows_h_proxy.h" - - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } -#endif // Platform diff --git a/include/internal/catch_debugger.h b/include/internal/catch_debugger.h index 279bec06..f842ff5b 100644 --- a/include/internal/catch_debugger.h +++ b/include/internal/catch_debugger.h @@ -11,12 +11,8 @@ #include "catch_platform.h" -#include - -namespace Catch{ - +namespace Catch { bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); } #ifdef CATCH_PLATFORM_MAC diff --git a/include/internal/catch_stream.cpp b/include/internal/catch_stream.cpp index 81dbdd47..4278317d 100644 --- a/include/internal/catch_stream.cpp +++ b/include/internal/catch_stream.cpp @@ -10,7 +10,7 @@ #include "catch_common.h" #include "catch_enforce.h" #include "catch_stream.h" -#include "catch_debugger.h" +#include "catch_debug_console.h" #include #include From bcb430b8372eacb2c091a93327724eb8221e8c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 14:02:14 +0200 Subject: [PATCH 295/398] Clean up various minor things --- include/internal/catch_assertionresult.cpp | 3 +++ include/internal/catch_assertionresult.h | 5 +---- include/internal/catch_fatal_condition.cpp | 9 ++++----- include/internal/catch_reporter_registry.hpp | 4 ++-- include/internal/catch_test_case_info.cpp | 3 +-- include/internal/catch_wildcard_pattern.hpp | 2 -- include/reporters/catch_reporter_bases.hpp | 2 +- 7 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 776fdc72..ea416856 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -9,6 +9,9 @@ #include "catch_assertionresult.h" namespace Catch { + AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): + resultType(_resultType), + lazyExpression(_lazyExpression) {} std::string AssertionResultData::reconstructExpression() const { diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index b1177fa4..dfa2fab0 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -21,10 +21,7 @@ namespace Catch { { AssertionResultData() = delete; - AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ) - : resultType( _resultType ), - lazyExpression( _lazyExpression ) - {} + AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); ResultWas::OfType resultType = ResultWas::Unknown; std::string message; diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp index 51773f42..3de65f73 100644 --- a/include/internal/catch_fatal_condition.cpp +++ b/include/internal/catch_fatal_condition.cpp @@ -47,9 +47,9 @@ namespace Catch { }; LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); + for (auto const& def : signalDefs) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { + reportFatal(def.name); } } // If its not an exception we care about, pass it along. @@ -123,8 +123,7 @@ namespace Catch { void FatalConditionHandler::handleSignal( int sig ) { std::string name = ""; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - SignalDefs &def = signalDefs[i]; + for (auto const& def : signalDefs) { if (sig == def.id) { name = def.name; break; diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index 0c015fb9..c3bf3b61 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -21,14 +21,14 @@ namespace Catch { ~ReporterRegistry() override {} IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { - FactoryMap::const_iterator it = m_factories.find( name ); + auto it = m_factories.find( name ); if( it == m_factories.end() ) return nullptr; return it->second->create( ReporterConfig( config ) ); } void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { - m_factories.insert( { name, factory } ); + m_factories.emplace(name, factory); } void registerListener( IReporterFactoryPtr const& factory ) { m_listeners.push_back( factory ); diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index d97b5996..54ecc2b6 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -57,8 +57,7 @@ namespace Catch { std::vector tags; std::string desc, tag; bool inTag = false; - for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { - char c = _descOrTags[i]; + for (char c : _descOrTags) { if( !inTag ) { if( c == '[' ) inTag = true; diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp index e163650c..4dae7171 100644 --- a/include/internal/catch_wildcard_pattern.hpp +++ b/include/internal/catch_wildcard_pattern.hpp @@ -10,8 +10,6 @@ #include "catch_common.h" -#include - namespace Catch { diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index cfba9415..1c7efb64 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -174,7 +174,7 @@ namespace Catch { } else { SectionNode& parentNode = *m_sectionStack.back(); - typename SectionNode::ChildSections::const_iterator it = + auto it = std::find_if( parentNode.childSections.begin(), parentNode.childSections.end(), BySectionInfo( sectionInfo ) ); From 92444d8b7266a4781b4ab555fde9ed50a67bf6b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 15:36:09 +0200 Subject: [PATCH 296/398] Remove catch_context.h from the common include path --- include/catch.hpp | 1 - include/internal/catch_benchmark.cpp | 1 + include/internal/catch_run_context.cpp | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/catch.hpp b/include/catch.hpp index d49c7461..acc2c9cc 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -31,7 +31,6 @@ # endif #endif -#include "internal/catch_context.h" #include "internal/catch_tag_alias_autoregistrar.h" #include "internal/catch_test_registry.hpp" #include "internal/catch_capture.hpp" diff --git a/include/internal/catch_benchmark.cpp b/include/internal/catch_benchmark.cpp index d92b255c..742418f7 100644 --- a/include/internal/catch_benchmark.cpp +++ b/include/internal/catch_benchmark.cpp @@ -9,6 +9,7 @@ #include "catch_benchmark.h" #include "catch_capture.hpp" #include "catch_interfaces_reporter.h" +#include "catch_context.h" namespace Catch { diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index d5b69ae5..24e3df1e 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -1,4 +1,5 @@ #include "catch_run_context.hpp" +#include "catch_context.h" #include "catch_enforce.h" #include From 6e46f2983085045ef0c3f2a9fa020a70b0ff9c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 15:40:19 +0200 Subject: [PATCH 297/398] Remove empty compiler detection If they are needed in the future, they can be reinstated, but there is no point in keeping them around currently. --- .../internal/catch_compiler_capabilities.h | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index c1066a56..56fd4673 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -76,34 +76,6 @@ #endif // __CYGWIN__ -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - - -#endif // __GNUC__ - //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER From 4453fefb00b6757b2414783c38c2ddfdd56320d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 15:45:58 +0200 Subject: [PATCH 298/398] Remove check for compiler version before using __COUNTER__ All still supported compiler versions support __COUNTER__. User can also still turn off use of __COUNTER__ by defining CATCH_CONFIG_NO_COUNTER. --- include/internal/catch_compiler_capabilities.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index 56fd4673..3bd40461 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -86,15 +86,10 @@ //////////////////////////////////////////////////////////////////////////////// -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ - ( defined __clang__ && __clang_major__ >= 3 ) - +// All supported compilers support COUNTER macro, +//but user still might want to turn it off #define CATCH_INTERNAL_CONFIG_COUNTER -#endif - // Now set the actual defines based on the above + anything the user has configured From dd8e79c529f159415b5c567884e11d09bfd2ee0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 29 Aug 2017 16:44:02 +0200 Subject: [PATCH 299/398] Streamline includes in external interfaces --- include/catch_session.hpp | 1 + include/internal/catch_config.cpp | 1 + include/internal/catch_config.hpp | 4 ++-- include/internal/catch_context.h | 4 ++-- include/internal/catch_impl.hpp | 2 -- include/internal/catch_interfaces_reporter.h | 1 - include/internal/catch_list.cpp | 1 + include/internal/catch_registry_hub.cpp | 1 + include/internal/catch_run_context.cpp | 1 + include/internal/catch_run_context.hpp | 2 ++ 10 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index a423a3be..f02b93d9 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -13,6 +13,7 @@ #include "internal/catch_enforce.h" #include "internal/catch_list.h" #include "internal/catch_run_context.hpp" +#include "internal/catch_stream.h" #include "internal/catch_test_spec.hpp" #include "internal/catch_version.h" #include "internal/catch_interfaces_reporter.h" diff --git a/include/internal/catch_config.cpp b/include/internal/catch_config.cpp index d88a3d14..0f79a9ad 100644 --- a/include/internal/catch_config.cpp +++ b/include/internal/catch_config.cpp @@ -7,6 +7,7 @@ #include "catch_config.hpp" #include "catch_enforce.h" +#include "catch_stream.h" namespace Catch { diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index d2ca6202..0f86137f 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -9,9 +9,7 @@ #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED #include "catch_test_spec_parser.hpp" -#include "catch_context.h" #include "catch_interfaces_config.h" -#include "catch_stream.h" #include #include @@ -23,6 +21,8 @@ namespace Catch { + struct IStream; + struct ConfigData { bool listTests = false; bool listTags = false; diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 7815be22..39307f59 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -22,7 +22,7 @@ namespace Catch { struct IContext { - virtual ~IContext(); + virtual ~IContext() = default; virtual IResultCapture* getResultCapture() = 0; virtual IRunner* getRunner() = 0; @@ -31,7 +31,7 @@ namespace Catch { struct IMutableContext : IContext { - virtual ~IMutableContext(); + virtual ~IMutableContext() = default; virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setRunner( IRunner* runner ) = 0; virtual void setConfig( IConfigPtr const& config ) = 0; diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 0d846e1d..785f3ddc 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -46,7 +46,6 @@ namespace Catch { CoutStream::~CoutStream() noexcept {} DebugOutStream::~DebugOutStream() noexcept {} StreamBufBase::~StreamBufBase() noexcept {} - IContext::~IContext() {} IResultCapture::~IResultCapture() {} ITestInvoker::~ITestInvoker() {} ITestCaseRegistry::~ITestCaseRegistry() {} @@ -55,7 +54,6 @@ namespace Catch { IExceptionTranslator::~IExceptionTranslator() {} IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} IConfig::~IConfig() {} void Config::dummy() {} diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index def3684b..d1a5cb7c 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -11,7 +11,6 @@ #include "catch_section_info.h" #include "catch_common.h" #include "catch_config.hpp" -#include "catch_context.h" #include "catch_totals.hpp" #include "catch_test_case_info.h" #include "catch_assertionresult.h" diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index fa1b8793..8f2f291a 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -12,6 +12,7 @@ #include "catch_interfaces_reporter.h" #include "catch_interfaces_testcase.h" +#include "catch_stream.h" #include "catch_text.h" #include "catch_console_colour.hpp" diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 454b5e06..7daa5572 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -8,6 +8,7 @@ #include "catch_interfaces_registry_hub.h" +#include "catch_context.h" #include "catch_test_case_registry_impl.hpp" #include "catch_reporter_registry.hpp" #include "catch_exception_translator_registry.h" diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 24e3df1e..5d640e48 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -1,6 +1,7 @@ #include "catch_run_context.hpp" #include "catch_context.h" #include "catch_enforce.h" +#include "catch_stream.h" #include #include diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index ca2316c1..40e77d29 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -26,6 +26,8 @@ namespace Catch { + struct IMutableContext; + class StreamRedirect { public: From 66124d9e38f23762542be86bf26a5f5a56fbda4b Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Mon, 28 Aug 2017 22:20:33 +0200 Subject: [PATCH 300/398] Make Current, Older releases sections, add subsections for each minor release --- docs/release-notes.md | 107 +++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 48 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index d076c8b3..c7d47983 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -53,18 +53,23 @@ * New library (TextFlow) is used for formatting text to output -# 1.9.6 -### Improvements +# Older versions + +## 1.9.x + +### 1.9.6 + +#### Improvements * Catch's runtime overhead has been significantly decreased (#937, #939) * Added `--list-extra-info` cli option (#934). * It lists all tests together with extra information, ie filename, line number and description. -# 1.9.5 +### 1.9.5 -### Fixes +#### Fixes * Truthy expressions are now reconstructed properly, not as booleans (#914) * Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871) * Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855) @@ -72,35 +77,35 @@ * Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`. * Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927) -### Improvements +#### Improvements * CMake integration script now incorporates debug messages and registers tests in an improved way (#911) * Various documentation improvements -# 1.9.4 +### 1.9.4 -### Fixes +#### Fixes * `CATCH_FAIL` macro no longer causes compilation error without variadic macro support * `INFO` messages are no longer cleared after being reported once -### Improvements and minor changes +#### Improvements and minor changes * Catch now uses `wmain` when compiled under Windows and `UNICODE` is defined. * Note that Catch still officially supports only ASCII -# 1.9.3 +### 1.9.3 -### Fixes +#### Fixes * Completed the fix for (lack of) uint64_t in earlier Visual Studios -# 1.9.2 +### 1.9.2 -### Improvements and minor changes +#### Improvements and minor changes * All of `Approx`'s member functions now accept strong typedefs in C++11 mode (#888) * Previously `Approx::scale`, `Approx::epsilon`, `Approx::margin` and `Approx::operator()` didn't. -### Fixes +#### Fixes * POSIX signals are now disabled by default under QNX (#889) * QNX does not support current enough (2001) POSIX specification * JUnit no longer counts exceptions as failures if given test case is marked as ok to fail. @@ -108,22 +113,22 @@ * Catch no longer attempts to define `uint64_t` on windows (#862) * This was causing trouble when compiled under Cygwin -### Other +#### Other * Catch is now compiled under MSVC 2017 using `std:c++latest` (C++17 mode) in CI * We now provide cmake script that autoregisters Catch tests into ctest. * See `contrib` folder. -# 1.9.1 +### 1.9.1 -### Fixes +#### Fixes * Unexpected exceptions are no longer ignored by default (#885, #887) -# 1.9.0 +### 1.9.0 -### Improvements and minor changes +#### Improvements and minor changes * Catch no longer attempts to ensure the exception type passed by user in `REQUIRE_THROWS_AS` is a constant reference. * It was causing trouble when `REQUIRE_THROWS_AS` was used inside templated functions * This actually reverts changes made in v1.7.2 @@ -137,7 +142,7 @@ * When Catch is compiled using C++11, `Approx` is now constructible with anything that can be explicitly converted to `double`. * Captured messages are now printed on unexpected exceptions -### Fixes: +#### Fixes: * Clang's `-Wexit-time-destructors` should be suppressed for Catch's internals * GCC's `-Wparentheses` is now suppressed for all TU's that include `catch.hpp`. * This is functionally a revert of changes made in 1.8.0, where we tried using `_Pragma` based suppression. This should have kept the suppression local to Catch's assertions, but bugs in GCC's handling of `_Pragma`s in C++ mode meant that it did not always work. @@ -146,16 +151,18 @@ * [Details can be found in documentation](configuration.md#catch_config_cpp11_stream_insertable_check) -### Other notes: +#### Other notes: * We have added VS 2017 to our CI * Work on Catch 2 should start soon -# 1.8.2 +## 1.8.x + +### 1.8.2 -### Improvements and minor changes +#### Improvements and minor changes * TAP reporter now behaves as if `-s` was always set * This should be more consistent with the protocol desired behaviour. * Compact reporter now obeys `-d yes` argument (#780) @@ -169,7 +176,7 @@ * Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion. -### Fixes: +#### Fixes: * Catch no longer attempts to reconstruct expression that led to a fatal error (#810) * This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition. * Fixed (C4265) missing virtual destructor warning in Matchers (#844) @@ -186,21 +193,21 @@ * Regression in Objective-C bindings (Matchers) fixed (#854) -### Other notes: +#### Other notes: * We have added VS 2013 and 2015 to our CI * Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser). -# 1.8.1 +### 1.8.1 -### Fixes +#### Fixes Cygwin issue with `gettimeofday` - `#define` was not early enough -# 1.8.0 +### 1.8.0 -### New features/ minor changes +#### New features/ minor changes * Matchers have new, simpler (and documented) interface. * Catch provides string and vector matchers. @@ -220,7 +227,7 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough * `Approx` now supports an optional margin of absolute error * It has also received [new documentation](assertions.md#top). -### Fixes +#### Fixes * Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer. * Fixed C4512 ("assignment operator could not be generated") warnings under VS2013. * Cygwin compatibility fixes @@ -231,13 +238,15 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough * Otherwise it is supressed for the whole TU * Fixed test spec parser issue (with escapes in multiple names) -### Other +#### Other * Various documentation fixes and improvements -# 1.7.2 +## 1.7.x -### Fixes and minor improvements +### 1.7.2 + +#### Fixes and minor improvements Xml: (technically the first two are breaking changes but are also fixes and arguably break few if any people) @@ -256,9 +265,9 @@ Other: * Silenced a few more warnings in different circumstances * Travis improvements -# 1.7.1 +### 1.7.1 -### Fixes: +#### Fixes: * Fixed inconsistency in defining `NOMINMAX` and `WIN32_LEAN_AND_MEAN` inside `catch.hpp`. * Fixed SEH-related compilation error under older MinGW compilers, by making Windows SEH handling opt-in for compilers other than MSVC. * For specifics, look into the [documentation](configuration.md#top). @@ -268,9 +277,9 @@ Other: * Fixed possible infinite recursion in Windows SEH. * Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators. -## 1.7.0 +### 1.7.0 -### Features/ Changes: +#### Features/ Changes: * Catch now runs significantly faster for passing tests * Microbenchmark focused on Catch's overhead went from ~3.4s to ~0.7s. * Real world test using [JSON for Modern C++](https://github.com/nlohmann/json)'s test suite went from ~6m 25s to ~4m 14s. @@ -284,28 +293,30 @@ Other: * Certain characters (space, tab, etc) are now pretty printed. * This means that a `char c = ' '; REQUIRE(c == '\t');` would be printed as `' ' == '\t'`, instead of ` == 9`. -### Fixes: +#### Fixes: * Text formatting no longer attempts to access out-of-bounds characters under certain conditions. * THROW family of assertions no longer trigger `-Wunused-value` on expressions containing explicit cast. * Breaking into debugger under OS X works again and no longer required `DEBUG` to be defined. * Compilation no longer breaks under certain compiler if a lambda is used inside assertion macro. -### Other: +#### Other: * Catch's CMakeLists now defines install command. * Catch's CMakeLists now generates projects with warnings enabled. -## 1.6.1 +## 1.6.x -### Features/ Changes: +### 1.6.1 + +#### Features/ Changes: * Catch now supports breaking into debugger on Linux -### Fixes: +#### Fixes: * Generators no longer leak memory (generators are still unsupported in general) * JUnit reporter now reports UTC timestamps, instead of "tbd" * `CHECK_THAT` macro is now properly defined as `CATCH_CHECK_THAT` when using `CATCH_` prefixed macros -### Other: +#### Other: * Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro. * The use of `__COUNTER__` is supressed when Catch is parsed by CLion * This change is not active when compiling a binary @@ -315,28 +326,28 @@ Other: * This can be disabled if needed, see [documentation](configuration.md#top) for details. -## 1.6.0 +### 1.6.0 -### Cmake/ projects: +#### Cmake/ projects: * Moved CMakeLists.txt to root, made it friendlier for CLion and generating XCode and VS projects, and removed the manually maintained XCode and VS projects. -### Features/ Changes: +#### Features/ Changes: * Approx now supports `>=` and `<=` * Can now use `\` to escape chars in test names on command line * Standardize C++11 feature toggles -### Fixes: +#### Fixes: * Blue shell colour * Missing argument to `CATCH_CHECK_THROWS` * Don't encode extended ASCII in XML * use `std::shuffle` on more compilers (fixes deprecation warning/error) * Use `__COUNTER__` more consistently (where available) -### Other: +#### Other: * Tweaks and changes to scripts - particularly for Approval test - to make them more portable -# Older versions +# Even Older versions Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history --- From c5553019cc26a688c6a9d25bc57d66d248d004e9 Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Mon, 28 Aug 2017 22:32:06 +0200 Subject: [PATCH 301/398] Fix heading levels - page title (chapter): 1 - sections: 2 --- docs/build-systems.md | 10 +++++----- docs/configuration.md | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/build-systems.md b/docs/build-systems.md index 1033490d..2f7953ca 100644 --- a/docs/build-systems.md +++ b/docs/build-systems.md @@ -3,13 +3,13 @@ Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both. -# Continuous Integration systems +## Continuous Integration systems Probably the most important aspect to using Catch with a build server is the use of different reporters. Catch comes bundled with three reporters that should cover the majority of build servers out there - although adding more for better integration with some is always a possibility (currently we also offer TeamCity, TAP and Automake reporters). Two of these reporters are built in (XML and JUnit) and the third (TeamCity) is included as a separate header. It's possible that the other two may be split out in the future too - as that would make the core of Catch smaller for those that don't need them. -## XML Reporter +### XML Reporter ```-r xml``` The XML Reporter writes in an XML format that is specific to Catch. @@ -18,7 +18,7 @@ The advantage of this format is that it corresponds well to the way Catch works The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course. -## JUnit Reporter +### JUnit Reporter ```-r junit``` The JUnit Reporter writes in an XML format that mimics the JUnit ANT schema. @@ -53,9 +53,9 @@ The Automake Reporter writes out the [meta tags](https://www.gnu.org/software/au Because of the incremental nature of Catch's test suites and ability to run specific tests, our implementation of TAP reporter writes out the number of tests in a suite last. -# Low-level tools +## Low-level tools -## CMake +### CMake In general we recommend "vendoring" Catch's single-include releases inside your own repository. If you do this, the following example shows a minimal CMake project: ```CMake diff --git a/docs/configuration.md b/docs/configuration.md index 2e5fc6f9..9685973f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -5,7 +5,7 @@ Catch is designed to "just work" as much as possible. For most people the only c Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a set of macros for configuring how it is built. -# main()/ implementation +## main()/ implementation CATCH_CONFIG_MAIN // Designates this as implementation file and defines main() CATCH_CONFIG_RUNNER // Designates this as implementation file @@ -20,14 +20,14 @@ Brings in various parts of Catch that are required for user defined Reporters an Implied by both `CATCH_CONFIG_MAIN` and `CATCH_CONFIG_RUNNER`. -# Prefixing Catch macros +## Prefixing Catch macros CATCH_CONFIG_PREFIX_ALL To keep test code clean and uncluttered Catch uses short macro names (e.g. ```TEST_CASE``` and ```REQUIRE```). Occasionally these may conflict with identifiers from platform headers or the system under test. In this case the above identifier can be defined. This will cause all the Catch user macros to be prefixed with ```CATCH_``` (e.g. ```CATCH_TEST_CASE``` and ```CATCH_REQUIRE```). -# Terminal colour +## Terminal colour CATCH_CONFIG_COLOUR_NONE // completely disables all text colouring CATCH_CONFIG_COLOUR_WINDOWS // forces the Win32 console API to be used @@ -43,14 +43,14 @@ Note that when ANSI colour codes are used "unistd.h" must be includable - along Typically you should place the ```#define``` before #including "catch.hpp" in your main source file - but if you prefer you can define it for your whole project by whatever your IDE or build system provides for you to do so. -# Console width +## Console width CATCH_CONFIG_CONSOLE_WIDTH = x // where x is a number Catch formats output intended for the console to fit within a fixed number of characters. This is especially important as indentation is used extensively and uncontrolled line wraps break this. By default a console width of 80 is assumed but this can be controlled by defining the above identifier to be a different value. -# stdout +## stdout CATCH_CONFIG_NOSTDOUT @@ -64,7 +64,7 @@ This can be useful on certain platforms that do not provide the standard iostrea -# Other toggles +## Other toggles CATCH_CONFIG_COUNTER // Use __COUNTER__ to generate unique names for test cases CATCH_CONFIG_WINDOWS_SEH // Enable SEH handling on Windows @@ -83,29 +83,29 @@ Currently Catch enables `CATCH_CONFIG_WINDOWS_SEH` only when compiled with MSVC, These toggles can be disabled by using `_NO_` form of the toggle, e.g. `CATCH_CONFIG_NO_WINDOWS_SEH`. -## `CATCH_CONFIG_FAST_COMPILE` +### `CATCH_CONFIG_FAST_COMPILE` Defining this flag speeds up compilation of test files by ~20%, by making 2 changes: * The `-b` (`--break`) flag no longer makes Catch break into debugger in the same stack frame as the failed test, but rather in a stack frame *below*. * Non-exception family of macros ({`REQUIRE`,`CHECK`}{`_`,`_FALSE`, `_FALSE`}, no longer use local try-cache block. This disables exception translation, but should not lead to false negatives. `CATCH_CONFIG_FAST_COMPILE` has to be either defined, or not defined, in all translation units that are linked into single test binary, or the behaviour of setting `-b` flag and throwing unexpected exceptions will be unpredictable. -## `CATCH_CONFIG_DISABLE_MATCHERS` +### `CATCH_CONFIG_DISABLE_MATCHERS` When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matchers are ifdef-ed away from the translation unit. Doing so will speed up compilation of that TU. _Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._ -## `CATCH_CONFIG_DISABLE_STRINGIFICATION` +### `CATCH_CONFIG_DISABLE_STRINGIFICATION` This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#Visual Studio 2017 -- raw string literal in assert fails to compile) -## `CATCH_CONFIG_DISABLE` +### `CATCH_CONFIG_DISABLE` This toggle removes most of Catch from given file. This means that `TEST_CASE`s are not registered and assertions are turned into no-ops. Useful for keeping tests within implementation files (ie for functions with internal linkage), instead of in external files. This feature is considered experimental and might change at any point. _Inspired by Doctest's `DOCTEST_CONFIG_DISABLE`_ -# Windows header clutter +## Windows header clutter On Windows Catch includes `windows.h`. To minimize global namespace clutter in the implementation file, it defines `NOMINMAX` and `WIN32_LEAN_AND_MEAN` before including it. You can control this behaviour via two macros: From 07211cea9c5d916f590a3791e845b1c83c8db81e Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Mon, 28 Aug 2017 22:42:26 +0200 Subject: [PATCH 302/398] Add table of contents --- docs/assertions.md | 6 ++++++ docs/command-line.md | 24 ++++++++++++++++++++++++ docs/configuration.md | 9 +++++++++ docs/slow-compiles.md | 6 ++++++ docs/tutorial.md | 9 +++++++++ 5 files changed, 54 insertions(+) diff --git a/docs/assertions.md b/docs/assertions.md index 3150b584..66d127bb 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -1,6 +1,12 @@ # Assertion Macros +**Contents** +[Natural Expressions](#natural-expressions) +[Exceptions](#exceptions) +[Matcher expressions](#matcher-expressions) +[Thread Safety](#thread-safety) + Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc). Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxilliary macros as well. We'll describe all of these here. diff --git a/docs/command-line.md b/docs/command-line.md index 12517bcc..00d55852 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -1,6 +1,30 @@ # Command line +**Contents** +[Specifying which tests to run](#specifying-which-tests-to-run) +[Choosing a reporter to use](#choosing-a-reporter-to-use) +[Breaking into the debugger](#breaking-into-the-debugger) +[Showing results for successful tests](#showing-results-for-successful-tests) +[Aborting after a certain number of failures](#aborting-after-a-certain-number-of-failures) +[Listing available tests, tags or reporters](#listing-available-tests-tags-or-reporters) +[Sending output to a file](#sending-output-to-a-file) +[Naming a test run](#naming-a-test-run) +[Eliding assertions expected to throw](#eliding-assertions-expected-to-throw) +[Make whitespace visible](#make-whitespace-visible) +[Warnings](#warnings) +[Reporting timings](#reporting-timings) +[Load test names to run from a file](#load-test-names-to-run-from-a-file) +[Just test names](#just-test-names) +[Specify the order test cases are run](#specify-the-order-test-cases-are-run) +[Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator) +[Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard) +[Wait for key before continuing](#wait-for-key-before-continuing) +[Specify multiples of clock resolution to run benchmarks for](#specify-multiples-of-clock-resolution-to-run-benchmarks-for) +[Usage](#usage) +[Specify the section to run](#specify-the-section-to-run) +[Filenames as tags](#filenames-as-tags) + Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available. Click one of the followings links to take you straight to that option - or scroll on to browse the available options. diff --git a/docs/configuration.md b/docs/configuration.md index 9685973f..937e6122 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,6 +1,15 @@ # Compile-time configuration +**Contents** +[main()/ implementation](#main-implementation) +[Prefixing Catch macros](#prefixing-catch-macros) +[Terminal colour](#terminal-colour) +[Console width](#console-width) +[stdout](#stdout) +[Other toggles](#other-toggles) +[Windows header clutter](#windows-header-clutter) + Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). Nonetheless there are still some occasions where finer control is needed. For these occasions Catch exposes a set of macros for configuring how it is built. diff --git a/docs/slow-compiles.md b/docs/slow-compiles.md index d1806d03..9696757d 100644 --- a/docs/slow-compiles.md +++ b/docs/slow-compiles.md @@ -1,6 +1,12 @@ # Why do my tests take so long to compile? +**Contents** +[Short answer](#short-answer) +[Long answer](#long-answer) +[Practical example](#practical-example) +[Other possible solutions](#other-possible-solutions) + Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that? Catch is implemented entirely in headers. There is a little overhead due to this - but not as much as you might think - and you can minimise it simply by organising your test code as follows: diff --git a/docs/tutorial.md b/docs/tutorial.md index 80465ba2..ebc20fd2 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -1,6 +1,15 @@ # Tutorial +**Contents** +[Getting Catch](#getting-catch) +[Where to put it?](#where-to-put-it) +[Writing tests](#writing-tests) +[Test cases and sections](#test-cases-and-sections) +[BDD-Style](#bdd-style) +[Scaling up](#scaling-up) +[Next steps](#next-steps) + ## Getting Catch The simplest way to get Catch is to download the latest [single header version](https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. From 61d2c375ddf765ee2f88f8a3b92f517ea380abb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 11:40:29 +0200 Subject: [PATCH 303/398] Add evaluation specialization for T* and long Fixes #1005 --- include/internal/catch_decomposer.h | 8 +++++++ .../Baselines/console.std.approved.txt | 4 ++-- .../Baselines/console.sw.approved.txt | 23 +++++++++++++++++-- .../Baselines/console.swa4.approved.txt | 23 +++++++++++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 3 ++- .../SelfTest/Baselines/xml.sw.approved.txt | 23 +++++++++++++++++-- projects/SelfTest/DecompositionTests.cpp | 7 ++++++ 7 files changed, 82 insertions(+), 9 deletions(-) diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 8cb4c1d4..5613e774 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -80,14 +80,22 @@ namespace Catch { template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; template + auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + template auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + template + auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; template auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) != rhs; }; template auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; template + auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + template auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + template + auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; template diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 50991312..11df0389 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1020,6 +1020,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 183 | 132 passed | 47 failed | 4 failed as expected -assertions: 882 | 765 passed | 96 failed | 21 failed as expected +test cases: 184 | 133 passed | 47 failed | 4 failed as expected +assertions: 884 | 767 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index ae2f6928..14fdcd9d 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -14,6 +14,25 @@ PASSED: with message: yay +------------------------------------------------------------------------------- +#1005: Comparing pointer to int and long (NULL can be either on various + systems) +------------------------------------------------------------------------------- +DecompositionTests.cpp: +............................................................................... + +DecompositionTests.cpp:: +PASSED: + REQUIRE( fptr == 0 ) +with expansion: + 0 == 0 + +DecompositionTests.cpp:: +PASSED: + REQUIRE( fptr == 0l ) +with expansion: + 0 == 0 + ------------------------------------------------------------------------------- #748 - captures with unexpected exceptions outside assertions @@ -7535,6 +7554,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 183 | 129 passed | 50 failed | 4 failed as expected -assertions: 884 | 761 passed | 102 failed | 21 failed as expected +test cases: 184 | 130 passed | 50 failed | 4 failed as expected +assertions: 886 | 763 passed | 102 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index bdacd9cb..06c24e86 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -14,6 +14,25 @@ PASSED: with message: yay +------------------------------------------------------------------------------- +#1005: Comparing pointer to int and long (NULL can be either on various + systems) +------------------------------------------------------------------------------- +DecompositionTests.cpp: +............................................................................... + +DecompositionTests.cpp:: +PASSED: + REQUIRE( fptr == 0 ) +with expansion: + 0 == 0 + +DecompositionTests.cpp:: +PASSED: + REQUIRE( fptr == 0l ) +with expansion: + 0 == 0 + ------------------------------------------------------------------------------- #748 - captures with unexpected exceptions outside assertions @@ -218,6 +237,6 @@ ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) =============================================================================== -test cases: 8 | 5 passed | 1 failed | 2 failed as expected -assertions: 24 | 17 passed | 4 failed | 3 failed as expected +test cases: 9 | 6 passed | 1 failed | 2 failed as expected +assertions: 26 | 19 passed | 4 failed | 3 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index e49e19e4..15fa38f0 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,8 +1,9 @@ - + + expected exception diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 68607f0b..7f2b4b03 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -4,6 +4,25 @@ + + + + fptr == 0 + + + 0 == 0 + + + + + fptr == 0l + + + 0 == 0 + + + +
@@ -8287,7 +8306,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/DecompositionTests.cpp b/projects/SelfTest/DecompositionTests.cpp index f2e04260..1b44b602 100644 --- a/projects/SelfTest/DecompositionTests.cpp +++ b/projects/SelfTest/DecompositionTests.cpp @@ -7,6 +7,7 @@ */ #include +#include struct truthy { truthy(bool b):m_value(b){} @@ -26,3 +27,9 @@ std::ostream& operator<<(std::ostream& o, truthy) { TEST_CASE( "Reconstruction should be based on stringification: #914" , "[Decomposition][failing][.]") { CHECK(truthy(false)); } + +TEST_CASE("#1005: Comparing pointer to int and long (NULL can be either on various systems)", "[Decomposition]") { + FILE* fptr = nullptr; + REQUIRE(fptr == 0); + REQUIRE(fptr == 0l); +} From 4dcdcc0ac3035e221094d0c0a47919282c99d8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 12:16:10 +0200 Subject: [PATCH 304/398] Change developBuild to work same as *Release --- scripts/developBuild.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/developBuild.py b/scripts/developBuild.py index d751f108..a8115fe2 100755 --- a/scripts/developBuild.py +++ b/scripts/developBuild.py @@ -1,13 +1,10 @@ #!/usr/bin/env python from __future__ import print_function -from releaseCommon import Version +import releaseCommon -v = Version() +v = releaseCommon.Version() v.incrementBuildNumber() -v.updateVersionFile() -v.updateReadmeFile() -v.updateConanFile() -v.updateConanTestFile() +releaseCommon.performUpdates(v) print( "Updated Version.hpp, README and Conan to v{0}".format( v.getVersionString() ) ) From fc495ba0cbea0d935436ecc94ab32ea1db8e00c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 12:20:21 +0200 Subject: [PATCH 305/398] Dev build 3 --- conanfile.py | 2 +- include/internal/catch_version.cpp | 2 +- single_include/catch.hpp | 687 +++++++++++++++++------------ test_package/conanfile.py | 2 +- 4 files changed, 416 insertions(+), 277 deletions(-) diff --git a/conanfile.py b/conanfile.py index 4b7990a6..506235ae 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.0.0-develop.2" + version = "2.0.0-develop.3" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index 96e66d5a..36f58e22 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 2 ); + static Version version( 2, 0, 0, "develop", 3 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 2b440890..c775b8db 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.0.0-develop.2 - * Generated: 2017-08-18 15:57:31.231591 + * Catch v2.0.0-develop.3 + * Generated: 2017-08-30 12:15:54.096665 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. @@ -49,6 +49,24 @@ # define CATCH_CONFIG_EXTERNAL_INTERFACES #endif +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_MAC == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h #ifdef CATCH_IMPL # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED @@ -56,43 +74,6 @@ # endif #endif -// start catch_context.h - -#include - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IConfig; - - using IConfigPtr = std::shared_ptr; - - struct IContext - { - virtual ~IContext(); - - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual IConfigPtr getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext(); - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( IConfigPtr const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); -} - -// end catch_context.h // start catch_tag_alias_autoregistrar.h // start catch_common.h @@ -164,30 +145,6 @@ namespace Catch { #endif // __CYGWIN__ -//////////////////////////////////////////////////////////////////////////////// -// Borland -#ifdef __BORLANDC__ - -#endif // __BORLANDC__ - -//////////////////////////////////////////////////////////////////////////////// -// EDG -#ifdef __EDG_VERSION__ - -#endif // __EDG_VERSION__ - -//////////////////////////////////////////////////////////////////////////////// -// Digital Mars -#ifdef __DMC__ - -#endif // __DMC__ - -//////////////////////////////////////////////////////////////////////////////// -// GCC -#ifdef __GNUC__ - -#endif // __GNUC__ - //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER @@ -198,15 +155,10 @@ namespace Catch { //////////////////////////////////////////////////////////////////////////////// -// Use __COUNTER__ if the compiler supports it -#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ - ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ - ( defined __clang__ && __clang_major__ >= 3 ) - +// All supported compilers support COUNTER macro, +//but user still might want to turn it off #define CATCH_INTERNAL_CONFIG_COUNTER -#endif - // Now set the actual defines based on the above + anything the user has configured // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for @@ -465,6 +417,19 @@ struct AutoReg : NonCopyable { } // end namespace Catch +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ + static void TestName() + #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ + namespace{ \ + struct TestName : ClassName { \ + void test(); \ + }; \ + } \ + void TestName::test() + +#endif + /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ @@ -498,7 +463,7 @@ struct AutoReg : NonCopyable { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ - Catch::AutoReg( 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::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS // end catch_test_registry.hpp @@ -919,14 +884,22 @@ namespace Catch { template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; template + auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + template auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + template + auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; template auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) != rhs; }; template auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; template + auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + template auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + template + auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; template class ExprLhs { @@ -1236,6 +1209,14 @@ namespace Catch { } // end catch_interfaces_capture.h +#if !defined(CATCH_CONFIG_DISABLE) + +#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) + #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ +#else + #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" +#endif + #if defined(CATCH_CONFIG_FAST_COMPILE) /////////////////////////////////////////////////////////////////////////////// // We can speedup compilation significantly by breaking into debugger lower in @@ -1256,30 +1237,8 @@ namespace Catch { // start catch_debugger.h -// start catch_platform.h - -#ifdef __APPLE__ -# include -# if TARGET_OS_MAC == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -# define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h -#include - -namespace Catch{ - +namespace Catch { bool isDebuggerActive(); - void writeToDebugConsole( std::string const& text ); } #ifdef CATCH_PLATFORM_MAC @@ -1328,7 +1287,7 @@ namespace Catch{ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ @@ -1351,7 +1310,7 @@ namespace Catch{ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ try { \ static_cast(__VA_ARGS__); \ catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ @@ -1365,7 +1324,7 @@ namespace Catch{ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__); \ @@ -1382,7 +1341,7 @@ namespace Catch{ /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(expr); \ @@ -1415,7 +1374,7 @@ namespace Catch{ // 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, #__VA_ARGS__ ", " #matcher, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__); \ @@ -1429,6 +1388,8 @@ namespace Catch{ INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( Catch::alwaysFalse() ) +#endif // CATCH_CONFIG_DISABLE + // end catch_capture.hpp // start catch_section.h @@ -1589,9 +1550,6 @@ namespace Catch { // end catch_benchmark.h // start catch_interfaces_exception.h -#include -#include - // start catch_interfaces_registry_hub.h #include @@ -1640,6 +1598,14 @@ namespace Catch { } // end catch_interfaces_registry_hub.h +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ + static std::string translatorName( signature ) +#endif + +#include +#include + namespace Catch { using exceptionTranslateFunction = std::string(*)(); @@ -2212,7 +2178,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ @@ -2222,7 +2188,7 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ do { \ - Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ static_cast(__VA_ARGS__ ); \ @@ -2540,8 +2506,6 @@ return @ desc; \ #ifdef CATCH_CONFIG_EXTERNAL_INTERFACES // start catch_external_interfaces.h -#ifndef TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H -#define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H // start catch_reporter_bases.hpp @@ -2580,8 +2544,6 @@ return @ desc; \ // start catch_wildcard_pattern.hpp -#include - namespace Catch { class WildcardPattern { @@ -2823,69 +2785,6 @@ namespace Catch { } // end catch_interfaces_config.h -// start catch_stream.h - -// start catch_streambuf.h - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() noexcept; - }; -} - -// end catch_streambuf.h -#include -#include -#include -#include - -namespace Catch { - - std::ostream& cout(); - std::ostream& cerr(); - std::ostream& clog(); - - struct IStream { - virtual ~IStream() noexcept; - virtual std::ostream& stream() const = 0; - }; - - class FileStream : public IStream { - mutable std::ofstream m_ofs; - public: - FileStream( std::string const& filename ); - ~FileStream() noexcept override; - public: // IStream - std::ostream& stream() const override; - }; - - class CoutStream : public IStream { - mutable std::ostream m_os; - public: - CoutStream(); - ~CoutStream() noexcept override; - - public: // IStream - std::ostream& stream() const override; - }; - - class DebugOutStream : public IStream { - std::unique_ptr m_streamBuf; - mutable std::ostream m_os; - public: - DebugOutStream(); - ~DebugOutStream() noexcept override; - - public: // IStream - std::ostream& stream() const override; - }; -} - -// end catch_stream.h #include #include #include @@ -2896,6 +2795,8 @@ namespace Catch { namespace Catch { + struct IStream; + struct ConfigData { bool listTests = false; bool listTags = false; @@ -2992,10 +2893,7 @@ namespace Catch { { AssertionResultData() = delete; - AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ) - : resultType( _resultType ), - lazyExpression( _lazyExpression ) - {} + AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); ResultWas::OfType resultType = ResultWas::Unknown; std::string message; @@ -3468,7 +3366,7 @@ namespace Catch { } else { SectionNode& parentNode = *m_sectionStack.back(); - typename SectionNode::ChildSections::const_iterator it = + auto it = std::find_if( parentNode.childSections.begin(), parentNode.childSections.end(), BySectionInfo( sectionInfo ) ); @@ -3611,14 +3509,22 @@ namespace Catch { }; } +#if !defined(CATCH_CONFIG_DISABLE) + #define CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } #define CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } +#else // CATCH_CONFIG_DISABLE + +#define CATCH_REGISTER_REPORTER(name, reporterType) +#define CATCH_REGISTER_LISTENER(listenerType) + +#endif // CATCH_CONFIG_DISABLE + // end catch_reporter_registrars.hpp -#endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H // end catch_external_interfaces.h #endif @@ -5285,6 +5191,8 @@ namespace Catch { namespace Catch { + struct IMutableContext; + class StreamRedirect { public: @@ -5400,6 +5308,69 @@ namespace Catch { } // end namespace Catch // end catch_run_context.hpp +// start catch_stream.h + +// start catch_streambuf.h + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() noexcept; + }; +} + +// end catch_streambuf.h +#include +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + std::ostream& clog(); + + struct IStream { + virtual ~IStream() noexcept; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + ~FileStream() noexcept override; + public: // IStream + std::ostream& stream() const override; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + ~CoutStream() noexcept override; + + public: // IStream + std::ostream& stream() const override; + }; + + class DebugOutStream : public IStream { + std::unique_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + ~DebugOutStream() noexcept override; + + public: // IStream + std::ostream& stream() const override; + }; +} + +// end catch_stream.h // start catch_version.h #include @@ -5636,12 +5607,12 @@ namespace Catch { int run() { if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { Catch::cout() << "...waiting for enter/ return before starting" << std::endl; - std::getchar(); + static_cast(std::getchar()); } int exitCode = runInternal(); if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; - std::getchar(); + static_cast(std::getchar()); } return exitCode; } @@ -5738,6 +5709,43 @@ std::string StringMaker::convert(Catch::Detail::Approx co // end catch_approx.cpp // start catch_assertionhandler.cpp +// start catch_context.h + +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IConfig; + + using IConfigPtr = std::shared_ptr; + + struct IContext + { + virtual ~IContext() = default; + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual IConfigPtr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext() = default; + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( IConfigPtr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); +} + +// end catch_context.h #include namespace Catch { @@ -5871,6 +5879,9 @@ namespace Catch { // start catch_assertionresult.cpp namespace Catch { + AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): + resultType(_resultType), + lazyExpression(_lazyExpression) {} std::string AssertionResultData::reconstructExpression() const { @@ -6645,7 +6656,18 @@ namespace Catch { bool isDebuggerActive() { return false; } } #endif // Platform +// end catch_debugger.cpp +// start catch_debug_console.cpp +// start catch_debug_console.h + +#include + +namespace Catch { + void writeToDebugConsole( std::string const& text ); +} + +// end catch_debug_console.h #ifdef CATCH_PLATFORM_WINDOWS namespace Catch { @@ -6661,7 +6683,7 @@ namespace Catch { } } #endif // Platform -// end catch_debugger.cpp +// end catch_debug_console.cpp // start catch_decomposer.cpp namespace Catch { @@ -6797,9 +6819,9 @@ namespace Catch { }; LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { - for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); + for (auto const& def : signalDefs) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { + reportFatal(def.name); } } // If its not an exception we care about, pass it along. @@ -6870,8 +6892,7 @@ namespace Catch { void FatalConditionHandler::handleSignal( int sig ) { std::string name = ""; - for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { - SignalDefs &def = signalDefs[i]; + for (auto const& def : signalDefs) { if (sig == def.id) { name = def.name; break; @@ -7499,14 +7520,14 @@ namespace Catch { ~ReporterRegistry() override {} IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { - FactoryMap::const_iterator it = m_factories.find( name ); + auto it = m_factories.find( name ); if( it == m_factories.end() ) return nullptr; return it->second->create( ReporterConfig( config ) ); } void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { - m_factories.insert( { name, factory } ); + m_factories.emplace(name, factory); } void registerListener( IReporterFactoryPtr const& factory ) { m_listeners.push_back( factory ); @@ -7775,7 +7796,10 @@ namespace Catch { if (result.getResultType() == ResultWas::Ok) { m_totals.assertions.passed++; } else if (!result.isOk()) { - m_totals.assertions.failed++; + if( m_activeTestCase->getTestCaseInfo().okToFail() ) + m_totals.assertions.failedButOk++; + else + m_totals.assertions.failed++; } // We have no use for the return value (whether messages should be cleared), because messages were made scoped @@ -7960,13 +7984,6 @@ namespace Catch { Counts assertions = m_totals.assertions - prevAssertions; bool missingAssertions = testForMissingAssertions(assertions); - - if (testCaseInfo.okToFail()) { - std::swap(assertions.failedButOk, assertions.failed); - m_totals.assertions.failed -= assertions.failedButOk; - m_totals.assertions.failedButOk += assertions.failedButOk; - } - SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); m_reporter->sectionEnded(testCaseSectionStats); } @@ -8163,77 +8180,6 @@ namespace Catch { #endif } // end catch_stream.cpp -// start catch_string_manip.cpp - -#include -#include -#include -#include - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } - -} -// end catch_string_manip.cpp // start catch_stringref.cpp #include @@ -8390,6 +8336,77 @@ namespace Catch { } // namespace Catch // end catch_stringref.cpp +// start catch_string_manip.cpp + +#include +#include +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); + } + bool startsWith( std::string const& s, char prefix ) { + return !s.empty() && s[0] == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); + } + bool endsWith( std::string const& s, char suffix ) { + return !s.empty() && s[s.size()-1] == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << 's'; + return os; + } + +} +// end catch_string_manip.cpp // start catch_tag_alias.cpp namespace Catch { @@ -8466,7 +8483,6 @@ namespace Catch { TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { if( startsWith( tag, '.' ) || - tag == "hide" || tag == "!hide" ) return TestCaseInfo::IsHidden; else if( tag == "!throws" ) @@ -8498,14 +8514,13 @@ namespace Catch { std::string const& _descOrTags, SourceLineInfo const& _lineInfo ) { - bool isHidden( startsWith( _name, "./" ) ); // Legacy support + bool isHidden = false; // Parse out tags std::vector tags; std::string desc, tag; bool inTag = false; - for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { - char c = _descOrTags[i]; + for (char c : _descOrTags) { if( !inTag ) { if( c == '[' ) inTag = true; @@ -8529,7 +8544,6 @@ namespace Catch { } } if( isHidden ) { - tags.push_back( "hide" ); tags.push_back( "." ); } @@ -9500,7 +9514,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 2 ); + static Version version( 2, 0, 0, "develop", 3 ); return version; } @@ -11343,7 +11357,6 @@ namespace Catch { CoutStream::~CoutStream() noexcept {} DebugOutStream::~DebugOutStream() noexcept {} StreamBufBase::~StreamBufBase() noexcept {} - IContext::~IContext() {} IResultCapture::~IResultCapture() {} ITestInvoker::~ITestInvoker() {} ITestCaseRegistry::~ITestCaseRegistry() {} @@ -11352,7 +11365,6 @@ namespace Catch { IExceptionTranslator::~IExceptionTranslator() {} IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} IRunner::~IRunner() {} - IMutableContext::~IMutableContext() {} IConfig::~IConfig() {} void Config::dummy() {} @@ -11408,6 +11420,7 @@ int main (int argc, char * const argv[]) { # undef CLARA_CONFIG_MAIN #endif +#if !defined(CATCH_CONFIG_DISABLE) ////// // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL @@ -11531,6 +11544,132 @@ int main (int argc, char * const argv[]) { using Catch::Detail::Approx; +#else +////// +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( ... ) (void)(0) +#define CATCH_REQUIRE_FALSE( ... ) (void)(0) + +#define CATCH_REQUIRE_THROWS( ... ) (void)(0) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif// CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) + +#define CATCH_CHECK( ... ) (void)(0) +#define CATCH_CHECK_FALSE( ... ) (void)(0) +#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) +#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CATCH_CHECK_NOFAIL( ... ) (void)(0) + +#define CATCH_CHECK_THROWS( ... ) (void)(0) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW( ... ) (void)(0) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THAT( arg, matcher ) (void)(0) + +#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define CATCH_INFO( msg ) (void)(0) +#define CATCH_WARN( msg ) (void)(0) +#define CATCH_CAPTURE( msg ) (void)(0) + +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define CATCH_SECTION( ... ) +#define CATCH_FAIL( ... ) (void)(0) +#define CATCH_FAIL_CHECK( ... ) (void)(0) +#define CATCH_SUCCEED( ... ) (void)(0) + +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +// "BDD-style" convenience wrappers +#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define CATCH_GIVEN( desc ) +#define CATCH_WHEN( desc ) +#define CATCH_AND_WHEN( desc ) +#define CATCH_THEN( desc ) +#define CATCH_AND_THEN( desc ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( ... ) (void)(0) +#define REQUIRE_FALSE( ... ) (void)(0) + +#define REQUIRE_THROWS( ... ) (void)(0) +#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW( ... ) (void)(0) + +#define CHECK( ... ) (void)(0) +#define CHECK_FALSE( ... ) (void)(0) +#define CHECKED_IF( ... ) if (__VA_ARGS__) +#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CHECK_NOFAIL( ... ) (void)(0) + +#define CHECK_THROWS( ... ) (void)(0) +#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW( ... ) (void)(0) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THAT( arg, matcher ) (void)(0) + +#define REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define INFO( msg ) (void)(0) +#define WARN( msg ) (void)(0) +#define CAPTURE( msg ) (void)(0) + +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define METHOD_AS_TEST_CASE( method, ... ) +#define REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define SECTION( ... ) +#define FAIL( ... ) (void)(0) +#define FAIL_CHECK( ... ) (void)(0) +#define SUCCEED( ... ) (void)(0) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// "BDD-style" convenience wrappers +#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) + +#define GIVEN( desc ) +#define WHEN( desc ) +#define AND_WHEN( desc ) +#define THEN( desc ) +#define AND_THEN( desc ) + +using Catch::Detail::Approx; + +#endif + // start catch_reenable_warnings.h diff --git a/test_package/conanfile.py b/test_package/conanfile.py index c96cf111..ebefc8ac 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.0.0-develop.2@%s/%s" % (username, channel) + requires = "Catch/2.0.0-develop.3@%s/%s" % (username, channel) def build(self): cmake = CMake(self) From 13213faa4e1c6dd9b9883ab4cd570d6550fbd43a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 12:43:23 +0200 Subject: [PATCH 306/398] Update release notes in regards to CATCH_CONFIG_DISABLE --- docs/release-notes.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index c7d47983..aa8f4957 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -36,11 +36,14 @@ * All parts of matchers can be removed from a TU by defining `CATCH_CONFIG_DISABLE_MATCHERS` * This can be used to somewhat speed up compilation times * An experimental implementation of `CATCH_CONFIG_DISABLE` has been added - * Speeds up compilation by removing away Catch tests - * Currently removes all assertions and prevents `TEST_CASE` registrations + * Inspired by Doctest's `DOCTEST_CONFIG_DISABLE` * Useful for implementing tests in source files * ie for functions in anonymous namespaces - * Inspired by Doctest's `DOCTEST_CONFIG_DISABLE` + * Removes all assertions + * Prevents `TEST_CASE` registrations + * Exception translators are not registered + * Reporters are not registered + * Listeners are not registered ## Fixes From cde57d9365856718c04708d72e8a02f94b4fcb79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 15:28:33 +0200 Subject: [PATCH 307/398] Remove tag alias registry interface from the common path --- include/catch.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/catch.hpp b/include/catch.hpp index acc2c9cc..459aacae 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -39,7 +39,6 @@ #include "internal/catch_interfaces_exception.h" #include "internal/catch_approx.hpp" #include "internal/catch_compiler_capabilities.h" -#include "internal/catch_interfaces_tag_alias_registry.h" #ifndef CATCH_CONFIG_DISABLE_MATCHERS #include "internal/catch_capture_matchers.h" From 48db47c737d5a463021181ba1de5cf69ddf46831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 15:29:50 +0200 Subject: [PATCH 308/398] Remove unused internal macro from the common path --- include/internal/catch_common.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 269643ae..fa04044a 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -18,9 +18,6 @@ # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - #include #include #include From 0673b9be35584ff35d3412134b9c9b58117ad7b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 15:32:44 +0200 Subject: [PATCH 309/398] Split RNG related things into its own file This further removes 2 function declarations from the common path --- CMakeLists.txt | 2 + include/catch_session.hpp | 1 + include/internal/catch_common.cpp | 8 ---- include/internal/catch_common.h | 3 -- .../catch_random_number_generator.cpp | 31 ++++++++++++++ .../internal/catch_random_number_generator.h | 40 +++++++++++++++++++ include/internal/catch_run_context.cpp | 1 + .../catch_test_case_registry_impl.cpp | 4 +- .../catch_test_case_registry_impl.hpp | 15 ------- 9 files changed, 76 insertions(+), 29 deletions(-) create mode 100644 include/internal/catch_random_number_generator.cpp create mode 100644 include/internal/catch_random_number_generator.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8248ed99..ad104328 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_objc_arc.hpp ${HEADER_DIR}/internal/catch_option.hpp ${HEADER_DIR}/internal/catch_platform.h + ${HEADER_DIR}/internal/catch_random_number_generator.h ${HEADER_DIR}/internal/catch_reenable_warnings.h ${HEADER_DIR}/internal/catch_reporter_registrars.hpp ${HEADER_DIR}/internal/catch_reporter_registry.hpp @@ -218,6 +219,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp ${HEADER_DIR}/internal/catch_registry_hub.cpp ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp + ${HEADER_DIR}/internal/catch_random_number_generator.cpp ${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_run_context.cpp ${HEADER_DIR}/internal/catch_section.cpp diff --git a/include/catch_session.hpp b/include/catch_session.hpp index f02b93d9..ed1a826a 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -17,6 +17,7 @@ #include "internal/catch_test_spec.hpp" #include "internal/catch_version.h" #include "internal/catch_interfaces_reporter.h" +#include "internal/catch_random_number_generator.h" #include "internal/catch_startup_exception_registry.h" #include "internal/catch_text.h" diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp index 01c18ba4..9c18b543 100644 --- a/include/internal/catch_common.cpp +++ b/include/internal/catch_common.cpp @@ -29,14 +29,6 @@ namespace Catch { return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); } - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) - std::srand( config.rngSeed() ); - } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << '(' << info.line << ')'; diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index fa04044a..dfc0258b 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -67,9 +67,6 @@ namespace Catch { bool alwaysTrue(); bool alwaysFalse(); - void seedRng( IConfig const& config ); - unsigned int rngSeed(); - // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as diff --git a/include/internal/catch_random_number_generator.cpp b/include/internal/catch_random_number_generator.cpp new file mode 100644 index 00000000..7149a58b --- /dev/null +++ b/include/internal/catch_random_number_generator.cpp @@ -0,0 +1,31 @@ +/* + * Created by Martin on 30/08/2017. + * + * 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) + */ + +#include "catch_random_number_generator.h" +#include "catch_context.h" +#include "catch_interfaces_config.h" + +#include + +namespace Catch { + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { + return std::rand() % n; + } + RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { + return std::rand() % max(); + } + +} diff --git a/include/internal/catch_random_number_generator.h b/include/internal/catch_random_number_generator.h new file mode 100644 index 00000000..859e6cdf --- /dev/null +++ b/include/internal/catch_random_number_generator.h @@ -0,0 +1,40 @@ +/* + * Created by Martin on 30/08/2017. + * + * 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) + */ +#ifndef TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED +#define TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED + +#include "catch_random_number_generator.h" + +#include + +namespace Catch { + + struct IConfig; + + void seedRng( IConfig const& config ); + + unsigned int rngSeed(); + + struct RandomNumberGenerator { + using result_type = std::ptrdiff_t; + + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return 1000000; } + + result_type operator()( result_type n ) const; + result_type operator()() const; + + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; + std::shuffle( vector.begin(), vector.end(), rng ); + } + }; + +} + +#endif // TWOBLUECUBES_CATCH_RANDOM_NUMBER_GENERATOR_H_INCLUDED diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 5d640e48..8b22398c 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -1,6 +1,7 @@ #include "catch_run_context.hpp" #include "catch_context.h" #include "catch_enforce.h" +#include "catch_random_number_generator.h" #include "catch_stream.h" #include diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp index 0bf0000f..85385a9c 100644 --- a/include/internal/catch_test_case_registry_impl.cpp +++ b/include/internal/catch_test_case_registry_impl.cpp @@ -10,6 +10,7 @@ #include "catch_context.h" #include "catch_enforce.h" #include "catch_interfaces_registry_hub.h" +#include "catch_random_number_generator.h" #include "catch_string_manip.h" #include "catch_test_case_info.h" @@ -17,9 +18,6 @@ namespace Catch { - RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { return std::rand() % n; } - RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { return std::rand() % max(); } - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { std::vector sorted = unsortedTestCases; diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index ee412d9e..f49ad970 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -22,21 +22,6 @@ namespace Catch { class TestCase; struct IConfig; - struct RandomNumberGenerator { - using result_type = std::ptrdiff_t; - - result_type operator()( result_type n ) const; - - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return 1000000; } - result_type operator()() const; - template - static void shuffle( V& vector ) { - RandomNumberGenerator rng; - std::shuffle( vector.begin(), vector.end(), rng ); - } - }; - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); From 46e28791ffeec1f9e6d6696883414f7e650485a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 15:42:23 +0200 Subject: [PATCH 310/398] Stitch .cpp files into single header in deterministic order --- scripts/generateSingleHeader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/generateSingleHeader.py b/scripts/generateSingleHeader.py index 1b9b10e7..b1d18673 100755 --- a/scripts/generateSingleHeader.py +++ b/scripts/generateSingleHeader.py @@ -57,7 +57,8 @@ def generate(v): cppFiles = [] for dir in dirs: cppFiles += glob(os.path.join(dir, '*.cpp')) - for fname in cppFiles: + # To minimize random diffs, sort the files before processing them + for fname in sorted(cppFiles): dir, name = fname.rsplit(os.path.sep, 1) dir += os.path.sep parseFile(dir, name) From 255f7d7369a4d0851fe0efebe2689d1da20ae5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 15:42:01 +0200 Subject: [PATCH 311/398] Minor cleanup --- include/internal/catch_common.h | 2 -- include/internal/catch_context.h | 2 -- include/internal/catch_decomposer.h | 4 ++-- include/internal/catch_interfaces_capture.h | 2 -- include/internal/catch_interfaces_reporter.h | 1 - include/internal/catch_interfaces_runner.h | 1 - 6 files changed, 2 insertions(+), 10 deletions(-) diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index dfc0258b..53602ee6 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -24,8 +24,6 @@ namespace Catch { - struct IConfig; - struct CaseSensitive { enum Choice { Yes, No diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 39307f59..5569eb71 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -12,8 +12,6 @@ namespace Catch { - class TestCase; - class Stream; struct IResultCapture; struct IRunner; struct IConfig; diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 5613e774..03c11568 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -50,8 +50,8 @@ namespace Catch { } public: - BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) - : m_result( comparisionResult ), + BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) + : m_result( comparisonResult ), m_lhs( lhs ), m_op( op ), m_rhs( rhs ) diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index e8000154..d153a8bc 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -12,13 +12,11 @@ namespace Catch { - class TestCase; class AssertionResult; struct AssertionInfo; struct SectionInfo; struct SectionEndInfo; struct MessageInfo; - class ScopedMessageBuilder; struct Counts; struct BenchmarkInfo; struct BenchmarkStats; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index d1a5cb7c..be3044f9 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -165,7 +165,6 @@ namespace Catch { size_t iterations; uint64_t elapsedTimeInNanoseconds; }; - class MultipleReporters; struct IStreamingReporter { virtual ~IStreamingReporter() = default; diff --git a/include/internal/catch_interfaces_runner.h b/include/internal/catch_interfaces_runner.h index 25decfb0..a0deaf7e 100644 --- a/include/internal/catch_interfaces_runner.h +++ b/include/internal/catch_interfaces_runner.h @@ -9,7 +9,6 @@ #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED namespace Catch { - class TestCase; struct IRunner { virtual ~IRunner(); From 9796c516bb7920b7362809ceaccdf6995a24d0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 18:06:48 +0200 Subject: [PATCH 312/398] Always compile matchers implementation --- include/catch.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/catch.hpp b/include/catch.hpp index 459aacae..7ff7c8b9 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -20,6 +20,9 @@ #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL # define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif #endif #include "internal/catch_platform.h" From 49a1408ff23a7b0d34818168f9eca114b23559a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 18:07:29 +0200 Subject: [PATCH 313/398] Fix compilation of main file with CATCH_CONFIG_FAST_COMPILE --- include/internal/catch_capture.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index c914bffe..9f205465 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -11,6 +11,7 @@ #include "catch_assertionhandler.h" #include "catch_message.h" #include "catch_interfaces_capture.h" +#include "catch_debugger.h" #if !defined(CATCH_CONFIG_DISABLE) @@ -38,8 +39,6 @@ #else // CATCH_CONFIG_FAST_COMPILE -#include "catch_debugger.h" - /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. From 97edf7ce65e8358c9a5dd18ae3adbcbe4c7e4e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 18:11:52 +0200 Subject: [PATCH 314/398] Fix-up compilation benchmark script --- scripts/benchmarkCompile.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/benchmarkCompile.py b/scripts/benchmarkCompile.py index 685d1257..586c26ac 100755 --- a/scripts/benchmarkCompile.py +++ b/scripts/benchmarkCompile.py @@ -59,7 +59,7 @@ def compile_main(): return end_t - start_t def compile_files(): - cpp_files = glob.glob('*.cpp') + cpp_files = glob.glob('tests*.cpp') start_t = time.time() subprocess.check_call([compiler_path, '-c'] + flags + cpp_files) end_t = time.time() @@ -114,7 +114,7 @@ parser.add_argument('benchmark_kind', nargs='?', default='all', choices=options, parser.add_argument('-I', '--catch-header', default='catch.hpp', help = 'Path to catch.hpp, default: catch.hpp') parser.add_argument('-c', '--compiler', default='g++', help = 'Compiler to use, default: g++') -parser.add_argument('-f', '--flags', nargs='*', help = 'Flags to be passed to the compiler') +parser.add_argument('-f', '--flags', help = 'Flags to be passed to the compiler. Pass as "," separated list') # Allow creating files only, without running the whole thing parser.add_argument('-g', '--generate-files', action='store_true', help='Generate test files and quit') @@ -137,7 +137,7 @@ if args.generate_files: os.chdir(dir_name) if args.flags: - flags = args.flags + flags = args.flags.split(',') print('Time needed for ...') if args.benchmark_kind in ('all', 'main'): From a4df0b2c37f4f474aa0c379c484659300d315def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 19:16:25 +0200 Subject: [PATCH 315/398] Remove obsoleted utility functions on matchers Natural operators, &&, || and ! are preferred and do not have limited arity. --- docs/release-notes.md | 3 +++ include/internal/catch_matchers.hpp | 25 ------------------------- projects/SelfTest/MatchersTests.cpp | 10 ---------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index aa8f4957..c790e066 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -17,6 +17,9 @@ * `*_THROWS_AS(expr, exception_type)` now unconditionally appends `const&` to the exception type. * `CATCH_CONFIG_FAST_COMPILE` now affects the `CHECK_` family of assertions as well as `REQUIRE_` family of assertions * This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section. +* Removed deprecated matcher utility functions `Not`, `AllOf` and `AnyOf`. + * They are superseded by operators `!`, `&&` and `||`, which are natural and do not have limited arity + ## Improvements * Reporters and Listeners can be defined in files different from the main file diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 5a3f0818..91923831 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -148,31 +148,6 @@ namespace Matchers { } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - // - deprecated: prefer ||, && and ! - template - Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { - return Impl::MatchNotOf( underlyingMatcher ); - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAllOf() && m1 && m2; - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAllOf() && m1 && m2 && m3; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAnyOf() || m1 || m2; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAnyOf() || m1 || m2 || m3; - } - } // namespace Matchers using namespace Matchers; diff --git a/projects/SelfTest/MatchersTests.cpp b/projects/SelfTest/MatchersTests.cpp index 52a49230..0482ed43 100644 --- a/projects/SelfTest/MatchersTests.cpp +++ b/projects/SelfTest/MatchersTests.cpp @@ -50,16 +50,6 @@ TEST_CASE("Equals string matcher", "[.][failing][matchers]") CHECK_THAT( testStringForMatching(), Equals( "something else" ) ); } -TEST_CASE("AllOf matcher", "[matchers]") -{ - CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ); -} -TEST_CASE("AnyOf matcher", "[matchers]") -{ - CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ); - CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ); -} - TEST_CASE("Equals", "[matchers]") { CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ); From 6388fc946fccbad45be0a01e26e74904bac11977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 30 Aug 2017 20:03:54 +0200 Subject: [PATCH 316/398] Remove last usage of NotImplementedException TeamCity reporter now uses CATCH_ERROR instead --- CMakeLists.txt | 2 -- include/internal/catch_impl.hpp | 3 -- .../catch_notimplemented_exception.cpp | 25 ------------- .../internal/catch_notimplemented_exception.h | 35 ------------------- include/reporters/catch_reporter_teamcity.hpp | 4 +-- 5 files changed, 2 insertions(+), 67 deletions(-) delete mode 100644 include/internal/catch_notimplemented_exception.cpp delete mode 100644 include/internal/catch_notimplemented_exception.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ad104328..592b7c05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,6 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_matchers_string.h ${HEADER_DIR}/internal/catch_matchers_vector.h ${HEADER_DIR}/internal/catch_message.h - ${HEADER_DIR}/internal/catch_notimplemented_exception.h ${HEADER_DIR}/internal/catch_objc.hpp ${HEADER_DIR}/internal/catch_objc_arc.hpp ${HEADER_DIR}/internal/catch_option.hpp @@ -216,7 +215,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_matchers.cpp ${HEADER_DIR}/internal/catch_matchers_string.cpp ${HEADER_DIR}/internal/catch_message.cpp - ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp ${HEADER_DIR}/internal/catch_registry_hub.cpp ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp ${HEADER_DIR}/internal/catch_random_number_generator.cpp diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 785f3ddc..d9a644d0 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -17,9 +17,6 @@ #endif -#include "internal/catch_notimplemented_exception.h" - - // Temporary hack to fix separately provided reporters #include "../reporters/catch_reporter_bases.hpp" #include "catch_reporter_registrars.hpp" diff --git a/include/internal/catch_notimplemented_exception.cpp b/include/internal/catch_notimplemented_exception.cpp deleted file mode 100644 index f44d8e10..00000000 --- a/include/internal/catch_notimplemented_exception.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Created by Phil on 5/8/2012. - * Copyright 2012 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) - */ - -#include "catch_notimplemented_exception.h" -#include - -namespace Catch { - - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) { - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); - } - - const char* NotImplementedException::what() const noexcept { - return m_what.c_str(); - } - -} // end namespace Catch diff --git a/include/internal/catch_notimplemented_exception.h b/include/internal/catch_notimplemented_exception.h deleted file mode 100644 index 19e185b6..00000000 --- a/include/internal/catch_notimplemented_exception.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Created by Phil on 5/8/2012. - * Copyright 2012 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) - */ -#ifndef TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED -#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED - -#include "catch_common.h" - -#include - -namespace Catch { - - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); - - virtual ~NotImplementedException() noexcept = default; - - virtual const char* what() const noexcept override; - - private: - std::string m_what; - }; - -} // end namespace Catch - -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) - -#endif // TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 3fcbbd4e..d17026a8 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -97,12 +97,12 @@ namespace Catch { case ResultWas::Ok: case ResultWas::Info: case ResultWas::Warning: - + CATCH_ERROR( "Internal error in TeamCity reporter" ); // These cases are here to prevent compiler warnings case ResultWas::Unknown: case ResultWas::FailureBit: case ResultWas::Exception: - CATCH_NOT_IMPLEMENTED; + CATCH_ERROR( "Not implemented" ); } if( assertionStats.infoMessages.size() == 1 ) msg << " with message:"; From e87174253480c4bd5237350a246b042269c70561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 31 Aug 2017 10:31:52 +0200 Subject: [PATCH 317/398] Move session to internal, split apart implementation --- CMakeLists.txt | 3 +- include/catch_session.hpp | 265 ------------------- include/internal/catch_common.h | 4 +- include/internal/catch_config.hpp | 3 + include/internal/catch_default_main.hpp | 2 + include/internal/catch_external_interfaces.h | 1 + include/internal/catch_impl.hpp | 13 - include/internal/catch_session.cpp | 251 ++++++++++++++++++ include/internal/catch_session.h | 52 ++++ include/internal/catch_stream.h | 8 +- include/internal/catch_streambuf.h | 2 +- 11 files changed, 318 insertions(+), 286 deletions(-) delete mode 100644 include/catch_session.hpp create mode 100644 include/internal/catch_session.cpp create mode 100644 include/internal/catch_session.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 592b7c05..ca86274f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,7 +105,6 @@ CheckFileList(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps) # Please keep these ordered alphabetically set(TOP_LEVEL_HEADERS ${HEADER_DIR}/catch.hpp - ${HEADER_DIR}/catch_session.hpp ${HEADER_DIR}/catch_with_main.hpp ) CheckFileList(TOP_LEVEL_HEADERS ${HEADER_DIR}) @@ -169,6 +168,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_benchmark.h ${HEADER_DIR}/internal/catch_section.h ${HEADER_DIR}/internal/catch_section_info.h + ${HEADER_DIR}/internal/catch_session.h ${HEADER_DIR}/internal/catch_startup_exception_registry.h ${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_streambuf.h @@ -222,6 +222,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_run_context.cpp ${HEADER_DIR}/internal/catch_section.cpp ${HEADER_DIR}/internal/catch_section_info.cpp + ${HEADER_DIR}/internal/catch_session.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp ${HEADER_DIR}/internal/catch_stream.cpp ${HEADER_DIR}/internal/catch_stringref.cpp diff --git a/include/catch_session.hpp b/include/catch_session.hpp deleted file mode 100644 index ed1a826a..00000000 --- a/include/catch_session.hpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Created by Phil on 31/10/2010. - * Copyright 2010 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) - */ -#ifndef TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED - -#include "internal/catch_commandline.hpp" -#include "internal/catch_console_colour.hpp" -#include "internal/catch_enforce.h" -#include "internal/catch_list.h" -#include "internal/catch_run_context.hpp" -#include "internal/catch_stream.h" -#include "internal/catch_test_spec.hpp" -#include "internal/catch_version.h" -#include "internal/catch_interfaces_reporter.h" -#include "internal/catch_random_number_generator.h" -#include "internal/catch_startup_exception_registry.h" -#include "internal/catch_text.h" - -#include -#include -#include -#include - -namespace Catch { - - IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { - auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); - CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); - - return reporter; - } - -#ifndef CATCH_CONFIG_DEFAULT_REPORTER -#define CATCH_CONFIG_DEFAULT_REPORTER "console" -#endif - - IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { - auto const& reporterNames = config->getReporterNames(); - if( reporterNames.empty() ) - return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config ); - - IStreamingReporterPtr reporter; - for( auto const& name : reporterNames ) - addReporter( reporter, createReporter( name, config ) ); - return reporter; - } - void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) { - auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); - for( auto const& listener : listeners ) - addReporter(reporters, listener->create( ReporterConfig( config ) ) ); - } - - - Totals runTests( std::shared_ptr const& config ) { - - IStreamingReporterPtr reporter = makeReporter( config ); - addListeners( reporter, config ); - - RunContext context( config, std::move( reporter ) ); - - Totals totals; - - context.testGroupStarting( config->name(), 1, 1 ); - - TestSpec testSpec = config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector const& allTestCases = getAllTestCasesSorted( *config ); - for( auto const& testCase : allTestCases ) { - if( !context.aborting() && matchTest( testCase, testSpec, *config ) ) - totals += context.runTest( testCase ); - else - context.reporter().skipTest( testCase ); - } - - context.testGroupEnded( config->name(), totals, 1, 1 ); - return totals; - } - - void applyFilenamesAsTags( IConfig const& config ) { - auto& tests = const_cast&>( getAllTestCasesSorted( config ) ); - for( auto& testCase : tests ) { - auto tags = testCase.tags; - - std::string filename = testCase.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\\/" ); - if( lastSlash != std::string::npos ) - filename = filename.substr( lastSlash+1 ); - - std::string::size_type lastDot = filename.find_last_of( '.' ); - if( lastDot != std::string::npos ) - filename = filename.substr( 0, lastDot ); - - tags.push_back( '#' + filename ); - setTags( testCase, tags ); - } - } - - - class Session : NonCopyable { - static const int MaxExitCode; - public: - - Session() { - static bool alreadyInstantiated = false; - if( alreadyInstantiated ) - CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); - alreadyInstantiated = true; - m_cli = makeCommandLineParser( m_configData ); - } - ~Session() override { - Catch::cleanUp(); - } - - void showHelp() const { - Catch::cout() - << "\nCatch v" << libraryVersion() << "\n" - << m_cli << std::endl - << "For more detailed usage please see the project docs\n" << std::endl; - } - void libIdentify() { - Catch::cout() - << std::left << std::setw(16) << "description: " << "A Catch test executable\n" - << std::left << std::setw(16) << "category: " << "testframework\n" - << std::left << std::setw(16) << "framework: " << "Catch Test\n" - << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; - } - - int applyCommandLine( int argc, char* argv[] ) { - auto result = m_cli.parse( clara::Args( argc, argv ) ); - if( !result ) { - Catch::cerr() - << Colour( Colour::Red ) - << "\nError(s) in input:\n" - << Column( result.errorMessage() ).indent( 2 ) - << "\n\n"; - Catch::cerr() << "Run with -? for usage\n" << std::endl; - return MaxExitCode; - } - - if( m_configData.showHelp ) - showHelp(); - if( m_configData.libIdentify ) - libIdentify(); - m_config.reset(); - return 0; - } - - void useConfigData( ConfigData const& configData ) { - m_configData = configData; - m_config.reset(); - } - - int run( int argc, char* argv[] ) { - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - Catch::cerr() << "Errors occured during startup!" << '\n'; - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch ( std::exception const& ex ) { - Catch::cerr() << ex.what() << '\n'; - } - } - return 1; - } - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - - #if defined(WIN32) && defined(UNICODE) - int run( int argc, wchar_t* const argv[] ) { - - char **utf8Argv = new char *[ argc ]; - - for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); - - utf8Argv[ i ] = new char[ bufSize ]; - - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); - } - - int returnCode = run( argc, utf8Argv ); - - for ( int i = 0; i < argc; ++i ) - delete [] utf8Argv[ i ]; - - delete [] utf8Argv; - - return returnCode; - } - #endif - int run() { - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before starting" << std::endl; - static_cast(std::getchar()); - } - int exitCode = runInternal(); - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; - static_cast(std::getchar()); - } - return exitCode; - } - - clara::Parser const& cli() const { - return m_cli; - } - void cli( clara::Parser const& newParser ) { - m_cli = newParser; - } - ConfigData& configData() { - return m_configData; - } - Config& config() { - if( !m_config ) - m_config = std::make_shared( m_configData ); - return *m_config; - } - private: - int runInternal() { - if( m_configData.showHelp || m_configData.libIdentify ) - return 0; - - try - { - config(); // Force config to be constructed - - seedRng( *m_config ); - - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags( *m_config ); - - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); - - return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); - } - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return MaxExitCode; - } - } - - clara::Parser m_cli; - ConfigData m_configData; - std::shared_ptr m_config; - }; - - const int Session::MaxExitCode = 255; - -} // end namespace Catch - -#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 53602ee6..5e22825d 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -36,8 +36,8 @@ namespace Catch { NonCopyable& operator = ( NonCopyable && ) = delete; protected: - NonCopyable() {} - virtual ~NonCopyable(); + NonCopyable() = default; + virtual ~NonCopyable() = default; }; struct SourceLineInfo { diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 0f86137f..80847be5 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -11,6 +11,9 @@ #include "catch_test_spec_parser.hpp" #include "catch_interfaces_config.h" +// Libstdc++ doesn't like incomplete classes for unique_ptr +#include "catch_stream.h" + #include #include #include diff --git a/include/internal/catch_default_main.hpp b/include/internal/catch_default_main.hpp index 9b7c2890..8155c43f 100644 --- a/include/internal/catch_default_main.hpp +++ b/include/internal/catch_default_main.hpp @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED +#include "catch_session.h" + #ifndef __OBJC__ #if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) diff --git a/include/internal/catch_external_interfaces.h b/include/internal/catch_external_interfaces.h index dffd5187..4eb55256 100644 --- a/include/internal/catch_external_interfaces.h +++ b/include/internal/catch_external_interfaces.h @@ -8,6 +8,7 @@ #define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED #include "../reporters/catch_reporter_bases.hpp" +#include "catch_console_colour.hpp" #include "catch_reporter_registrars.hpp" #endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index d9a644d0..5debe23c 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -17,15 +17,8 @@ #endif -// Temporary hack to fix separately provided reporters -#include "../reporters/catch_reporter_bases.hpp" -#include "catch_reporter_registrars.hpp" -// - #include "internal/catch_leak_detector.h" - -#include "../catch_session.hpp" #include "catch_test_spec.hpp" #include "catch_test_case_tracker.hpp" @@ -37,12 +30,6 @@ namespace Catch { // These are all here to avoid warnings about not having any out of line // virtual methods - NonCopyable::~NonCopyable() {} - IStream::~IStream() noexcept {} - FileStream::~FileStream() noexcept {} - CoutStream::~CoutStream() noexcept {} - DebugOutStream::~DebugOutStream() noexcept {} - StreamBufBase::~StreamBufBase() noexcept {} IResultCapture::~IResultCapture() {} ITestInvoker::~ITestInvoker() {} ITestCaseRegistry::~ITestCaseRegistry() {} diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp new file mode 100644 index 00000000..d10e9510 --- /dev/null +++ b/include/internal/catch_session.cpp @@ -0,0 +1,251 @@ +/* + * Created by Martin on 31/08/2017. + * + * 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) + */ + +#include "catch_session.h" +#include "catch_commandline.hpp" +#include "catch_console_colour.hpp" +#include "catch_enforce.h" +#include "catch_list.h" +#include "catch_run_context.hpp" +#include "catch_stream.h" +#include "catch_test_spec.hpp" +#include "catch_version.h" +#include "catch_interfaces_reporter.h" +#include "catch_random_number_generator.h" +#include "catch_startup_exception_registry.h" +#include "catch_text.h" + +#include +#include + +static const int MaxExitCode = 255; + + +namespace Catch { + + IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { + auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); + CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); + + return reporter; + } + +#ifndef CATCH_CONFIG_DEFAULT_REPORTER +#define CATCH_CONFIG_DEFAULT_REPORTER "console" +#endif + + IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { + auto const& reporterNames = config->getReporterNames(); + if( reporterNames.empty() ) + return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config ); + + IStreamingReporterPtr reporter; + for( auto const& name : reporterNames ) + addReporter( reporter, createReporter( name, config ) ); + return reporter; + } + void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) { + auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( auto const& listener : listeners ) + addReporter(reporters, listener->create( ReporterConfig( config ) ) ); + } + + + Totals runTests( std::shared_ptr const& config ) { + + IStreamingReporterPtr reporter = makeReporter( config ); + addListeners( reporter, config ); + + RunContext context( config, std::move( reporter ) ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector const& allTestCases = getAllTestCasesSorted( *config ); + for( auto const& testCase : allTestCases ) { + if( !context.aborting() && matchTest( testCase, testSpec, *config ) ) + totals += context.runTest( testCase ); + else + context.reporter().skipTest( testCase ); + } + + context.testGroupEnded( config->name(), totals, 1, 1 ); + return totals; + } + + void applyFilenamesAsTags( IConfig const& config ) { + auto& tests = const_cast&>( getAllTestCasesSorted( config ) ); + for( auto& testCase : tests ) { + auto tags = testCase.tags; + + std::string filename = testCase.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( '.' ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.push_back( '#' + filename ); + setTags( testCase, tags ); + } + } + + + Session::Session() { + static bool alreadyInstantiated = false; + if( alreadyInstantiated ) + CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); + alreadyInstantiated = true; + m_cli = makeCommandLineParser( m_configData ); + } + Session::~Session() { + Catch::cleanUp(); + } + + void Session::showHelp() const { + Catch::cout() + << "\nCatch v" << libraryVersion() << "\n" + << m_cli << std::endl + << "For more detailed usage please see the project docs\n" << std::endl; + } + void Session::libIdentify() { + Catch::cout() + << std::left << std::setw(16) << "description: " << "A Catch test executable\n" + << std::left << std::setw(16) << "category: " << "testframework\n" + << std::left << std::setw(16) << "framework: " << "Catch Test\n" + << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; + } + + int Session::applyCommandLine( int argc, char* argv[] ) { + auto result = m_cli.parse( clara::Args( argc, argv ) ); + if( !result ) { + Catch::cerr() + << Colour( Colour::Red ) + << "\nError(s) in input:\n" + << Column( result.errorMessage() ).indent( 2 ) + << "\n\n"; + Catch::cerr() << "Run with -? for usage\n" << std::endl; + return MaxExitCode; + } + + if( m_configData.showHelp ) + showHelp(); + if( m_configData.libIdentify ) + libIdentify(); + m_config.reset(); + return 0; + } + + void Session::useConfigData( ConfigData const& configData ) { + m_configData = configData; + m_config.reset(); + } + + int Session::run( int argc, char* argv[] ) { + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + Catch::cerr() << "Errors occured during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << ex.what() << '\n'; + } + } + return 1; + } + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + +#if defined(WIN32) && defined(UNICODE) + int Session::run( int argc, wchar_t* const argv[] ) { + + char **utf8Argv = new char *[ argc ]; + + for ( int i = 0; i < argc; ++i ) { + int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + + utf8Argv[ i ] = new char[ bufSize ]; + + WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); + } + + int returnCode = run( argc, utf8Argv ); + + for ( int i = 0; i < argc; ++i ) + delete [] utf8Argv[ i ]; + + delete [] utf8Argv; + + return returnCode; + } +#endif + int Session::run() { + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before starting" << std::endl; + static_cast(std::getchar()); + } + int exitCode = runInternal(); + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; + static_cast(std::getchar()); + } + return exitCode; + } + + clara::Parser const& Session::cli() const { + return m_cli; + } + void Session::cli( clara::Parser const& newParser ) { + m_cli = newParser; + } + ConfigData& Session::configData() { + return m_configData; + } + Config& Session::config() { + if( !m_config ) + m_config = std::make_shared( m_configData ); + return *m_config; + } + + int Session::runInternal() { + if( m_configData.showHelp || m_configData.libIdentify ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return MaxExitCode; + } + } + +} // end namespace Catch diff --git a/include/internal/catch_session.h b/include/internal/catch_session.h new file mode 100644 index 00000000..492d6d31 --- /dev/null +++ b/include/internal/catch_session.h @@ -0,0 +1,52 @@ +/* + * Created by Phil on 31/10/2010. + * Copyright 2010 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) + */ +#ifndef TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +#include "catch_commandline.hpp" +#include "catch_config.hpp" +#include "catch_text.h" + +#include + +namespace Catch { + + class Session : NonCopyable { + public: + + Session(); + ~Session() override; + + void showHelp() const; + void libIdentify(); + + int applyCommandLine( int argc, char* argv[] ); + + void useConfigData( ConfigData const& configData ); + + int run( int argc, char* argv[] ); + #if defined(WIN32) && defined(UNICODE) + int run( int argc, wchar_t* const argv[] ); + #endif + int run(); + + clara::Parser const& cli() const; + void cli( clara::Parser const& newParser ); + ConfigData& configData(); + Config& config(); + private: + int runInternal(); + + clara::Parser m_cli; + ConfigData m_configData; + std::shared_ptr m_config; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index 488e8b20..1ab59ca3 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -24,7 +24,7 @@ namespace Catch { struct IStream { - virtual ~IStream() noexcept; + virtual ~IStream() = default; virtual std::ostream& stream() const = 0; }; @@ -32,7 +32,7 @@ namespace Catch { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); - ~FileStream() noexcept override; + ~FileStream() override = default; public: // IStream std::ostream& stream() const override; }; @@ -42,7 +42,7 @@ namespace Catch { mutable std::ostream m_os; public: CoutStream(); - ~CoutStream() noexcept override; + ~CoutStream() override = default; public: // IStream std::ostream& stream() const override; @@ -54,7 +54,7 @@ namespace Catch { mutable std::ostream m_os; public: DebugOutStream(); - ~DebugOutStream() noexcept override; + ~DebugOutStream() override = default; public: // IStream std::ostream& stream() const override; diff --git a/include/internal/catch_streambuf.h b/include/internal/catch_streambuf.h index dba84357..7fd17e40 100644 --- a/include/internal/catch_streambuf.h +++ b/include/internal/catch_streambuf.h @@ -16,7 +16,7 @@ namespace Catch { class StreamBufBase : public std::streambuf { public: - virtual ~StreamBufBase() noexcept; + virtual ~StreamBufBase() = default; }; } From e8ec6bd73c305399e2395a6aa8271d94f9cc0afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 31 Aug 2017 11:46:37 +0200 Subject: [PATCH 318/398] General cleanup for C++11 Also less allocations and less stack usage on the fatal condition path --- include/internal/catch_assertionresult.h | 2 +- include/internal/catch_fatal_condition.cpp | 14 ++-- include/internal/catch_fatal_condition.h | 6 -- include/internal/catch_run_context.cpp | 11 ++- include/internal/catch_session.cpp | 92 ++++++++++++---------- 5 files changed, 63 insertions(+), 62 deletions(-) diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index dfa2fab0..6a4b61f1 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -23,7 +23,7 @@ namespace Catch { AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); - ResultWas::OfType resultType = ResultWas::Unknown; + ResultWas::OfType resultType; std::string message; LazyExpression lazyExpression; diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp index 3de65f73..be1c333e 100644 --- a/include/internal/catch_fatal_condition.cpp +++ b/include/internal/catch_fatal_condition.cpp @@ -12,16 +12,12 @@ #include "catch_context.h" #include "catch_interfaces_capture.h" -namespace Catch { - +namespace { // Report the error condition - void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); + void reportFatal( char const * const message ) { + Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); } - -} // namespace Catch +} #if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// @@ -122,7 +118,7 @@ namespace Catch { void FatalConditionHandler::handleSignal( int sig ) { - std::string name = ""; + char const * name = ""; for (auto const& def : signalDefs) { if (sig == def.id) { name = def.name; diff --git a/include/internal/catch_fatal_condition.h b/include/internal/catch_fatal_condition.h index 97f371ae..9977702a 100644 --- a/include/internal/catch_fatal_condition.h +++ b/include/internal/catch_fatal_condition.h @@ -13,12 +13,6 @@ #include "catch_platform.h" #include "catch_compiler_capabilities.h" -namespace Catch { - - // Report the error condition - void reportFatal( std::string const& message ); - -} // namespace Catch #if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// #include "catch_windows_h_proxy.h" diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 8b22398c..7cb8f8dc 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -211,8 +211,7 @@ namespace Catch { void RunContext::handleFatalErrorCondition(std::string const & message) { // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. - AssertionResultData tempResult( ResultWas::Unknown, { false } ); - tempResult.resultType = ResultWas::FatalErrorCondition; + AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); tempResult.message = message; AssertionResult result(m_lastAssertionInfo, tempResult); @@ -221,7 +220,7 @@ namespace Catch { handleUnfinishedSections(); // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); Counts assertions; @@ -229,7 +228,7 @@ namespace Catch { SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); m_reporter->sectionEnded(testCaseSectionStats); - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + auto const& testInfo = m_activeTestCase->getTestCaseInfo(); Totals deltaTotals; deltaTotals.testCases.failed = 1; @@ -263,7 +262,7 @@ namespace Catch { } void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); m_reporter->sectionStarting(testCaseSection); Counts prevAssertions = m_totals.assertions; @@ -325,7 +324,7 @@ namespace Catch { } IResultCapture& getResultCapture() { - if (IResultCapture* capture = getCurrentContext().getResultCapture()) + if (auto* capture = getCurrentContext().getResultCapture()) return *capture; else CATCH_INTERNAL_ERROR("No result capture instance"); diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp index d10e9510..54c9d783 100644 --- a/include/internal/catch_session.cpp +++ b/include/internal/catch_session.cpp @@ -22,14 +22,16 @@ #include #include -static const int MaxExitCode = 255; +namespace { + const int MaxExitCode = 255; + using Catch::IStreamingReporterPtr; + using Catch::IConfigPtr; + using Catch::Config; -namespace Catch { - - IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { - auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); - CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); + IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { + auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); + CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); return reporter; } @@ -38,69 +40,79 @@ namespace Catch { #define CATCH_CONFIG_DEFAULT_REPORTER "console" #endif - IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { + IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { auto const& reporterNames = config->getReporterNames(); - if( reporterNames.empty() ) - return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config ); + if (reporterNames.empty()) + return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config); IStreamingReporterPtr reporter; - for( auto const& name : reporterNames ) - addReporter( reporter, createReporter( name, config ) ); + for (auto const& name : reporterNames) + addReporter(reporter, createReporter(name, config)); return reporter; } - void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) { - auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); - for( auto const& listener : listeners ) - addReporter(reporters, listener->create( ReporterConfig( config ) ) ); + +#undef CATCH_CONFIG_DEFAULT_REPORTER + + void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) { + auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); + for (auto const& listener : listeners) + addReporter(reporters, listener->create(Catch::ReporterConfig(config))); } - Totals runTests( std::shared_ptr const& config ) { + Catch::Totals runTests(std::shared_ptr const& config) { + using namespace Catch; + IStreamingReporterPtr reporter = makeReporter(config); + addListeners(reporter, config); - IStreamingReporterPtr reporter = makeReporter( config ); - addListeners( reporter, config ); - - RunContext context( config, std::move( reporter ) ); + RunContext context(config, std::move(reporter)); Totals totals; - context.testGroupStarting( config->name(), 1, 1 ); + context.testGroupStarting(config->name(), 1, 1); TestSpec testSpec = config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + if (!testSpec.hasFilters()) + testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests - std::vector const& allTestCases = getAllTestCasesSorted( *config ); - for( auto const& testCase : allTestCases ) { - if( !context.aborting() && matchTest( testCase, testSpec, *config ) ) - totals += context.runTest( testCase ); + auto const& allTestCases = getAllTestCasesSorted(*config); + for (auto const& testCase : allTestCases) { + if (!context.aborting() && matchTest(testCase, testSpec, *config)) + totals += context.runTest(testCase); else - context.reporter().skipTest( testCase ); + context.reporter().skipTest(testCase); } - context.testGroupEnded( config->name(), totals, 1, 1 ); + context.testGroupEnded(config->name(), totals, 1, 1); return totals; } - void applyFilenamesAsTags( IConfig const& config ) { - auto& tests = const_cast&>( getAllTestCasesSorted( config ) ); - for( auto& testCase : tests ) { + void applyFilenamesAsTags(Catch::IConfig const& config) { + using namespace Catch; + auto& tests = const_cast&>(getAllTestCasesSorted(config)); + for (auto& testCase : tests) { auto tags = testCase.tags; std::string filename = testCase.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\\/" ); - if( lastSlash != std::string::npos ) - filename = filename.substr( lastSlash+1 ); + auto lastSlash = filename.find_last_of("\\/"); + if (lastSlash != std::string::npos) { + filename.erase(0, lastSlash); + filename[0] = '#'; + } - std::string::size_type lastDot = filename.find_last_of( '.' ); - if( lastDot != std::string::npos ) - filename = filename.substr( 0, lastDot ); + auto lastDot = filename.find_last_of('.'); + if (lastDot != std::string::npos) { + filename.erase(lastDot); + } - tags.push_back( '#' + filename ); - setTags( testCase, tags ); + tags.push_back(std::move(filename)); + setTags(testCase, tags); } } +} + +namespace Catch { Session::Session() { static bool alreadyInstantiated = false; From 4e4a13dfb4b0e7dc60aacd2c8da01493ccb9b2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 31 Aug 2017 11:50:34 +0200 Subject: [PATCH 319/398] Update approvals after removing deprecated matcher helpers --- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 37 +------------------ .../SelfTest/Baselines/junit.sw.approved.txt | 4 +- .../SelfTest/Baselines/xml.sw.approved.txt | 34 +---------------- 4 files changed, 7 insertions(+), 72 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 11df0389..42d62c9c 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1020,6 +1020,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 184 | 133 passed | 47 failed | 4 failed as expected -assertions: 884 | 767 passed | 96 failed | 21 failed as expected +test cases: 182 | 131 passed | 47 failed | 4 failed as expected +assertions: 881 | 764 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 14fdcd9d..02ec81d7 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -508,19 +508,6 @@ PASSED: with expansion: 100.3 == Approx( 100.0 ) -------------------------------------------------------------------------------- -AllOf matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "string" and - contains: "abc" ) - ------------------------------------------------------------------------------- An expression with side-effects should only be evaluated once ------------------------------------------------------------------------------- @@ -565,26 +552,6 @@ PASSED: with message: anonymous test case -------------------------------------------------------------------------------- -AnyOf matcher -------------------------------------------------------------------------------- -MatchersTests.cpp: -............................................................................... - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "string" or contains: - "not there" ) - -MatchersTests.cpp:: -PASSED: - CHECK_THAT( testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) ) -with expansion: - "this string contains 'abc' as a substring" ( contains: "not there" or - contains: "string" ) - ------------------------------------------------------------------------------- Approximate PI ------------------------------------------------------------------------------- @@ -7554,6 +7521,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 184 | 130 passed | 50 failed | 4 failed as expected -assertions: 886 | 763 passed | 102 failed | 21 failed as expected +test cases: 182 | 128 passed | 50 failed | 4 failed as expected +assertions: 883 | 760 passed | 102 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 15fa38f0..9c693386 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -92,7 +92,6 @@ TrickyTests.cpp: - @@ -101,7 +100,6 @@ ExceptionTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 7f2b4b03..1acc1d74 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -521,17 +521,6 @@
- - - - testStringForMatching(), AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) - - - "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) - - - - @@ -579,25 +568,6 @@ - - - - testStringForMatching(), AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) - - - "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) - - - - - testStringForMatching(), AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) - - - "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) - - - - @@ -8306,7 +8276,7 @@ loose text artifact
- + - + From 3a5b9512562fc176cbee7a40c602efe11780fb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 31 Aug 2017 12:00:35 +0200 Subject: [PATCH 320/398] Make approval tests part of ctest --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca86274f..6888be88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,6 +317,8 @@ if (NOT NO_SELFTEST) add_test(NAME ListTags COMMAND SelfTest --list-tags) set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags") + add_test(NAME ApprovalTests COMMAND ../scripts/approvalTests.py ./SelfTest) + set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed") endif() # !NO_SELFTEST From 115db71bab371c610f58b8eed1095247a1778bf6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 31 Aug 2017 16:14:27 +0100 Subject: [PATCH 321/398] Incorporated Clara with TextFlow fix for assertion with consecutive newlines fixes #1012 --- include/external/clara.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 091c2fa8..4abcd16f 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -135,7 +135,7 @@ namespace Catch { namespace clara { namespace TextFlow { auto operator *() const -> std::string { assert( m_stringIndex < m_column.m_strings.size() ); - assert( m_pos < m_end ); + assert( m_pos <= m_end ); if( m_pos + m_column.m_width < m_end ) return addIndentAndSuffix(line().substr(m_pos, m_len)); else From be067bce37f669d022bc6843a2fbe00a4446462e Mon Sep 17 00:00:00 2001 From: offa Date: Thu, 31 Aug 2017 23:38:52 +0200 Subject: [PATCH 322/398] Explicit ctor used to fix compilation failures caused by copy initialization. --- include/reporters/catch_reporter_multi.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/reporters/catch_reporter_multi.cpp b/include/reporters/catch_reporter_multi.cpp index b21672c3..017b628d 100644 --- a/include/reporters/catch_reporter_multi.cpp +++ b/include/reporters/catch_reporter_multi.cpp @@ -7,7 +7,7 @@ */ #include "catch_reporter_multi.h" - + namespace Catch { void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { @@ -19,10 +19,10 @@ namespace Catch { } std::set MultipleReporters::getSupportedVerbosities() { - return { }; + return std::set{ }; } - + void MultipleReporters::noMatchingTestCases( std::string const& spec ) { for( auto const& reporter : m_reporters ) reporter->noMatchingTestCases( spec ); From 792d3d0a261c0926e6ba06383256b117597ce10f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 1 Sep 2017 09:41:28 +0100 Subject: [PATCH 323/398] Fixed alignment of getSupportedVerbosities in MultipleReporters --- include/reporters/catch_reporter_multi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_multi.h index a69729ec..ec14f458 100644 --- a/include/reporters/catch_reporter_multi.h +++ b/include/reporters/catch_reporter_multi.h @@ -22,7 +22,7 @@ namespace Catch { void noMatchingTestCases( std::string const& spec ) override; - static std::set getSupportedVerbosities(); + static std::set getSupportedVerbosities(); void testRunStarting( TestRunInfo const& testRunInfo ) override; void testGroupStarting( GroupInfo const& groupInfo ) override; From 35bad896842f89b3d07e99c463200ea1dc1bc0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 1 Sep 2017 17:54:01 +0200 Subject: [PATCH 324/398] Fix ctest failure on windows --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6888be88..2196a893 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,7 +317,7 @@ if (NOT NO_SELFTEST) add_test(NAME ListTags COMMAND SelfTest --list-tags) set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags") - add_test(NAME ApprovalTests COMMAND ../scripts/approvalTests.py ./SelfTest) + add_test(NAME ApprovalTests COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $) set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed") endif() # !NO_SELFTEST From b3a923133d7b97210867981d189525cfef21166d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 1 Sep 2017 19:12:15 +0200 Subject: [PATCH 325/398] Actually fix AppVeyor ctest Note, this doesn't mean it will start passing, just that it will run the approval tests properly Some changes are needed before it passes, as the Windows output somewhat differs. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2196a893..2903ad9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,7 +317,7 @@ if (NOT NO_SELFTEST) add_test(NAME ListTags COMMAND SelfTest --list-tags) set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags") - add_test(NAME ApprovalTests COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $) + add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $) set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed") endif() # !NO_SELFTEST From ab5d176195f7b9fc0bee52da9f7643b79fab35e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 1 Sep 2017 20:28:49 +0200 Subject: [PATCH 326/398] Fix/disable failing approval tests --- CMakeLists.txt | 1 + .../Baselines/console.std.approved.txt | 18 +------ .../Baselines/console.sw.approved.txt | 50 ++----------------- .../SelfTest/Baselines/junit.sw.approved.txt | 5 +- .../SelfTest/Baselines/xml.sw.approved.txt | 45 ++--------------- projects/SelfTest/ConditionTests.cpp | 3 +- projects/SelfTest/MessageTests.cpp | 6 +-- projects/SelfTest/TrickyTests.cpp | 17 +++++-- scripts/approvalTests.py | 12 +++-- 9 files changed, 37 insertions(+), 120 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2903ad9e..c6f4b900 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -317,6 +317,7 @@ if (NOT NO_SELFTEST) add_test(NAME ListTags COMMAND SelfTest --list-tags) set_tests_properties(ListTags PROPERTIES PASS_REGULAR_EXPRESSION "[0-9]+ tags") + # AppVeyor has a Python 2.7 in path, but doesn't have .py files as autorunnable add_test(NAME ApprovalTests COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/approvalTests.py $) set_tests_properties(ApprovalTests PROPERTIES FAIL_REGULAR_EXPRESSION "Results differed") endif() # !NO_SELFTEST diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 42d62c9c..dfa2fa92 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -644,20 +644,6 @@ MessageTests.cpp:: FAILED: explicitly with message: Message from section two -------------------------------------------------------------------------------- -Pointers can be converted to strings -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -warning: - actual address of p: 0x - -MessageTests.cpp:: -warning: - toString(p): 0x - ------------------------------------------------------------------------------- Reconstruction should be based on stringification: #914 ------------------------------------------------------------------------------- @@ -1020,6 +1006,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 182 | 131 passed | 47 failed | 4 failed as expected -assertions: 881 | 764 passed | 96 failed | 21 failed as expected +test cases: 179 | 128 passed | 47 failed | 4 failed as expected +assertions: 879 | 762 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 02ec81d7..bcba36a1 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -955,20 +955,6 @@ PASSED: with expansion: 0x == 0x -------------------------------------------------------------------------------- -Comparing member function pointers -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - CHECK( m == &S::f ) -with expansion: - 0x - == - 0x - ------------------------------------------------------------------------------- Comparison with explicitly convertible types ------------------------------------------------------------------------------- @@ -1182,11 +1168,9 @@ with expansion: ConditionTests.cpp:: PASSED: - REQUIRE( (std::numeric_limits::max)() > ul ) + REQUIRE( (std::numeric_limits::max)() > ul ) with expansion: - 18446744073709551615 (0x) - > - 4 + 4294967295 (0x) > 4 ------------------------------------------------------------------------------- Contains string matcher @@ -2096,18 +2080,6 @@ PASSED: with expansion: !{?} -------------------------------------------------------------------------------- -Operators at different namespace levels not hijacked by Koenig lookup -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( 0x == o ) -with expansion: - 3221225472 (0x) == {?} - ------------------------------------------------------------------------------- Ordering comparison checks that should fail ------------------------------------------------------------------------------- @@ -3432,20 +3404,6 @@ PASSED: with expansion: 0 != 0x -------------------------------------------------------------------------------- -Pointers can be converted to strings -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - -MessageTests.cpp:: -warning: - actual address of p: 0x - -MessageTests.cpp:: -warning: - toString(p): 0x - ------------------------------------------------------------------------------- Process can be configured on command line empty args don't cause a crash @@ -7521,6 +7479,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 182 | 128 passed | 50 failed | 4 failed as expected -assertions: 883 | 760 passed | 102 failed | 21 failed as expected +test cases: 179 | 125 passed | 50 failed | 4 failed as expected +assertions: 881 | 758 passed | 102 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 9c693386..13c48c19 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -116,7 +116,6 @@ ExceptionTests.cpp: - @@ -335,7 +334,6 @@ ExceptionTests.cpp: - ConditionTests.cpp: @@ -441,7 +439,6 @@ MessageTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 1acc1d74..9ab6d491 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1023,19 +1023,6 @@ - - - - m == &S::f - - - 0x -== -0x - - - - @@ -1296,12 +1283,10 @@ - (std::numeric_limits<unsigned long>::max)() > ul + (std::numeric_limits<uint32_t>::max)() > ul - 18446744073709551615 (0x) -> -4 + 4294967295 (0x) > 4 @@ -2388,17 +2373,6 @@ - - - - 0x == o - - - 3221225472 (0x) == {?} - - - - @@ -3962,15 +3936,6 @@ - - - actual address of p: 0x - - - toString(p): 0x - - -
@@ -4824,7 +4789,7 @@ A string sent directly to stderr - +
@@ -8276,7 +8241,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index 565d9815..00ff6060 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -13,6 +13,7 @@ #include #include +#include struct TestData { int int_seven = 7; @@ -184,7 +185,7 @@ TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigne REQUIRE( 5 == c ); REQUIRE( 6 == uc ); - REQUIRE( (std::numeric_limits::max)() > ul ); + REQUIRE( (std::numeric_limits::max)() > ul ); } // Disable warnings about sign conversions for the next two tests diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp index 437ba53d..6082a4e6 100644 --- a/projects/SelfTest/MessageTests.cpp +++ b/projects/SelfTest/MessageTests.cpp @@ -85,7 +85,7 @@ TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) { } } -TEST_CASE( "Standard error is reported and redirected", "[messages][.]" ) { +TEST_CASE( "Standard error is reported and redirected", "[messages][.][approvals]" ) { SECTION( "std::cerr" ) { std::cerr << "Write to std::cerr" << std::endl; } @@ -98,7 +98,7 @@ TEST_CASE( "Standard error is reported and redirected", "[messages][.]" ) { std::cerr << ' '; std::clog << "writes"; std::cerr << " to error"; - std::clog << " streams\n"; + std::clog << " streams" << std::endl; } } @@ -130,7 +130,7 @@ TEST_CASE( "sends information to INFO", "[.][failing]" ) { REQUIRE( false ); } -TEST_CASE( "Pointers can be converted to strings", "[messages][.]" ) { +TEST_CASE( "Pointers can be converted to strings", "[messages][.][approvals]" ) { int p; WARN( "actual address of p: " << &p ); WARN( "toString(p): " << ::Catch::Detail::stringify( &p ) ); diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index f551d3bf..90abb4a8 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -175,7 +175,7 @@ namespace ObjectWithConversions TEST_CASE ( "Operators at different namespace levels not hijacked by Koenig lookup", - "[Tricky]" + "[Tricky][approvals]" ) { Object o; @@ -211,9 +211,16 @@ namespace ObjectWithNonConstEqualityOperator namespace EnumBitFieldTests { - enum Bits {bit0 = 0x0001, bit1 = 0x0002, bit2 = 0x0004, bit3 = 0x0008, bit1and2 = 0x0006, - bit30 = 0x40000000, bit31 = 0x80000000, - bit30and31 = 0xc0000000}; + enum Bits : uint32_t { + bit0 = 0x0001, + bit1 = 0x0002, + bit2 = 0x0004, + bit3 = 0x0008, + bit1and2 = bit1 | bit2, + bit30 = 0x40000000, + bit31 = 0x80000000, + bit30and31 = bit30 | bit31 + }; TEST_CASE( "Test enum bit values", "[Tricky]" ) { @@ -365,7 +372,7 @@ struct S }; -TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer]" ) +TEST_CASE( "Comparing member function pointers", "[Tricky][member function pointer][approvals]" ) { typedef void (S::*MF)(); MF m = &S::f; diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py index 49553349..5c0c63ec 100755 --- a/scripts/approvalTests.py +++ b/scripts/approvalTests.py @@ -41,6 +41,8 @@ errnoParser = re.compile(r''' \(\*__errno_location\ \(\)\) | \(\*__error\(\)\) + | + \(\*_errno\(\)\) ''', re.VERBOSE) if len(sys.argv) == 2: @@ -145,15 +147,15 @@ print("Running approvals against executable:") print(" " + cmdPath) # Standard console reporter -approve("console.std", ["~[!nonportable]~[!benchmark]", "--order", "lex"]) +approve("console.std", ["~[!nonportable]~[!benchmark]~[approvals]", "--order", "lex"]) # console reporter, include passes, warn about No Assertions -approve("console.sw", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "--order", "lex"]) +approve("console.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "--order", "lex"]) # console reporter, include passes, warn about No Assertions, limit failures to first 4 -approve("console.swa4", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"]) +approve("console.swa4", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-x", "4", "--order", "lex"]) # junit reporter, include passes, warn about No Assertions -approve("junit.sw", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"]) +approve("junit.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "junit", "--order", "lex"]) # xml reporter, include passes, warn about No Assertions -approve("xml.sw", ["~[!nonportable]~[!benchmark]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"]) +approve("xml.sw", ["~[!nonportable]~[!benchmark]~[approvals]", "-s", "-w", "NoAssertions", "-r", "xml", "--order", "lex"]) if overallResult != 0: print("If these differences are expected, run approve.py to approve new baselines.") From aef2e4d9e771cf18330708c9ba65b38cff629f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 2 Sep 2017 20:29:05 +0200 Subject: [PATCH 327/398] Update baselines --- .../Baselines/console.std.approved.txt | 5 +-- .../Baselines/console.sw.approved.txt | 37 +------------------ .../SelfTest/Baselines/junit.sw.approved.txt | 12 +----- .../SelfTest/Baselines/xml.sw.approved.txt | 22 +---------- 4 files changed, 6 insertions(+), 70 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index dfa2fa92..042224ac 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -657,9 +657,6 @@ with expansion: A string sent directly to stdout A string sent directly to stderr -Write to std::cerr -Write to std::clog -Interleaved writes to error streams Message from section one Message from section two ------------------------------------------------------------------------------- @@ -1006,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 179 | 128 passed | 47 failed | 4 failed as expected +test cases: 178 | 127 passed | 47 failed | 4 failed as expected assertions: 879 | 762 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index bcba36a1..ea723223 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -4195,39 +4195,6 @@ PASSED: with expansion: Approx( 1.23 ) != 1.24 -Write to std::cerr -------------------------------------------------------------------------------- -Standard error is reported and redirected - std::cerr -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'std::cerr' - -Write to std::clog -------------------------------------------------------------------------------- -Standard error is reported and redirected - std::clog -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'std::clog' - -Interleaved writes to error streams -------------------------------------------------------------------------------- -Standard error is reported and redirected - Interleaved writes to cerr and clog -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'Interleaved writes to cerr and clog' - Message from section one ------------------------------------------------------------------------------- Standard output from all sections is reported @@ -7479,6 +7446,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 179 | 125 passed | 50 failed | 4 failed as expected -assertions: 881 | 758 passed | 102 failed | 21 failed as expected +test cases: 178 | 125 passed | 49 failed | 4 failed as expected +assertions: 878 | 758 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 13c48c19..d0026667 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -488,13 +488,6 @@ A string sent directly to stderr - - -Write to std::cerr -Write to std::clog -Interleaved writes to error streams - - Message from section one @@ -801,9 +794,6 @@ Message from section two A string sent directly to stderr -Write to std::cerr -Write to std::clog -Interleaved writes to error streams diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 9ab6d491..310e3e0a 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -4789,24 +4789,6 @@ A string sent directly to stderr
- -
- -
-
- -
-
- -
- - -Write to std::cerr -Write to std::clog -Interleaved writes to error streams - - -
@@ -8241,7 +8223,7 @@ loose text artifact
- + - + From b00041143483949b35f3670ba9ceb5452bf5102d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 6 Sep 2017 14:42:44 +0200 Subject: [PATCH 328/398] Stop accepting non-const comparison operators A) non-const comparison operators should not exist and should not be encouraged B) The logic breaks comparing function pointers certain way C) It was inconsistent anyway, as it only applied to `==` and `!=` Closes #925 --- include/internal/catch_decomposer.h | 8 +--- .../Baselines/console.sw.approved.txt | 24 +++++------ .../Baselines/console.swa4.approved.txt | 16 ++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 2 +- .../SelfTest/Baselines/xml.sw.approved.txt | 22 +++++----- projects/SelfTest/TrickyTests.cpp | 42 +++++++------------ 6 files changed, 56 insertions(+), 58 deletions(-) diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 03c11568..c61ca856 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -76,7 +76,7 @@ namespace Catch { // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template - auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) == rhs; }; + auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; template @@ -87,7 +87,7 @@ namespace Catch { auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; template - auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) != rhs; }; + auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; template auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; template @@ -150,10 +150,6 @@ namespace Catch { } struct Decomposer { - template - auto operator <= ( T& lhs ) -> ExprLhs { - return ExprLhs( lhs ); - } template auto operator <= ( T const& lhs ) -> ExprLhs { return ExprLhs( lhs ); diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index ea723223..76a0819d 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -156,6 +156,18 @@ with expansion: with message: dummy := 0 +------------------------------------------------------------------------------- +#925: comparing function pointer to function address failed to compile +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( utility::synchronizing_callback != test.testMethod_uponComplete_arg ) +with expansion: + 1 != 0 + ------------------------------------------------------------------------------- #961 -- Dynamically created sections should all be reported Looped section 0 @@ -1215,18 +1227,6 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: custom std exception -------------------------------------------------------------------------------- -Demonstrate that a non-const == is not used -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( t == 1u ) -with expansion: - {?} == 1 - ------------------------------------------------------------------------------- EndsWith string matcher ------------------------------------------------------------------------------- diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index 06c24e86..ef9fd05f 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -156,6 +156,18 @@ with expansion: with message: dummy := 0 +------------------------------------------------------------------------------- +#925: comparing function pointer to function address failed to compile +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( utility::synchronizing_callback != test.testMethod_uponComplete_arg ) +with expansion: + 1 != 0 + ------------------------------------------------------------------------------- #961 -- Dynamically created sections should all be reported Looped section 0 @@ -237,6 +249,6 @@ ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) =============================================================================== -test cases: 9 | 6 passed | 1 failed | 2 failed as expected -assertions: 26 | 19 passed | 4 failed | 3 failed as expected +test cases: 10 | 7 passed | 1 failed | 2 failed as expected +assertions: 27 | 20 passed | 4 failed | 3 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index d0026667..88abcd9c 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -27,6 +27,7 @@ MiscTests.cpp:
+ @@ -143,7 +144,6 @@ custom std exception ExceptionTests.cpp: - MatchersTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 310e3e0a..5e1312ca 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -169,6 +169,17 @@ + + + + utility::synchronizing_callback != test.testMethod_uponComplete_arg + + + 1 != 0 + + + +
@@ -1336,17 +1347,6 @@ - - - - t == 1u - - - {?} == 1 - - - - diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 90abb4a8..312638f2 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -183,32 +183,6 @@ namespace ObjectWithConversions } } -namespace ObjectWithNonConstEqualityOperator -{ - struct Test - { - Test( unsigned int v ) - : m_value(v) - {} - - bool operator==( const Test&rhs ) - { - return (m_value == rhs.m_value); - } - bool operator==( const Test&rhs ) const - { - return (m_value != rhs.m_value); - } - unsigned int m_value; - }; - - TEST_CASE("Demonstrate that a non-const == is not used", "[Tricky]" ) - { - Test t( 1 ); - REQUIRE( t == 1u ); - } -} - namespace EnumBitFieldTests { enum Bits : uint32_t { @@ -448,3 +422,19 @@ TEST_CASE( "non-copyable objects", "[.][failing]" ) { std::type_info const& ti = typeid(int); CHECK( ti == typeid(int) ); } + +// #925 +using signal_t = void (*) (void*); + +struct TestClass { + signal_t testMethod_uponComplete_arg = nullptr; +}; + +namespace utility { + inline static void synchronizing_callback( void * ) { } +} + +TEST_CASE("#925: comparing function pointer to function address failed to compile") { + TestClass test; + REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg); +} From 8d03cb4915ae5cae960bc069738c9050233ec79e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 6 Sep 2017 15:15:48 +0200 Subject: [PATCH 329/398] Use StringRef to pass comparison operator name to BinaryExpr Some nominally C++11 platforms do not have SSO (I am looking at you libstdc++), where this avoids meaningless allocations. --- include/internal/catch_decomposer.cpp | 2 +- include/internal/catch_decomposer.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_decomposer.cpp b/include/internal/catch_decomposer.cpp index f7da22b5..f8b282dc 100644 --- a/include/internal/catch_decomposer.cpp +++ b/include/internal/catch_decomposer.cpp @@ -11,7 +11,7 @@ namespace Catch { - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) { + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { if( lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && rhs.find('\n') == std::string::npos ) diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index c61ca856..48f87f60 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -32,13 +32,13 @@ namespace Catch { virtual ~ITransientExpression() = default; }; - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); template class BinaryExpr : public ITransientExpression { bool m_result; LhsT m_lhs; - std::string m_op; + StringRef m_op; RhsT m_rhs; auto isBinaryExpression() const -> bool override { return true; } From 2d37649377ee70704b49fac01e4dab273c808742 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 6 Sep 2017 15:43:26 +0100 Subject: [PATCH 330/398] Fixed Objective-C mode --- include/catch.hpp | 1 + include/internal/catch_default_main.hpp | 2 +- include/internal/catch_objc.hpp | 29 +++++++++++++++---------- include/internal/catch_tostring.cpp | 16 -------------- include/internal/catch_tostring.h | 25 ++++++++++++++------- 5 files changed, 36 insertions(+), 37 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 7ff7c8b9..61321400 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -42,6 +42,7 @@ #include "internal/catch_interfaces_exception.h" #include "internal/catch_approx.hpp" #include "internal/catch_compiler_capabilities.h" +#include "internal/catch_string_manip.h" #ifndef CATCH_CONFIG_DISABLE_MATCHERS #include "internal/catch_capture_matchers.h" diff --git a/include/internal/catch_default_main.hpp b/include/internal/catch_default_main.hpp index 8155c43f..4372e9cc 100644 --- a/include/internal/catch_default_main.hpp +++ b/include/internal/catch_default_main.hpp @@ -32,7 +32,7 @@ int main (int argc, char * const argv[]) { #endif Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); + int result = Catch::Session().run( argc, (char**)argv ); #if !CATCH_ARC_ENABLED [pool drain]; diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 188f5577..93fbfdfb 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -18,6 +18,8 @@ // in catch.hpp first to make sure they are included by the single // header for non obj-usage #include "catch_test_case_info.h" +#include "catch_string_manip.h" +#include "catch_tostring.h" /////////////////////////////////////////////////////////////////////////////// // This protocol is really only here for (self) documenting purposes, since @@ -91,7 +93,7 @@ namespace Catch { std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); const char* className = class_getName( cls ); - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) ); noTestMethods++; } } @@ -118,7 +120,7 @@ namespace Catch { return false; } - NSString* m_substr; + NSString* CATCH_ARC_STRONG m_substr; }; struct Equals : StringHolder { @@ -130,7 +132,7 @@ namespace Catch { } std::string describe() const override { - return "equals string: " + Catch::toString( m_substr ); + return "equals string: " + Catch::Detail::stringify( m_substr ); } }; @@ -143,7 +145,7 @@ namespace Catch { } std::string describe() const override { - return "contains string: " + Catch::toString( m_substr ); + return "contains string: " + Catch::Detail::stringify( m_substr ); } }; @@ -156,7 +158,7 @@ namespace Catch { } std::string describe() const override { - return "starts with: " + Catch::toString( m_substr ); + return "starts with: " + Catch::Detail::stringify( m_substr ); } }; struct EndsWith : StringHolder { @@ -168,7 +170,7 @@ namespace Catch { } std::string describe() const override { - return "ends with: " + Catch::toString( m_substr ); + return "ends with: " + Catch::Detail::stringify( m_substr ); } }; @@ -196,15 +198,18 @@ namespace Catch { } // namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ +#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix +#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ +{ \ return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +} \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ { \ return @ desc; \ } \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) +-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) + +#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) #endif // TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED diff --git a/include/internal/catch_tostring.cpp b/include/internal/catch_tostring.cpp index f3b9267c..56aefa63 100644 --- a/include/internal/catch_tostring.cpp +++ b/include/internal/catch_tostring.cpp @@ -210,20 +210,4 @@ std::string StringMaker::convert(double value) { } -#ifdef __OBJC__ -std::string StringMaker::convert(NSString* nsstring) { - if (!nsstring) - return "nil"; - return "@" + toString([nsstring UTF8String]); -} -std::string StringMaker::convert(NSString* CATCH_ARC_STRONG nsstring) { - if (!nsstring) - return "nil"; - return "@" + toString([nsstring UTF8String]); -} -std::string StringMaker::convert(NSObject* nsObject) { - return ::Catch::Detail::stringify([nsObject description]); -} -#endif - } // end namespace Catch diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 81d122d6..5a82eba6 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -299,17 +299,26 @@ namespace Catch { #ifdef __OBJC__ template<> struct StringMaker { - static std::string convert(NSString* nsstring); + static std::string convert(NSString * nsstring) { + if (!nsstring) + return "nil"; + return std::string("@") + [nsstring UTF8String]; + } }; template<> - struct StringMaker { - static std::string convert(NSString * CATCH_ARC_STRONG nsstring); + struct StringMaker { + static std::string convert(NSObject* nsObject) { + return ::Catch::Detail::stringify([nsObject description]); + } + }; - template<> - struct StringMaker { - static std::string convert(NSObject* nsObject); - }; -#endif + namespace Detail { + inline std::string stringify( NSString* nsstring ) { + return StringMaker::convert( nsstring ); + } + + } // namespace Detail +#endif // __OBJC__ } // namespace Catch From 4e5a67bc445728b415df7026cb9b1cadc012f457 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 6 Sep 2017 15:44:05 +0100 Subject: [PATCH 331/398] Added back OCTest project --- .../OCTest/OCTest.xcodeproj/project.pbxproj | 483 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../XCode/OCTest/OCTest/CatchOCTestCase.h | 25 + .../XCode/OCTest/OCTest/CatchOCTestCase.mm | 87 ++++ projects/XCode/OCTest/OCTest/Main.mm | 2 + projects/XCode/OCTest/OCTest/OCTest.1 | 79 +++ projects/XCode/OCTest/OCTest/OCTest.mm | 28 + projects/XCode/OCTest/OCTest/TestObj.h | 28 + projects/XCode/OCTest/OCTest/TestObj.m | 25 + 9 files changed, 764 insertions(+) create mode 100644 projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj create mode 100644 projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 projects/XCode/OCTest/OCTest/CatchOCTestCase.h create mode 100644 projects/XCode/OCTest/OCTest/CatchOCTestCase.mm create mode 100644 projects/XCode/OCTest/OCTest/Main.mm create mode 100644 projects/XCode/OCTest/OCTest/OCTest.1 create mode 100644 projects/XCode/OCTest/OCTest/OCTest.mm create mode 100644 projects/XCode/OCTest/OCTest/TestObj.h create mode 100644 projects/XCode/OCTest/OCTest/TestObj.m diff --git a/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj new file mode 100644 index 00000000..03cd3714 --- /dev/null +++ b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj @@ -0,0 +1,483 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 2621EE1A1F602F2C00D9AA4C /* catch_approx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE191F602F2C00D9AA4C /* catch_approx.cpp */; }; + 2621EE4A1F602F8300D9AA4C /* catch_assertionhandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1B1F602F8200D9AA4C /* catch_assertionhandler.cpp */; }; + 2621EE4B1F602F8300D9AA4C /* catch_assertionresult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1C1F602F8200D9AA4C /* catch_assertionresult.cpp */; }; + 2621EE4C1F602F8300D9AA4C /* catch_benchmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1D1F602F8200D9AA4C /* catch_benchmark.cpp */; }; + 2621EE4D1F602F8300D9AA4C /* catch_capture_matchers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1E1F602F8200D9AA4C /* catch_capture_matchers.cpp */; }; + 2621EE4E1F602F8300D9AA4C /* catch_commandline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1F1F602F8200D9AA4C /* catch_commandline.cpp */; }; + 2621EE4F1F602F8300D9AA4C /* catch_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE201F602F8200D9AA4C /* catch_common.cpp */; }; + 2621EE501F602F8300D9AA4C /* catch_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE211F602F8200D9AA4C /* catch_config.cpp */; }; + 2621EE511F602F8300D9AA4C /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE221F602F8200D9AA4C /* catch_console_colour.cpp */; }; + 2621EE521F602F8300D9AA4C /* catch_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE231F602F8200D9AA4C /* catch_context.cpp */; }; + 2621EE531F602F8300D9AA4C /* catch_debug_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE241F602F8200D9AA4C /* catch_debug_console.cpp */; }; + 2621EE541F602F8300D9AA4C /* catch_debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE251F602F8200D9AA4C /* catch_debugger.cpp */; }; + 2621EE551F602F8300D9AA4C /* catch_decomposer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE261F602F8200D9AA4C /* catch_decomposer.cpp */; }; + 2621EE561F602F8300D9AA4C /* catch_errno_guard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE271F602F8200D9AA4C /* catch_errno_guard.cpp */; }; + 2621EE571F602F8300D9AA4C /* catch_exception_translator_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE281F602F8200D9AA4C /* catch_exception_translator_registry.cpp */; }; + 2621EE581F602F8300D9AA4C /* catch_fatal_condition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE291F602F8200D9AA4C /* catch_fatal_condition.cpp */; }; + 2621EE591F602F8300D9AA4C /* catch_interfaces_reporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2A1F602F8200D9AA4C /* catch_interfaces_reporter.cpp */; }; + 2621EE5A1F602F8300D9AA4C /* catch_leak_detector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2B1F602F8300D9AA4C /* catch_leak_detector.cpp */; }; + 2621EE5B1F602F8300D9AA4C /* catch_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2C1F602F8300D9AA4C /* catch_list.cpp */; }; + 2621EE5C1F602F8300D9AA4C /* catch_matchers_string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2D1F602F8300D9AA4C /* catch_matchers_string.cpp */; }; + 2621EE5D1F602F8300D9AA4C /* catch_matchers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2E1F602F8300D9AA4C /* catch_matchers.cpp */; }; + 2621EE5E1F602F8300D9AA4C /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2F1F602F8300D9AA4C /* catch_message.cpp */; }; + 2621EE5F1F602F8300D9AA4C /* catch_random_number_generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE301F602F8300D9AA4C /* catch_random_number_generator.cpp */; }; + 2621EE601F602F8300D9AA4C /* catch_registry_hub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE311F602F8300D9AA4C /* catch_registry_hub.cpp */; }; + 2621EE611F602F8300D9AA4C /* catch_result_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE321F602F8300D9AA4C /* catch_result_type.cpp */; }; + 2621EE621F602F8300D9AA4C /* catch_run_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE331F602F8300D9AA4C /* catch_run_context.cpp */; }; + 2621EE631F602F8300D9AA4C /* catch_section_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE341F602F8300D9AA4C /* catch_section_info.cpp */; }; + 2621EE641F602F8300D9AA4C /* catch_section.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE351F602F8300D9AA4C /* catch_section.cpp */; }; + 2621EE651F602F8300D9AA4C /* catch_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE361F602F8300D9AA4C /* catch_session.cpp */; }; + 2621EE661F602F8300D9AA4C /* catch_startup_exception_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE371F602F8300D9AA4C /* catch_startup_exception_registry.cpp */; }; + 2621EE671F602F8300D9AA4C /* catch_stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE381F602F8300D9AA4C /* catch_stream.cpp */; }; + 2621EE681F602F8300D9AA4C /* catch_string_manip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE391F602F8300D9AA4C /* catch_string_manip.cpp */; }; + 2621EE691F602F8300D9AA4C /* catch_stringref.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3A1F602F8300D9AA4C /* catch_stringref.cpp */; }; + 2621EE6A1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3B1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp */; }; + 2621EE6B1F602F8300D9AA4C /* catch_tag_alias_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3C1F602F8300D9AA4C /* catch_tag_alias_registry.cpp */; }; + 2621EE6C1F602F8300D9AA4C /* catch_tag_alias.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3D1F602F8300D9AA4C /* catch_tag_alias.cpp */; }; + 2621EE6D1F602F8300D9AA4C /* catch_test_case_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3E1F602F8300D9AA4C /* catch_test_case_info.cpp */; }; + 2621EE6E1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3F1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp */; }; + 2621EE6F1F602F8300D9AA4C /* catch_test_case_tracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE401F602F8300D9AA4C /* catch_test_case_tracker.cpp */; }; + 2621EE701F602F8300D9AA4C /* catch_test_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE411F602F8300D9AA4C /* catch_test_registry.cpp */; }; + 2621EE711F602F8300D9AA4C /* catch_test_spec_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE421F602F8300D9AA4C /* catch_test_spec_parser.cpp */; }; + 2621EE721F602F8300D9AA4C /* catch_test_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE431F602F8300D9AA4C /* catch_test_spec.cpp */; }; + 2621EE731F602F8300D9AA4C /* catch_timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE441F602F8300D9AA4C /* catch_timer.cpp */; }; + 2621EE741F602F8300D9AA4C /* catch_tostring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE451F602F8300D9AA4C /* catch_tostring.cpp */; }; + 2621EE751F602F8300D9AA4C /* catch_totals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE461F602F8300D9AA4C /* catch_totals.cpp */; }; + 2621EE761F602F8300D9AA4C /* catch_version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE471F602F8300D9AA4C /* catch_version.cpp */; }; + 2621EE771F602F8300D9AA4C /* catch_wildcard_pattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE481F602F8300D9AA4C /* catch_wildcard_pattern.cpp */; }; + 2621EE781F602F8300D9AA4C /* catch_xmlwriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE491F602F8300D9AA4C /* catch_xmlwriter.cpp */; }; + 2621EE7F1F60360800D9AA4C /* catch_reporter_bases.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE791F60360800D9AA4C /* catch_reporter_bases.cpp */; }; + 2621EE801F60360800D9AA4C /* catch_reporter_compact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7A1F60360800D9AA4C /* catch_reporter_compact.cpp */; }; + 2621EE811F60360800D9AA4C /* catch_reporter_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7B1F60360800D9AA4C /* catch_reporter_console.cpp */; }; + 2621EE821F60360800D9AA4C /* catch_reporter_junit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */; }; + 2621EE831F60360800D9AA4C /* catch_reporter_multi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */; }; + 2621EE841F60360800D9AA4C /* catch_reporter_xml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */; }; + 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A63D2AB14E3C1A900F615CB /* OCTest.1 */; }; + 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2B214E3C1E600F615CB /* Main.mm */; }; + 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A63D2BF14E4544700F615CB /* Foundation.framework */; }; + 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */; }; + 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C314E454CC00F615CB /* OCTest.mm */; }; + 4A63D2C814E454CC00F615CB /* TestObj.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2C514E454CC00F615CB /* TestObj.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 4A63D2A314E3C1A900F615CB /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2621EE191F602F2C00D9AA4C /* catch_approx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_approx.cpp; path = ../../../include/internal/catch_approx.cpp; sourceTree = ""; }; + 2621EE1B1F602F8200D9AA4C /* catch_assertionhandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_assertionhandler.cpp; path = ../../../include/internal/catch_assertionhandler.cpp; sourceTree = ""; }; + 2621EE1C1F602F8200D9AA4C /* catch_assertionresult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_assertionresult.cpp; path = ../../../include/internal/catch_assertionresult.cpp; sourceTree = ""; }; + 2621EE1D1F602F8200D9AA4C /* catch_benchmark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_benchmark.cpp; path = ../../../include/internal/catch_benchmark.cpp; sourceTree = ""; }; + 2621EE1E1F602F8200D9AA4C /* catch_capture_matchers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_capture_matchers.cpp; path = ../../../include/internal/catch_capture_matchers.cpp; sourceTree = ""; }; + 2621EE1F1F602F8200D9AA4C /* catch_commandline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_commandline.cpp; path = ../../../include/internal/catch_commandline.cpp; sourceTree = ""; }; + 2621EE201F602F8200D9AA4C /* catch_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_common.cpp; path = ../../../include/internal/catch_common.cpp; sourceTree = ""; }; + 2621EE211F602F8200D9AA4C /* catch_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_config.cpp; path = ../../../include/internal/catch_config.cpp; sourceTree = ""; }; + 2621EE221F602F8200D9AA4C /* catch_console_colour.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_console_colour.cpp; path = ../../../include/internal/catch_console_colour.cpp; sourceTree = ""; }; + 2621EE231F602F8200D9AA4C /* catch_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_context.cpp; path = ../../../include/internal/catch_context.cpp; sourceTree = ""; }; + 2621EE241F602F8200D9AA4C /* catch_debug_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_debug_console.cpp; path = ../../../include/internal/catch_debug_console.cpp; sourceTree = ""; }; + 2621EE251F602F8200D9AA4C /* catch_debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_debugger.cpp; path = ../../../include/internal/catch_debugger.cpp; sourceTree = ""; }; + 2621EE261F602F8200D9AA4C /* catch_decomposer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_decomposer.cpp; path = ../../../include/internal/catch_decomposer.cpp; sourceTree = ""; }; + 2621EE271F602F8200D9AA4C /* catch_errno_guard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_errno_guard.cpp; path = ../../../include/internal/catch_errno_guard.cpp; sourceTree = ""; }; + 2621EE281F602F8200D9AA4C /* catch_exception_translator_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_exception_translator_registry.cpp; path = ../../../include/internal/catch_exception_translator_registry.cpp; sourceTree = ""; }; + 2621EE291F602F8200D9AA4C /* catch_fatal_condition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_fatal_condition.cpp; path = ../../../include/internal/catch_fatal_condition.cpp; sourceTree = ""; }; + 2621EE2A1F602F8200D9AA4C /* catch_interfaces_reporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_reporter.cpp; path = ../../../include/internal/catch_interfaces_reporter.cpp; sourceTree = ""; }; + 2621EE2B1F602F8300D9AA4C /* catch_leak_detector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_leak_detector.cpp; path = ../../../include/internal/catch_leak_detector.cpp; sourceTree = ""; }; + 2621EE2C1F602F8300D9AA4C /* catch_list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_list.cpp; path = ../../../include/internal/catch_list.cpp; sourceTree = ""; }; + 2621EE2D1F602F8300D9AA4C /* catch_matchers_string.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_matchers_string.cpp; path = ../../../include/internal/catch_matchers_string.cpp; sourceTree = ""; }; + 2621EE2E1F602F8300D9AA4C /* catch_matchers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_matchers.cpp; path = ../../../include/internal/catch_matchers.cpp; sourceTree = ""; }; + 2621EE2F1F602F8300D9AA4C /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../include/internal/catch_message.cpp; sourceTree = ""; }; + 2621EE301F602F8300D9AA4C /* catch_random_number_generator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_random_number_generator.cpp; path = ../../../include/internal/catch_random_number_generator.cpp; sourceTree = ""; }; + 2621EE311F602F8300D9AA4C /* catch_registry_hub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_registry_hub.cpp; path = ../../../include/internal/catch_registry_hub.cpp; sourceTree = ""; }; + 2621EE321F602F8300D9AA4C /* catch_result_type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_result_type.cpp; path = ../../../include/internal/catch_result_type.cpp; sourceTree = ""; }; + 2621EE331F602F8300D9AA4C /* catch_run_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_run_context.cpp; path = ../../../include/internal/catch_run_context.cpp; sourceTree = ""; }; + 2621EE341F602F8300D9AA4C /* catch_section_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_section_info.cpp; path = ../../../include/internal/catch_section_info.cpp; sourceTree = ""; }; + 2621EE351F602F8300D9AA4C /* catch_section.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_section.cpp; path = ../../../include/internal/catch_section.cpp; sourceTree = ""; }; + 2621EE361F602F8300D9AA4C /* catch_session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_session.cpp; path = ../../../include/internal/catch_session.cpp; sourceTree = ""; }; + 2621EE371F602F8300D9AA4C /* catch_startup_exception_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_startup_exception_registry.cpp; path = ../../../include/internal/catch_startup_exception_registry.cpp; sourceTree = ""; }; + 2621EE381F602F8300D9AA4C /* catch_stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_stream.cpp; path = ../../../include/internal/catch_stream.cpp; sourceTree = ""; }; + 2621EE391F602F8300D9AA4C /* catch_string_manip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_string_manip.cpp; path = ../../../include/internal/catch_string_manip.cpp; sourceTree = ""; }; + 2621EE3A1F602F8300D9AA4C /* catch_stringref.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_stringref.cpp; path = ../../../include/internal/catch_stringref.cpp; sourceTree = ""; }; + 2621EE3B1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tag_alias_autoregistrar.cpp; path = ../../../include/internal/catch_tag_alias_autoregistrar.cpp; sourceTree = ""; }; + 2621EE3C1F602F8300D9AA4C /* catch_tag_alias_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tag_alias_registry.cpp; path = ../../../include/internal/catch_tag_alias_registry.cpp; sourceTree = ""; }; + 2621EE3D1F602F8300D9AA4C /* catch_tag_alias.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tag_alias.cpp; path = ../../../include/internal/catch_tag_alias.cpp; sourceTree = ""; }; + 2621EE3E1F602F8300D9AA4C /* catch_test_case_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_case_info.cpp; path = ../../../include/internal/catch_test_case_info.cpp; sourceTree = ""; }; + 2621EE3F1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_case_registry_impl.cpp; path = ../../../include/internal/catch_test_case_registry_impl.cpp; sourceTree = ""; }; + 2621EE401F602F8300D9AA4C /* catch_test_case_tracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_case_tracker.cpp; path = ../../../include/internal/catch_test_case_tracker.cpp; sourceTree = ""; }; + 2621EE411F602F8300D9AA4C /* catch_test_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_registry.cpp; path = ../../../include/internal/catch_test_registry.cpp; sourceTree = ""; }; + 2621EE421F602F8300D9AA4C /* catch_test_spec_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_spec_parser.cpp; path = ../../../include/internal/catch_test_spec_parser.cpp; sourceTree = ""; }; + 2621EE431F602F8300D9AA4C /* catch_test_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_spec.cpp; path = ../../../include/internal/catch_test_spec.cpp; sourceTree = ""; }; + 2621EE441F602F8300D9AA4C /* catch_timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_timer.cpp; path = ../../../include/internal/catch_timer.cpp; sourceTree = ""; }; + 2621EE451F602F8300D9AA4C /* catch_tostring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tostring.cpp; path = ../../../include/internal/catch_tostring.cpp; sourceTree = ""; }; + 2621EE461F602F8300D9AA4C /* catch_totals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_totals.cpp; path = ../../../include/internal/catch_totals.cpp; sourceTree = ""; }; + 2621EE471F602F8300D9AA4C /* catch_version.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_version.cpp; path = ../../../include/internal/catch_version.cpp; sourceTree = ""; }; + 2621EE481F602F8300D9AA4C /* catch_wildcard_pattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_wildcard_pattern.cpp; path = ../../../include/internal/catch_wildcard_pattern.cpp; sourceTree = ""; }; + 2621EE491F602F8300D9AA4C /* catch_xmlwriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_xmlwriter.cpp; path = ../../../include/internal/catch_xmlwriter.cpp; sourceTree = ""; }; + 2621EE791F60360800D9AA4C /* catch_reporter_bases.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_bases.cpp; path = ../../../include/reporters/catch_reporter_bases.cpp; sourceTree = ""; }; + 2621EE7A1F60360800D9AA4C /* catch_reporter_compact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_compact.cpp; path = ../../../include/reporters/catch_reporter_compact.cpp; sourceTree = ""; }; + 2621EE7B1F60360800D9AA4C /* catch_reporter_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_console.cpp; path = ../../../include/reporters/catch_reporter_console.cpp; sourceTree = ""; }; + 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_junit.cpp; path = ../../../include/reporters/catch_reporter_junit.cpp; sourceTree = ""; }; + 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_multi.cpp; path = ../../../include/reporters/catch_reporter_multi.cpp; sourceTree = ""; }; + 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_xml.cpp; path = ../../../include/reporters/catch_reporter_xml.cpp; sourceTree = ""; }; + 4A63D2A514E3C1A900F615CB /* OCTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OCTest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A63D2AB14E3C1A900F615CB /* OCTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = OCTest.1; sourceTree = ""; }; + 4A63D2B214E3C1E600F615CB /* Main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Main.mm; sourceTree = ""; }; + 4A63D2BF14E4544700F615CB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CatchOCTestCase.h; sourceTree = ""; }; + 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CatchOCTestCase.mm; sourceTree = ""; }; + 4A63D2C314E454CC00F615CB /* OCTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCTest.mm; sourceTree = ""; }; + 4A63D2C414E454CC00F615CB /* TestObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObj.h; sourceTree = ""; }; + 4A63D2C514E454CC00F615CB /* TestObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObj.m; sourceTree = ""; }; + 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc.hpp; path = ../../../include/internal/catch_objc.hpp; sourceTree = ""; }; + 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc_arc.hpp; path = ../../../include/internal/catch_objc_arc.hpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4A63D2A214E3C1A900F615CB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4A63D29A14E3C1A900F615CB = { + isa = PBXGroup; + children = ( + 4AA0D94F154C0A63004B4193 /* Catch */, + 4A63D2BF14E4544700F615CB /* Foundation.framework */, + 4A63D2A814E3C1A900F615CB /* OCTest */, + 4A63D2A614E3C1A900F615CB /* Products */, + ); + sourceTree = ""; + }; + 4A63D2A614E3C1A900F615CB /* Products */ = { + isa = PBXGroup; + children = ( + 4A63D2A514E3C1A900F615CB /* OCTest */, + ); + name = Products; + sourceTree = ""; + }; + 4A63D2A814E3C1A900F615CB /* OCTest */ = { + isa = PBXGroup; + children = ( + 4A63D2C114E454CC00F615CB /* CatchOCTestCase.h */, + 4A63D2C214E454CC00F615CB /* CatchOCTestCase.mm */, + 4A63D2C314E454CC00F615CB /* OCTest.mm */, + 4A63D2C414E454CC00F615CB /* TestObj.h */, + 4A63D2C514E454CC00F615CB /* TestObj.m */, + 4A63D2B214E3C1E600F615CB /* Main.mm */, + 4A63D2AB14E3C1A900F615CB /* OCTest.1 */, + ); + path = OCTest; + sourceTree = ""; + }; + 4AA0D94F154C0A63004B4193 /* Catch */ = { + isa = PBXGroup; + children = ( + 2621EE791F60360800D9AA4C /* catch_reporter_bases.cpp */, + 2621EE7A1F60360800D9AA4C /* catch_reporter_compact.cpp */, + 2621EE7B1F60360800D9AA4C /* catch_reporter_console.cpp */, + 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */, + 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */, + 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */, + 2621EE1B1F602F8200D9AA4C /* catch_assertionhandler.cpp */, + 2621EE1C1F602F8200D9AA4C /* catch_assertionresult.cpp */, + 2621EE1D1F602F8200D9AA4C /* catch_benchmark.cpp */, + 2621EE1E1F602F8200D9AA4C /* catch_capture_matchers.cpp */, + 2621EE1F1F602F8200D9AA4C /* catch_commandline.cpp */, + 2621EE201F602F8200D9AA4C /* catch_common.cpp */, + 2621EE211F602F8200D9AA4C /* catch_config.cpp */, + 2621EE221F602F8200D9AA4C /* catch_console_colour.cpp */, + 2621EE231F602F8200D9AA4C /* catch_context.cpp */, + 2621EE241F602F8200D9AA4C /* catch_debug_console.cpp */, + 2621EE251F602F8200D9AA4C /* catch_debugger.cpp */, + 2621EE261F602F8200D9AA4C /* catch_decomposer.cpp */, + 2621EE271F602F8200D9AA4C /* catch_errno_guard.cpp */, + 2621EE281F602F8200D9AA4C /* catch_exception_translator_registry.cpp */, + 2621EE291F602F8200D9AA4C /* catch_fatal_condition.cpp */, + 2621EE2A1F602F8200D9AA4C /* catch_interfaces_reporter.cpp */, + 2621EE2B1F602F8300D9AA4C /* catch_leak_detector.cpp */, + 2621EE2C1F602F8300D9AA4C /* catch_list.cpp */, + 2621EE2D1F602F8300D9AA4C /* catch_matchers_string.cpp */, + 2621EE2E1F602F8300D9AA4C /* catch_matchers.cpp */, + 2621EE2F1F602F8300D9AA4C /* catch_message.cpp */, + 2621EE301F602F8300D9AA4C /* catch_random_number_generator.cpp */, + 2621EE311F602F8300D9AA4C /* catch_registry_hub.cpp */, + 2621EE321F602F8300D9AA4C /* catch_result_type.cpp */, + 2621EE331F602F8300D9AA4C /* catch_run_context.cpp */, + 2621EE341F602F8300D9AA4C /* catch_section_info.cpp */, + 2621EE351F602F8300D9AA4C /* catch_section.cpp */, + 2621EE361F602F8300D9AA4C /* catch_session.cpp */, + 2621EE371F602F8300D9AA4C /* catch_startup_exception_registry.cpp */, + 2621EE381F602F8300D9AA4C /* catch_stream.cpp */, + 2621EE391F602F8300D9AA4C /* catch_string_manip.cpp */, + 2621EE3A1F602F8300D9AA4C /* catch_stringref.cpp */, + 2621EE3B1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp */, + 2621EE3C1F602F8300D9AA4C /* catch_tag_alias_registry.cpp */, + 2621EE3D1F602F8300D9AA4C /* catch_tag_alias.cpp */, + 2621EE3E1F602F8300D9AA4C /* catch_test_case_info.cpp */, + 2621EE3F1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp */, + 2621EE401F602F8300D9AA4C /* catch_test_case_tracker.cpp */, + 2621EE411F602F8300D9AA4C /* catch_test_registry.cpp */, + 2621EE421F602F8300D9AA4C /* catch_test_spec_parser.cpp */, + 2621EE431F602F8300D9AA4C /* catch_test_spec.cpp */, + 2621EE441F602F8300D9AA4C /* catch_timer.cpp */, + 2621EE451F602F8300D9AA4C /* catch_tostring.cpp */, + 2621EE461F602F8300D9AA4C /* catch_totals.cpp */, + 2621EE471F602F8300D9AA4C /* catch_version.cpp */, + 2621EE481F602F8300D9AA4C /* catch_wildcard_pattern.cpp */, + 2621EE491F602F8300D9AA4C /* catch_xmlwriter.cpp */, + 2621EE191F602F2C00D9AA4C /* catch_approx.cpp */, + 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */, + 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */, + ); + name = Catch; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4A63D2A414E3C1A900F615CB /* OCTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */; + buildPhases = ( + 4A63D2A114E3C1A900F615CB /* Sources */, + 4A63D2A214E3C1A900F615CB /* Frameworks */, + 4A63D2A314E3C1A900F615CB /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OCTest; + productName = OCTest; + productReference = 4A63D2A514E3C1A900F615CB /* OCTest */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4A63D29C14E3C1A900F615CB /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + }; + buildConfigurationList = 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 4A63D29A14E3C1A900F615CB; + productRefGroup = 4A63D2A614E3C1A900F615CB /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4A63D2A414E3C1A900F615CB /* OCTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 4A63D2A114E3C1A900F615CB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2621EE841F60360800D9AA4C /* catch_reporter_xml.cpp in Sources */, + 2621EE561F602F8300D9AA4C /* catch_errno_guard.cpp in Sources */, + 2621EE4F1F602F8300D9AA4C /* catch_common.cpp in Sources */, + 2621EE731F602F8300D9AA4C /* catch_timer.cpp in Sources */, + 2621EE6E1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp in Sources */, + 2621EE6F1F602F8300D9AA4C /* catch_test_case_tracker.cpp in Sources */, + 2621EE6D1F602F8300D9AA4C /* catch_test_case_info.cpp in Sources */, + 2621EE5A1F602F8300D9AA4C /* catch_leak_detector.cpp in Sources */, + 2621EE501F602F8300D9AA4C /* catch_config.cpp in Sources */, + 2621EE6A1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp in Sources */, + 2621EE751F602F8300D9AA4C /* catch_totals.cpp in Sources */, + 2621EE801F60360800D9AA4C /* catch_reporter_compact.cpp in Sources */, + 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */, + 2621EE711F602F8300D9AA4C /* catch_test_spec_parser.cpp in Sources */, + 2621EE5F1F602F8300D9AA4C /* catch_random_number_generator.cpp in Sources */, + 2621EE531F602F8300D9AA4C /* catch_debug_console.cpp in Sources */, + 2621EE821F60360800D9AA4C /* catch_reporter_junit.cpp in Sources */, + 2621EE4C1F602F8300D9AA4C /* catch_benchmark.cpp in Sources */, + 2621EE5B1F602F8300D9AA4C /* catch_list.cpp in Sources */, + 2621EE581F602F8300D9AA4C /* catch_fatal_condition.cpp in Sources */, + 2621EE5D1F602F8300D9AA4C /* catch_matchers.cpp in Sources */, + 2621EE7F1F60360800D9AA4C /* catch_reporter_bases.cpp in Sources */, + 2621EE591F602F8300D9AA4C /* catch_interfaces_reporter.cpp in Sources */, + 2621EE611F602F8300D9AA4C /* catch_result_type.cpp in Sources */, + 2621EE781F602F8300D9AA4C /* catch_xmlwriter.cpp in Sources */, + 2621EE601F602F8300D9AA4C /* catch_registry_hub.cpp in Sources */, + 2621EE5E1F602F8300D9AA4C /* catch_message.cpp in Sources */, + 2621EE4B1F602F8300D9AA4C /* catch_assertionresult.cpp in Sources */, + 2621EE4D1F602F8300D9AA4C /* catch_capture_matchers.cpp in Sources */, + 2621EE761F602F8300D9AA4C /* catch_version.cpp in Sources */, + 2621EE721F602F8300D9AA4C /* catch_test_spec.cpp in Sources */, + 2621EE621F602F8300D9AA4C /* catch_run_context.cpp in Sources */, + 2621EE6C1F602F8300D9AA4C /* catch_tag_alias.cpp in Sources */, + 2621EE1A1F602F2C00D9AA4C /* catch_approx.cpp in Sources */, + 2621EE511F602F8300D9AA4C /* catch_console_colour.cpp in Sources */, + 2621EE771F602F8300D9AA4C /* catch_wildcard_pattern.cpp in Sources */, + 2621EE811F60360800D9AA4C /* catch_reporter_console.cpp in Sources */, + 2621EE691F602F8300D9AA4C /* catch_stringref.cpp in Sources */, + 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */, + 2621EE831F60360800D9AA4C /* catch_reporter_multi.cpp in Sources */, + 2621EE541F602F8300D9AA4C /* catch_debugger.cpp in Sources */, + 2621EE741F602F8300D9AA4C /* catch_tostring.cpp in Sources */, + 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */, + 2621EE5C1F602F8300D9AA4C /* catch_matchers_string.cpp in Sources */, + 2621EE4E1F602F8300D9AA4C /* catch_commandline.cpp in Sources */, + 2621EE651F602F8300D9AA4C /* catch_session.cpp in Sources */, + 2621EE661F602F8300D9AA4C /* catch_startup_exception_registry.cpp in Sources */, + 2621EE641F602F8300D9AA4C /* catch_section.cpp in Sources */, + 2621EE701F602F8300D9AA4C /* catch_test_registry.cpp in Sources */, + 2621EE681F602F8300D9AA4C /* catch_string_manip.cpp in Sources */, + 4A63D2C814E454CC00F615CB /* TestObj.m in Sources */, + 2621EE671F602F8300D9AA4C /* catch_stream.cpp in Sources */, + 2621EE551F602F8300D9AA4C /* catch_decomposer.cpp in Sources */, + 2621EE4A1F602F8300D9AA4C /* catch_assertionhandler.cpp in Sources */, + 2621EE631F602F8300D9AA4C /* catch_section_info.cpp in Sources */, + 2621EE521F602F8300D9AA4C /* catch_context.cpp in Sources */, + 2621EE571F602F8300D9AA4C /* catch_exception_translator_registry.cpp in Sources */, + 2621EE6B1F602F8300D9AA4C /* catch_tag_alias_registry.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 4A63D2AD14E3C1A900F615CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../../include; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 4A63D2AE14E3C1A900F615CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ../../../include; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 4A63D2B014E3C1A900F615CB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + HEADER_SEARCH_PATHS = ../../../include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 4A63D2B114E3C1A900F615CB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + HEADER_SEARCH_PATHS = ../../../include; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4A63D29F14E3C1A900F615CB /* Build configuration list for PBXProject "OCTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A63D2AD14E3C1A900F615CB /* Debug */, + 4A63D2AE14E3C1A900F615CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4A63D2AF14E3C1A900F615CB /* Build configuration list for PBXNativeTarget "OCTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4A63D2B014E3C1A900F615CB /* Debug */, + 4A63D2B114E3C1A900F615CB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 4A63D29C14E3C1A900F615CB /* Project object */; +} diff --git a/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..119e61c5 --- /dev/null +++ b/projects/XCode/OCTest/OCTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/projects/XCode/OCTest/OCTest/CatchOCTestCase.h b/projects/XCode/OCTest/OCTest/CatchOCTestCase.h new file mode 100644 index 00000000..bd26239a --- /dev/null +++ b/projects/XCode/OCTest/OCTest/CatchOCTestCase.h @@ -0,0 +1,25 @@ +// +// CatchOCTestCase.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 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) +#ifndef TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED +#define TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED + +#include "catch.hpp" + +#import +#import "TestObj.h" + +@interface TestFixture : NSObject +{ + TestObj* obj; +} + +@end + +#endif // TWOBLUECUBES_CATCHOCTESTCASE_H_INCLUDED diff --git a/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm b/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm new file mode 100644 index 00000000..9bd1fa09 --- /dev/null +++ b/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm @@ -0,0 +1,87 @@ +// +// CatchOCTestCase.mm +// OCTest +// +// Created by Phil Nash on 13/11/2010. +// Copyright 2010 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) + +#import "CatchOCTestCase.h" + + +@implementation TestFixture + + +-(void) setUp +{ + obj = [[TestObj alloc] init]; +} + +-(void) tearDown +{ + arcSafeRelease( obj ); +} + +OC_TEST_CASE( "This is a test case", "" ) +{ + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); +} + +OC_TEST_CASE( "This is another test case", "" ) +{ + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 2; + + REQUIRE( obj.int_val == 2 ); +} + +OC_TEST_CASE( "tests a boolean value", "[!shouldfail]" ) +{ + CHECK( [obj isTrue] == NO ); + CHECK( [obj isFalse] == YES ); +} + +OC_TEST_CASE( "throws an Objective-C exception", "[!throws][!shouldfail]" ) +{ + @throw [[NSException alloc] initWithName: NSGenericException + reason: @"Objective-C exception" + userInfo: nil]; +} +OC_TEST_CASE( "throws a std c++ exception", "[!throws][!shouldfail]" ) +{ + throw std::domain_error( "std C++ exception" ); +} + +/////////////////////////////////////////////////////////////////////////// +template +void useObject( const T& object ){} + +template +void useObject( const T* object ){} + +OC_TEST_CASE( "Matches work with OC types (NSString so far)", "[!shouldfail]" ) +{ + using namespace Catch::Matchers; + + REQUIRE_THAT( @"This is a string", Equals( @"This isnt a string" ) ); + REQUIRE_THAT( @"This is a string", Contains( @"is a" ) ); + REQUIRE_THAT( @"This is a string", StartsWith( @"This" ) ); + REQUIRE_THAT( @"This is a string", EndsWith( @"string" ) ); +} + +OC_TEST_CASE( "nil NSString should not crash the test", "[!shouldfail]" ) +{ + using namespace Catch::Matchers; + + CHECK_THAT( (NSString*)nil, Equals( @"This should fail, but not crash" ) ); + CHECK_THAT( (NSString*)nil, StartsWith( @"anything" ) ); +} + +@end diff --git a/projects/XCode/OCTest/OCTest/Main.mm b/projects/XCode/OCTest/OCTest/Main.mm new file mode 100644 index 00000000..569dc4d9 --- /dev/null +++ b/projects/XCode/OCTest/OCTest/Main.mm @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#import "catch.hpp" diff --git a/projects/XCode/OCTest/OCTest/OCTest.1 b/projects/XCode/OCTest/OCTest/OCTest.1 new file mode 100644 index 00000000..38afeb5f --- /dev/null +++ b/projects/XCode/OCTest/OCTest/OCTest.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 09/02/2012 \" DATE +.Dt OCTest 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm OCTest, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/projects/XCode/OCTest/OCTest/OCTest.mm b/projects/XCode/OCTest/OCTest/OCTest.mm new file mode 100644 index 00000000..fa3ffea6 --- /dev/null +++ b/projects/XCode/OCTest/OCTest/OCTest.mm @@ -0,0 +1,28 @@ +/* + * OCTest.mm + * OCTest + * + * Created by Phil on 13/11/2010. + * Copyright 2010 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) + * + */ + +#import "catch.hpp" + +#import "TestObj.h" + +TEST_CASE( "OCTest/TestObj", "tests TestObj" ) +{ + TestObj* obj = [[TestObj alloc] init]; + + REQUIRE( obj.int_val == 0 ); + + obj.int_val = 1; + + REQUIRE( obj.int_val == 1 ); + + arcSafeRelease( obj ); +} diff --git a/projects/XCode/OCTest/OCTest/TestObj.h b/projects/XCode/OCTest/OCTest/TestObj.h new file mode 100644 index 00000000..8443921f --- /dev/null +++ b/projects/XCode/OCTest/OCTest/TestObj.h @@ -0,0 +1,28 @@ +// +// TestObj.h +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 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) +#ifndef TWOBLUECUBES_TESTOBJ_H_INCLUDED +#define TWOBLUECUBES_TESTOBJ_H_INCLUDED + +#import + + +@interface TestObj : NSObject { + + int int_val; +} + +-(BOOL) isTrue; +-(BOOL) isFalse; + +@property (nonatomic, assign ) int int_val; + +@end + +#endif // TWOBLUECUBES_TESTOBJ_H_INCLUDED diff --git a/projects/XCode/OCTest/OCTest/TestObj.m b/projects/XCode/OCTest/OCTest/TestObj.m new file mode 100644 index 00000000..2c7dc99b --- /dev/null +++ b/projects/XCode/OCTest/OCTest/TestObj.m @@ -0,0 +1,25 @@ +// +// TestObj.m +// OCTest +// +// Created by Phil on 13/11/2010. +// Copyright 2010 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) + +#import "TestObj.h" + + +@implementation TestObj + +@synthesize int_val; + +-(BOOL) isTrue { + return YES; +} +-(BOOL) isFalse { + return NO; +} + +@end From 8c39f9a725b527c8b5d04317dea92a58ae6d9c25 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 7 Sep 2017 11:15:07 +0100 Subject: [PATCH 332/398] Suppress MSVC warning about meaningless function type qualifier in generic code --- include/internal/catch_decomposer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 48f87f60..5d4bb0d1 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -18,6 +18,7 @@ #pragma warning(disable:4389) // '==' : signed/unsigned mismatch #pragma warning(disable:4018) // more "signed/unsigned mismatch" #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#pragma warning(disable:4180) // qualifier applied to function type has no meaning #endif namespace Catch { From c5608f0202eb8ffd360e58db081fef248d675a6b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 7 Sep 2017 11:24:33 +0100 Subject: [PATCH 333/398] Changed all .hpp extensions to .h where there is now a corresponding .cpp --- include/catch.hpp | 4 ++-- include/internal/catch_approx.cpp | 2 +- include/internal/{catch_approx.hpp => catch_approx.h} | 0 include/internal/catch_capture_matchers.h | 2 +- include/internal/catch_commandline.cpp | 2 +- .../{catch_commandline.hpp => catch_commandline.h} | 0 include/internal/catch_config.hpp | 2 +- include/internal/catch_console_colour.cpp | 2 +- .../{catch_console_colour.hpp => catch_console_colour.h} | 0 include/internal/catch_external_interfaces.h | 2 +- include/internal/catch_impl.hpp | 4 ++-- include/internal/catch_interfaces_reporter.h | 2 +- include/internal/catch_list.cpp | 4 ++-- include/internal/catch_matchers.cpp | 2 +- include/internal/{catch_matchers.hpp => catch_matchers.h} | 0 include/internal/catch_matchers_string.h | 2 +- include/internal/catch_matchers_vector.h | 2 +- include/internal/catch_registry_hub.cpp | 2 +- include/internal/catch_run_context.cpp | 2 +- .../{catch_run_context.hpp => catch_run_context.h} | 8 ++++---- include/internal/catch_section.h | 2 +- include/internal/catch_section_info.h | 2 +- include/internal/catch_session.cpp | 8 ++++---- include/internal/catch_session.h | 2 +- include/internal/catch_tag_alias_registry.cpp | 2 +- include/internal/catch_test_case_info.cpp | 2 +- include/internal/catch_test_case_registry_impl.cpp | 2 +- ..._registry_impl.hpp => catch_test_case_registry_impl.h} | 4 ++-- include/internal/catch_test_case_tracker.cpp | 2 +- ...ch_test_case_tracker.hpp => catch_test_case_tracker.h} | 0 include/internal/catch_test_registry.cpp | 4 ++-- .../{catch_test_registry.hpp => catch_test_registry.h} | 0 include/internal/catch_test_spec.cpp | 2 +- .../internal/{catch_test_spec.hpp => catch_test_spec.h} | 2 +- include/internal/catch_test_spec_parser.cpp | 2 +- ...atch_test_spec_parser.hpp => catch_test_spec_parser.h} | 2 +- include/internal/catch_totals.cpp | 2 +- include/internal/{catch_totals.hpp => catch_totals.h} | 0 include/internal/catch_wildcard_pattern.cpp | 2 +- ...atch_wildcard_pattern.hpp => catch_wildcard_pattern.h} | 0 include/internal/catch_xmlwriter.cpp | 2 +- .../internal/{catch_xmlwriter.hpp => catch_xmlwriter.h} | 0 include/reporters/catch_reporter_compact.cpp | 2 +- include/reporters/catch_reporter_console.cpp | 2 +- include/reporters/catch_reporter_junit.cpp | 2 +- include/reporters/catch_reporter_xml.cpp | 2 +- projects/SelfTest/CmdLineTests.cpp | 2 +- projects/SelfTest/MiscTests.cpp | 2 +- projects/SelfTest/PartTrackerTests.cpp | 2 +- projects/SelfTest/SurrogateCpps/catch_console_colour.cpp | 2 +- .../SelfTest/SurrogateCpps/catch_test_case_tracker.cpp | 2 +- projects/SelfTest/SurrogateCpps/catch_test_spec.cpp | 2 +- projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp | 2 +- 53 files changed, 55 insertions(+), 55 deletions(-) rename include/internal/{catch_approx.hpp => catch_approx.h} (100%) rename include/internal/{catch_commandline.hpp => catch_commandline.h} (100%) rename include/internal/{catch_console_colour.hpp => catch_console_colour.h} (100%) rename include/internal/{catch_matchers.hpp => catch_matchers.h} (100%) rename include/internal/{catch_run_context.hpp => catch_run_context.h} (97%) rename include/internal/{catch_test_case_registry_impl.hpp => catch_test_case_registry_impl.h} (97%) rename include/internal/{catch_test_case_tracker.hpp => catch_test_case_tracker.h} (100%) rename include/internal/{catch_test_registry.hpp => catch_test_registry.h} (100%) rename include/internal/{catch_test_spec.hpp => catch_test_spec.h} (98%) rename include/internal/{catch_test_spec_parser.hpp => catch_test_spec_parser.h} (98%) rename include/internal/{catch_totals.hpp => catch_totals.h} (100%) rename include/internal/{catch_wildcard_pattern.hpp => catch_wildcard_pattern.h} (100%) rename include/internal/{catch_xmlwriter.hpp => catch_xmlwriter.h} (100%) diff --git a/include/catch.hpp b/include/catch.hpp index 61321400..118337c9 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -35,12 +35,12 @@ #endif #include "internal/catch_tag_alias_autoregistrar.h" -#include "internal/catch_test_registry.hpp" +#include "internal/catch_test_registry.h" #include "internal/catch_capture.hpp" #include "internal/catch_section.h" #include "internal/catch_benchmark.h" #include "internal/catch_interfaces_exception.h" -#include "internal/catch_approx.hpp" +#include "internal/catch_approx.h" #include "internal/catch_compiler_capabilities.h" #include "internal/catch_string_manip.h" diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp index 419a9cd6..51f4b243 100644 --- a/include/internal/catch_approx.cpp +++ b/include/internal/catch_approx.cpp @@ -6,7 +6,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_approx.hpp" +#include "catch_approx.h" #include diff --git a/include/internal/catch_approx.hpp b/include/internal/catch_approx.h similarity index 100% rename from include/internal/catch_approx.hpp rename to include/internal/catch_approx.h diff --git a/include/internal/catch_capture_matchers.h b/include/internal/catch_capture_matchers.h index 3520ad2e..701ba1f6 100644 --- a/include/internal/catch_capture_matchers.h +++ b/include/internal/catch_capture_matchers.h @@ -9,7 +9,7 @@ #define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED #include "catch_capture.hpp" -#include "catch_matchers.hpp" +#include "catch_matchers.h" #include "catch_matchers_string.h" #include "catch_matchers_vector.h" diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index 1410baa4..89329032 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -6,7 +6,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_commandline.hpp" +#include "catch_commandline.h" #include "catch_string_manip.h" diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.h similarity index 100% rename from include/internal/catch_commandline.hpp rename to include/internal/catch_commandline.h diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 80847be5..23e1d1ed 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED -#include "catch_test_spec_parser.hpp" +#include "catch_test_spec_parser.h" #include "catch_interfaces_config.h" // Libstdc++ doesn't like incomplete classes for unique_ptr diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index a444b076..e33b8828 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -6,7 +6,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_console_colour.hpp" +#include "catch_console_colour.h" #include "catch_enforce.h" #include "catch_errno_guard.h" #include "catch_interfaces_config.h" diff --git a/include/internal/catch_console_colour.hpp b/include/internal/catch_console_colour.h similarity index 100% rename from include/internal/catch_console_colour.hpp rename to include/internal/catch_console_colour.h diff --git a/include/internal/catch_external_interfaces.h b/include/internal/catch_external_interfaces.h index 4eb55256..7abc69fc 100644 --- a/include/internal/catch_external_interfaces.h +++ b/include/internal/catch_external_interfaces.h @@ -8,7 +8,7 @@ #define TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED #include "../reporters/catch_reporter_bases.hpp" -#include "catch_console_colour.hpp" +#include "catch_console_colour.h" #include "catch_reporter_registrars.hpp" #endif // TWOBLUECUBES_CATCH_EXTERNAL_INTERFACES_H_INCLUDED diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 5debe23c..ae512ce1 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -19,8 +19,8 @@ #include "internal/catch_leak_detector.h" -#include "catch_test_spec.hpp" -#include "catch_test_case_tracker.hpp" +#include "catch_test_spec.h" +#include "catch_test_case_tracker.h" // Cpp files will be included in the single-header file here // ~*~* CATCH_CPP_STITCH_PLACE *~*~ diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index be3044f9..d4fb9dbf 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -11,7 +11,7 @@ #include "catch_section_info.h" #include "catch_common.h" #include "catch_config.hpp" -#include "catch_totals.hpp" +#include "catch_totals.h" #include "catch_test_case_info.h" #include "catch_assertionresult.h" #include "catch_message.h" diff --git a/include/internal/catch_list.cpp b/include/internal/catch_list.cpp index 8f2f291a..4391c441 100644 --- a/include/internal/catch_list.cpp +++ b/include/internal/catch_list.cpp @@ -15,8 +15,8 @@ #include "catch_stream.h" #include "catch_text.h" -#include "catch_console_colour.hpp" -#include "catch_test_spec_parser.hpp" +#include "catch_console_colour.h" +#include "catch_test_spec_parser.h" #include "catch_tostring.h" #include "catch_string_manip.h" diff --git a/include/internal/catch_matchers.cpp b/include/internal/catch_matchers.cpp index 38ae8c77..8621114b 100644 --- a/include/internal/catch_matchers.cpp +++ b/include/internal/catch_matchers.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_matchers.hpp" +#include "catch_matchers.h" namespace Catch { namespace Matchers { diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.h similarity index 100% rename from include/internal/catch_matchers.hpp rename to include/internal/catch_matchers.h diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index eca35789..3306951b 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED -#include "catch_matchers.hpp" +#include "catch_matchers.h" #include diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 4bf39d70..85994fb0 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED -#include "catch_matchers.hpp" +#include "catch_matchers.h" namespace Catch { namespace Matchers { diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 7daa5572..74d92ec0 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -9,7 +9,7 @@ #include "catch_interfaces_registry_hub.h" #include "catch_context.h" -#include "catch_test_case_registry_impl.hpp" +#include "catch_test_case_registry_impl.h" #include "catch_reporter_registry.hpp" #include "catch_exception_translator_registry.h" #include "catch_tag_alias_registry.h" diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 7cb8f8dc..13054862 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -1,4 +1,4 @@ -#include "catch_run_context.hpp" +#include "catch_run_context.h" #include "catch_context.h" #include "catch_enforce.h" #include "catch_random_number_generator.h" diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.h similarity index 97% rename from include/internal/catch_run_context.hpp rename to include/internal/catch_run_context.h index 40e77d29..64314cb2 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.h @@ -12,12 +12,12 @@ #include "catch_interfaces_reporter.h" #include "catch_interfaces_exception.h" #include "catch_config.hpp" -#include "catch_test_registry.hpp" +#include "catch_test_registry.h" #include "catch_test_case_info.h" #include "catch_capture.hpp" -#include "catch_totals.hpp" -#include "catch_test_spec.hpp" -#include "catch_test_case_tracker.hpp" +#include "catch_totals.h" +#include "catch_test_spec.h" +#include "catch_test_case_tracker.h" #include "catch_timer.h" #include "catch_assertionhandler.h" #include "catch_fatal_condition.h" diff --git a/include/internal/catch_section.h b/include/internal/catch_section.h index e3b14564..1e5b1c3c 100644 --- a/include/internal/catch_section.h +++ b/include/internal/catch_section.h @@ -9,7 +9,7 @@ #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED #include "catch_section_info.h" -#include "catch_totals.hpp" +#include "catch_totals.h" #include "catch_timer.h" #include diff --git a/include/internal/catch_section_info.h b/include/internal/catch_section_info.h index a10b2b77..86681ba7 100644 --- a/include/internal/catch_section_info.h +++ b/include/internal/catch_section_info.h @@ -9,7 +9,7 @@ #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED #include "catch_common.h" -#include "catch_totals.hpp" +#include "catch_totals.h" #include diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp index 54c9d783..d799b9ea 100644 --- a/include/internal/catch_session.cpp +++ b/include/internal/catch_session.cpp @@ -6,13 +6,13 @@ */ #include "catch_session.h" -#include "catch_commandline.hpp" -#include "catch_console_colour.hpp" +#include "catch_commandline.h" +#include "catch_console_colour.h" #include "catch_enforce.h" #include "catch_list.h" -#include "catch_run_context.hpp" +#include "catch_run_context.h" #include "catch_stream.h" -#include "catch_test_spec.hpp" +#include "catch_test_spec.h" #include "catch_version.h" #include "catch_interfaces_reporter.h" #include "catch_random_number_generator.h" diff --git a/include/internal/catch_session.h b/include/internal/catch_session.h index 492d6d31..dca8a051 100644 --- a/include/internal/catch_session.h +++ b/include/internal/catch_session.h @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED -#include "catch_commandline.hpp" +#include "catch_commandline.h" #include "catch_config.hpp" #include "catch_text.h" diff --git a/include/internal/catch_tag_alias_registry.cpp b/include/internal/catch_tag_alias_registry.cpp index f100ea9d..cfc98f17 100644 --- a/include/internal/catch_tag_alias_registry.cpp +++ b/include/internal/catch_tag_alias_registry.cpp @@ -7,7 +7,7 @@ */ #include "catch_tag_alias_registry.h" -#include "catch_console_colour.hpp" +#include "catch_console_colour.h" #include "catch_enforce.h" #include "catch_interfaces_registry_hub.h" #include "catch_stream.h" diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index 54ecc2b6..f21b6ef6 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -8,7 +8,7 @@ #include "catch_test_case_info.h" #include "catch_enforce.h" -#include "catch_test_spec.hpp" +#include "catch_test_spec.h" #include "catch_interfaces_testcase.h" #include "catch_string_manip.h" diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp index 85385a9c..b9aae92c 100644 --- a/include/internal/catch_test_case_registry_impl.cpp +++ b/include/internal/catch_test_case_registry_impl.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_test_case_registry_impl.hpp" +#include "catch_test_case_registry_impl.h" #include "catch_context.h" #include "catch_enforce.h" diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.h similarity index 97% rename from include/internal/catch_test_case_registry_impl.hpp rename to include/internal/catch_test_case_registry_impl.h index f49ad970..77d4b9ee 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.h @@ -8,8 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED -#include "catch_test_registry.hpp" -#include "catch_test_spec.hpp" +#include "catch_test_registry.h" +#include "catch_test_spec.h" #include "catch_interfaces_config.h" #include diff --git a/include/internal/catch_test_case_tracker.cpp b/include/internal/catch_test_case_tracker.cpp index 6960c75f..fb3f8d44 100644 --- a/include/internal/catch_test_case_tracker.cpp +++ b/include/internal/catch_test_case_tracker.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_test_case_tracker.hpp" +#include "catch_test_case_tracker.h" #include "catch_enforce.h" diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.h similarity index 100% rename from include/internal/catch_test_case_tracker.hpp rename to include/internal/catch_test_case_tracker.h diff --git a/include/internal/catch_test_registry.cpp b/include/internal/catch_test_registry.cpp index 7a796cce..b1c07f2d 100644 --- a/include/internal/catch_test_registry.cpp +++ b/include/internal/catch_test_registry.cpp @@ -5,8 +5,8 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_test_registry.hpp" -#include "catch_test_case_registry_impl.hpp" +#include "catch_test_registry.h" +#include "catch_test_case_registry_impl.h" #include "catch_interfaces_registry_hub.h" namespace Catch { diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.h similarity index 100% rename from include/internal/catch_test_registry.hpp rename to include/internal/catch_test_registry.h diff --git a/include/internal/catch_test_spec.cpp b/include/internal/catch_test_spec.cpp index c7f64f30..a1055c20 100644 --- a/include/internal/catch_test_spec.cpp +++ b/include/internal/catch_test_spec.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_test_spec.hpp" +#include "catch_test_spec.h" #include "catch_string_manip.h" #include diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.h similarity index 98% rename from include/internal/catch_test_spec.hpp rename to include/internal/catch_test_spec.h index 8967c5a9..e9ef3a31 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.h @@ -13,7 +13,7 @@ #pragma clang diagnostic ignored "-Wpadded" #endif -#include "catch_wildcard_pattern.hpp" +#include "catch_wildcard_pattern.h" #include "catch_test_case_info.h" #include diff --git a/include/internal/catch_test_spec_parser.cpp b/include/internal/catch_test_spec_parser.cpp index fcfc44c9..61c9e4df 100644 --- a/include/internal/catch_test_spec_parser.cpp +++ b/include/internal/catch_test_spec_parser.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_test_spec_parser.hpp" +#include "catch_test_spec_parser.h" namespace Catch { diff --git a/include/internal/catch_test_spec_parser.hpp b/include/internal/catch_test_spec_parser.h similarity index 98% rename from include/internal/catch_test_spec_parser.hpp rename to include/internal/catch_test_spec_parser.h index 497253d2..87f7f31f 100644 --- a/include/internal/catch_test_spec_parser.hpp +++ b/include/internal/catch_test_spec_parser.h @@ -13,7 +13,7 @@ #pragma clang diagnostic ignored "-Wpadded" #endif -#include "catch_test_spec.hpp" +#include "catch_test_spec.h" #include "catch_string_manip.h" #include "catch_interfaces_tag_alias_registry.h" diff --git a/include/internal/catch_totals.cpp b/include/internal/catch_totals.cpp index 3ddc6bab..0391fe82 100644 --- a/include/internal/catch_totals.cpp +++ b/include/internal/catch_totals.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_totals.hpp" +#include "catch_totals.h" namespace Catch { diff --git a/include/internal/catch_totals.hpp b/include/internal/catch_totals.h similarity index 100% rename from include/internal/catch_totals.hpp rename to include/internal/catch_totals.h diff --git a/include/internal/catch_wildcard_pattern.cpp b/include/internal/catch_wildcard_pattern.cpp index 106e49b4..f7303568 100644 --- a/include/internal/catch_wildcard_pattern.cpp +++ b/include/internal/catch_wildcard_pattern.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_wildcard_pattern.hpp" +#include "catch_wildcard_pattern.h" #include "catch_enforce.h" #include "catch_string_manip.h" diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.h similarity index 100% rename from include/internal/catch_wildcard_pattern.hpp rename to include/internal/catch_wildcard_pattern.h diff --git a/include/internal/catch_xmlwriter.cpp b/include/internal/catch_xmlwriter.cpp index acd9b282..a3316f46 100644 --- a/include/internal/catch_xmlwriter.cpp +++ b/include/internal/catch_xmlwriter.cpp @@ -5,7 +5,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#include "catch_xmlwriter.hpp" +#include "catch_xmlwriter.h" #include diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.h similarity index 100% rename from include/internal/catch_xmlwriter.hpp rename to include/internal/catch_xmlwriter.h diff --git a/include/reporters/catch_reporter_compact.cpp b/include/reporters/catch_reporter_compact.cpp index 80f3767d..74a09e4b 100644 --- a/include/reporters/catch_reporter_compact.cpp +++ b/include/reporters/catch_reporter_compact.cpp @@ -9,7 +9,7 @@ #include "catch_reporter_bases.hpp" #include "../internal/catch_reporter_registrars.hpp" -#include "../internal/catch_console_colour.hpp" +#include "internal/catch_console_colour.h" namespace { diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 63fad69a..a3662d9c 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -9,7 +9,7 @@ #include "catch_reporter_bases.hpp" #include "../internal/catch_reporter_registrars.hpp" -#include "../internal/catch_console_colour.hpp" +#include "internal/catch_console_colour.h" #include "../internal/catch_version.h" #include "../internal/catch_text.h" #include "../internal/catch_stringref.h" diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp index b40e9619..c0e2e3cf 100644 --- a/include/reporters/catch_reporter_junit.cpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -10,7 +10,7 @@ #include "../internal/catch_tostring.h" #include "../internal/catch_reporter_registrars.hpp" -#include "../internal/catch_xmlwriter.hpp" +#include "internal/catch_xmlwriter.h" #include "../internal/catch_timer.h" #include diff --git a/include/reporters/catch_reporter_xml.cpp b/include/reporters/catch_reporter_xml.cpp index 0033b310..abdfbce5 100644 --- a/include/reporters/catch_reporter_xml.cpp +++ b/include/reporters/catch_reporter_xml.cpp @@ -10,7 +10,7 @@ #include "../internal/catch_capture.hpp" #include "../internal/catch_reporter_registrars.hpp" -#include "../internal/catch_xmlwriter.hpp" +#include "internal/catch_xmlwriter.h" #include "../internal/catch_timer.h" namespace Catch { diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp index 50d4e9d5..c375d41b 100644 --- a/projects/SelfTest/CmdLineTests.cpp +++ b/projects/SelfTest/CmdLineTests.cpp @@ -7,7 +7,7 @@ */ #include "catch.hpp" -#include "internal/catch_test_spec_parser.hpp" +#include "internal/catch_test_spec_parser.h" #ifdef __clang__ # pragma clang diagnostic ignored "-Wc++98-compat" diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index e3a9318b..2151d77c 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -13,7 +13,7 @@ # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #endif -#include "../include/internal/catch_xmlwriter.hpp" +#include "internal/catch_xmlwriter.h" #include #include diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 26473de2..042c03a7 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -6,7 +6,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #include "internal/catch_suppress_warnings.h" -#include "internal/catch_test_case_tracker.hpp" +#include "internal/catch_test_case_tracker.h" namespace Catch diff --git a/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp b/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp index c28aa011..a2377500 100644 --- a/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_console_colour.cpp @@ -1,3 +1,3 @@ // This file is only here to verify (to the extent possible) the self sufficiency of the header #include "internal/catch_suppress_warnings.h" -#include "internal/catch_console_colour.hpp" +#include "internal/catch_console_colour.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_test_case_tracker.cpp b/projects/SelfTest/SurrogateCpps/catch_test_case_tracker.cpp index bd67a8a7..0d697b0f 100644 --- a/projects/SelfTest/SurrogateCpps/catch_test_case_tracker.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_test_case_tracker.cpp @@ -1,2 +1,2 @@ // This file is only here to verify (to the extent possible) the self sufficiency of the header -#include "internal/catch_test_case_tracker.hpp" +#include "internal/catch_test_case_tracker.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp b/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp index 9993b80a..8be135ec 100644 --- a/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_test_spec.cpp @@ -1,3 +1,3 @@ // This file is only here to verify (to the extent possible) the self sufficiency of the header #include "internal/catch_suppress_warnings.h" -#include "internal/catch_test_spec.hpp" +#include "internal/catch_test_spec.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp b/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp index 169d2d70..930e3825 100644 --- a/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp @@ -1,4 +1,4 @@ // This file is only here to verify (to the extent possible) the self sufficiency of the header #include "internal/catch_suppress_warnings.h" -#include "internal/catch_xmlwriter.hpp" +#include "internal/catch_xmlwriter.h" #include "internal/catch_reenable_warnings.h" From 03d41ce5b9c557af01e44a21871c80ffd266d150 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 7 Sep 2017 11:25:10 +0100 Subject: [PATCH 334/398] Suppressed meaningless function type qualifier warning in MSVC again (this time in catch_tostring.h) --- include/internal/catch_tostring.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 5a82eba6..2caa96de 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -20,6 +20,10 @@ #include "catch_objc_arc.hpp" #endif +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4180) // qualifier applied to function type has no meaning +#endif // We need a dummy global operator<< so we can bring it into Catch namespace later struct Catch_global_namespace_dummy; @@ -320,7 +324,10 @@ namespace Catch { } // namespace Detail #endif // __OBJC__ - } // namespace Catch +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #endif // TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED From ca7021ae195aaa93f029ee8421e5b1899a830bb6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 7 Sep 2017 12:58:44 +0100 Subject: [PATCH 335/398] Reflected file extension changes in CMakeLists.txt file --- CMakeLists.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6f4b900..92a9d5f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,18 +118,18 @@ CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external) # Please keep these ordered alphabetically set(INTERNAL_HEADERS - ${HEADER_DIR}/internal/catch_approx.hpp + ${HEADER_DIR}/internal/catch_approx.h ${HEADER_DIR}/internal/catch_assertionhandler.h ${HEADER_DIR}/internal/catch_assertioninfo.h ${HEADER_DIR}/internal/catch_assertionresult.h ${HEADER_DIR}/internal/catch_capture.hpp ${HEADER_DIR}/internal/catch_capture_matchers.h ${HEADER_DIR}/internal/catch_clara.h - ${HEADER_DIR}/internal/catch_commandline.hpp + ${HEADER_DIR}/internal/catch_commandline.h ${HEADER_DIR}/internal/catch_common.h ${HEADER_DIR}/internal/catch_compiler_capabilities.h ${HEADER_DIR}/internal/catch_config.hpp - ${HEADER_DIR}/internal/catch_console_colour.hpp + ${HEADER_DIR}/internal/catch_console_colour.h ${HEADER_DIR}/internal/catch_context.h ${HEADER_DIR}/internal/catch_debug_console.h ${HEADER_DIR}/internal/catch_debugger.h @@ -151,7 +151,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_interfaces_testcase.h ${HEADER_DIR}/internal/catch_leak_detector.h ${HEADER_DIR}/internal/catch_list.h - ${HEADER_DIR}/internal/catch_matchers.hpp + ${HEADER_DIR}/internal/catch_matchers.h ${HEADER_DIR}/internal/catch_matchers_string.h ${HEADER_DIR}/internal/catch_matchers_vector.h ${HEADER_DIR}/internal/catch_message.h @@ -164,7 +164,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_reporter_registrars.hpp ${HEADER_DIR}/internal/catch_reporter_registry.hpp ${HEADER_DIR}/internal/catch_result_type.h - ${HEADER_DIR}/internal/catch_run_context.hpp + ${HEADER_DIR}/internal/catch_run_context.h ${HEADER_DIR}/internal/catch_benchmark.h ${HEADER_DIR}/internal/catch_section.h ${HEADER_DIR}/internal/catch_section_info.h @@ -179,19 +179,19 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_tag_alias_autoregistrar.h ${HEADER_DIR}/internal/catch_tag_alias_registry.h ${HEADER_DIR}/internal/catch_test_case_info.h - ${HEADER_DIR}/internal/catch_test_case_registry_impl.hpp - ${HEADER_DIR}/internal/catch_test_case_tracker.hpp - ${HEADER_DIR}/internal/catch_test_registry.hpp - ${HEADER_DIR}/internal/catch_test_spec.hpp - ${HEADER_DIR}/internal/catch_test_spec_parser.hpp + ${HEADER_DIR}/internal/catch_test_case_registry_impl.h + ${HEADER_DIR}/internal/catch_test_case_tracker.h + ${HEADER_DIR}/internal/catch_test_registry.h + ${HEADER_DIR}/internal/catch_test_spec.h + ${HEADER_DIR}/internal/catch_test_spec_parser.h ${HEADER_DIR}/internal/catch_text.h ${HEADER_DIR}/internal/catch_timer.h ${HEADER_DIR}/internal/catch_tostring.h - ${HEADER_DIR}/internal/catch_totals.hpp + ${HEADER_DIR}/internal/catch_totals.h ${HEADER_DIR}/internal/catch_version.h - ${HEADER_DIR}/internal/catch_wildcard_pattern.hpp + ${HEADER_DIR}/internal/catch_wildcard_pattern.h ${HEADER_DIR}/internal/catch_windows_h_proxy.h - ${HEADER_DIR}/internal/catch_xmlwriter.hpp + ${HEADER_DIR}/internal/catch_xmlwriter.h ) set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_approx.cpp From 6105282c4f74984eede1f6ab37b2340f4db19f8a Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 7 Sep 2017 15:04:30 +0100 Subject: [PATCH 336/398] Removed function pointer comparison test from approvals as it has different serilaisation behaviour in MSVC --- .../SelfTest/Baselines/console.std.approved.txt | 4 ++-- .../SelfTest/Baselines/console.sw.approved.txt | 16 ++-------------- .../SelfTest/Baselines/console.swa4.approved.txt | 16 ++-------------- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +-- projects/SelfTest/Baselines/xml.sw.approved.txt | 15 ++------------- projects/SelfTest/TrickyTests.cpp | 3 ++- 6 files changed, 11 insertions(+), 46 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 042224ac..b18370b6 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 178 | 127 passed | 47 failed | 4 failed as expected -assertions: 879 | 762 passed | 96 failed | 21 failed as expected +test cases: 177 | 126 passed | 47 failed | 4 failed as expected +assertions: 878 | 761 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 76a0819d..110e28d8 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -156,18 +156,6 @@ with expansion: with message: dummy := 0 -------------------------------------------------------------------------------- -#925: comparing function pointer to function address failed to compile -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( utility::synchronizing_callback != test.testMethod_uponComplete_arg ) -with expansion: - 1 != 0 - ------------------------------------------------------------------------------- #961 -- Dynamically created sections should all be reported Looped section 0 @@ -7446,6 +7434,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 178 | 125 passed | 49 failed | 4 failed as expected -assertions: 878 | 758 passed | 99 failed | 21 failed as expected +test cases: 177 | 124 passed | 49 failed | 4 failed as expected +assertions: 877 | 757 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index ef9fd05f..06c24e86 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -156,18 +156,6 @@ with expansion: with message: dummy := 0 -------------------------------------------------------------------------------- -#925: comparing function pointer to function address failed to compile -------------------------------------------------------------------------------- -TrickyTests.cpp: -............................................................................... - -TrickyTests.cpp:: -PASSED: - REQUIRE( utility::synchronizing_callback != test.testMethod_uponComplete_arg ) -with expansion: - 1 != 0 - ------------------------------------------------------------------------------- #961 -- Dynamically created sections should all be reported Looped section 0 @@ -249,6 +237,6 @@ ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) =============================================================================== -test cases: 10 | 7 passed | 1 failed | 2 failed as expected -assertions: 27 | 20 passed | 4 failed | 3 failed as expected +test cases: 9 | 6 passed | 1 failed | 2 failed as expected +assertions: 26 | 19 passed | 4 failed | 3 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 88abcd9c..9c0c8204 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -27,7 +27,6 @@ MiscTests.cpp: - diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 5e1312ca..6ab21f15 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -169,17 +169,6 @@ - - - - utility::synchronizing_callback != test.testMethod_uponComplete_arg - - - 1 != 0 - - - -
@@ -8223,7 +8212,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 312638f2..c3f8a240 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -434,7 +434,8 @@ namespace utility { inline static void synchronizing_callback( void * ) { } } -TEST_CASE("#925: comparing function pointer to function address failed to compile") { +TEST_CASE("#925: comparing function pointer to function address failed to compile", "[!nonportable]" ) { + TestClass test; REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg); } From 9aa96712aec495d5a0d580f773c292803cc662aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 7 Sep 2017 16:51:33 +0200 Subject: [PATCH 337/398] Sweep out some extra warnings Swept: `-Wpadded` in some places (where it caused extra size, instead of just saying "hey, we padded struct at the end to align, just as standard says") `-Wweak-vtables` everywhere (Clang) `-Wexit-time-destructors` everywhere (Clang) `-Wmissing-noreturn` everywhere (Clang) The last three are enabled for Clang compilation going forward. Also enabled `-Wunreachable-code` for Clang and GCC --- CMakeLists.txt | 26 ++++++---- include/internal/catch_assertionresult.cpp | 4 +- include/internal/catch_assertionresult.h | 5 +- include/internal/catch_clara.h | 9 ++++ include/internal/catch_common.cpp | 3 ++ include/internal/catch_common.h | 4 +- .../internal/catch_compiler_capabilities.h | 14 +++--- include/internal/catch_config.hpp | 1 - include/internal/catch_console_colour.cpp | 12 +++++ include/internal/catch_context.cpp | 5 ++ include/internal/catch_context.h | 4 +- include/internal/catch_decomposer.cpp | 2 + include/internal/catch_decomposer.h | 22 ++++---- include/internal/catch_fatal_condition.cpp | 4 +- include/internal/catch_impl.hpp | 23 ++------- include/internal/catch_interfaces_capture.cpp | 5 ++ include/internal/catch_interfaces_config.cpp | 5 ++ .../internal/catch_interfaces_exception.cpp | 6 +++ .../catch_interfaces_registry_hub.cpp | 6 +++ .../internal/catch_interfaces_reporter.cpp | 13 +++++ include/internal/catch_interfaces_reporter.h | 14 +++--- include/internal/catch_interfaces_runner.cpp | 5 ++ .../internal/catch_interfaces_testcase.cpp | 6 +++ include/internal/catch_matchers.cpp | 2 + include/internal/catch_matchers.h | 2 +- include/internal/catch_message.h | 2 +- include/internal/catch_registry_hub.cpp | 5 +- .../internal/catch_reporter_registrars.hpp | 9 ++-- include/internal/catch_reporter_registry.cpp | 34 +++++++++++++ include/internal/catch_reporter_registry.h | 37 ++++++++++++++ include/internal/catch_reporter_registry.hpp | 50 ------------------- include/internal/catch_run_context.cpp | 2 +- include/internal/catch_stream.cpp | 2 + include/internal/catch_stream.h | 2 +- include/internal/catch_streambuf.cpp | 12 +++++ include/internal/catch_streambuf.h | 4 +- include/internal/catch_stringref.cpp | 12 +++++ include/internal/catch_test_case_tracker.cpp | 11 +++- include/internal/catch_test_case_tracker.h | 6 +-- include/internal/catch_test_registry.cpp | 2 + include/internal/catch_test_registry.h | 18 +++---- include/internal/catch_test_spec.cpp | 5 ++ include/internal/catch_test_spec.h | 8 +-- include/internal/catch_tostring.cpp | 12 +++++ include/internal/catch_tostring.h | 3 +- include/reporters/catch_reporter_tap.hpp | 4 +- .../Baselines/console.std.approved.txt | 2 +- .../Baselines/console.sw.approved.txt | 2 +- .../SelfTest/Baselines/xml.sw.approved.txt | 3 -- projects/SelfTest/ConditionTests.cpp | 7 +++ projects/SelfTest/ExceptionTests.cpp | 8 +++ projects/SelfTest/MatchersTests.cpp | 14 +++++- .../catch_interfaces_capture.cpp | 3 -- .../SurrogateCpps/catch_interfaces_config.cpp | 2 - .../catch_interfaces_exception.cpp | 2 - .../catch_interfaces_registry_hub.cpp | 3 -- .../SurrogateCpps/catch_interfaces_runner.cpp | 1 - .../catch_interfaces_testcase.cpp | 2 - .../SurrogateCpps/catch_streambuf.cpp | 3 -- projects/SelfTest/TestMain.cpp | 2 +- projects/SelfTest/TrickyTests.cpp | 5 +- 61 files changed, 319 insertions(+), 182 deletions(-) create mode 100644 include/internal/catch_interfaces_capture.cpp create mode 100644 include/internal/catch_interfaces_config.cpp create mode 100644 include/internal/catch_interfaces_exception.cpp create mode 100644 include/internal/catch_interfaces_registry_hub.cpp create mode 100644 include/internal/catch_interfaces_runner.cpp create mode 100644 include/internal/catch_interfaces_testcase.cpp create mode 100644 include/internal/catch_reporter_registry.cpp create mode 100644 include/internal/catch_reporter_registry.h delete mode 100644 include/internal/catch_reporter_registry.hpp create mode 100644 include/internal/catch_streambuf.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp delete mode 100644 projects/SelfTest/SurrogateCpps/catch_streambuf.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 92a9d5f9..c8a17f18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,16 +85,9 @@ CheckFileList(TEST_SOURCES ${SELF_TEST_DIR}) set(SURROGATE_SOURCES ${SELF_TEST_DIR}/SurrogateCpps/catch_console_colour.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_debugger.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_capture.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_config.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_exception.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_registry_hub.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_reporter.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_runner.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_interfaces_testcase.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_option.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_stream.cpp - ${SELF_TEST_DIR}/SurrogateCpps/catch_streambuf.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_test_case_tracker.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_test_spec.cpp ${SELF_TEST_DIR}/SurrogateCpps/catch_xmlwriter.cpp @@ -162,7 +155,7 @@ set(INTERNAL_HEADERS ${HEADER_DIR}/internal/catch_random_number_generator.h ${HEADER_DIR}/internal/catch_reenable_warnings.h ${HEADER_DIR}/internal/catch_reporter_registrars.hpp - ${HEADER_DIR}/internal/catch_reporter_registry.hpp + ${HEADER_DIR}/internal/catch_reporter_registry.h ${HEADER_DIR}/internal/catch_result_type.h ${HEADER_DIR}/internal/catch_run_context.h ${HEADER_DIR}/internal/catch_benchmark.h @@ -210,6 +203,12 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_errno_guard.cpp ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp ${HEADER_DIR}/internal/catch_fatal_condition.cpp + ${HEADER_DIR}/internal/catch_interfaces_capture.cpp + ${HEADER_DIR}/internal/catch_interfaces_config.cpp + ${HEADER_DIR}/internal/catch_interfaces_exception.cpp + ${HEADER_DIR}/internal/catch_interfaces_registry_hub.cpp + ${HEADER_DIR}/internal/catch_interfaces_runner.cpp + ${HEADER_DIR}/internal/catch_interfaces_testcase.cpp ${HEADER_DIR}/internal/catch_list.cpp ${HEADER_DIR}/internal/catch_leak_detector.cpp ${HEADER_DIR}/internal/catch_matchers.cpp @@ -218,6 +217,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_registry_hub.cpp ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp ${HEADER_DIR}/internal/catch_random_number_generator.cpp + ${HEADER_DIR}/internal/catch_reporter_registry.cpp ${HEADER_DIR}/internal/catch_result_type.cpp ${HEADER_DIR}/internal/catch_run_context.cpp ${HEADER_DIR}/internal/catch_section.cpp @@ -225,6 +225,7 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_session.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp ${HEADER_DIR}/internal/catch_stream.cpp + ${HEADER_DIR}/internal/catch_streambuf.cpp ${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_string_manip.cpp ${HEADER_DIR}/internal/catch_tag_alias.cpp @@ -298,8 +299,13 @@ if (NOT NO_SELFTEST) # Add desired warnings if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) - target_compile_options( SelfTest PRIVATE -Wall -Wextra ) - target_compile_options( Benchmark PRIVATE -Wall -Wextra ) + target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code ) + target_compile_options( Benchmark PRIVATE -Wall -Wextra -Wunreachable-code ) + endif() + # Clang specific warning go here + if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) + # Actually keep these + target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn ) endif() if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX ) diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index ea416856..7a3a2e08 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -10,8 +10,8 @@ namespace Catch { AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): - resultType(_resultType), - lazyExpression(_lazyExpression) {} + lazyExpression(_lazyExpression), + resultType(_resultType) {} std::string AssertionResultData::reconstructExpression() const { diff --git a/include/internal/catch_assertionresult.h b/include/internal/catch_assertionresult.h index 6a4b61f1..fa8e09f2 100644 --- a/include/internal/catch_assertionresult.h +++ b/include/internal/catch_assertionresult.h @@ -23,13 +23,12 @@ namespace Catch { AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); - ResultWas::OfType resultType; std::string message; - + mutable std::string reconstructedExpression; LazyExpression lazyExpression; + ResultWas::OfType resultType; std::string reconstructExpression() const; - mutable std::string reconstructedExpression; }; class AssertionResult { diff --git a/include/internal/catch_clara.h b/include/internal/catch_clara.h index abe7626b..bdf70250 100644 --- a/include/internal/catch_clara.h +++ b/include/internal/catch_clara.h @@ -16,9 +16,18 @@ #endif #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wshadow" +#endif #include "../external/clara.hpp" +#ifdef __clang__ +#pragma clang diagnostic pop +#endif // Restore Clara's value for console width, if present #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH diff --git a/include/internal/catch_common.cpp b/include/internal/catch_common.cpp index 9c18b543..0f2f6eb4 100644 --- a/include/internal/catch_common.cpp +++ b/include/internal/catch_common.cpp @@ -46,4 +46,7 @@ namespace Catch { return std::string(); } + NonCopyable::NonCopyable() = default; + NonCopyable::~NonCopyable() = default; + } diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 5e22825d..617a9343 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -36,8 +36,8 @@ namespace Catch { NonCopyable& operator = ( NonCopyable && ) = delete; protected: - NonCopyable() = default; - virtual ~NonCopyable() = default; + NonCopyable(); + virtual ~NonCopyable(); }; struct SourceLineInfo { diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index 3bd40461..18cf9e01 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -35,11 +35,11 @@ #ifdef __clang__ - -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ _Pragma( "clang diagnostic pop" ) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ @@ -111,9 +111,9 @@ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 23e1d1ed..fcaa0500 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -62,7 +62,6 @@ namespace Catch { class Config : public IConfig { - virtual void dummy(); public: Config() = default; diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index e33b8828..13290544 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -6,6 +6,13 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + + #include "catch_console_colour.h" #include "catch_enforce.h" #include "catch_errno_guard.h" @@ -202,3 +209,8 @@ namespace Catch { } } // end namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + diff --git a/include/internal/catch_context.cpp b/include/internal/catch_context.cpp index 3d406dda..c917a1d4 100644 --- a/include/internal/catch_context.cpp +++ b/include/internal/catch_context.cpp @@ -24,6 +24,8 @@ namespace Catch { return m_config; } + virtual ~Context() override; + public: // IMutableContext virtual void setResultCapture( IResultCapture* resultCapture ) override { m_resultCapture = resultCapture; @@ -59,4 +61,7 @@ namespace Catch { delete currentContext; currentContext = nullptr; } + IContext::~IContext() = default; + IMutableContext::~IMutableContext() = default; + Context::~Context() = default; } diff --git a/include/internal/catch_context.h b/include/internal/catch_context.h index 5569eb71..c88236a9 100644 --- a/include/internal/catch_context.h +++ b/include/internal/catch_context.h @@ -20,7 +20,7 @@ namespace Catch { struct IContext { - virtual ~IContext() = default; + virtual ~IContext(); virtual IResultCapture* getResultCapture() = 0; virtual IRunner* getRunner() = 0; @@ -29,7 +29,7 @@ namespace Catch { struct IMutableContext : IContext { - virtual ~IMutableContext() = default; + virtual ~IMutableContext(); virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setRunner( IRunner* runner ) = 0; virtual void setConfig( IConfigPtr const& config ) = 0; diff --git a/include/internal/catch_decomposer.cpp b/include/internal/catch_decomposer.cpp index f8b282dc..8c19629b 100644 --- a/include/internal/catch_decomposer.cpp +++ b/include/internal/catch_decomposer.cpp @@ -11,6 +11,8 @@ namespace Catch { + ITransientExpression::~ITransientExpression() = default; + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { if( lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 5d4bb0d1..786a052e 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -30,7 +30,7 @@ namespace Catch { // We don't actually need a virtual destructore, but many static analysers // complain if it's not here :-( - virtual ~ITransientExpression() = default; + virtual ~ITransientExpression(); }; void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); @@ -79,24 +79,24 @@ namespace Catch { template auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; template - auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } template - auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } template - auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } template - auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } template auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; template - auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } template - auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } template - auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } template - auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } template @@ -162,8 +162,4 @@ namespace Catch { } // end namespace Catch -#ifdef _MSC_VER -#pragma warning(pop) -#endif - #endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp index be1c333e..39b63455 100644 --- a/include/internal/catch_fatal_condition.cpp +++ b/include/internal/catch_fatal_condition.cpp @@ -35,7 +35,7 @@ namespace Catch { // There is no 1-1 mapping between signals and windows exceptions. // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { + static SignalDefs signalDefs[] = { { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, @@ -107,7 +107,7 @@ namespace Catch { int id; const char* name; }; - SignalDefs signalDefs[] = { + static SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGILL, "SIGILL - Illegal instruction signal" }, { SIGFPE, "SIGFPE - Floating point error signal" }, diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index ae512ce1..0b29a39f 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -8,39 +8,22 @@ #ifndef TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-vtables" #endif - -#include "internal/catch_leak_detector.h" - +// Keep these here for external reporters #include "catch_test_spec.h" #include "catch_test_case_tracker.h" +#include "catch_leak_detector.h" + // Cpp files will be included in the single-header file here // ~*~* CATCH_CPP_STITCH_PLACE *~*~ namespace Catch { LeakDetector leakDetector; - - // These are all here to avoid warnings about not having any out of line - // virtual methods - IResultCapture::~IResultCapture() {} - ITestInvoker::~ITestInvoker() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IRunner::~IRunner() {} - IConfig::~IConfig() {} - - void Config::dummy() {} } #ifdef __clang__ diff --git a/include/internal/catch_interfaces_capture.cpp b/include/internal/catch_interfaces_capture.cpp new file mode 100644 index 00000000..3c090bfe --- /dev/null +++ b/include/internal/catch_interfaces_capture.cpp @@ -0,0 +1,5 @@ +#include "catch_interfaces_capture.h" + +namespace Catch { + IResultCapture::~IResultCapture() = default; +} diff --git a/include/internal/catch_interfaces_config.cpp b/include/internal/catch_interfaces_config.cpp new file mode 100644 index 00000000..b6f5daa2 --- /dev/null +++ b/include/internal/catch_interfaces_config.cpp @@ -0,0 +1,5 @@ +#include "internal/catch_interfaces_config.h" + +namespace Catch { + IConfig::~IConfig() = default; +} diff --git a/include/internal/catch_interfaces_exception.cpp b/include/internal/catch_interfaces_exception.cpp new file mode 100644 index 00000000..8494a2cc --- /dev/null +++ b/include/internal/catch_interfaces_exception.cpp @@ -0,0 +1,6 @@ +#include "internal/catch_interfaces_exception.h" + +namespace Catch { + IExceptionTranslator::~IExceptionTranslator() = default; + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; +} diff --git a/include/internal/catch_interfaces_registry_hub.cpp b/include/internal/catch_interfaces_registry_hub.cpp new file mode 100644 index 00000000..bd5b8082 --- /dev/null +++ b/include/internal/catch_interfaces_registry_hub.cpp @@ -0,0 +1,6 @@ +#include "internal/catch_interfaces_registry_hub.h" + +namespace Catch { + IRegistryHub::~IRegistryHub() = default; + IMutableRegistryHub::~IMutableRegistryHub() = default; +} diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp index c7b2e861..06e409ae 100644 --- a/include/internal/catch_interfaces_reporter.cpp +++ b/include/internal/catch_interfaces_reporter.cpp @@ -50,6 +50,8 @@ namespace Catch { } } + AssertionStats::~AssertionStats() = default; + SectionStats::SectionStats( SectionInfo const& _sectionInfo, Counts const& _assertions, double _durationInSeconds, @@ -60,6 +62,8 @@ namespace Catch { missingAssertions( _missingAssertions ) {} + SectionStats::~SectionStats() = default; + TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, Totals const& _totals, @@ -73,6 +77,8 @@ namespace Catch { aborting( _aborting ) {} + TestCaseStats::~TestCaseStats() = default; + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, Totals const& _totals, @@ -87,6 +93,8 @@ namespace Catch { aborting( false ) {} + TestGroupStats::~TestGroupStats() = default; + TestRunStats::TestRunStats( TestRunInfo const& _runInfo, Totals const& _totals, bool _aborting ) @@ -95,9 +103,14 @@ namespace Catch { aborting( _aborting ) {} + TestRunStats::~TestRunStats() = default; + bool IStreamingReporter::isMulti() const { return false; } + IReporterFactory::~IReporterFactory() = default; + IReporterRegistry::~IReporterRegistry() = default; + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { if( !existingReporter ) { diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index d4fb9dbf..43beca68 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -80,7 +80,7 @@ namespace Catch { AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats && ) = default; - virtual ~AssertionStats() = default; + virtual ~AssertionStats(); AssertionResult assertionResult; std::vector infoMessages; @@ -96,7 +96,7 @@ namespace Catch { SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats && ) = default; - virtual ~SectionStats() = default; + virtual ~SectionStats(); SectionInfo sectionInfo; Counts assertions; @@ -115,7 +115,7 @@ namespace Catch { TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats && ) = default; - virtual ~TestCaseStats() = default; + virtual ~TestCaseStats(); TestCaseInfo testInfo; Totals totals; @@ -134,7 +134,7 @@ namespace Catch { TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats && ) = default; - virtual ~TestGroupStats() = default; + virtual ~TestGroupStats(); GroupInfo groupInfo; Totals totals; @@ -150,7 +150,7 @@ namespace Catch { TestRunStats( TestRunStats && ) = default; TestRunStats& operator = ( TestRunStats const& ) = default; TestRunStats& operator = ( TestRunStats && ) = default; - virtual ~TestRunStats() = default; + virtual ~TestRunStats(); TestRunInfo runInfo; Totals totals; @@ -206,7 +206,7 @@ namespace Catch { using IStreamingReporterPtr = std::unique_ptr; struct IReporterFactory { - virtual ~IReporterFactory() = default; + virtual ~IReporterFactory(); virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; @@ -216,7 +216,7 @@ namespace Catch { using FactoryMap = std::map; using Listeners = std::vector; - virtual ~IReporterRegistry() = default; + virtual ~IReporterRegistry(); virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; diff --git a/include/internal/catch_interfaces_runner.cpp b/include/internal/catch_interfaces_runner.cpp new file mode 100644 index 00000000..2b052eb8 --- /dev/null +++ b/include/internal/catch_interfaces_runner.cpp @@ -0,0 +1,5 @@ +#include "internal/catch_interfaces_runner.h" + +namespace Catch { + IRunner::~IRunner() = default; +} diff --git a/include/internal/catch_interfaces_testcase.cpp b/include/internal/catch_interfaces_testcase.cpp new file mode 100644 index 00000000..35c3db08 --- /dev/null +++ b/include/internal/catch_interfaces_testcase.cpp @@ -0,0 +1,6 @@ +#include "internal/catch_interfaces_testcase.h" + +namespace Catch { + ITestInvoker::~ITestInvoker() = default; + ITestCaseRegistry::~ITestCaseRegistry() = default; +} diff --git a/include/internal/catch_matchers.cpp b/include/internal/catch_matchers.cpp index 8621114b..32104a11 100644 --- a/include/internal/catch_matchers.cpp +++ b/include/internal/catch_matchers.cpp @@ -17,6 +17,8 @@ namespace Matchers { return m_cachedToString; } + MatcherUntypedBase::~MatcherUntypedBase() = default; + } // namespace Impl } // namespace Matchers diff --git a/include/internal/catch_matchers.h b/include/internal/catch_matchers.h index 91923831..8c15d425 100644 --- a/include/internal/catch_matchers.h +++ b/include/internal/catch_matchers.h @@ -29,7 +29,7 @@ namespace Matchers { std::string toString() const; protected: - virtual ~MatcherUntypedBase() = default; + virtual ~MatcherUntypedBase(); virtual std::string describe() const = 0; mutable std::string m_cachedToString; }; diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h index 553882b7..c90d30d3 100644 --- a/include/internal/catch_message.h +++ b/include/internal/catch_message.h @@ -21,9 +21,9 @@ namespace Catch { ResultWas::OfType _type ); std::string macroName; + std::string message; SourceLineInfo lineInfo; ResultWas::OfType type; - std::string message; unsigned int sequence; bool operator == ( MessageInfo const& other ) const; diff --git a/include/internal/catch_registry_hub.cpp b/include/internal/catch_registry_hub.cpp index 74d92ec0..ab5ad361 100644 --- a/include/internal/catch_registry_hub.cpp +++ b/include/internal/catch_registry_hub.cpp @@ -10,7 +10,7 @@ #include "catch_context.h" #include "catch_test_case_registry_impl.h" -#include "catch_reporter_registry.hpp" +#include "catch_reporter_registry.h" #include "catch_exception_translator_registry.h" #include "catch_tag_alias_registry.h" #include "catch_startup_exception_registry.h" @@ -23,8 +23,7 @@ namespace Catch { private NonCopyable { public: // IRegistryHub - RegistryHub() { - } + RegistryHub() = default; IReporterRegistry const& getReporterRegistry() const override { return m_reporterRegistry; } diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 6d30a833..ce88fa34 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -58,11 +58,14 @@ namespace Catch { #if !defined(CATCH_CONFIG_DISABLE) #define CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #define CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS #else // CATCH_CONFIG_DISABLE #define CATCH_REGISTER_REPORTER(name, reporterType) diff --git a/include/internal/catch_reporter_registry.cpp b/include/internal/catch_reporter_registry.cpp new file mode 100644 index 00000000..f017e059 --- /dev/null +++ b/include/internal/catch_reporter_registry.cpp @@ -0,0 +1,34 @@ +/* + * Created by Martin on 31/08/2017. + * + * 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) + */ +#include "catch_reporter_registry.h" + +namespace Catch { + + ReporterRegistry::~ReporterRegistry() = default; + + IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { + auto it = m_factories.find( name ); + if( it == m_factories.end() ) + return nullptr; + return it->second->create( ReporterConfig( config ) ); + } + + void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { + m_factories.emplace(name, factory); + } + void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { + m_listeners.push_back( factory ); + } + + IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { + return m_factories; + } + IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { + return m_listeners; + } + +} diff --git a/include/internal/catch_reporter_registry.h b/include/internal/catch_reporter_registry.h new file mode 100644 index 00000000..916e9247 --- /dev/null +++ b/include/internal/catch_reporter_registry.h @@ -0,0 +1,37 @@ +/* + * Created by Phil on 29/10/2010. + * Copyright 2010 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) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRY_H_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_H_INCLUDED + +#include "catch_interfaces_reporter.h" + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + ~ReporterRegistry() override; + + IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; + + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); + void registerListener( IReporterFactoryPtr const& factory ); + + FactoryMap const& getFactories() const override; + Listeners const& getListeners() const override; + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_H_INCLUDED diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp deleted file mode 100644 index c3bf3b61..00000000 --- a/include/internal/catch_reporter_registry.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Created by Phil on 29/10/2010. - * Copyright 2010 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) - */ -#ifndef TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED -#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED - -#include "catch_interfaces_reporter.h" - -#include - -namespace Catch { - - class ReporterRegistry : public IReporterRegistry { - - public: - - ~ReporterRegistry() override {} - - IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { - auto it = m_factories.find( name ); - if( it == m_factories.end() ) - return nullptr; - return it->second->create( ReporterConfig( config ) ); - } - - void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { - m_factories.emplace(name, factory); - } - void registerListener( IReporterFactoryPtr const& factory ) { - m_listeners.push_back( factory ); - } - - FactoryMap const& getFactories() const override { - return m_factories; - } - Listeners const& getListeners() const override { - return m_listeners; - } - - private: - FactoryMap m_factories; - Listeners m_listeners; - }; -} - -#endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 13054862..60f133a0 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -329,4 +329,4 @@ namespace Catch { else CATCH_INTERNAL_ERROR("No result capture instance"); } -} \ No newline at end of file +} diff --git a/include/internal/catch_stream.cpp b/include/internal/catch_stream.cpp index 4278317d..14a89bac 100644 --- a/include/internal/catch_stream.cpp +++ b/include/internal/catch_stream.cpp @@ -57,6 +57,8 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// + Catch::IStream::~IStream() = default; + FileStream::FileStream( std::string const& filename ) { m_ofs.open( filename.c_str() ); CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index 1ab59ca3..41780b98 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -24,7 +24,7 @@ namespace Catch { struct IStream { - virtual ~IStream() = default; + virtual ~IStream(); virtual std::ostream& stream() const = 0; }; diff --git a/include/internal/catch_streambuf.cpp b/include/internal/catch_streambuf.cpp new file mode 100644 index 00000000..608917fb --- /dev/null +++ b/include/internal/catch_streambuf.cpp @@ -0,0 +1,12 @@ +/* + * Created by Martin on 31/08/2017. + * + * 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) + */ + +#include "catch_streambuf.h" + +namespace Catch { + StreamBufBase::~StreamBufBase() = default; +} diff --git a/include/internal/catch_streambuf.h b/include/internal/catch_streambuf.h index 7fd17e40..18b94ccb 100644 --- a/include/internal/catch_streambuf.h +++ b/include/internal/catch_streambuf.h @@ -8,15 +8,13 @@ #ifndef TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED -#include "catch_compiler_capabilities.h" - #include namespace Catch { class StreamBufBase : public std::streambuf { public: - virtual ~StreamBufBase() = default; + virtual ~StreamBufBase(); }; } diff --git a/include/internal/catch_stringref.cpp b/include/internal/catch_stringref.cpp index e22b6c94..059f1c6f 100644 --- a/include/internal/catch_stringref.cpp +++ b/include/internal/catch_stringref.cpp @@ -5,12 +5,20 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + #include "catch_stringref.h" #include #include #include + + namespace Catch { auto getEmptyStringRef() -> StringRef { @@ -160,3 +168,7 @@ namespace Catch { } } // namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif diff --git a/include/internal/catch_test_case_tracker.cpp b/include/internal/catch_test_case_tracker.cpp index fb3f8d44..bcb7793f 100644 --- a/include/internal/catch_test_case_tracker.cpp +++ b/include/internal/catch_test_case_tracker.cpp @@ -14,7 +14,10 @@ #include #include -CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif namespace Catch { namespace TestCaseTracking { @@ -25,6 +28,8 @@ namespace TestCaseTracking { {} + ITracker::~ITracker() = default; + TrackerContext& TrackerContext::instance() { static TrackerContext s_instance; @@ -276,4 +281,6 @@ using TestCaseTracking::IndexTracker; } // namespace Catch -CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#if defined(__clang__) +# pragma clang diagnostic pop +#endif diff --git a/include/internal/catch_test_case_tracker.h b/include/internal/catch_test_case_tracker.h index c9738252..a4b0440a 100644 --- a/include/internal/catch_test_case_tracker.h +++ b/include/internal/catch_test_case_tracker.h @@ -15,8 +15,6 @@ #include #include -CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS - namespace Catch { namespace TestCaseTracking { @@ -32,7 +30,7 @@ namespace TestCaseTracking { using ITrackerPtr = std::shared_ptr; struct ITracker { - virtual ~ITracker() = default; + virtual ~ITracker(); // static queries virtual NameAndLocation const& nameAndLocation() const = 0; @@ -182,6 +180,4 @@ using TestCaseTracking::IndexTracker; } // namespace Catch -CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - #endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED diff --git a/include/internal/catch_test_registry.cpp b/include/internal/catch_test_registry.cpp index b1c07f2d..ec50e92c 100644 --- a/include/internal/catch_test_registry.cpp +++ b/include/internal/catch_test_registry.cpp @@ -32,4 +32,6 @@ namespace Catch { getMutableRegistryHub().registerStartupException(); } } + + AutoReg::~AutoReg() = default; } diff --git a/include/internal/catch_test_registry.h b/include/internal/catch_test_registry.h index 19f08c2a..afba1dbc 100644 --- a/include/internal/catch_test_registry.h +++ b/include/internal/catch_test_registry.h @@ -42,7 +42,7 @@ struct NameAndTags { struct AutoReg : NonCopyable { AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; - ~AutoReg() = default; + ~AutoReg(); }; } // end namespace Catch @@ -63,38 +63,38 @@ struct AutoReg : NonCopyable { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ static void TestName() #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, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + 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_ETD_WARNINGS + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ \ struct TestName : 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_ETD_WARNINGS \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ void TestName::test() #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, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED diff --git a/include/internal/catch_test_spec.cpp b/include/internal/catch_test_spec.cpp index a1055c20..d9c149d5 100644 --- a/include/internal/catch_test_spec.cpp +++ b/include/internal/catch_test_spec.cpp @@ -15,6 +15,11 @@ namespace Catch { + TestSpec::Pattern::~Pattern() = default; + TestSpec::NamePattern::~NamePattern() = default; + TestSpec::TagPattern::~TagPattern() = default; + TestSpec::ExcludedPattern::~ExcludedPattern() = default; + TestSpec::NamePattern::NamePattern( std::string const& name ) : m_wildcardPattern( toLower( name ), CaseSensitive::No ) {} diff --git a/include/internal/catch_test_spec.h b/include/internal/catch_test_spec.h index e9ef3a31..baf8b019 100644 --- a/include/internal/catch_test_spec.h +++ b/include/internal/catch_test_spec.h @@ -24,7 +24,7 @@ namespace Catch { class TestSpec { struct Pattern { - virtual ~Pattern() = default; + virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; using PatternPtr = std::shared_ptr; @@ -32,7 +32,7 @@ namespace Catch { class NamePattern : public Pattern { public: NamePattern( std::string const& name ); - virtual ~NamePattern() = default; + virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const override; private: WildcardPattern m_wildcardPattern; @@ -41,7 +41,7 @@ namespace Catch { class TagPattern : public Pattern { public: TagPattern( std::string const& tag ); - virtual ~TagPattern() = default; + virtual ~TagPattern(); virtual bool matches( TestCaseInfo const& testCase ) const override; private: std::string m_tag; @@ -50,7 +50,7 @@ namespace Catch { class ExcludedPattern : public Pattern { public: ExcludedPattern( PatternPtr const& underlyingPattern ); - virtual ~ExcludedPattern() = default; + virtual ~ExcludedPattern(); virtual bool matches( TestCaseInfo const& testCase ) const override; private: PatternPtr m_underlyingPattern; diff --git a/include/internal/catch_tostring.cpp b/include/internal/catch_tostring.cpp index 56aefa63..1b47178d 100644 --- a/include/internal/catch_tostring.cpp +++ b/include/internal/catch_tostring.cpp @@ -6,6 +6,13 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + + #include "catch_tostring.h" #include "catch_interfaces_config.h" #include "catch_context.h" @@ -211,3 +218,8 @@ std::string StringMaker::convert(double value) { } // end namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 2caa96de..b5d31397 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -22,9 +22,10 @@ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4180) // qualifier applied to function type has no meaning +#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); diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index 47661598..dbcad5ee 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -64,13 +64,13 @@ namespace Catch { public: AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; AssertionPrinter( AssertionPrinter const& ) = delete; - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, size_t counter ) + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, size_t _counter ) : stream( _stream ) , result( _stats.assertionResult ) , messages( _stats.infoMessages ) , itMessage( _stats.infoMessages.begin() ) , printInfoMessages( true ) - , counter(counter) + , counter(_counter) {} void print() { diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index b18370b6..9b2defd5 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 177 | 126 passed | 47 failed | 4 failed as expected +test cases: 176 | 125 passed | 47 failed | 4 failed as expected assertions: 878 | 761 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 110e28d8..be582975 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -7434,6 +7434,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 177 | 124 passed | 49 failed | 4 failed as expected +test cases: 176 | 123 passed | 49 failed | 4 failed as expected assertions: 877 | 757 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 6ab21f15..f3a9ee6d 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -6946,9 +6946,6 @@ Message from section two
- - - diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index 00ff6060..4bc09817 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -6,7 +6,9 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifdef __clang__ +# pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wdouble-promotion" #endif #include "catch.hpp" @@ -161,6 +163,11 @@ TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" ) CHECK( data.str_hello <= "a" ); } +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + + // Comparisons with int literals TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigned" ) { diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 6c7cdb2c..4d092f44 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -14,6 +14,10 @@ #ifdef _MSC_VER #pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection #endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif namespace { @@ -219,3 +223,7 @@ TEST_CASE( "#748 - captures with unexpected exceptions", "[.][failing][!throws][ REQUIRE_THROWS( thisThrows() ); } } + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif diff --git a/projects/SelfTest/MatchersTests.cpp b/projects/SelfTest/MatchersTests.cpp index 0482ed43..2a9040a8 100644 --- a/projects/SelfTest/MatchersTests.cpp +++ b/projects/SelfTest/MatchersTests.cpp @@ -8,6 +8,12 @@ #include "catch.hpp" +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#pragma clang diagnostic ignored "-Wpadded" +#endif + #ifndef CATCH_CONFIG_DISABLE_MATCHERS inline const char* testStringForMatching() @@ -166,16 +172,18 @@ TEST_CASE( "Vector matchers that fail", "[matchers][vector][.][failing]" ) { #include struct SpecialException : std::exception { - SpecialException(int i):i(i) {} + SpecialException(int i_):i(i_) {} int i; }; void doesNotThrow() {} +[[noreturn]] void throws(int i) { throw SpecialException{ i }; } +[[noreturn]] void throwsAsInt(int i) { throw i; } @@ -217,3 +225,7 @@ TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.fail } #endif // CATCH_CONFIG_DISABLE_MATCHERS + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp deleted file mode 100644 index f46dae48..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_capture.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// This file is only here to verify (to the extent possible) the self sufficiency of the header -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_interfaces_capture.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp deleted file mode 100644 index 46f80e86..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_config.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_interfaces_config.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp deleted file mode 100644 index f5ad4870..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_interfaces_exception.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp deleted file mode 100644 index b399d862..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// This file is only here to verify (to the extent possible) the self sufficiency of the header -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_interfaces_registry_hub.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp deleted file mode 100644 index 800f32ab..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_runner.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "internal/catch_interfaces_runner.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp deleted file mode 100644 index 0d6903cc..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_testcase.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_interfaces_testcase.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp b/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp deleted file mode 100644 index a9222e4b..00000000 --- a/projects/SelfTest/SurrogateCpps/catch_streambuf.cpp +++ /dev/null @@ -1,3 +0,0 @@ -// This file is only here to verify (to the extent possible) the self sufficiency of the header -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_streambuf.h" diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index cdb13c52..68271b7e 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -265,4 +265,4 @@ struct AutoTestReg { REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered" ); } }; -AutoTestReg autoTestReg; +static AutoTestReg autoTestReg; diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index c3f8a240..78f7052f 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -381,12 +381,9 @@ TEST_CASE( "has printf" ) { printf( "loose text artifact\n" ); } -TEST_CASE( "assertions with commas are allowed" ) { -} - namespace { struct constructor_throws { - constructor_throws() { + [[noreturn]] constructor_throws() { throw 1; } }; From eaf850cd0c2c3322a1dddb9a2e37210db3f15df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 11 Sep 2017 21:09:35 +0200 Subject: [PATCH 338/398] Do not use SEH and console api under UWP Fixes #1020 --- include/internal/catch_compiler_capabilities.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index 18cf9e01..e7d506ed 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -80,7 +80,13 @@ // Visual C++ #ifdef _MSC_VER -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif #endif // _MSC_VER From 4e852672033ac989e303a4a00de607738e64e7e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 14 Sep 2017 19:57:59 +0200 Subject: [PATCH 339/398] Add fatalErrorEncountered method to Reporter/Listener interface An empty default implementation is provided to keep backward compatibility. Called when signal or Structured Exception is encountered. Related to #1005 --- include/internal/catch_interfaces_reporter.cpp | 2 +- include/internal/catch_interfaces_reporter.h | 4 ++++ include/internal/catch_run_context.cpp | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp index 06e409ae..3859c546 100644 --- a/include/internal/catch_interfaces_reporter.cpp +++ b/include/internal/catch_interfaces_reporter.cpp @@ -105,7 +105,7 @@ namespace Catch { TestRunStats::~TestRunStats() = default; - + void IStreamingReporter::fatalErrorEncountered( StringRef name ) {} bool IStreamingReporter::isMulti() const { return false; } IReporterFactory::~IReporterFactory() = default; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 43beca68..318ce669 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -16,6 +16,7 @@ #include "catch_assertionresult.h" #include "catch_message.h" #include "catch_option.hpp" +#include "catch_stringref.h" #include @@ -201,6 +202,9 @@ namespace Catch { virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + // Default empty implementation provided + virtual void fatalErrorEncountered( StringRef name ); + virtual bool isMulti() const; }; using IStreamingReporterPtr = std::unique_ptr; diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index 60f133a0..b034ec62 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -209,6 +209,9 @@ namespace Catch { } void RunContext::handleFatalErrorCondition(std::string const & message) { + // First notify reporter that bad things happened + m_reporter->fatalErrorEncountered(message); + // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); From 40209d1ae0fefc6ee4144be6bcb1366ef1444506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 14 Sep 2017 20:05:25 +0200 Subject: [PATCH 340/398] Use StringRef on fatal error path So far the fatal error path only uses string literals, so this removes an allocation from that context --- include/internal/catch_interfaces_capture.h | 4 +++- include/internal/catch_run_context.cpp | 2 +- include/internal/catch_run_context.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index d153a8bc..5b370114 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -10,6 +10,8 @@ #include +#include "catch_stringref.h" + namespace Catch { class AssertionResult; @@ -43,7 +45,7 @@ namespace Catch { virtual void exceptionEarlyReported() = 0; - virtual void handleFatalErrorCondition( std::string const& message ) = 0; + virtual void handleFatalErrorCondition( StringRef message ) = 0; virtual bool lastAssertionPassed() = 0; virtual void assertionPassed() = 0; diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index b034ec62..11b85b24 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -208,7 +208,7 @@ namespace Catch { m_shouldReportUnexpected = false; } - void RunContext::handleFatalErrorCondition(std::string const & message) { + void RunContext::handleFatalErrorCondition( StringRef message ) { // First notify reporter that bad things happened m_reporter->fatalErrorEncountered(message); diff --git a/include/internal/catch_run_context.h b/include/internal/catch_run_context.h index 64314cb2..3f238171 100644 --- a/include/internal/catch_run_context.h +++ b/include/internal/catch_run_context.h @@ -100,7 +100,7 @@ namespace Catch { void exceptionEarlyReported() override; - void handleFatalErrorCondition(std::string const& message) override; + void handleFatalErrorCondition( StringRef message ) override; bool lastAssertionPassed() override; From 8da0d0473bde28328988b44efab1c4f996fa56cc Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 18 Sep 2017 17:13:17 +0100 Subject: [PATCH 341/398] qualified a load of size_ts with std:: namespace (all those not from Clara) --- include/internal/catch_benchmark.h | 4 ++-- include/internal/catch_debugger.cpp | 4 ++-- include/internal/catch_interfaces_reporter.cpp | 2 +- include/internal/catch_interfaces_reporter.h | 2 +- include/internal/catch_matchers_vector.h | 2 +- include/internal/catch_objc.hpp | 4 ++-- include/internal/catch_run_context.h | 2 +- include/internal/catch_stream.cpp | 2 +- include/internal/catch_stringref.h | 2 +- include/internal/catch_test_case_info.cpp | 2 +- .../internal/catch_test_case_registry_impl.h | 2 +- include/internal/catch_test_spec_parser.h | 2 +- include/internal/catch_timer.cpp | 2 +- include/reporters/catch_reporter_bases.cpp | 2 +- include/reporters/catch_reporter_console.cpp | 2 +- include/reporters/catch_reporter_junit.cpp | 2 +- include/reporters/catch_reporter_tap.hpp | 6 +++--- projects/Benchmark/StringificationBench.cpp | 18 +++++++++--------- projects/SelfTest/MiscTests.cpp | 4 ++-- 19 files changed, 33 insertions(+), 33 deletions(-) diff --git a/include/internal/catch_benchmark.h b/include/internal/catch_benchmark.h index 2e33c163..e546713c 100644 --- a/include/internal/catch_benchmark.h +++ b/include/internal/catch_benchmark.h @@ -19,8 +19,8 @@ namespace Catch { class BenchmarkLooper { std::string m_name; - size_t m_count = 0; - size_t m_iterationsToRun = 1; + std::size_t m_count = 0; + std::size_t m_iterationsToRun = 1; uint64_t m_resolution; Timer m_timer; diff --git a/include/internal/catch_debugger.cpp b/include/internal/catch_debugger.cpp index a467e9fd..c1ef340c 100644 --- a/include/internal/catch_debugger.cpp +++ b/include/internal/catch_debugger.cpp @@ -20,7 +20,7 @@ #include #include - namespace Catch{ + namespace Catch { // The following function is taken directly from the following technical note: // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html @@ -31,7 +31,7 @@ int mib[4]; struct kinfo_proc info; - size_t size; + std::size_t size; // Initialize the flags so that, if sysctl fails for some bizarre // reason, we get a predictable result. diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp index 3859c546..129a5f4d 100644 --- a/include/internal/catch_interfaces_reporter.cpp +++ b/include/internal/catch_interfaces_reporter.cpp @@ -105,7 +105,7 @@ namespace Catch { TestRunStats::~TestRunStats() = default; - void IStreamingReporter::fatalErrorEncountered( StringRef name ) {} + void IStreamingReporter::fatalErrorEncountered( StringRef ) {} bool IStreamingReporter::isMulti() const { return false; } IReporterFactory::~IReporterFactory() = default; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 318ce669..b620abb6 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -163,7 +163,7 @@ namespace Catch { }; struct BenchmarkStats { BenchmarkInfo info; - size_t iterations; + std::size_t iterations; uint64_t elapsedTimeInNanoseconds; }; diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 85994fb0..ae2741b1 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -78,7 +78,7 @@ namespace Matchers { // - then just call that directly if (m_comparator.size() != v.size()) return false; - for (size_t i = 0; i < v.size(); ++i) + for (std::size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != v[i]) return false; return true; diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 93fbfdfb..b43f3352 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -72,8 +72,8 @@ namespace Catch { } } - inline size_t registerTestMethods() { - size_t noTestMethods = 0; + inline std::size_t registerTestMethods() { + std::size_t noTestMethods = 0; int noClasses = objc_getClassList( nullptr, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); diff --git a/include/internal/catch_run_context.h b/include/internal/catch_run_context.h index 3f238171..56e03a7a 100644 --- a/include/internal/catch_run_context.h +++ b/include/internal/catch_run_context.h @@ -135,7 +135,7 @@ namespace Catch { std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; - size_t m_prevPassed = 0; + std::size_t m_prevPassed = 0; bool m_shouldReportUnexpected = true; }; diff --git a/include/internal/catch_stream.cpp b/include/internal/catch_stream.cpp index 14a89bac..73889ce8 100644 --- a/include/internal/catch_stream.cpp +++ b/include/internal/catch_stream.cpp @@ -18,7 +18,7 @@ namespace Catch { - template + template class StreamBufImpl : public StreamBufBase { char data[bufferSize]; WriterF m_writer; diff --git a/include/internal/catch_stringref.h b/include/internal/catch_stringref.h index 5870151c..b2aad29c 100644 --- a/include/internal/catch_stringref.h +++ b/include/internal/catch_stringref.h @@ -25,7 +25,7 @@ namespace Catch { class StringRef { friend struct StringRefTestAccess; - using size_type = size_t; + using size_type = std::size_t; char const* m_start; size_type m_size; diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp index f21b6ef6..1f56dbf7 100644 --- a/include/internal/catch_test_case_info.cpp +++ b/include/internal/catch_test_case_info.cpp @@ -131,7 +131,7 @@ namespace Catch { std::string TestCaseInfo::tagsAsString() const { std::string ret; // '[' and ']' per tag - size_t full_size = 2 * tags.size(); + std::size_t full_size = 2 * tags.size(); for (const auto& tag : tags) { full_size += tag.size(); } diff --git a/include/internal/catch_test_case_registry_impl.h b/include/internal/catch_test_case_registry_impl.h index 77d4b9ee..ad45e5a0 100644 --- a/include/internal/catch_test_case_registry_impl.h +++ b/include/internal/catch_test_case_registry_impl.h @@ -43,7 +43,7 @@ namespace Catch { std::vector m_functions; mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; mutable std::vector m_sortedFunctions; - size_t m_unnamedCount = 0; + std::size_t m_unnamedCount = 0; std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; diff --git a/include/internal/catch_test_spec_parser.h b/include/internal/catch_test_spec_parser.h index 87f7f31f..79ce8898 100644 --- a/include/internal/catch_test_spec_parser.h +++ b/include/internal/catch_test_spec_parser.h @@ -45,7 +45,7 @@ namespace Catch { template void addPattern() { std::string token = subString(); - for( size_t i = 0; i < m_escapeChars.size(); ++i ) + for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); m_escapeChars.clear(); if( startsWith( token, "exclude:" ) ) { diff --git a/include/internal/catch_timer.cpp b/include/internal/catch_timer.cpp index ec1d8bb5..a6f37e8e 100644 --- a/include/internal/catch_timer.cpp +++ b/include/internal/catch_timer.cpp @@ -20,7 +20,7 @@ namespace Catch { uint64_t sum = 0; static const uint64_t iterations = 1000000; - for( size_t i = 0; i < iterations; ++i ) { + for( std::size_t i = 0; i < iterations; ++i ) { uint64_t ticks; uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); diff --git a/include/reporters/catch_reporter_bases.cpp b/include/reporters/catch_reporter_bases.cpp index 1db7868c..c2059b5a 100644 --- a/include/reporters/catch_reporter_bases.cpp +++ b/include/reporters/catch_reporter_bases.cpp @@ -28,7 +28,7 @@ namespace Catch { // + 1 for decimal point // + 3 for the 3 decimal places // + 1 for null terminator - const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; char buffer[maxDoubleSize]; // Save previous errno, to prevent sprintf from overwriting it diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index a3662d9c..12ba72ec 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -95,7 +95,7 @@ namespace { tp.m_currentColumn++; auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = ( strSize+2 < static_cast( colInfo.width ) ) + auto padding = ( strSize+2 < static_cast( colInfo.width ) ) ? std::string( colInfo.width-(strSize+2), ' ' ) : std::string(); if( colInfo.justification == ColumnInfo::Left ) diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp index c0e2e3cf..bb7f6d9c 100644 --- a/include/reporters/catch_reporter_junit.cpp +++ b/include/reporters/catch_reporter_junit.cpp @@ -26,7 +26,7 @@ namespace Catch { // Also, UTC only, again because of backward compatibility (%z is C++11) time_t rawtime; std::time(&rawtime); - const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); #ifdef _MSC_VER std::tm timeInfo = {}; diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index dbcad5ee..edb75b5a 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -59,12 +59,12 @@ namespace Catch { } private: - size_t counter = 0; + std::size_t counter = 0; class AssertionPrinter { public: AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; AssertionPrinter( AssertionPrinter const& ) = delete; - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, size_t _counter ) + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter ) : stream( _stream ) , result( _stats.assertionResult ) , messages( _stats.infoMessages ) @@ -232,7 +232,7 @@ namespace Catch { std::vector messages; std::vector::const_iterator itMessage; bool printInfoMessages; - size_t counter; + std::size_t counter; }; void printTotals( const Totals& totals ) const { diff --git a/projects/Benchmark/StringificationBench.cpp b/projects/Benchmark/StringificationBench.cpp index 1c14939b..765b4e96 100644 --- a/projects/Benchmark/StringificationBench.cpp +++ b/projects/Benchmark/StringificationBench.cpp @@ -11,11 +11,11 @@ /////////////////////////////////////////////////////////////////////////////// TEST_CASE("Successful tests -- REQUIRE", "[Success]") { - const size_t sz = 1 * 1024 * 1024; + const std::size_t sz = 1 * 1024 * 1024; - std::vector vec; vec.reserve(sz); - for (size_t i = 0; i < sz; ++i){ + std::vector vec; vec.reserve(sz); + for (std::size_t i = 0; i < sz; ++i){ vec.push_back(i); REQUIRE(vec.back() == i); } @@ -23,11 +23,11 @@ TEST_CASE("Successful tests -- REQUIRE", "[Success]") { /////////////////////////////////////////////////////////////////////////////// TEST_CASE("Successful tests -- CHECK", "[Success]") { - const size_t sz = 1 * 1024 * 1024; + const std::size_t sz = 1 * 1024 * 1024; - std::vector vec; vec.reserve(sz); - for (size_t i = 0; i < sz; ++i){ + std::vector vec; vec.reserve(sz); + for (std::size_t i = 0; i < sz; ++i){ vec.push_back(i); CHECK(vec.back() == i); } @@ -35,11 +35,11 @@ TEST_CASE("Successful tests -- CHECK", "[Success]") { /////////////////////////////////////////////////////////////////////////////// TEST_CASE("Unsuccessful tests -- CHECK", "[Failure]") { - const size_t sz = 1024 * 1024; + const std::size_t sz = 1024 * 1024; - std::vector vec; vec.reserve(sz); - for (size_t i = 0; i < sz; ++i){ + std::vector vec; vec.reserve(sz); + for (std::size_t i = 0; i < sz; ++i){ vec.push_back(i); CHECK(vec.size() == i); } diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 2151d77c..ff9a0a10 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -96,7 +96,7 @@ TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) { TEST_CASE( "looped tests", "[.][failing]" ) { static const int fib[] = { 1, 1, 2, 3, 5, 8, 13, 21 }; - for( size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) { + for( std::size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) { INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" ); CHECK( ( fib[i] % 2 ) == 0 ); } @@ -163,7 +163,7 @@ TEST_CASE( "send a single char to INFO", "[failing][.]" ) { } TEST_CASE( "atomic if", "[failing][0]") { - size_t x = 0; + std::size_t x = 0; if( x ) REQUIRE(x > 0); From a63b4a75bd2084b103c3e6dd49a239db838ab1b8 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 19 Sep 2017 14:37:35 +0100 Subject: [PATCH 342/398] Updated OCTest project --- .../OCTest/OCTest.xcodeproj/project.pbxproj | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj index 03cd3714..c2611c6f 100644 --- a/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj +++ b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj @@ -61,6 +61,14 @@ 2621EE821F60360800D9AA4C /* catch_reporter_junit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */; }; 2621EE831F60360800D9AA4C /* catch_reporter_multi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */; }; 2621EE841F60360800D9AA4C /* catch_reporter_xml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */; }; + 4A5C29A11F7152A4007CB94C /* catch_interfaces_capture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C29991F7152A4007CB94C /* catch_interfaces_capture.cpp */; }; + 4A5C29A21F7152A4007CB94C /* catch_interfaces_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299A1F7152A4007CB94C /* catch_interfaces_config.cpp */; }; + 4A5C29A31F7152A4007CB94C /* catch_interfaces_exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299B1F7152A4007CB94C /* catch_interfaces_exception.cpp */; }; + 4A5C29A41F7152A4007CB94C /* catch_interfaces_registry_hub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299C1F7152A4007CB94C /* catch_interfaces_registry_hub.cpp */; }; + 4A5C29A51F7152A4007CB94C /* catch_interfaces_runner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299D1F7152A4007CB94C /* catch_interfaces_runner.cpp */; }; + 4A5C29A61F7152A4007CB94C /* catch_interfaces_testcase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299E1F7152A4007CB94C /* catch_interfaces_testcase.cpp */; }; + 4A5C29A71F7152A4007CB94C /* catch_reporter_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299F1F7152A4007CB94C /* catch_reporter_registry.cpp */; }; + 4A5C29A81F7152A4007CB94C /* catch_streambuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C29A01F7152A4007CB94C /* catch_streambuf.cpp */; }; 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A63D2AB14E3C1A900F615CB /* OCTest.1 */; }; 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2B214E3C1E600F615CB /* Main.mm */; }; 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A63D2BF14E4544700F615CB /* Foundation.framework */; }; @@ -137,6 +145,14 @@ 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_junit.cpp; path = ../../../include/reporters/catch_reporter_junit.cpp; sourceTree = ""; }; 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_multi.cpp; path = ../../../include/reporters/catch_reporter_multi.cpp; sourceTree = ""; }; 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_xml.cpp; path = ../../../include/reporters/catch_reporter_xml.cpp; sourceTree = ""; }; + 4A5C29991F7152A4007CB94C /* catch_interfaces_capture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_capture.cpp; path = ../../../include/internal/catch_interfaces_capture.cpp; sourceTree = ""; }; + 4A5C299A1F7152A4007CB94C /* catch_interfaces_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_config.cpp; path = ../../../include/internal/catch_interfaces_config.cpp; sourceTree = ""; }; + 4A5C299B1F7152A4007CB94C /* catch_interfaces_exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_exception.cpp; path = ../../../include/internal/catch_interfaces_exception.cpp; sourceTree = ""; }; + 4A5C299C1F7152A4007CB94C /* catch_interfaces_registry_hub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_registry_hub.cpp; path = ../../../include/internal/catch_interfaces_registry_hub.cpp; sourceTree = ""; }; + 4A5C299D1F7152A4007CB94C /* catch_interfaces_runner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_runner.cpp; path = ../../../include/internal/catch_interfaces_runner.cpp; sourceTree = ""; }; + 4A5C299E1F7152A4007CB94C /* catch_interfaces_testcase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_testcase.cpp; path = ../../../include/internal/catch_interfaces_testcase.cpp; sourceTree = ""; }; + 4A5C299F1F7152A4007CB94C /* catch_reporter_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_registry.cpp; path = ../../../include/internal/catch_reporter_registry.cpp; sourceTree = ""; }; + 4A5C29A01F7152A4007CB94C /* catch_streambuf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_streambuf.cpp; path = ../../../include/internal/catch_streambuf.cpp; sourceTree = ""; }; 4A63D2A514E3C1A900F615CB /* OCTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OCTest; sourceTree = BUILT_PRODUCTS_DIR; }; 4A63D2AB14E3C1A900F615CB /* OCTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = OCTest.1; sourceTree = ""; }; 4A63D2B214E3C1E600F615CB /* Main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Main.mm; sourceTree = ""; }; @@ -197,6 +213,14 @@ 4AA0D94F154C0A63004B4193 /* Catch */ = { isa = PBXGroup; children = ( + 4A5C29991F7152A4007CB94C /* catch_interfaces_capture.cpp */, + 4A5C299A1F7152A4007CB94C /* catch_interfaces_config.cpp */, + 4A5C299B1F7152A4007CB94C /* catch_interfaces_exception.cpp */, + 4A5C299C1F7152A4007CB94C /* catch_interfaces_registry_hub.cpp */, + 4A5C299D1F7152A4007CB94C /* catch_interfaces_runner.cpp */, + 4A5C299E1F7152A4007CB94C /* catch_interfaces_testcase.cpp */, + 4A5C299F1F7152A4007CB94C /* catch_reporter_registry.cpp */, + 4A5C29A01F7152A4007CB94C /* catch_streambuf.cpp */, 2621EE791F60360800D9AA4C /* catch_reporter_bases.cpp */, 2621EE7A1F60360800D9AA4C /* catch_reporter_compact.cpp */, 2621EE7B1F60360800D9AA4C /* catch_reporter_console.cpp */, @@ -307,6 +331,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4A5C29A51F7152A4007CB94C /* catch_interfaces_runner.cpp in Sources */, 2621EE841F60360800D9AA4C /* catch_reporter_xml.cpp in Sources */, 2621EE561F602F8300D9AA4C /* catch_errno_guard.cpp in Sources */, 2621EE4F1F602F8300D9AA4C /* catch_common.cpp in Sources */, @@ -314,12 +339,14 @@ 2621EE6E1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp in Sources */, 2621EE6F1F602F8300D9AA4C /* catch_test_case_tracker.cpp in Sources */, 2621EE6D1F602F8300D9AA4C /* catch_test_case_info.cpp in Sources */, + 4A5C29A21F7152A4007CB94C /* catch_interfaces_config.cpp in Sources */, 2621EE5A1F602F8300D9AA4C /* catch_leak_detector.cpp in Sources */, 2621EE501F602F8300D9AA4C /* catch_config.cpp in Sources */, 2621EE6A1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp in Sources */, 2621EE751F602F8300D9AA4C /* catch_totals.cpp in Sources */, 2621EE801F60360800D9AA4C /* catch_reporter_compact.cpp in Sources */, 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */, + 4A5C29A61F7152A4007CB94C /* catch_interfaces_testcase.cpp in Sources */, 2621EE711F602F8300D9AA4C /* catch_test_spec_parser.cpp in Sources */, 2621EE5F1F602F8300D9AA4C /* catch_random_number_generator.cpp in Sources */, 2621EE531F602F8300D9AA4C /* catch_debug_console.cpp in Sources */, @@ -328,6 +355,7 @@ 2621EE5B1F602F8300D9AA4C /* catch_list.cpp in Sources */, 2621EE581F602F8300D9AA4C /* catch_fatal_condition.cpp in Sources */, 2621EE5D1F602F8300D9AA4C /* catch_matchers.cpp in Sources */, + 4A5C29A41F7152A4007CB94C /* catch_interfaces_registry_hub.cpp in Sources */, 2621EE7F1F60360800D9AA4C /* catch_reporter_bases.cpp in Sources */, 2621EE591F602F8300D9AA4C /* catch_interfaces_reporter.cpp in Sources */, 2621EE611F602F8300D9AA4C /* catch_result_type.cpp in Sources */, @@ -341,10 +369,12 @@ 2621EE621F602F8300D9AA4C /* catch_run_context.cpp in Sources */, 2621EE6C1F602F8300D9AA4C /* catch_tag_alias.cpp in Sources */, 2621EE1A1F602F2C00D9AA4C /* catch_approx.cpp in Sources */, + 4A5C29A31F7152A4007CB94C /* catch_interfaces_exception.cpp in Sources */, 2621EE511F602F8300D9AA4C /* catch_console_colour.cpp in Sources */, 2621EE771F602F8300D9AA4C /* catch_wildcard_pattern.cpp in Sources */, 2621EE811F60360800D9AA4C /* catch_reporter_console.cpp in Sources */, 2621EE691F602F8300D9AA4C /* catch_stringref.cpp in Sources */, + 4A5C29A11F7152A4007CB94C /* catch_interfaces_capture.cpp in Sources */, 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */, 2621EE831F60360800D9AA4C /* catch_reporter_multi.cpp in Sources */, 2621EE541F602F8300D9AA4C /* catch_debugger.cpp in Sources */, @@ -352,6 +382,7 @@ 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */, 2621EE5C1F602F8300D9AA4C /* catch_matchers_string.cpp in Sources */, 2621EE4E1F602F8300D9AA4C /* catch_commandline.cpp in Sources */, + 4A5C29A71F7152A4007CB94C /* catch_reporter_registry.cpp in Sources */, 2621EE651F602F8300D9AA4C /* catch_session.cpp in Sources */, 2621EE661F602F8300D9AA4C /* catch_startup_exception_registry.cpp in Sources */, 2621EE641F602F8300D9AA4C /* catch_section.cpp in Sources */, @@ -361,6 +392,7 @@ 2621EE671F602F8300D9AA4C /* catch_stream.cpp in Sources */, 2621EE551F602F8300D9AA4C /* catch_decomposer.cpp in Sources */, 2621EE4A1F602F8300D9AA4C /* catch_assertionhandler.cpp in Sources */, + 4A5C29A81F7152A4007CB94C /* catch_streambuf.cpp in Sources */, 2621EE631F602F8300D9AA4C /* catch_section_info.cpp in Sources */, 2621EE521F602F8300D9AA4C /* catch_context.cpp in Sources */, 2621EE571F602F8300D9AA4C /* catch_exception_translator_registry.cpp in Sources */, From b9ff7ec301a6b47cb02a0021b1ab773226fbf17b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 19 Sep 2017 14:38:18 +0100 Subject: [PATCH 343/398] Fixed issues for ObjC use (see #1011) --- .../catch_exception_translator_registry.cpp | 2 +- include/reporters/catch_reporter_console.cpp | 342 +++++++++--------- 2 files changed, 172 insertions(+), 172 deletions(-) diff --git a/include/internal/catch_exception_translator_registry.cpp b/include/internal/catch_exception_translator_registry.cpp index 98b92316..ce45194b 100644 --- a/include/internal/catch_exception_translator_registry.cpp +++ b/include/internal/catch_exception_translator_registry.cpp @@ -30,7 +30,7 @@ namespace Catch { return tryTranslators(); } @catch (NSException *exception) { - return Catch::toString( [exception description] ); + return Catch::Detail::stringify( [exception description] ); } #else return tryTranslators(); diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 12ba72ec..31a46bd9 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -17,179 +17,179 @@ #include #include -namespace { - std::size_t makeRatio( std::size_t number, std::size_t total ) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; - return ( ratio == 0 && number > 0 ) ? 1 : ratio; - } - - std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { - if( i > j && i > k ) - return i; - else if( j > k ) - return j; - else - return k; - } - - struct ColumnInfo { - enum Justification { Left, Right }; - std::string name; - int width; - Justification justification; - }; - struct ColumnBreak {}; - struct RowBreak {}; - - class TablePrinter { - std::ostream& m_os; - std::vector m_columnInfos; - std::ostringstream m_oss; - int m_currentColumn = -1; - bool m_isOpen = false; - - public: - TablePrinter( std::ostream& os, std::vector const& columnInfos ) - : m_os( os ), - m_columnInfos( columnInfos ) - {} - - auto columnInfos() const -> std::vector const& { - return m_columnInfos; - } - - void open() { - if( !m_isOpen ) { - m_isOpen = true; - *this << RowBreak(); - for( auto const& info : m_columnInfos ) - *this << info.name << ColumnBreak(); - *this << RowBreak(); - m_os << Catch::getLineOfChars<'-'>() << "\n"; - } - } - void close() { - if( m_isOpen ) { - *this << RowBreak(); - m_os << std::endl; - m_isOpen = false; - } - } - - template - friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { - tp.m_oss << value; - return tp; - } - - friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { - auto colStr = tp.m_oss.str(); - // This takes account of utf8 encodings - auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); - tp.m_oss.str(""); - tp.open(); - if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { - tp.m_currentColumn = -1; - tp.m_os << "\n"; - } - tp.m_currentColumn++; - - auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = ( strSize+2 < static_cast( colInfo.width ) ) - ? std::string( colInfo.width-(strSize+2), ' ' ) - : std::string(); - if( colInfo.justification == ColumnInfo::Left ) - tp.m_os << colStr << padding << " "; - else - tp.m_os << padding << colStr << " "; - return tp; - } - - friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { - if( tp.m_currentColumn > 0 ) { - tp.m_os << "\n"; - tp.m_currentColumn = -1; - } - return tp; - } - }; - - class Duration { - enum class Unit { - Auto, - Nanoseconds, - Microseconds, - Milliseconds, - Seconds, - Minutes - }; - static const uint64_t s_nanosecondsInAMicrosecond = 1000; - static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; - static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; - static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; - - uint64_t m_inNanoseconds; - Unit m_units; - - public: - Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) - : m_inNanoseconds( inNanoseconds ), - m_units( units ) - { - if( m_units == Unit::Auto ) { - if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) - m_units = Unit::Nanoseconds; - else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) - m_units = Unit::Microseconds; - else if( m_inNanoseconds < s_nanosecondsInASecond ) - m_units = Unit::Milliseconds; - else if( m_inNanoseconds < s_nanosecondsInAMinute ) - m_units = Unit::Seconds; - else - m_units = Unit::Minutes; - } - - } - - auto value() const -> double { - switch( m_units ) { - case Unit::Microseconds: - return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); - case Unit::Milliseconds: - return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); - case Unit::Seconds: - return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); - case Unit::Minutes: - return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); - default: - return static_cast( m_inNanoseconds ); - } - } - auto unitsAsString() const -> std::string { - switch( m_units ) { - case Unit::Nanoseconds: - return "ns"; - case Unit::Microseconds: - return "µs"; - case Unit::Milliseconds: - return "ms"; - case Unit::Seconds: - return "s"; - case Unit::Minutes: - return "m"; - default: - return "** internal error **"; - } - - } - friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { - return os << duration.value() << " " << duration.unitsAsString(); - } - }; -} - namespace Catch { + namespace { + std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + + std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + struct ColumnInfo { + enum Justification { Left, Right }; + std::string name; + int width; + Justification justification; + }; + struct ColumnBreak {}; + struct RowBreak {}; + + class TablePrinter { + std::ostream& m_os; + std::vector m_columnInfos; + std::ostringstream m_oss; + int m_currentColumn = -1; + bool m_isOpen = false; + + public: + TablePrinter( std::ostream& os, std::vector const& columnInfos ) + : m_os( os ), + m_columnInfos( columnInfos ) + {} + + auto columnInfos() const -> std::vector const& { + return m_columnInfos; + } + + void open() { + if( !m_isOpen ) { + m_isOpen = true; + *this << RowBreak(); + for( auto const& info : m_columnInfos ) + *this << info.name << ColumnBreak(); + *this << RowBreak(); + m_os << Catch::getLineOfChars<'-'>() << "\n"; + } + } + void close() { + if( m_isOpen ) { + *this << RowBreak(); + m_os << std::endl; + m_isOpen = false; + } + } + + template + friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { + tp.m_oss << value; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { + auto colStr = tp.m_oss.str(); + // This takes account of utf8 encodings + auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); + tp.m_oss.str(""); + tp.open(); + if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { + tp.m_currentColumn = -1; + tp.m_os << "\n"; + } + tp.m_currentColumn++; + + auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; + auto padding = ( strSize+2 < static_cast( colInfo.width ) ) + ? std::string( colInfo.width-(strSize+2), ' ' ) + : std::string(); + if( colInfo.justification == ColumnInfo::Left ) + tp.m_os << colStr << padding << " "; + else + tp.m_os << padding << colStr << " "; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { + if( tp.m_currentColumn > 0 ) { + tp.m_os << "\n"; + tp.m_currentColumn = -1; + } + return tp; + } + }; + + class Duration { + enum class Unit { + Auto, + Nanoseconds, + Microseconds, + Milliseconds, + Seconds, + Minutes + }; + static const uint64_t s_nanosecondsInAMicrosecond = 1000; + static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; + static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; + static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; + + uint64_t m_inNanoseconds; + Unit m_units; + + public: + Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) + : m_inNanoseconds( inNanoseconds ), + m_units( units ) + { + if( m_units == Unit::Auto ) { + if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) + m_units = Unit::Nanoseconds; + else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) + m_units = Unit::Microseconds; + else if( m_inNanoseconds < s_nanosecondsInASecond ) + m_units = Unit::Milliseconds; + else if( m_inNanoseconds < s_nanosecondsInAMinute ) + m_units = Unit::Seconds; + else + m_units = Unit::Minutes; + } + + } + + auto value() const -> double { + switch( m_units ) { + case Unit::Microseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); + case Unit::Milliseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); + case Unit::Seconds: + return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); + case Unit::Minutes: + return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); + default: + return static_cast( m_inNanoseconds ); + } + } + auto unitsAsString() const -> std::string { + switch( m_units ) { + case Unit::Nanoseconds: + return "ns"; + case Unit::Microseconds: + return "µs"; + case Unit::Milliseconds: + return "ms"; + case Unit::Seconds: + return "s"; + case Unit::Minutes: + return "m"; + default: + return "** internal error **"; + } + + } + friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { + return os << duration.value() << " " << duration.unitsAsString(); + } + }; + } // end anon namespace + struct ConsoleReporter : StreamingReporterBase { TablePrinter m_tablePrinter; From 0a146e3af7dfa8dd3be2b0e7a9804818076895da Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 19 Sep 2017 14:59:12 +0100 Subject: [PATCH 344/398] OCTest project now #includes all cpp files, so they all get __OBJC__ defined --- include/reporters/catch_reporter_multi.h | 4 + .../OCTest/OCTest.xcodeproj/project.pbxproj | 256 +----------------- projects/XCode/OCTest/catch_objc_impl.mm | 68 +++++ 3 files changed, 76 insertions(+), 252 deletions(-) create mode 100644 projects/XCode/OCTest/catch_objc_impl.mm diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_multi.h index ec14f458..02924c9c 100644 --- a/include/reporters/catch_reporter_multi.h +++ b/include/reporters/catch_reporter_multi.h @@ -4,6 +4,8 @@ * 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) */ +#ifndef TWOBLUECUBES_CATCH_MULTI_REPORTER_H_INCLUDED +#define TWOBLUECUBES_CATCH_MULTI_REPORTER_H_INCLUDED #include "../internal/catch_interfaces_reporter.h" @@ -43,3 +45,5 @@ namespace Catch { }; } // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_MULTI_REPORTER_H_INCLUDED diff --git a/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj index c2611c6f..91e2cd9a 100644 --- a/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj +++ b/projects/XCode/OCTest/OCTest.xcodeproj/project.pbxproj @@ -7,68 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 2621EE1A1F602F2C00D9AA4C /* catch_approx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE191F602F2C00D9AA4C /* catch_approx.cpp */; }; - 2621EE4A1F602F8300D9AA4C /* catch_assertionhandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1B1F602F8200D9AA4C /* catch_assertionhandler.cpp */; }; - 2621EE4B1F602F8300D9AA4C /* catch_assertionresult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1C1F602F8200D9AA4C /* catch_assertionresult.cpp */; }; - 2621EE4C1F602F8300D9AA4C /* catch_benchmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1D1F602F8200D9AA4C /* catch_benchmark.cpp */; }; - 2621EE4D1F602F8300D9AA4C /* catch_capture_matchers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1E1F602F8200D9AA4C /* catch_capture_matchers.cpp */; }; - 2621EE4E1F602F8300D9AA4C /* catch_commandline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE1F1F602F8200D9AA4C /* catch_commandline.cpp */; }; - 2621EE4F1F602F8300D9AA4C /* catch_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE201F602F8200D9AA4C /* catch_common.cpp */; }; - 2621EE501F602F8300D9AA4C /* catch_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE211F602F8200D9AA4C /* catch_config.cpp */; }; - 2621EE511F602F8300D9AA4C /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE221F602F8200D9AA4C /* catch_console_colour.cpp */; }; - 2621EE521F602F8300D9AA4C /* catch_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE231F602F8200D9AA4C /* catch_context.cpp */; }; - 2621EE531F602F8300D9AA4C /* catch_debug_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE241F602F8200D9AA4C /* catch_debug_console.cpp */; }; - 2621EE541F602F8300D9AA4C /* catch_debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE251F602F8200D9AA4C /* catch_debugger.cpp */; }; - 2621EE551F602F8300D9AA4C /* catch_decomposer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE261F602F8200D9AA4C /* catch_decomposer.cpp */; }; - 2621EE561F602F8300D9AA4C /* catch_errno_guard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE271F602F8200D9AA4C /* catch_errno_guard.cpp */; }; - 2621EE571F602F8300D9AA4C /* catch_exception_translator_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE281F602F8200D9AA4C /* catch_exception_translator_registry.cpp */; }; - 2621EE581F602F8300D9AA4C /* catch_fatal_condition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE291F602F8200D9AA4C /* catch_fatal_condition.cpp */; }; - 2621EE591F602F8300D9AA4C /* catch_interfaces_reporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2A1F602F8200D9AA4C /* catch_interfaces_reporter.cpp */; }; - 2621EE5A1F602F8300D9AA4C /* catch_leak_detector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2B1F602F8300D9AA4C /* catch_leak_detector.cpp */; }; - 2621EE5B1F602F8300D9AA4C /* catch_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2C1F602F8300D9AA4C /* catch_list.cpp */; }; - 2621EE5C1F602F8300D9AA4C /* catch_matchers_string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2D1F602F8300D9AA4C /* catch_matchers_string.cpp */; }; - 2621EE5D1F602F8300D9AA4C /* catch_matchers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2E1F602F8300D9AA4C /* catch_matchers.cpp */; }; - 2621EE5E1F602F8300D9AA4C /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE2F1F602F8300D9AA4C /* catch_message.cpp */; }; - 2621EE5F1F602F8300D9AA4C /* catch_random_number_generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE301F602F8300D9AA4C /* catch_random_number_generator.cpp */; }; - 2621EE601F602F8300D9AA4C /* catch_registry_hub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE311F602F8300D9AA4C /* catch_registry_hub.cpp */; }; - 2621EE611F602F8300D9AA4C /* catch_result_type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE321F602F8300D9AA4C /* catch_result_type.cpp */; }; - 2621EE621F602F8300D9AA4C /* catch_run_context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE331F602F8300D9AA4C /* catch_run_context.cpp */; }; - 2621EE631F602F8300D9AA4C /* catch_section_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE341F602F8300D9AA4C /* catch_section_info.cpp */; }; - 2621EE641F602F8300D9AA4C /* catch_section.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE351F602F8300D9AA4C /* catch_section.cpp */; }; - 2621EE651F602F8300D9AA4C /* catch_session.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE361F602F8300D9AA4C /* catch_session.cpp */; }; - 2621EE661F602F8300D9AA4C /* catch_startup_exception_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE371F602F8300D9AA4C /* catch_startup_exception_registry.cpp */; }; - 2621EE671F602F8300D9AA4C /* catch_stream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE381F602F8300D9AA4C /* catch_stream.cpp */; }; - 2621EE681F602F8300D9AA4C /* catch_string_manip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE391F602F8300D9AA4C /* catch_string_manip.cpp */; }; - 2621EE691F602F8300D9AA4C /* catch_stringref.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3A1F602F8300D9AA4C /* catch_stringref.cpp */; }; - 2621EE6A1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3B1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp */; }; - 2621EE6B1F602F8300D9AA4C /* catch_tag_alias_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3C1F602F8300D9AA4C /* catch_tag_alias_registry.cpp */; }; - 2621EE6C1F602F8300D9AA4C /* catch_tag_alias.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3D1F602F8300D9AA4C /* catch_tag_alias.cpp */; }; - 2621EE6D1F602F8300D9AA4C /* catch_test_case_info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3E1F602F8300D9AA4C /* catch_test_case_info.cpp */; }; - 2621EE6E1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE3F1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp */; }; - 2621EE6F1F602F8300D9AA4C /* catch_test_case_tracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE401F602F8300D9AA4C /* catch_test_case_tracker.cpp */; }; - 2621EE701F602F8300D9AA4C /* catch_test_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE411F602F8300D9AA4C /* catch_test_registry.cpp */; }; - 2621EE711F602F8300D9AA4C /* catch_test_spec_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE421F602F8300D9AA4C /* catch_test_spec_parser.cpp */; }; - 2621EE721F602F8300D9AA4C /* catch_test_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE431F602F8300D9AA4C /* catch_test_spec.cpp */; }; - 2621EE731F602F8300D9AA4C /* catch_timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE441F602F8300D9AA4C /* catch_timer.cpp */; }; - 2621EE741F602F8300D9AA4C /* catch_tostring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE451F602F8300D9AA4C /* catch_tostring.cpp */; }; - 2621EE751F602F8300D9AA4C /* catch_totals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE461F602F8300D9AA4C /* catch_totals.cpp */; }; - 2621EE761F602F8300D9AA4C /* catch_version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE471F602F8300D9AA4C /* catch_version.cpp */; }; - 2621EE771F602F8300D9AA4C /* catch_wildcard_pattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE481F602F8300D9AA4C /* catch_wildcard_pattern.cpp */; }; - 2621EE781F602F8300D9AA4C /* catch_xmlwriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE491F602F8300D9AA4C /* catch_xmlwriter.cpp */; }; - 2621EE7F1F60360800D9AA4C /* catch_reporter_bases.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE791F60360800D9AA4C /* catch_reporter_bases.cpp */; }; - 2621EE801F60360800D9AA4C /* catch_reporter_compact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7A1F60360800D9AA4C /* catch_reporter_compact.cpp */; }; - 2621EE811F60360800D9AA4C /* catch_reporter_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7B1F60360800D9AA4C /* catch_reporter_console.cpp */; }; - 2621EE821F60360800D9AA4C /* catch_reporter_junit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */; }; - 2621EE831F60360800D9AA4C /* catch_reporter_multi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */; }; - 2621EE841F60360800D9AA4C /* catch_reporter_xml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */; }; - 4A5C29A11F7152A4007CB94C /* catch_interfaces_capture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C29991F7152A4007CB94C /* catch_interfaces_capture.cpp */; }; - 4A5C29A21F7152A4007CB94C /* catch_interfaces_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299A1F7152A4007CB94C /* catch_interfaces_config.cpp */; }; - 4A5C29A31F7152A4007CB94C /* catch_interfaces_exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299B1F7152A4007CB94C /* catch_interfaces_exception.cpp */; }; - 4A5C29A41F7152A4007CB94C /* catch_interfaces_registry_hub.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299C1F7152A4007CB94C /* catch_interfaces_registry_hub.cpp */; }; - 4A5C29A51F7152A4007CB94C /* catch_interfaces_runner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299D1F7152A4007CB94C /* catch_interfaces_runner.cpp */; }; - 4A5C29A61F7152A4007CB94C /* catch_interfaces_testcase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299E1F7152A4007CB94C /* catch_interfaces_testcase.cpp */; }; - 4A5C29A71F7152A4007CB94C /* catch_reporter_registry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C299F1F7152A4007CB94C /* catch_reporter_registry.cpp */; }; - 4A5C29A81F7152A4007CB94C /* catch_streambuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C29A01F7152A4007CB94C /* catch_streambuf.cpp */; }; + 4A5C29AA1F715603007CB94C /* catch_objc_impl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A5C29A91F715603007CB94C /* catch_objc_impl.mm */; }; 4A63D2AC14E3C1A900F615CB /* OCTest.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4A63D2AB14E3C1A900F615CB /* OCTest.1 */; }; 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4A63D2B214E3C1E600F615CB /* Main.mm */; }; 4A63D2C014E4544700F615CB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A63D2BF14E4544700F615CB /* Foundation.framework */; }; @@ -91,68 +30,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 2621EE191F602F2C00D9AA4C /* catch_approx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_approx.cpp; path = ../../../include/internal/catch_approx.cpp; sourceTree = ""; }; - 2621EE1B1F602F8200D9AA4C /* catch_assertionhandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_assertionhandler.cpp; path = ../../../include/internal/catch_assertionhandler.cpp; sourceTree = ""; }; - 2621EE1C1F602F8200D9AA4C /* catch_assertionresult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_assertionresult.cpp; path = ../../../include/internal/catch_assertionresult.cpp; sourceTree = ""; }; - 2621EE1D1F602F8200D9AA4C /* catch_benchmark.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_benchmark.cpp; path = ../../../include/internal/catch_benchmark.cpp; sourceTree = ""; }; - 2621EE1E1F602F8200D9AA4C /* catch_capture_matchers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_capture_matchers.cpp; path = ../../../include/internal/catch_capture_matchers.cpp; sourceTree = ""; }; - 2621EE1F1F602F8200D9AA4C /* catch_commandline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_commandline.cpp; path = ../../../include/internal/catch_commandline.cpp; sourceTree = ""; }; - 2621EE201F602F8200D9AA4C /* catch_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_common.cpp; path = ../../../include/internal/catch_common.cpp; sourceTree = ""; }; - 2621EE211F602F8200D9AA4C /* catch_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_config.cpp; path = ../../../include/internal/catch_config.cpp; sourceTree = ""; }; - 2621EE221F602F8200D9AA4C /* catch_console_colour.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_console_colour.cpp; path = ../../../include/internal/catch_console_colour.cpp; sourceTree = ""; }; - 2621EE231F602F8200D9AA4C /* catch_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_context.cpp; path = ../../../include/internal/catch_context.cpp; sourceTree = ""; }; - 2621EE241F602F8200D9AA4C /* catch_debug_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_debug_console.cpp; path = ../../../include/internal/catch_debug_console.cpp; sourceTree = ""; }; - 2621EE251F602F8200D9AA4C /* catch_debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_debugger.cpp; path = ../../../include/internal/catch_debugger.cpp; sourceTree = ""; }; - 2621EE261F602F8200D9AA4C /* catch_decomposer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_decomposer.cpp; path = ../../../include/internal/catch_decomposer.cpp; sourceTree = ""; }; - 2621EE271F602F8200D9AA4C /* catch_errno_guard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_errno_guard.cpp; path = ../../../include/internal/catch_errno_guard.cpp; sourceTree = ""; }; - 2621EE281F602F8200D9AA4C /* catch_exception_translator_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_exception_translator_registry.cpp; path = ../../../include/internal/catch_exception_translator_registry.cpp; sourceTree = ""; }; - 2621EE291F602F8200D9AA4C /* catch_fatal_condition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_fatal_condition.cpp; path = ../../../include/internal/catch_fatal_condition.cpp; sourceTree = ""; }; - 2621EE2A1F602F8200D9AA4C /* catch_interfaces_reporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_reporter.cpp; path = ../../../include/internal/catch_interfaces_reporter.cpp; sourceTree = ""; }; - 2621EE2B1F602F8300D9AA4C /* catch_leak_detector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_leak_detector.cpp; path = ../../../include/internal/catch_leak_detector.cpp; sourceTree = ""; }; - 2621EE2C1F602F8300D9AA4C /* catch_list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_list.cpp; path = ../../../include/internal/catch_list.cpp; sourceTree = ""; }; - 2621EE2D1F602F8300D9AA4C /* catch_matchers_string.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_matchers_string.cpp; path = ../../../include/internal/catch_matchers_string.cpp; sourceTree = ""; }; - 2621EE2E1F602F8300D9AA4C /* catch_matchers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_matchers.cpp; path = ../../../include/internal/catch_matchers.cpp; sourceTree = ""; }; - 2621EE2F1F602F8300D9AA4C /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../include/internal/catch_message.cpp; sourceTree = ""; }; - 2621EE301F602F8300D9AA4C /* catch_random_number_generator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_random_number_generator.cpp; path = ../../../include/internal/catch_random_number_generator.cpp; sourceTree = ""; }; - 2621EE311F602F8300D9AA4C /* catch_registry_hub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_registry_hub.cpp; path = ../../../include/internal/catch_registry_hub.cpp; sourceTree = ""; }; - 2621EE321F602F8300D9AA4C /* catch_result_type.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_result_type.cpp; path = ../../../include/internal/catch_result_type.cpp; sourceTree = ""; }; - 2621EE331F602F8300D9AA4C /* catch_run_context.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_run_context.cpp; path = ../../../include/internal/catch_run_context.cpp; sourceTree = ""; }; - 2621EE341F602F8300D9AA4C /* catch_section_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_section_info.cpp; path = ../../../include/internal/catch_section_info.cpp; sourceTree = ""; }; - 2621EE351F602F8300D9AA4C /* catch_section.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_section.cpp; path = ../../../include/internal/catch_section.cpp; sourceTree = ""; }; - 2621EE361F602F8300D9AA4C /* catch_session.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_session.cpp; path = ../../../include/internal/catch_session.cpp; sourceTree = ""; }; - 2621EE371F602F8300D9AA4C /* catch_startup_exception_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_startup_exception_registry.cpp; path = ../../../include/internal/catch_startup_exception_registry.cpp; sourceTree = ""; }; - 2621EE381F602F8300D9AA4C /* catch_stream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_stream.cpp; path = ../../../include/internal/catch_stream.cpp; sourceTree = ""; }; - 2621EE391F602F8300D9AA4C /* catch_string_manip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_string_manip.cpp; path = ../../../include/internal/catch_string_manip.cpp; sourceTree = ""; }; - 2621EE3A1F602F8300D9AA4C /* catch_stringref.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_stringref.cpp; path = ../../../include/internal/catch_stringref.cpp; sourceTree = ""; }; - 2621EE3B1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tag_alias_autoregistrar.cpp; path = ../../../include/internal/catch_tag_alias_autoregistrar.cpp; sourceTree = ""; }; - 2621EE3C1F602F8300D9AA4C /* catch_tag_alias_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tag_alias_registry.cpp; path = ../../../include/internal/catch_tag_alias_registry.cpp; sourceTree = ""; }; - 2621EE3D1F602F8300D9AA4C /* catch_tag_alias.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tag_alias.cpp; path = ../../../include/internal/catch_tag_alias.cpp; sourceTree = ""; }; - 2621EE3E1F602F8300D9AA4C /* catch_test_case_info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_case_info.cpp; path = ../../../include/internal/catch_test_case_info.cpp; sourceTree = ""; }; - 2621EE3F1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_case_registry_impl.cpp; path = ../../../include/internal/catch_test_case_registry_impl.cpp; sourceTree = ""; }; - 2621EE401F602F8300D9AA4C /* catch_test_case_tracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_case_tracker.cpp; path = ../../../include/internal/catch_test_case_tracker.cpp; sourceTree = ""; }; - 2621EE411F602F8300D9AA4C /* catch_test_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_registry.cpp; path = ../../../include/internal/catch_test_registry.cpp; sourceTree = ""; }; - 2621EE421F602F8300D9AA4C /* catch_test_spec_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_spec_parser.cpp; path = ../../../include/internal/catch_test_spec_parser.cpp; sourceTree = ""; }; - 2621EE431F602F8300D9AA4C /* catch_test_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_test_spec.cpp; path = ../../../include/internal/catch_test_spec.cpp; sourceTree = ""; }; - 2621EE441F602F8300D9AA4C /* catch_timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_timer.cpp; path = ../../../include/internal/catch_timer.cpp; sourceTree = ""; }; - 2621EE451F602F8300D9AA4C /* catch_tostring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_tostring.cpp; path = ../../../include/internal/catch_tostring.cpp; sourceTree = ""; }; - 2621EE461F602F8300D9AA4C /* catch_totals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_totals.cpp; path = ../../../include/internal/catch_totals.cpp; sourceTree = ""; }; - 2621EE471F602F8300D9AA4C /* catch_version.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_version.cpp; path = ../../../include/internal/catch_version.cpp; sourceTree = ""; }; - 2621EE481F602F8300D9AA4C /* catch_wildcard_pattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_wildcard_pattern.cpp; path = ../../../include/internal/catch_wildcard_pattern.cpp; sourceTree = ""; }; - 2621EE491F602F8300D9AA4C /* catch_xmlwriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_xmlwriter.cpp; path = ../../../include/internal/catch_xmlwriter.cpp; sourceTree = ""; }; - 2621EE791F60360800D9AA4C /* catch_reporter_bases.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_bases.cpp; path = ../../../include/reporters/catch_reporter_bases.cpp; sourceTree = ""; }; - 2621EE7A1F60360800D9AA4C /* catch_reporter_compact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_compact.cpp; path = ../../../include/reporters/catch_reporter_compact.cpp; sourceTree = ""; }; - 2621EE7B1F60360800D9AA4C /* catch_reporter_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_console.cpp; path = ../../../include/reporters/catch_reporter_console.cpp; sourceTree = ""; }; - 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_junit.cpp; path = ../../../include/reporters/catch_reporter_junit.cpp; sourceTree = ""; }; - 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_multi.cpp; path = ../../../include/reporters/catch_reporter_multi.cpp; sourceTree = ""; }; - 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_xml.cpp; path = ../../../include/reporters/catch_reporter_xml.cpp; sourceTree = ""; }; - 4A5C29991F7152A4007CB94C /* catch_interfaces_capture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_capture.cpp; path = ../../../include/internal/catch_interfaces_capture.cpp; sourceTree = ""; }; - 4A5C299A1F7152A4007CB94C /* catch_interfaces_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_config.cpp; path = ../../../include/internal/catch_interfaces_config.cpp; sourceTree = ""; }; - 4A5C299B1F7152A4007CB94C /* catch_interfaces_exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_exception.cpp; path = ../../../include/internal/catch_interfaces_exception.cpp; sourceTree = ""; }; - 4A5C299C1F7152A4007CB94C /* catch_interfaces_registry_hub.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_registry_hub.cpp; path = ../../../include/internal/catch_interfaces_registry_hub.cpp; sourceTree = ""; }; - 4A5C299D1F7152A4007CB94C /* catch_interfaces_runner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_runner.cpp; path = ../../../include/internal/catch_interfaces_runner.cpp; sourceTree = ""; }; - 4A5C299E1F7152A4007CB94C /* catch_interfaces_testcase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_interfaces_testcase.cpp; path = ../../../include/internal/catch_interfaces_testcase.cpp; sourceTree = ""; }; - 4A5C299F1F7152A4007CB94C /* catch_reporter_registry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_reporter_registry.cpp; path = ../../../include/internal/catch_reporter_registry.cpp; sourceTree = ""; }; - 4A5C29A01F7152A4007CB94C /* catch_streambuf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_streambuf.cpp; path = ../../../include/internal/catch_streambuf.cpp; sourceTree = ""; }; + 4A5C29A91F715603007CB94C /* catch_objc_impl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = catch_objc_impl.mm; sourceTree = ""; }; 4A63D2A514E3C1A900F615CB /* OCTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = OCTest; sourceTree = BUILT_PRODUCTS_DIR; }; 4A63D2AB14E3C1A900F615CB /* OCTest.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = OCTest.1; sourceTree = ""; }; 4A63D2B214E3C1E600F615CB /* Main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Main.mm; sourceTree = ""; }; @@ -162,8 +40,6 @@ 4A63D2C314E454CC00F615CB /* OCTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = OCTest.mm; sourceTree = ""; }; 4A63D2C414E454CC00F615CB /* TestObj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestObj.h; sourceTree = ""; }; 4A63D2C514E454CC00F615CB /* TestObj.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestObj.m; sourceTree = ""; }; - 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc.hpp; path = ../../../include/internal/catch_objc.hpp; sourceTree = ""; }; - 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_objc_arc.hpp; path = ../../../include/internal/catch_objc_arc.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -213,70 +89,7 @@ 4AA0D94F154C0A63004B4193 /* Catch */ = { isa = PBXGroup; children = ( - 4A5C29991F7152A4007CB94C /* catch_interfaces_capture.cpp */, - 4A5C299A1F7152A4007CB94C /* catch_interfaces_config.cpp */, - 4A5C299B1F7152A4007CB94C /* catch_interfaces_exception.cpp */, - 4A5C299C1F7152A4007CB94C /* catch_interfaces_registry_hub.cpp */, - 4A5C299D1F7152A4007CB94C /* catch_interfaces_runner.cpp */, - 4A5C299E1F7152A4007CB94C /* catch_interfaces_testcase.cpp */, - 4A5C299F1F7152A4007CB94C /* catch_reporter_registry.cpp */, - 4A5C29A01F7152A4007CB94C /* catch_streambuf.cpp */, - 2621EE791F60360800D9AA4C /* catch_reporter_bases.cpp */, - 2621EE7A1F60360800D9AA4C /* catch_reporter_compact.cpp */, - 2621EE7B1F60360800D9AA4C /* catch_reporter_console.cpp */, - 2621EE7C1F60360800D9AA4C /* catch_reporter_junit.cpp */, - 2621EE7D1F60360800D9AA4C /* catch_reporter_multi.cpp */, - 2621EE7E1F60360800D9AA4C /* catch_reporter_xml.cpp */, - 2621EE1B1F602F8200D9AA4C /* catch_assertionhandler.cpp */, - 2621EE1C1F602F8200D9AA4C /* catch_assertionresult.cpp */, - 2621EE1D1F602F8200D9AA4C /* catch_benchmark.cpp */, - 2621EE1E1F602F8200D9AA4C /* catch_capture_matchers.cpp */, - 2621EE1F1F602F8200D9AA4C /* catch_commandline.cpp */, - 2621EE201F602F8200D9AA4C /* catch_common.cpp */, - 2621EE211F602F8200D9AA4C /* catch_config.cpp */, - 2621EE221F602F8200D9AA4C /* catch_console_colour.cpp */, - 2621EE231F602F8200D9AA4C /* catch_context.cpp */, - 2621EE241F602F8200D9AA4C /* catch_debug_console.cpp */, - 2621EE251F602F8200D9AA4C /* catch_debugger.cpp */, - 2621EE261F602F8200D9AA4C /* catch_decomposer.cpp */, - 2621EE271F602F8200D9AA4C /* catch_errno_guard.cpp */, - 2621EE281F602F8200D9AA4C /* catch_exception_translator_registry.cpp */, - 2621EE291F602F8200D9AA4C /* catch_fatal_condition.cpp */, - 2621EE2A1F602F8200D9AA4C /* catch_interfaces_reporter.cpp */, - 2621EE2B1F602F8300D9AA4C /* catch_leak_detector.cpp */, - 2621EE2C1F602F8300D9AA4C /* catch_list.cpp */, - 2621EE2D1F602F8300D9AA4C /* catch_matchers_string.cpp */, - 2621EE2E1F602F8300D9AA4C /* catch_matchers.cpp */, - 2621EE2F1F602F8300D9AA4C /* catch_message.cpp */, - 2621EE301F602F8300D9AA4C /* catch_random_number_generator.cpp */, - 2621EE311F602F8300D9AA4C /* catch_registry_hub.cpp */, - 2621EE321F602F8300D9AA4C /* catch_result_type.cpp */, - 2621EE331F602F8300D9AA4C /* catch_run_context.cpp */, - 2621EE341F602F8300D9AA4C /* catch_section_info.cpp */, - 2621EE351F602F8300D9AA4C /* catch_section.cpp */, - 2621EE361F602F8300D9AA4C /* catch_session.cpp */, - 2621EE371F602F8300D9AA4C /* catch_startup_exception_registry.cpp */, - 2621EE381F602F8300D9AA4C /* catch_stream.cpp */, - 2621EE391F602F8300D9AA4C /* catch_string_manip.cpp */, - 2621EE3A1F602F8300D9AA4C /* catch_stringref.cpp */, - 2621EE3B1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp */, - 2621EE3C1F602F8300D9AA4C /* catch_tag_alias_registry.cpp */, - 2621EE3D1F602F8300D9AA4C /* catch_tag_alias.cpp */, - 2621EE3E1F602F8300D9AA4C /* catch_test_case_info.cpp */, - 2621EE3F1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp */, - 2621EE401F602F8300D9AA4C /* catch_test_case_tracker.cpp */, - 2621EE411F602F8300D9AA4C /* catch_test_registry.cpp */, - 2621EE421F602F8300D9AA4C /* catch_test_spec_parser.cpp */, - 2621EE431F602F8300D9AA4C /* catch_test_spec.cpp */, - 2621EE441F602F8300D9AA4C /* catch_timer.cpp */, - 2621EE451F602F8300D9AA4C /* catch_tostring.cpp */, - 2621EE461F602F8300D9AA4C /* catch_totals.cpp */, - 2621EE471F602F8300D9AA4C /* catch_version.cpp */, - 2621EE481F602F8300D9AA4C /* catch_wildcard_pattern.cpp */, - 2621EE491F602F8300D9AA4C /* catch_xmlwriter.cpp */, - 2621EE191F602F2C00D9AA4C /* catch_approx.cpp */, - 4ABEA80615C90E10009F0424 /* catch_objc_arc.hpp */, - 4AA0D951154C0A7A004B4193 /* catch_objc.hpp */, + 4A5C29A91F715603007CB94C /* catch_objc_impl.mm */, ); name = Catch; sourceTree = ""; @@ -331,72 +144,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4A5C29A51F7152A4007CB94C /* catch_interfaces_runner.cpp in Sources */, - 2621EE841F60360800D9AA4C /* catch_reporter_xml.cpp in Sources */, - 2621EE561F602F8300D9AA4C /* catch_errno_guard.cpp in Sources */, - 2621EE4F1F602F8300D9AA4C /* catch_common.cpp in Sources */, - 2621EE731F602F8300D9AA4C /* catch_timer.cpp in Sources */, - 2621EE6E1F602F8300D9AA4C /* catch_test_case_registry_impl.cpp in Sources */, - 2621EE6F1F602F8300D9AA4C /* catch_test_case_tracker.cpp in Sources */, - 2621EE6D1F602F8300D9AA4C /* catch_test_case_info.cpp in Sources */, - 4A5C29A21F7152A4007CB94C /* catch_interfaces_config.cpp in Sources */, - 2621EE5A1F602F8300D9AA4C /* catch_leak_detector.cpp in Sources */, - 2621EE501F602F8300D9AA4C /* catch_config.cpp in Sources */, - 2621EE6A1F602F8300D9AA4C /* catch_tag_alias_autoregistrar.cpp in Sources */, - 2621EE751F602F8300D9AA4C /* catch_totals.cpp in Sources */, - 2621EE801F60360800D9AA4C /* catch_reporter_compact.cpp in Sources */, 4A63D2B314E3C1E600F615CB /* Main.mm in Sources */, - 4A5C29A61F7152A4007CB94C /* catch_interfaces_testcase.cpp in Sources */, - 2621EE711F602F8300D9AA4C /* catch_test_spec_parser.cpp in Sources */, - 2621EE5F1F602F8300D9AA4C /* catch_random_number_generator.cpp in Sources */, - 2621EE531F602F8300D9AA4C /* catch_debug_console.cpp in Sources */, - 2621EE821F60360800D9AA4C /* catch_reporter_junit.cpp in Sources */, - 2621EE4C1F602F8300D9AA4C /* catch_benchmark.cpp in Sources */, - 2621EE5B1F602F8300D9AA4C /* catch_list.cpp in Sources */, - 2621EE581F602F8300D9AA4C /* catch_fatal_condition.cpp in Sources */, - 2621EE5D1F602F8300D9AA4C /* catch_matchers.cpp in Sources */, - 4A5C29A41F7152A4007CB94C /* catch_interfaces_registry_hub.cpp in Sources */, - 2621EE7F1F60360800D9AA4C /* catch_reporter_bases.cpp in Sources */, - 2621EE591F602F8300D9AA4C /* catch_interfaces_reporter.cpp in Sources */, - 2621EE611F602F8300D9AA4C /* catch_result_type.cpp in Sources */, - 2621EE781F602F8300D9AA4C /* catch_xmlwriter.cpp in Sources */, - 2621EE601F602F8300D9AA4C /* catch_registry_hub.cpp in Sources */, - 2621EE5E1F602F8300D9AA4C /* catch_message.cpp in Sources */, - 2621EE4B1F602F8300D9AA4C /* catch_assertionresult.cpp in Sources */, - 2621EE4D1F602F8300D9AA4C /* catch_capture_matchers.cpp in Sources */, - 2621EE761F602F8300D9AA4C /* catch_version.cpp in Sources */, - 2621EE721F602F8300D9AA4C /* catch_test_spec.cpp in Sources */, - 2621EE621F602F8300D9AA4C /* catch_run_context.cpp in Sources */, - 2621EE6C1F602F8300D9AA4C /* catch_tag_alias.cpp in Sources */, - 2621EE1A1F602F2C00D9AA4C /* catch_approx.cpp in Sources */, - 4A5C29A31F7152A4007CB94C /* catch_interfaces_exception.cpp in Sources */, - 2621EE511F602F8300D9AA4C /* catch_console_colour.cpp in Sources */, - 2621EE771F602F8300D9AA4C /* catch_wildcard_pattern.cpp in Sources */, - 2621EE811F60360800D9AA4C /* catch_reporter_console.cpp in Sources */, - 2621EE691F602F8300D9AA4C /* catch_stringref.cpp in Sources */, - 4A5C29A11F7152A4007CB94C /* catch_interfaces_capture.cpp in Sources */, + 4A5C29AA1F715603007CB94C /* catch_objc_impl.mm in Sources */, 4A63D2C614E454CC00F615CB /* CatchOCTestCase.mm in Sources */, - 2621EE831F60360800D9AA4C /* catch_reporter_multi.cpp in Sources */, - 2621EE541F602F8300D9AA4C /* catch_debugger.cpp in Sources */, - 2621EE741F602F8300D9AA4C /* catch_tostring.cpp in Sources */, 4A63D2C714E454CC00F615CB /* OCTest.mm in Sources */, - 2621EE5C1F602F8300D9AA4C /* catch_matchers_string.cpp in Sources */, - 2621EE4E1F602F8300D9AA4C /* catch_commandline.cpp in Sources */, - 4A5C29A71F7152A4007CB94C /* catch_reporter_registry.cpp in Sources */, - 2621EE651F602F8300D9AA4C /* catch_session.cpp in Sources */, - 2621EE661F602F8300D9AA4C /* catch_startup_exception_registry.cpp in Sources */, - 2621EE641F602F8300D9AA4C /* catch_section.cpp in Sources */, - 2621EE701F602F8300D9AA4C /* catch_test_registry.cpp in Sources */, - 2621EE681F602F8300D9AA4C /* catch_string_manip.cpp in Sources */, 4A63D2C814E454CC00F615CB /* TestObj.m in Sources */, - 2621EE671F602F8300D9AA4C /* catch_stream.cpp in Sources */, - 2621EE551F602F8300D9AA4C /* catch_decomposer.cpp in Sources */, - 2621EE4A1F602F8300D9AA4C /* catch_assertionhandler.cpp in Sources */, - 4A5C29A81F7152A4007CB94C /* catch_streambuf.cpp in Sources */, - 2621EE631F602F8300D9AA4C /* catch_section_info.cpp in Sources */, - 2621EE521F602F8300D9AA4C /* catch_context.cpp in Sources */, - 2621EE571F602F8300D9AA4C /* catch_exception_translator_registry.cpp in Sources */, - 2621EE6B1F602F8300D9AA4C /* catch_tag_alias_registry.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/projects/XCode/OCTest/catch_objc_impl.mm b/projects/XCode/OCTest/catch_objc_impl.mm new file mode 100644 index 00000000..5b081ad7 --- /dev/null +++ b/projects/XCode/OCTest/catch_objc_impl.mm @@ -0,0 +1,68 @@ +// This file #includes all the .cpp files into a single .mm +// - so they get compiled as ObjectiveC++ + +#include "../../../include/internal/catch_approx.cpp" +#include "../../../include/internal/catch_assertionhandler.cpp" +#include "../../../include/internal/catch_assertionresult.cpp" +#include "../../../include/internal/catch_benchmark.cpp" +#include "../../../include/internal/catch_capture_matchers.cpp" +#include "../../../include/internal/catch_commandline.cpp" +#include "../../../include/internal/catch_common.cpp" +#include "../../../include/internal/catch_config.cpp" +#include "../../../include/internal/catch_console_colour.cpp" +#include "../../../include/internal/catch_context.cpp" +#include "../../../include/internal/catch_debug_console.cpp" +#include "../../../include/internal/catch_debugger.cpp" +#include "../../../include/internal/catch_decomposer.cpp" +#include "../../../include/internal/catch_errno_guard.cpp" +#include "../../../include/internal/catch_exception_translator_registry.cpp" +#include "../../../include/internal/catch_fatal_condition.cpp" +#include "../../../include/internal/catch_interfaces_capture.cpp" +#include "../../../include/internal/catch_interfaces_config.cpp" +#include "../../../include/internal/catch_interfaces_exception.cpp" +#include "../../../include/internal/catch_interfaces_registry_hub.cpp" +#include "../../../include/internal/catch_interfaces_reporter.cpp" +#include "../../../include/internal/catch_interfaces_runner.cpp" +#include "../../../include/internal/catch_interfaces_testcase.cpp" +#include "../../../include/internal/catch_leak_detector.cpp" +#include "../../../include/internal/catch_list.cpp" +#include "../../../include/internal/catch_matchers.cpp" +#include "../../../include/internal/catch_matchers_string.cpp" +#include "../../../include/internal/catch_message.cpp" +#include "../../../include/internal/catch_random_number_generator.cpp" +#include "../../../include/internal/catch_registry_hub.cpp" +#include "../../../include/internal/catch_reporter_registry.cpp" +#include "../../../include/internal/catch_result_type.cpp" +#include "../../../include/internal/catch_run_context.cpp" +#include "../../../include/internal/catch_section.cpp" +#include "../../../include/internal/catch_section_info.cpp" +#include "../../../include/internal/catch_session.cpp" +#include "../../../include/internal/catch_startup_exception_registry.cpp" +#include "../../../include/internal/catch_stream.cpp" +#include "../../../include/internal/catch_streambuf.cpp" +#include "../../../include/internal/catch_string_manip.cpp" +#include "../../../include/internal/catch_stringref.cpp" +#include "../../../include/internal/catch_tag_alias.cpp" +#include "../../../include/internal/catch_tag_alias_autoregistrar.cpp" +#include "../../../include/internal/catch_tag_alias_registry.cpp" +#include "../../../include/internal/catch_test_case_info.cpp" +#include "../../../include/internal/catch_test_case_registry_impl.cpp" +#include "../../../include/internal/catch_test_case_tracker.cpp" +#include "../../../include/internal/catch_test_registry.cpp" +#include "../../../include/internal/catch_test_spec.cpp" +#include "../../../include/internal/catch_test_spec_parser.cpp" +#include "../../../include/internal/catch_timer.cpp" +#include "../../../include/internal/catch_tostring.cpp" +#include "../../../include/internal/catch_totals.cpp" +#include "../../../include/internal/catch_version.cpp" +#include "../../../include/internal/catch_wildcard_pattern.cpp" +#include "../../../include/internal/catch_xmlwriter.cpp" + + +// Reporters +#include "../../../include/reporters/catch_reporter_bases.cpp" +#include "../../../include/reporters/catch_reporter_compact.cpp" +#include "../../../include/reporters/catch_reporter_console.cpp" +#include "../../../include/reporters/catch_reporter_junit.cpp" +#include "../../../include/reporters/catch_reporter_multi.cpp" +#include "../../../include/reporters/catch_reporter_xml.cpp" From 54f1ce2af287c85e88eff6813d3bc107a8e0c576 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 19 Sep 2017 15:25:33 +0100 Subject: [PATCH 345/398] Don't use console colour if running in XCode --- include/internal/catch_console_colour.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index 13290544..946e2903 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -20,6 +20,7 @@ #include "catch_stream.h" #include "catch_context.h" #include "catch_platform.h" +#include "catch_debugger.h" namespace Catch { namespace { @@ -156,6 +157,13 @@ namespace { } }; + bool useColourOnPlatform() { + return +#ifdef CATCH_PLATFORM_MAC + !isDebuggerActive() && +#endif + isatty(STDOUT_FILENO); + } IColourImpl* platformColourInstance() { ErrnoGuard guard; IConfigPtr config = getCurrentContext().getConfig(); @@ -163,7 +171,7 @@ namespace { ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = isatty(STDOUT_FILENO) + colourMode = useColourOnPlatform() ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes From e9f0773f37e896a17701b57ea6ff83902a713381 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 19 Sep 2017 17:36:20 +0100 Subject: [PATCH 346/398] Updated release notes --- docs/release-notes.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index c790e066..c134b3fa 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -19,6 +19,7 @@ * This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section. * Removed deprecated matcher utility functions `Not`, `AllOf` and `AnyOf`. * They are superseded by operators `!`, `&&` and `||`, which are natural and do not have limited arity +* No longer accept non-const comparison operators ## Improvements @@ -47,9 +48,13 @@ * Exception translators are not registered * Reporters are not registered * Listeners are not registered +* More warnings are silenced +* Don't use console colour if running in XCode ## Fixes - +* Explicit constructor in reporter base class +* Many fixes for building in Objective-C context +* Do not use SEH and console api under UWP ## Internal changes * The development version now uses .cpp files instead of header files containing implementation. @@ -59,7 +64,6 @@ * New library (TextFlow) is used for formatting text to output - # Older versions ## 1.9.x From bd46f66754f11b5644913f6eb8a1900971f3e0ad Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 19 Sep 2017 17:42:20 +0100 Subject: [PATCH 347/398] dev build 4 --- conanfile.py | 2 +- include/internal/catch_version.cpp | 2 +- single_include/catch.hpp | 3751 ++++++++++++++-------------- test_package/conanfile.py | 2 +- 4 files changed, 1936 insertions(+), 1821 deletions(-) diff --git a/conanfile.py b/conanfile.py index 506235ae..d1dfa81d 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.0.0-develop.3" + version = "2.0.0-develop.4" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index 36f58e22..b635800b 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 3 ); + static Version version( 2, 0, 0, "develop", 4 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index c775b8db..e5ae6198 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.0.0-develop.3 - * Generated: 2017-08-30 12:15:54.096665 + * Catch v2.0.0-develop.4 + * Generated: 2017-09-19 17:37:34.480115 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. @@ -47,6 +47,9 @@ #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL # define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif #endif // start catch_platform.h @@ -106,10 +109,11 @@ #ifdef __clang__ -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ _Pragma( "clang diagnostic push" ) \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ _Pragma( "clang diagnostic pop" ) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ @@ -149,7 +153,13 @@ // Visual C++ #ifdef _MSC_VER -#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif #endif // _MSC_VER @@ -179,9 +189,9 @@ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS -# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #endif // end catch_compiler_capabilities.h @@ -193,17 +203,12 @@ # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif -#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr -#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) - #include #include #include namespace Catch { - struct IConfig; - struct CaseSensitive { enum Choice { Yes, No @@ -216,7 +221,7 @@ namespace Catch { NonCopyable& operator = ( NonCopyable && ) = delete; protected: - NonCopyable() {} + NonCopyable(); virtual ~NonCopyable(); }; @@ -245,9 +250,6 @@ namespace Catch { bool alwaysTrue(); bool alwaysFalse(); - void seedRng( IConfig const& config ); - unsigned int rngSeed(); - // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as @@ -276,7 +278,7 @@ namespace Catch { #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } // end catch_tag_alias_autoregistrar.h -// start catch_test_registry.hpp +// start catch_test_registry.h // start catch_interfaces_testcase.h @@ -330,7 +332,7 @@ namespace Catch { class StringRef { friend struct StringRefTestAccess; - using size_type = size_t; + using size_type = std::size_t; char const* m_start; size_type m_size; @@ -412,7 +414,7 @@ struct NameAndTags { struct AutoReg : NonCopyable { AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef classOrMethod, NameAndTags const& nameAndTags ) noexcept; - ~AutoReg() = default; + ~AutoReg(); }; } // end namespace Catch @@ -433,40 +435,40 @@ struct AutoReg : NonCopyable { /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ static void TestName() #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, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + 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_ETD_WARNINGS + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace{ \ struct TestName : 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_ETD_WARNINGS \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ void TestName::test() #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, ... ) \ - CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ - CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS -// end catch_test_registry.hpp +// end catch_test_registry.h // start catch_capture.hpp // start catch_assertionhandler.h @@ -528,6 +530,11 @@ inline id performOptionalSelector( id obj, SEL sel ) { // end catch_objc_arc.hpp #endif +#ifdef _MSC_VER +#pragma warning(push) +#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); @@ -801,20 +808,33 @@ namespace Catch { #ifdef __OBJC__ template<> struct StringMaker { - static std::string convert(NSString* nsstring); + static std::string convert(NSString * nsstring) { + if (!nsstring) + return "nil"; + return std::string("@") + [nsstring UTF8String]; + } }; template<> - struct StringMaker { - static std::string convert(NSString * CATCH_ARC_STRONG nsstring); + struct StringMaker { + static std::string convert(NSObject* nsObject) { + return ::Catch::Detail::stringify([nsObject description]); + } + }; - template<> - struct StringMaker { - static std::string convert(NSObject* nsObject); - }; -#endif + namespace Detail { + inline std::string stringify( NSString* nsstring ) { + return StringMaker::convert( nsstring ); + } + + } // namespace Detail +#endif // __OBJC__ } // namespace Catch +#ifdef _MSC_VER +#pragma warning(pop) +#endif + // end catch_tostring.h #include @@ -823,6 +843,7 @@ namespace Catch { #pragma warning(disable:4389) // '==' : signed/unsigned mismatch #pragma warning(disable:4018) // more "signed/unsigned mismatch" #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#pragma warning(disable:4180) // qualifier applied to function type has no meaning #endif namespace Catch { @@ -834,16 +855,16 @@ namespace Catch { // We don't actually need a virtual destructore, but many static analysers // complain if it's not here :-( - virtual ~ITransientExpression() = default; + virtual ~ITransientExpression(); }; - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); template class BinaryExpr : public ITransientExpression { bool m_result; LhsT m_lhs; - std::string m_op; + StringRef m_op; RhsT m_rhs; auto isBinaryExpression() const -> bool override { return true; } @@ -855,8 +876,8 @@ namespace Catch { } public: - BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) - : m_result( comparisionResult ), + BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) + : m_result( comparisonResult ), m_lhs( lhs ), m_op( op ), m_rhs( rhs ) @@ -880,26 +901,26 @@ namespace Catch { // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template - auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) == rhs; }; + auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; template - auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } template - auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); }; + auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } template - auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } template - auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; }; + auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } template - auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return const_cast( lhs ) != rhs; }; + auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; template - auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } template - auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); }; + auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } template - auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } template - auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; }; + auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } template class ExprLhs { @@ -953,10 +974,6 @@ namespace Catch { } struct Decomposer { - template - auto operator <= ( T& lhs ) -> ExprLhs { - return ExprLhs( lhs ); - } template auto operator <= ( T const& lhs ) -> ExprLhs { return ExprLhs( lhs ); @@ -968,10 +985,6 @@ namespace Catch { } // end namespace Catch -#ifdef _MSC_VER -#pragma warning(pop) -#endif - // end catch_decomposer.h // start catch_assertioninfo.h @@ -1111,9 +1124,9 @@ namespace Catch { ResultWas::OfType _type ); std::string macroName; + std::string message; SourceLineInfo lineInfo; ResultWas::OfType type; - std::string message; unsigned int sequence; bool operator == ( MessageInfo const& other ) const; @@ -1165,13 +1178,11 @@ namespace Catch { namespace Catch { - class TestCase; class AssertionResult; struct AssertionInfo; struct SectionInfo; struct SectionEndInfo; struct MessageInfo; - class ScopedMessageBuilder; struct Counts; struct BenchmarkInfo; struct BenchmarkStats; @@ -1198,7 +1209,7 @@ namespace Catch { virtual void exceptionEarlyReported() = 0; - virtual void handleFatalErrorCondition( std::string const& message ) = 0; + virtual void handleFatalErrorCondition( StringRef message ) = 0; virtual bool lastAssertionPassed() = 0; virtual void assertionPassed() = 0; @@ -1209,32 +1220,6 @@ namespace Catch { } // end catch_interfaces_capture.h -#if !defined(CATCH_CONFIG_DISABLE) - -#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) - #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ -#else - #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" -#endif - -#if defined(CATCH_CONFIG_FAST_COMPILE) -/////////////////////////////////////////////////////////////////////////////// -// We can speedup compilation significantly by breaking into debugger lower in -// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER -// macro in each assertion -#define INTERNAL_CATCH_REACT( handler ) \ - handler.reactWithDebugBreak(); - -/////////////////////////////////////////////////////////////////////////////// -// Another way to speed-up compilation is to omit local try-catch for REQUIRE* -// macros. -// This can potentially cause false negative, if the test code catches -// the exception before it propagates back up to the runner. -#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); -#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard(); - -#else // CATCH_CONFIG_FAST_COMPILE - // start catch_debugger.h namespace Catch { @@ -1270,6 +1255,32 @@ namespace Catch { #endif // end catch_debugger.h +#if !defined(CATCH_CONFIG_DISABLE) + +#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) + #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ +#else + #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" +#endif + +#if defined(CATCH_CONFIG_FAST_COMPILE) +/////////////////////////////////////////////////////////////////////////////// +// We can speedup compilation significantly by breaking into debugger lower in +// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER +// macro in each assertion +#define INTERNAL_CATCH_REACT( handler ) \ + handler.reactWithDebugBreak(); + +/////////////////////////////////////////////////////////////////////////////// +// Another way to speed-up compilation is to omit local try-catch for REQUIRE* +// macros. +// This can potentially cause false negative, if the test code catches +// the exception before it propagates back up to the runner. +#define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); +#define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard(); + +#else // CATCH_CONFIG_FAST_COMPILE + /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. @@ -1395,7 +1406,7 @@ namespace Catch { // start catch_section_info.h -// start catch_totals.hpp +// start catch_totals.h #include @@ -1426,7 +1437,7 @@ namespace Catch { }; } -// end catch_totals.hpp +// end catch_totals.h #include namespace Catch { @@ -1512,8 +1523,8 @@ namespace Catch { class BenchmarkLooper { std::string m_name; - size_t m_count = 0; - size_t m_iterationsToRun = 1; + std::size_t m_count = 0; + std::size_t m_iterationsToRun = 1; uint64_t m_resolution; Timer m_timer; @@ -1666,7 +1677,7 @@ namespace Catch { #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // end catch_interfaces_exception.h -// start catch_approx.hpp +// start catch_approx.h #include @@ -1777,31 +1788,39 @@ struct StringMaker { } // end namespace Catch -// end catch_approx.hpp -// start catch_interfaces_tag_alias_registry.h +// end catch_approx.h +// start catch_string_manip.h #include +#include namespace Catch { - struct TagAlias; + bool startsWith( std::string const& s, std::string const& prefix ); + bool startsWith( std::string const& s, char prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool endsWith( std::string const& s, char suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); - struct ITagAliasRegistry { - virtual ~ITagAliasRegistry(); - // Nullptr if not present - virtual TagAlias const* find( std::string const& alias ) const = 0; - virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + struct pluralise { + pluralise( std::size_t count, std::string const& label ); - static ITagAliasRegistry const& get(); + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; }; +} -} // end namespace Catch - -// end catch_interfaces_tag_alias_registry.h +// end catch_string_manip.h #ifndef CATCH_CONFIG_DISABLE_MATCHERS // start catch_capture_matchers.h -// start catch_matchers.hpp +// start catch_matchers.h #include #include @@ -1822,7 +1841,7 @@ namespace Matchers { std::string toString() const; protected: - virtual ~MatcherUntypedBase() = default; + virtual ~MatcherUntypedBase(); virtual std::string describe() const = 0; mutable std::string m_cachedToString; }; @@ -1940,30 +1959,6 @@ namespace Matchers { } // namespace Impl - // The following functions create the actual matcher objects. - // This allows the types to be inferred - // - deprecated: prefer ||, && and ! - template - Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { - return Impl::MatchNotOf( underlyingMatcher ); - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAllOf() && m1 && m2; - } - template - Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAllOf() && m1 && m2 && m3; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { - return Impl::MatchAnyOf() || m1 || m2; - } - template - Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { - return Impl::MatchAnyOf() || m1 || m2 || m3; - } - } // namespace Matchers using namespace Matchers; @@ -1971,7 +1966,7 @@ using Matchers::Impl::MatcherBase; } // namespace Catch -// end catch_matchers.hpp +// end catch_matchers.h // start catch_matchers_string.h #include @@ -2100,7 +2095,7 @@ namespace Matchers { // - then just call that directly if (m_comparator.size() != v.size()) return false; - for (size_t i = 0; i < v.size(); ++i) + for (std::size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != v[i]) return false; return true; @@ -2293,7 +2288,6 @@ namespace Catch { // start catch_interfaces_runner.h namespace Catch { - class TestCase; struct IRunner { virtual ~IRunner(); @@ -2364,8 +2358,8 @@ namespace Catch { } } - inline size_t registerTestMethods() { - size_t noTestMethods = 0; + inline std::size_t registerTestMethods() { + std::size_t noTestMethods = 0; int noClasses = objc_getClassList( nullptr, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); @@ -2385,7 +2379,7 @@ namespace Catch { std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); const char* className = class_getName( cls ); - getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) ); noTestMethods++; } } @@ -2412,7 +2406,7 @@ namespace Catch { return false; } - NSString* m_substr; + NSString* CATCH_ARC_STRONG m_substr; }; struct Equals : StringHolder { @@ -2424,7 +2418,7 @@ namespace Catch { } std::string describe() const override { - return "equals string: " + Catch::toString( m_substr ); + return "equals string: " + Catch::Detail::stringify( m_substr ); } }; @@ -2437,7 +2431,7 @@ namespace Catch { } std::string describe() const override { - return "contains string: " + Catch::toString( m_substr ); + return "contains string: " + Catch::Detail::stringify( m_substr ); } }; @@ -2450,7 +2444,7 @@ namespace Catch { } std::string describe() const override { - return "starts with: " + Catch::toString( m_substr ); + return "starts with: " + Catch::Detail::stringify( m_substr ); } }; struct EndsWith : StringHolder { @@ -2462,7 +2456,7 @@ namespace Catch { } std::string describe() const override { - return "ends with: " + Catch::toString( m_substr ); + return "ends with: " + Catch::Detail::stringify( m_substr ); } }; @@ -2490,16 +2484,19 @@ namespace Catch { } // namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define OC_TEST_CASE( name, desc )\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ -{\ +#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix +#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ +{ \ return @ name; \ -}\ -+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +} \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ { \ return @ desc; \ } \ --(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) +-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) + +#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) // end catch_objc.hpp #endif @@ -2528,21 +2525,21 @@ return @ desc; \ // start catch_config.hpp -// start catch_test_spec_parser.hpp +// start catch_test_spec_parser.h #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif -// start catch_test_spec.hpp +// start catch_test_spec.h #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif -// start catch_wildcard_pattern.hpp +// start catch_wildcard_pattern.h namespace Catch { @@ -2568,7 +2565,7 @@ namespace Catch }; } -// end catch_wildcard_pattern.hpp +// end catch_wildcard_pattern.h #include #include #include @@ -2577,7 +2574,7 @@ namespace Catch { class TestSpec { struct Pattern { - virtual ~Pattern() = default; + virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; using PatternPtr = std::shared_ptr; @@ -2585,7 +2582,7 @@ namespace Catch { class NamePattern : public Pattern { public: NamePattern( std::string const& name ); - virtual ~NamePattern() = default; + virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const override; private: WildcardPattern m_wildcardPattern; @@ -2594,7 +2591,7 @@ namespace Catch { class TagPattern : public Pattern { public: TagPattern( std::string const& tag ); - virtual ~TagPattern() = default; + virtual ~TagPattern(); virtual bool matches( TestCaseInfo const& testCase ) const override; private: std::string m_tag; @@ -2603,7 +2600,7 @@ namespace Catch { class ExcludedPattern : public Pattern { public: ExcludedPattern( PatternPtr const& underlyingPattern ); - virtual ~ExcludedPattern() = default; + virtual ~ExcludedPattern(); virtual bool matches( TestCaseInfo const& testCase ) const override; private: PatternPtr m_underlyingPattern; @@ -2630,35 +2627,27 @@ namespace Catch { #pragma clang diagnostic pop #endif -// end catch_test_spec.hpp -// start catch_string_manip.h +// end catch_test_spec.h +// start catch_interfaces_tag_alias_registry.h #include -#include namespace Catch { - bool startsWith( std::string const& s, std::string const& prefix ); - bool startsWith( std::string const& s, char prefix ); - bool endsWith( std::string const& s, std::string const& suffix ); - bool endsWith( std::string const& s, char suffix ); - bool contains( std::string const& s, std::string const& infix ); - void toLowerInPlace( std::string& s ); - std::string toLower( std::string const& s ); - std::string trim( std::string const& str ); - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + struct TagAlias; - struct pluralise { - pluralise( std::size_t count, std::string const& label ); + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + // Nullptr if not present + virtual TagAlias const* find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; - friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); - - std::size_t m_count; - std::string m_label; + static ITagAliasRegistry const& get(); }; -} -// end catch_string_manip.h +} // end namespace Catch + +// end catch_interfaces_tag_alias_registry.h namespace Catch { class TestSpecParser { @@ -2687,7 +2676,7 @@ namespace Catch { template void addPattern() { std::string token = subString(); - for( size_t i = 0; i < m_escapeChars.size(); ++i ) + for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); m_escapeChars.clear(); if( startsWith( token, "exclude:" ) ) { @@ -2714,7 +2703,7 @@ namespace Catch { #pragma clang diagnostic pop #endif -// end catch_test_spec_parser.hpp +// end catch_test_spec_parser.h // start catch_interfaces_config.h #include @@ -2785,6 +2774,71 @@ namespace Catch { } // end catch_interfaces_config.h +// Libstdc++ doesn't like incomplete classes for unique_ptr +// start catch_stream.h + +// start catch_streambuf.h + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase(); + }; +} + +// end catch_streambuf.h +#include +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + std::ostream& clog(); + + struct IStream { + virtual ~IStream(); + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + ~FileStream() override = default; + public: // IStream + std::ostream& stream() const override; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + ~CoutStream() override = default; + + public: // IStream + std::ostream& stream() const override; + }; + + class DebugOutStream : public IStream { + std::unique_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + ~DebugOutStream() override = default; + + public: // IStream + std::ostream& stream() const override; + }; +} + +// end catch_stream.h + #include #include #include @@ -2832,7 +2886,6 @@ namespace Catch { }; class Config : public IConfig { - virtual void dummy(); public: Config() = default; @@ -2895,13 +2948,12 @@ namespace Catch { AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); - ResultWas::OfType resultType = ResultWas::Unknown; std::string message; - + mutable std::string reconstructedExpression; LazyExpression lazyExpression; + ResultWas::OfType resultType; std::string reconstructExpression() const; - mutable std::string reconstructedExpression; }; class AssertionResult { @@ -3057,7 +3109,7 @@ namespace Catch { AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats && ) = default; - virtual ~AssertionStats() = default; + virtual ~AssertionStats(); AssertionResult assertionResult; std::vector infoMessages; @@ -3073,7 +3125,7 @@ namespace Catch { SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats && ) = default; - virtual ~SectionStats() = default; + virtual ~SectionStats(); SectionInfo sectionInfo; Counts assertions; @@ -3092,7 +3144,7 @@ namespace Catch { TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats && ) = default; - virtual ~TestCaseStats() = default; + virtual ~TestCaseStats(); TestCaseInfo testInfo; Totals totals; @@ -3111,7 +3163,7 @@ namespace Catch { TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats && ) = default; - virtual ~TestGroupStats() = default; + virtual ~TestGroupStats(); GroupInfo groupInfo; Totals totals; @@ -3127,7 +3179,7 @@ namespace Catch { TestRunStats( TestRunStats && ) = default; TestRunStats& operator = ( TestRunStats const& ) = default; TestRunStats& operator = ( TestRunStats && ) = default; - virtual ~TestRunStats() = default; + virtual ~TestRunStats(); TestRunInfo runInfo; Totals totals; @@ -3139,10 +3191,9 @@ namespace Catch { }; struct BenchmarkStats { BenchmarkInfo info; - size_t iterations; + std::size_t iterations; uint64_t elapsedTimeInNanoseconds; }; - class MultipleReporters; struct IStreamingReporter { virtual ~IStreamingReporter() = default; @@ -3179,12 +3230,15 @@ namespace Catch { virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + // Default empty implementation provided + virtual void fatalErrorEncountered( StringRef name ); + virtual bool isMulti() const; }; using IStreamingReporterPtr = std::unique_ptr; struct IReporterFactory { - virtual ~IReporterFactory() = default; + virtual ~IReporterFactory(); virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; @@ -3194,7 +3248,7 @@ namespace Catch { using FactoryMap = std::map; using Listeners = std::vector; - virtual ~IReporterRegistry() = default; + virtual ~IReporterRegistry(); virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; @@ -3462,6 +3516,64 @@ namespace Catch { } // end namespace Catch // end catch_reporter_bases.hpp +// start catch_console_colour.h + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour&& other ) noexcept; + Colour& operator=( Colour&& other ) noexcept; + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved = false; + }; + + std::ostream& operator << ( std::ostream& os, Colour const& ); + +} // end namespace Catch + +// end catch_console_colour.h // start catch_reporter_registrars.hpp @@ -3512,11 +3624,14 @@ namespace Catch { #if !defined(CATCH_CONFIG_DISABLE) #define CATCH_REGISTER_REPORTER( name, reporterType ) \ - namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS #define CATCH_REGISTER_LISTENER( listenerType ) \ - namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } - + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS #else // CATCH_CONFIG_DISABLE #define CATCH_REGISTER_REPORTER(name, reporterType) @@ -3531,41 +3646,183 @@ namespace Catch { #ifdef CATCH_IMPL // start catch_impl.hpp -// Collect all the implementation files together here -// These are the equivalent of what would usually be cpp files - #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-vtables" #endif -// start catch_notimplemented_exception.h +// Keep these here for external reporters +// start catch_test_case_tracker.h -#include +#include +#include +#include namespace Catch { +namespace TestCaseTracking { - class NotImplementedException : public std::exception - { - public: - NotImplementedException( SourceLineInfo const& lineInfo ); + struct NameAndLocation { + std::string name; + SourceLineInfo location; - virtual ~NotImplementedException() noexcept = default; - - virtual const char* what() const noexcept override; - - private: - std::string m_what; + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); }; -} // end namespace Catch + struct ITracker; -/////////////////////////////////////////////////////////////////////////////// -#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + using ITrackerPtr = std::shared_ptr; -// end catch_notimplemented_exception.h -// Temporary hack to fix separately provided reporters -// + struct ITracker { + virtual ~ITracker(); + + // static queries + virtual NameAndLocation const& nameAndLocation() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( ITrackerPtr const& child ) = 0; + virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + ITrackerPtr m_rootTracker; + ITracker* m_currentTracker = nullptr; + RunState m_runState = NotStarted; + + public: + + static TrackerContext& instance(); + + ITracker& startRun(); + void endRun(); + + void startCycle(); + void completeCycle(); + + bool completedCycle() const; + ITracker& currentTracker(); + void setCurrentTracker( ITracker* tracker ); + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + + class TrackerHasName { + NameAndLocation m_nameAndLocation; + public: + TrackerHasName( NameAndLocation const& nameAndLocation ); + bool operator ()( ITrackerPtr const& tracker ) const; + }; + + using Children = std::vector; + NameAndLocation m_nameAndLocation; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState = NotStarted; + + public: + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + + NameAndLocation const& nameAndLocation() const override; + bool isComplete() const override; + bool isSuccessfullyCompleted() const override; + bool isOpen() const override; + bool hasChildren() const override; + + void addChild( ITrackerPtr const& child ) override; + + ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; + ITracker& parent() override; + + void openChild() override; + + bool isSectionTracker() const override; + bool isIndexTracker() const override; + + void open(); + + void close() override; + void fail() override; + void markAsNeedingAnotherRun() override; + + private: + void moveToParent(); + void moveToThis(); + }; + + class SectionTracker : public TrackerBase { + std::vector m_filters; + public: + SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + + bool isSectionTracker() const override; + + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); + + void tryOpen(); + + void addInitialFilters( std::vector const& filters ); + void addNextFilters( std::vector const& filters ); + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index = -1; + public: + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); + + bool isIndexTracker() const override; + void close() override; + + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); + + int index() const; + + void moveNext(); + }; + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// end catch_test_case_tracker.h // start catch_leak_detector.h @@ -3577,9 +3834,351 @@ namespace Catch { } // end catch_leak_detector.h -// start catch_session.hpp +// Cpp files will be included in the single-header file here +// start catch_approx.cpp -// start catch_commandline.hpp +#include + +namespace Catch { +namespace Detail { + + double max(double lhs, double rhs) { + if (lhs < rhs) { + return rhs; + } + return lhs; + } + + Approx::Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_margin( 0.0 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx Approx::custom() { + return Approx( 0 ); + } + + std::string Approx::toString() const { + std::ostringstream oss; + oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; + return oss.str(); + } + +} // end namespace Detail + +std::string StringMaker::convert(Catch::Detail::Approx const& value) { + return value.toString(); +} + +} // end namespace Catch +// end catch_approx.cpp +// start catch_assertionhandler.cpp + +// start catch_context.h + +#include + +namespace Catch { + + struct IResultCapture; + struct IRunner; + struct IConfig; + + using IConfigPtr = std::shared_ptr; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual IConfigPtr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( IConfigPtr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); +} + +// end catch_context.h +#include + +namespace Catch { + + auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { + expr.streamReconstructedExpression( os ); + return os; + } + + LazyExpression::LazyExpression( bool isNegated ) + : m_isNegated( isNegated ) + {} + + LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} + + LazyExpression::operator bool() const { + return m_transientExpression != nullptr; + } + + auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { + if( lazyExpr.m_isNegated ) + os << "!"; + + if( lazyExpr ) { + if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) + os << "(" << *lazyExpr.m_transientExpression << ")"; + else + os << *lazyExpr.m_transientExpression; + } + else { + os << "{** error - unchecked empty expression requested **}"; + } + return os; + } + + AssertionHandler::AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } + { + getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); + } + AssertionHandler::~AssertionHandler() { + if ( m_inExceptionGuard ) { + handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ); + getCurrentContext().getResultCapture()->exceptionEarlyReported(); + } + } + + void AssertionHandler::handle( ITransientExpression const& expr ) { + + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + bool result = expr.getResult() != negated; + + handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); + } + void AssertionHandler::handle( ResultWas::OfType resultType ) { + handle( resultType, nullptr, false ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { + AssertionResultData data( resultType, LazyExpression( false ) ); + data.message = message; + handle( data, nullptr ); + } + void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { + AssertionResultData data( resultType, LazyExpression( negated ) ); + handle( data, expr ); + } + void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) { + + getResultCapture().assertionRun(); + + AssertionResult assertionResult{ m_assertionInfo, resultData }; + assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; + + getResultCapture().assertionEnded( assertionResult ); + + if( !assertionResult.isOk() ) { + m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); + m_shouldThrow = + getCurrentContext().getRunner()->aborting() || + (m_assertionInfo.resultDisposition & ResultDisposition::Normal); + } + } + + auto AssertionHandler::allowThrows() const -> bool { + return getCurrentContext().getConfig()->allowThrows(); + } + + auto AssertionHandler::shouldDebugBreak() const -> bool { + return m_shouldDebugBreak; + } + void AssertionHandler::reactWithDebugBreak() const { + if (m_shouldDebugBreak) { + /////////////////////////////////////////////////////////////////// + // To inspect the state during test, you need to go one level up the callstack + // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call + /////////////////////////////////////////////////////////////////// + CATCH_BREAK_INTO_DEBUGGER(); + } + reactWithoutDebugBreak(); + } + void AssertionHandler::reactWithoutDebugBreak() const { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + void AssertionHandler::useActiveException() { + handle( ResultWas::ThrewException, Catch::translateActiveException() ); + } + + void AssertionHandler::setExceptionGuard() { + assert( m_inExceptionGuard == false ); + m_inExceptionGuard = true; + } + void AssertionHandler::unsetExceptionGuard() { + assert( m_inExceptionGuard == true ); + m_inExceptionGuard = false; + } + + // 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 ) { + handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); + } + +} // namespace Catch +// end catch_assertionhandler.cpp +// start catch_assertionresult.cpp + +namespace Catch { + AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): + lazyExpression(_lazyExpression), + resultType(_resultType) {} + + std::string AssertionResultData::reconstructExpression() const { + + if( reconstructedExpression.empty() ) { + if( lazyExpression ) { + // !TBD Use stringstream for now, but rework above to pass stream in + std::ostringstream oss; + oss << lazyExpression; + reconstructedExpression = oss.str(); + } + } + return reconstructedExpression; + } + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return m_info.capturedExpression[0] != 0; + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if (isFalseTest(m_info.resultDisposition)) + return '!' + std::string(m_info.capturedExpression); + else + return m_info.capturedExpression; + } + + std::string AssertionResult::getExpressionInMacro() const { + std::string expr; + if( m_info.macroName[0] == 0 ) + expr = m_info.capturedExpression; + else { + expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); + expr += m_info.macroName; + expr += "( "; + expr += m_info.capturedExpression; + expr += " )"; + } + return expr; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + std::string expr = m_resultData.reconstructExpression(); + return expr.empty() + ? getExpression() + : expr; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch +// end catch_assertionresult.cpp +// start catch_benchmark.cpp + +namespace Catch { + + auto BenchmarkLooper::getResolution() -> uint64_t { + return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); + } + + void BenchmarkLooper::reportStart() { + getResultCapture().benchmarkStarting( { m_name } ); + } + auto BenchmarkLooper::needsMoreIterations() -> bool { + auto elapsed = m_timer.getElapsedNanoseconds(); + + // Exponentially increasing iterations until we're confident in our timer resolution + if( elapsed < m_resolution ) { + m_iterationsToRun *= 10; + return true; + } + + getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); + return false; + } + +} // end namespace Catch +// end catch_benchmark.cpp +// start catch_capture_matchers.cpp + +namespace Catch { + + using StringMatcher = Matchers::Impl::MatcherBase; + + // This is the general overload that takes a any string matcher + // There is another overload, in catch_assertinhandler.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 ) { + std::string exceptionMessage = Catch::translateActiveException(); + MatchExpr expr( exceptionMessage, matcher, matcherString ); + handler.handle( expr ); + } + +} // namespace Catch +// end catch_capture_matchers.cpp +// start catch_commandline.cpp + +// start catch_commandline.h // start catch_clara.h @@ -3590,6 +4189,13 @@ namespace Catch { #endif #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wshadow" +#endif + // start clara.hpp // v1.0 // See https://github.com/philsquared/Clara @@ -3720,7 +4326,7 @@ namespace Catch { namespace clara { namespace TextFlow { auto operator *() const -> std::string { assert( m_stringIndex < m_column.m_strings.size() ); - assert( m_pos < m_end ); + assert( m_pos <= m_end ); if( m_pos + m_column.m_width < m_end ) return addIndentAndSuffix(line().substr(m_pos, m_len)); else @@ -4804,6 +5410,10 @@ using detail::ParserResult; }} // namespace Catch::clara // end clara.hpp +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + // Restore Clara's value for console width, if present #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH @@ -4817,1202 +5427,7 @@ namespace Catch { } // end namespace Catch -// end catch_commandline.hpp -// start catch_console_colour.hpp - -namespace Catch { - - struct Colour { - enum Code { - None = 0, - - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White, - - // By intention - FileName = LightGrey, - Warning = Yellow, - ResultError = BrightRed, - ResultSuccess = BrightGreen, - ResultExpectedFailure = Warning, - - Error = BrightRed, - Success = Green, - - OriginalExpression = Cyan, - ReconstructedExpression = Yellow, - - SecondaryText = LightGrey, - Headers = White - }; - - // Use constructed object for RAII guard - Colour( Code _colourCode ); - Colour( Colour&& other ) noexcept; - Colour& operator=( Colour&& other ) noexcept; - ~Colour(); - - // Use static method for one-shot changes - static void use( Code _colourCode ); - - private: - bool m_moved = false; - }; - - std::ostream& operator << ( std::ostream& os, Colour const& ); - -} // end namespace Catch - -// end catch_console_colour.hpp -// start catch_list.h - -#include - -namespace Catch { - - std::size_t listTests( Config const& config ); - - std::size_t listTestsNamesOnly( Config const& config ); - - struct TagInfo { - void add( std::string const& spelling ); - std::string all() const; - - std::set spellings; - std::size_t count = 0; - }; - - std::size_t listTags( Config const& config ); - - std::size_t listReporters( Config const& /*config*/ ); - - Option list( Config const& config ); - -} // end namespace Catch - -// end catch_list.h -// start catch_run_context.hpp - -// start catch_test_case_tracker.hpp - -#include -#include -#include - -CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS - -namespace Catch { -namespace TestCaseTracking { - - struct NameAndLocation { - std::string name; - SourceLineInfo location; - - NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); - }; - - struct ITracker; - - using ITrackerPtr = std::shared_ptr; - - struct ITracker { - virtual ~ITracker() = default; - - // static queries - virtual NameAndLocation const& nameAndLocation() const = 0; - - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - virtual bool hasChildren() const = 0; - - virtual ITracker& parent() = 0; - - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; - - virtual void addChild( ITrackerPtr const& child ) = 0; - virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; - virtual void openChild() = 0; - - // Debug/ checking - virtual bool isSectionTracker() const = 0; - virtual bool isIndexTracker() const = 0; - }; - - class TrackerContext { - - enum RunState { - NotStarted, - Executing, - CompletedCycle - }; - - ITrackerPtr m_rootTracker; - ITracker* m_currentTracker = nullptr; - RunState m_runState = NotStarted; - - public: - - static TrackerContext& instance(); - - ITracker& startRun(); - void endRun(); - - void startCycle(); - void completeCycle(); - - bool completedCycle() const; - ITracker& currentTracker(); - void setCurrentTracker( ITracker* tracker ); - }; - - class TrackerBase : public ITracker { - protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; - - class TrackerHasName { - NameAndLocation m_nameAndLocation; - public: - TrackerHasName( NameAndLocation const& nameAndLocation ); - bool operator ()( ITrackerPtr const& tracker ) const; - }; - - using Children = std::vector; - NameAndLocation m_nameAndLocation; - TrackerContext& m_ctx; - ITracker* m_parent; - Children m_children; - CycleState m_runState = NotStarted; - - public: - TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - - NameAndLocation const& nameAndLocation() const override; - bool isComplete() const override; - bool isSuccessfullyCompleted() const override; - bool isOpen() const override; - bool hasChildren() const override; - - void addChild( ITrackerPtr const& child ) override; - - ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; - ITracker& parent() override; - - void openChild() override; - - bool isSectionTracker() const override; - bool isIndexTracker() const override; - - void open(); - - void close() override; - void fail() override; - void markAsNeedingAnotherRun() override; - - private: - void moveToParent(); - void moveToThis(); - }; - - class SectionTracker : public TrackerBase { - std::vector m_filters; - public: - SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); - - bool isSectionTracker() const override; - - static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); - - void tryOpen(); - - void addInitialFilters( std::vector const& filters ); - void addNextFilters( std::vector const& filters ); - }; - - class IndexTracker : public TrackerBase { - int m_size; - int m_index = -1; - public: - IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); - - bool isIndexTracker() const override; - void close() override; - - static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); - - int index() const; - - void moveNext(); - }; - -} // namespace TestCaseTracking - -using TestCaseTracking::ITracker; -using TestCaseTracking::TrackerContext; -using TestCaseTracking::SectionTracker; -using TestCaseTracking::IndexTracker; - -} // namespace Catch - -CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS - -// end catch_test_case_tracker.hpp -// start catch_fatal_condition.h - -#include - -namespace Catch { - - // Report the error condition - void reportFatal( std::string const& message ); - -} // namespace Catch - -#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// -// start catch_windows_h_proxy.h - - -#if defined(CATCH_PLATFORM_WINDOWS) -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX -# define NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINED_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - -// end catch_windows_h_proxy.h - -# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) - -namespace Catch { - struct FatalConditionHandler { - void reset(); - }; -} - -# else // CATCH_CONFIG_WINDOWS_SEH is defined - -namespace Catch { - - struct FatalConditionHandler { - - static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); - FatalConditionHandler(); - static void reset(); - ~FatalConditionHandler(); - - private: - static bool isSet; - static ULONG guaranteeSize; - static PVOID exceptionHandlerHandle; - }; - -} // namespace Catch - -# endif // CATCH_CONFIG_WINDOWS_SEH - -#else // Not Windows - assumed to be POSIX compatible ////////////////////////// - -# if !defined(CATCH_CONFIG_POSIX_SIGNALS) - -namespace Catch { - struct FatalConditionHandler { - void reset(); - }; -} - -# else // CATCH_CONFIG_POSIX_SIGNALS is defined - -#include - -namespace Catch { - - struct FatalConditionHandler { - - static bool isSet; - static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; - static stack_t oldSigStack; - static char altStackMem[]; - - static void handleSignal( int sig ); - - FatalConditionHandler(); - ~FatalConditionHandler(); - static void reset(); - }; - -} // namespace Catch - -# endif // CATCH_CONFIG_POSIX_SIGNALS - -#endif // not Windows - -// end catch_fatal_condition.h -#include - -namespace Catch { - - struct IMutableContext; - - class StreamRedirect { - - public: - StreamRedirect(std::ostream& stream, std::string& targetString); - - ~StreamRedirect(); - - private: - std::ostream& m_stream; - std::streambuf* m_prevBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - // StdErr has two constituent streams in C++, std::cerr and std::clog - // This means that we need to redirect 2 streams into 1 to keep proper - // order of writes and cannot use StreamRedirect on its own - class StdErrRedirect { - public: - StdErrRedirect(std::string& targetString); - ~StdErrRedirect(); - private: - std::streambuf* m_cerrBuf; - std::streambuf* m_clogBuf; - std::ostringstream m_oss; - std::string& m_targetString; - }; - - /////////////////////////////////////////////////////////////////////////// - - class RunContext : public IResultCapture, public IRunner { - - public: - RunContext( RunContext const& ) = delete; - RunContext& operator =( RunContext const& ) = delete; - - explicit RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter); - - virtual ~RunContext(); - - void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount); - void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount); - - Totals runTest(TestCase const& testCase); - - IConfigPtr config() const; - IStreamingReporter& reporter() const; - - private: // IResultCapture - - void assertionStarting(AssertionInfo const& info) override; - void assertionEnded(AssertionResult const& result) override; - - bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; - bool testForMissingAssertions(Counts& assertions); - - void sectionEnded(SectionEndInfo const& endInfo) override; - void sectionEndedEarly(SectionEndInfo const& endInfo) override; - - void benchmarkStarting( BenchmarkInfo const& info ) override; - void benchmarkEnded( BenchmarkStats const& stats ) override; - - void pushScopedMessage(MessageInfo const& message) override; - void popScopedMessage(MessageInfo const& message) override; - - std::string getCurrentTestName() const override; - - const AssertionResult* getLastResult() const override; - - void exceptionEarlyReported() override; - - void handleFatalErrorCondition(std::string const& message) override; - - bool lastAssertionPassed() override; - - void assertionPassed() override; - - void assertionRun() override; - - public: - // !TBD We need to do this another way! - bool aborting() const override; - - private: - - void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); - void invokeActiveTestCase(); - - private: - - void handleUnfinishedSections(); - - TestRunInfo m_runInfo; - IMutableContext& m_context; - TestCase const* m_activeTestCase = nullptr; - ITracker* m_testCaseTracker; - Option m_lastResult; - - IConfigPtr m_config; - Totals m_totals; - IStreamingReporterPtr m_reporter; - std::vector m_messages; - AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - size_t m_prevPassed = 0; - bool m_shouldReportUnexpected = true; - }; - - IResultCapture& getResultCapture(); - -} // end namespace Catch - -// end catch_run_context.hpp -// start catch_stream.h - -// start catch_streambuf.h - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() noexcept; - }; -} - -// end catch_streambuf.h -#include -#include -#include -#include - -namespace Catch { - - std::ostream& cout(); - std::ostream& cerr(); - std::ostream& clog(); - - struct IStream { - virtual ~IStream() noexcept; - virtual std::ostream& stream() const = 0; - }; - - class FileStream : public IStream { - mutable std::ofstream m_ofs; - public: - FileStream( std::string const& filename ); - ~FileStream() noexcept override; - public: // IStream - std::ostream& stream() const override; - }; - - class CoutStream : public IStream { - mutable std::ostream m_os; - public: - CoutStream(); - ~CoutStream() noexcept override; - - public: // IStream - std::ostream& stream() const override; - }; - - class DebugOutStream : public IStream { - std::unique_ptr m_streamBuf; - mutable std::ostream m_os; - public: - DebugOutStream(); - ~DebugOutStream() noexcept override; - - public: // IStream - std::ostream& stream() const override; - }; -} - -// end catch_stream.h -// start catch_version.h - -#include - -namespace Catch { - - // Versioning information - struct Version { - Version( Version const& ) = delete; - Version& operator=( Version const& ) = delete; - Version( unsigned int _majorVersion, - unsigned int _minorVersion, - unsigned int _patchNumber, - char const * const _branchName, - unsigned int _buildNumber ); - - unsigned int const majorVersion; - unsigned int const minorVersion; - unsigned int const patchNumber; - - // buildNumber is only used if branchName is not null - char const * const branchName; - unsigned int const buildNumber; - - friend std::ostream& operator << ( std::ostream& os, Version const& version ); - }; - - Version const& libraryVersion(); -} - -// end catch_version.h -// start catch_startup_exception_registry.h - -#include -#include - -namespace Catch { - - class StartupExceptionRegistry { - public: - void add(std::exception_ptr const& exception) noexcept; - std::vector const& getExceptions() const noexcept; - private: - std::vector m_exceptions; - }; - -} // end namespace Catch - -// end catch_startup_exception_registry.h -// start catch_text.h - -namespace Catch { - using namespace clara::TextFlow; -} - -// end catch_text.h -#include -#include -#include -#include - -namespace Catch { - - IStreamingReporterPtr createReporter( std::string const& reporterName, IConfigPtr const& config ) { - auto reporter = getRegistryHub().getReporterRegistry().create( reporterName, config ); - CATCH_ENFORCE( reporter, "No reporter registered with name: '" << reporterName << "'" ); - - return reporter; - } - -#ifndef CATCH_CONFIG_DEFAULT_REPORTER -#define CATCH_CONFIG_DEFAULT_REPORTER "console" -#endif - - IStreamingReporterPtr makeReporter( std::shared_ptr const& config ) { - auto const& reporterNames = config->getReporterNames(); - if( reporterNames.empty() ) - return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config ); - - IStreamingReporterPtr reporter; - for( auto const& name : reporterNames ) - addReporter( reporter, createReporter( name, config ) ); - return reporter; - } - void addListeners( IStreamingReporterPtr& reporters, IConfigPtr const& config ) { - auto const& listeners = getRegistryHub().getReporterRegistry().getListeners(); - for( auto const& listener : listeners ) - addReporter(reporters, listener->create( ReporterConfig( config ) ) ); - } - - Totals runTests( std::shared_ptr const& config ) { - - IStreamingReporterPtr reporter = makeReporter( config ); - addListeners( reporter, config ); - - RunContext context( config, std::move( reporter ) ); - - Totals totals; - - context.testGroupStarting( config->name(), 1, 1 ); - - TestSpec testSpec = config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector const& allTestCases = getAllTestCasesSorted( *config ); - for( auto const& testCase : allTestCases ) { - if( !context.aborting() && matchTest( testCase, testSpec, *config ) ) - totals += context.runTest( testCase ); - else - context.reporter().skipTest( testCase ); - } - - context.testGroupEnded( config->name(), totals, 1, 1 ); - return totals; - } - - void applyFilenamesAsTags( IConfig const& config ) { - auto& tests = const_cast&>( getAllTestCasesSorted( config ) ); - for( auto& testCase : tests ) { - auto tags = testCase.tags; - - std::string filename = testCase.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\\/" ); - if( lastSlash != std::string::npos ) - filename = filename.substr( lastSlash+1 ); - - std::string::size_type lastDot = filename.find_last_of( '.' ); - if( lastDot != std::string::npos ) - filename = filename.substr( 0, lastDot ); - - tags.push_back( '#' + filename ); - setTags( testCase, tags ); - } - } - - class Session : NonCopyable { - static const int MaxExitCode; - public: - - Session() { - static bool alreadyInstantiated = false; - if( alreadyInstantiated ) - CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); - alreadyInstantiated = true; - m_cli = makeCommandLineParser( m_configData ); - } - ~Session() override { - Catch::cleanUp(); - } - - void showHelp() const { - Catch::cout() - << "\nCatch v" << libraryVersion() << "\n" - << m_cli << std::endl - << "For more detailed usage please see the project docs\n" << std::endl; - } - void libIdentify() { - Catch::cout() - << std::left << std::setw(16) << "description: " << "A Catch test executable\n" - << std::left << std::setw(16) << "category: " << "testframework\n" - << std::left << std::setw(16) << "framework: " << "Catch Test\n" - << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; - } - - int applyCommandLine( int argc, char* argv[] ) { - auto result = m_cli.parse( clara::Args( argc, argv ) ); - if( !result ) { - Catch::cerr() - << Colour( Colour::Red ) - << "\nError(s) in input:\n" - << Column( result.errorMessage() ).indent( 2 ) - << "\n\n"; - Catch::cerr() << "Run with -? for usage\n" << std::endl; - return MaxExitCode; - } - - if( m_configData.showHelp ) - showHelp(); - if( m_configData.libIdentify ) - libIdentify(); - m_config.reset(); - return 0; - } - - void useConfigData( ConfigData const& configData ) { - m_configData = configData; - m_config.reset(); - } - - int run( int argc, char* argv[] ) { - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - Catch::cerr() << "Errors occured during startup!" << '\n'; - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch ( std::exception const& ex ) { - Catch::cerr() << ex.what() << '\n'; - } - } - return 1; - } - int returnCode = applyCommandLine( argc, argv ); - if( returnCode == 0 ) - returnCode = run(); - return returnCode; - } - - #if defined(WIN32) && defined(UNICODE) - int run( int argc, wchar_t* const argv[] ) { - - char **utf8Argv = new char *[ argc ]; - - for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); - - utf8Argv[ i ] = new char[ bufSize ]; - - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); - } - - int returnCode = run( argc, utf8Argv ); - - for ( int i = 0; i < argc; ++i ) - delete [] utf8Argv[ i ]; - - delete [] utf8Argv; - - return returnCode; - } - #endif - int run() { - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before starting" << std::endl; - static_cast(std::getchar()); - } - int exitCode = runInternal(); - if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { - Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; - static_cast(std::getchar()); - } - return exitCode; - } - - clara::Parser const& cli() const { - return m_cli; - } - void cli( clara::Parser const& newParser ) { - m_cli = newParser; - } - ConfigData& configData() { - return m_configData; - } - Config& config() { - if( !m_config ) - m_config = std::make_shared( m_configData ); - return *m_config; - } - private: - int runInternal() { - if( m_configData.showHelp || m_configData.libIdentify ) - return 0; - - try - { - config(); // Force config to be constructed - - seedRng( *m_config ); - - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags( *m_config ); - - // Handle list request - if( Option listed = list( config() ) ) - return static_cast( *listed ); - - return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); - } - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return MaxExitCode; - } - } - - clara::Parser m_cli; - ConfigData m_configData; - std::shared_ptr m_config; - }; - - const int Session::MaxExitCode = 255; - -} // end namespace Catch - -// end catch_session.hpp -// Cpp files will be included in the single-header file here -// start catch_approx.cpp - -#include - -namespace Catch { -namespace Detail { - - double max(double lhs, double rhs) { - if (lhs < rhs) { - return rhs; - } - return lhs; - } - - Approx::Approx ( double value ) - : m_epsilon( std::numeric_limits::epsilon()*100 ), - m_margin( 0.0 ), - m_scale( 1.0 ), - m_value( value ) - {} - - Approx Approx::custom() { - return Approx( 0 ); - } - - std::string Approx::toString() const { - std::ostringstream oss; - oss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; - return oss.str(); - } - -} // end namespace Detail - -std::string StringMaker::convert(Catch::Detail::Approx const& value) { - return value.toString(); -} - -} // end namespace Catch -// end catch_approx.cpp -// start catch_assertionhandler.cpp - -// start catch_context.h - -#include - -namespace Catch { - - class TestCase; - class Stream; - struct IResultCapture; - struct IRunner; - struct IConfig; - - using IConfigPtr = std::shared_ptr; - - struct IContext - { - virtual ~IContext() = default; - - virtual IResultCapture* getResultCapture() = 0; - virtual IRunner* getRunner() = 0; - virtual IConfigPtr getConfig() const = 0; - }; - - struct IMutableContext : IContext - { - virtual ~IMutableContext() = default; - virtual void setResultCapture( IResultCapture* resultCapture ) = 0; - virtual void setRunner( IRunner* runner ) = 0; - virtual void setConfig( IConfigPtr const& config ) = 0; - }; - - IContext& getCurrentContext(); - IMutableContext& getCurrentMutableContext(); - void cleanUpContext(); -} - -// end catch_context.h -#include - -namespace Catch { - - auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { - expr.streamReconstructedExpression( os ); - return os; - } - - LazyExpression::LazyExpression( bool isNegated ) - : m_isNegated( isNegated ) - {} - - LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} - - LazyExpression::operator bool() const { - return m_transientExpression != nullptr; - } - - auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { - if( lazyExpr.m_isNegated ) - os << "!"; - - if( lazyExpr ) { - if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) - os << "(" << *lazyExpr.m_transientExpression << ")"; - else - os << *lazyExpr.m_transientExpression; - } - else { - os << "{** error - unchecked empty expression requested **}"; - } - return os; - } - - AssertionHandler::AssertionHandler - ( StringRef macroName, - SourceLineInfo const& lineInfo, - StringRef capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } - { - getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); - } - AssertionHandler::~AssertionHandler() { - if ( m_inExceptionGuard ) { - handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ); - getCurrentContext().getResultCapture()->exceptionEarlyReported(); - } - } - - void AssertionHandler::handle( ITransientExpression const& expr ) { - - bool negated = isFalseTest( m_assertionInfo.resultDisposition ); - bool result = expr.getResult() != negated; - - handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); - } - void AssertionHandler::handle( ResultWas::OfType resultType ) { - handle( resultType, nullptr, false ); - } - void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { - AssertionResultData data( resultType, LazyExpression( false ) ); - data.message = message; - handle( data, nullptr ); - } - void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { - AssertionResultData data( resultType, LazyExpression( negated ) ); - handle( data, expr ); - } - void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) { - - getResultCapture().assertionRun(); - - AssertionResult assertionResult{ m_assertionInfo, resultData }; - assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; - - getResultCapture().assertionEnded( assertionResult ); - - if( !assertionResult.isOk() ) { - m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); - m_shouldThrow = - getCurrentContext().getRunner()->aborting() || - (m_assertionInfo.resultDisposition & ResultDisposition::Normal); - } - } - - auto AssertionHandler::allowThrows() const -> bool { - return getCurrentContext().getConfig()->allowThrows(); - } - - auto AssertionHandler::shouldDebugBreak() const -> bool { - return m_shouldDebugBreak; - } - void AssertionHandler::reactWithDebugBreak() const { - if (m_shouldDebugBreak) { - /////////////////////////////////////////////////////////////////// - // To inspect the state during test, you need to go one level up the callstack - // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call - /////////////////////////////////////////////////////////////////// - CATCH_BREAK_INTO_DEBUGGER(); - } - reactWithoutDebugBreak(); - } - void AssertionHandler::reactWithoutDebugBreak() const { - if( m_shouldThrow ) - throw Catch::TestFailureException(); - } - - void AssertionHandler::useActiveException() { - handle( ResultWas::ThrewException, Catch::translateActiveException() ); - } - - void AssertionHandler::setExceptionGuard() { - assert( m_inExceptionGuard == false ); - m_inExceptionGuard = true; - } - void AssertionHandler::unsetExceptionGuard() { - assert( m_inExceptionGuard == true ); - m_inExceptionGuard = false; - } - - // 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 ) { - handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); - } - -} // namespace Catch -// end catch_assertionhandler.cpp -// start catch_assertionresult.cpp - -namespace Catch { - AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): - resultType(_resultType), - lazyExpression(_lazyExpression) {} - - std::string AssertionResultData::reconstructExpression() const { - - if( reconstructedExpression.empty() ) { - if( lazyExpression ) { - // !TBD Use stringstream for now, but rework above to pass stream in - std::ostringstream oss; - oss << lazyExpression; - reconstructedExpression = oss.str(); - } - } - return reconstructedExpression; - } - - AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) - : m_info( info ), - m_resultData( data ) - {} - - // Result was a success - bool AssertionResult::succeeded() const { - return Catch::isOk( m_resultData.resultType ); - } - - // Result was a success, or failure is suppressed - bool AssertionResult::isOk() const { - return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); - } - - ResultWas::OfType AssertionResult::getResultType() const { - return m_resultData.resultType; - } - - bool AssertionResult::hasExpression() const { - return m_info.capturedExpression[0] != 0; - } - - bool AssertionResult::hasMessage() const { - return !m_resultData.message.empty(); - } - - std::string AssertionResult::getExpression() const { - if (isFalseTest(m_info.resultDisposition)) - return '!' + std::string(m_info.capturedExpression); - else - return m_info.capturedExpression; - } - - std::string AssertionResult::getExpressionInMacro() const { - std::string expr; - if( m_info.macroName[0] == 0 ) - expr = m_info.capturedExpression; - else { - expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); - expr += m_info.macroName; - expr += "( "; - expr += m_info.capturedExpression; - expr += " )"; - } - return expr; - } - - bool AssertionResult::hasExpandedExpression() const { - return hasExpression() && getExpandedExpression() != getExpression(); - } - - std::string AssertionResult::getExpandedExpression() const { - std::string expr = m_resultData.reconstructExpression(); - return expr.empty() - ? getExpression() - : expr; - } - - std::string AssertionResult::getMessage() const { - return m_resultData.message; - } - SourceLineInfo AssertionResult::getSourceInfo() const { - return m_info.lineInfo; - } - - std::string AssertionResult::getTestMacroName() const { - return m_info.macroName; - } - -} // end namespace Catch -// end catch_assertionresult.cpp -// start catch_benchmark.cpp - -namespace Catch { - - auto BenchmarkLooper::getResolution() -> uint64_t { - return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); - } - - void BenchmarkLooper::reportStart() { - getResultCapture().benchmarkStarting( { m_name } ); - } - auto BenchmarkLooper::needsMoreIterations() -> bool { - auto elapsed = m_timer.getElapsedNanoseconds(); - - // Exponentially increasing iterations until we're confident in our timer resolution - if( elapsed < m_resolution ) { - m_iterationsToRun *= 10; - return true; - } - - getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); - return false; - } - -} // end namespace Catch -// end catch_benchmark.cpp -// start catch_capture_matchers.cpp - -namespace Catch { - - using StringMatcher = Matchers::Impl::MatcherBase; - - // This is the general overload that takes a any string matcher - // There is another overload, in catch_assertinhandler.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 ) { - std::string exceptionMessage = Catch::translateActiveException(); - MatchExpr expr( exceptionMessage, matcher, matcherString ); - handler.handle( expr ); - } - -} // namespace Catch -// end catch_capture_matchers.cpp -// start catch_commandline.cpp - +// end catch_commandline.h #include #include @@ -6207,14 +5622,6 @@ namespace Catch { return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); } - void seedRng( IConfig const& config ) { - if( config.rngSeed() != 0 ) - std::srand( config.rngSeed() ); - } - unsigned int rngSeed() { - return getCurrentContext().getConfig()->rngSeed(); - } - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << '(' << info.line << ')'; @@ -6232,6 +5639,9 @@ namespace Catch { return std::string(); } + NonCopyable::NonCopyable() = default; + NonCopyable::~NonCopyable() = default; + } // end catch_common.cpp // start catch_config.cpp @@ -6301,6 +5711,11 @@ namespace Catch { // end catch_config.cpp // start catch_console_colour.cpp +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + // start catch_errno_guard.h namespace Catch { @@ -6346,6 +5761,34 @@ namespace Catch { #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) +# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +# endif +# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINED_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +// end catch_windows_h_proxy.h namespace Catch { namespace { @@ -6448,6 +5891,13 @@ namespace { } }; + bool useColourOnPlatform() { + return +#ifdef CATCH_PLATFORM_MAC + !isDebuggerActive() && +#endif + isatty(STDOUT_FILENO); + } IColourImpl* platformColourInstance() { ErrnoGuard guard; IConfigPtr config = getCurrentContext().getConfig(); @@ -6455,7 +5905,7 @@ namespace { ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) - colourMode = isatty(STDOUT_FILENO) + colourMode = useColourOnPlatform() ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes @@ -6501,6 +5951,11 @@ namespace Catch { } } // end namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + // end catch_console_colour.cpp // start catch_context.cpp @@ -6520,6 +5975,8 @@ namespace Catch { return m_config; } + virtual ~Context() override; + public: // IMutableContext virtual void setResultCapture( IResultCapture* resultCapture ) override { m_resultCapture = resultCapture; @@ -6555,8 +6012,38 @@ namespace Catch { delete currentContext; currentContext = nullptr; } + IContext::~IContext() = default; + IMutableContext::~IMutableContext() = default; + Context::~Context() = default; } // end catch_context.cpp +// start catch_debug_console.cpp + +// start catch_debug_console.h + +#include + +namespace Catch { + void writeToDebugConsole( std::string const& text ); +} + +// end catch_debug_console.h +#ifdef CATCH_PLATFORM_WINDOWS + + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } +#endif // Platform +// end catch_debug_console.cpp // start catch_debugger.cpp #ifdef CATCH_PLATFORM_MAC @@ -6567,7 +6054,7 @@ namespace Catch { #include #include - namespace Catch{ + namespace Catch { // The following function is taken directly from the following technical note: // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html @@ -6578,7 +6065,7 @@ namespace Catch { int mib[4]; struct kinfo_proc info; - size_t size; + std::size_t size; // Initialize the flags so that, if sysctl fails for some bizarre // reason, we get a predictable result. @@ -6657,38 +6144,13 @@ namespace Catch { } #endif // Platform // end catch_debugger.cpp -// start catch_debug_console.cpp - -// start catch_debug_console.h - -#include - -namespace Catch { - void writeToDebugConsole( std::string const& text ); -} - -// end catch_debug_console.h -#ifdef CATCH_PLATFORM_WINDOWS - - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - ::OutputDebugStringA( text.c_str() ); - } - } -#else - namespace Catch { - void writeToDebugConsole( std::string const& text ) { - // !TBD: Need a version for Mac/ XCode and other IDEs - Catch::cout() << text; - } - } -#endif // Platform -// end catch_debug_console.cpp // start catch_decomposer.cpp namespace Catch { - void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) { + ITransientExpression::~ITransientExpression() = default; + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { if( lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && rhs.find('\n') == std::string::npos ) @@ -6751,7 +6213,7 @@ namespace Catch { return tryTranslators(); } @catch (NSException *exception) { - return Catch::toString( [exception description] ); + return Catch::Detail::stringify( [exception description] ); } #else return tryTranslators(); @@ -6784,17 +6246,85 @@ namespace Catch { // end catch_exception_translator_registry.cpp // start catch_fatal_condition.cpp +// start catch_fatal_condition.h + +#include + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +# if !defined ( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +# else // CATCH_CONFIG_WINDOWS_SEH is defined + namespace Catch { - // Report the error condition - void reportFatal( std::string const& message ) { - IContext& context = Catch::getCurrentContext(); - IResultCapture* resultCapture = context.getResultCapture(); - resultCapture->handleFatalErrorCondition( message ); - } + struct FatalConditionHandler { + + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); + FatalConditionHandler(); + static void reset(); + ~FatalConditionHandler(); + + private: + static bool isSet; + static ULONG guaranteeSize; + static PVOID exceptionHandlerHandle; + }; } // namespace Catch +# endif // CATCH_CONFIG_WINDOWS_SEH + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +# if !defined(CATCH_CONFIG_POSIX_SIGNALS) + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +# else // CATCH_CONFIG_POSIX_SIGNALS is defined + +#include + +namespace Catch { + + struct FatalConditionHandler { + + static bool isSet; + static struct sigaction oldSigActions[];// [sizeof(signalDefs) / sizeof(SignalDefs)]; + static stack_t oldSigStack; + static char altStackMem[]; + + static void handleSignal( int sig ); + + FatalConditionHandler(); + ~FatalConditionHandler(); + static void reset(); + }; + +} // namespace Catch + +# endif // CATCH_CONFIG_POSIX_SIGNALS + +#endif // not Windows + +// end catch_fatal_condition.h +namespace { + // Report the error condition + void reportFatal( char const * const message ) { + Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); + } +} + #if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// # if !defined ( CATCH_CONFIG_WINDOWS_SEH ) @@ -6811,7 +6341,7 @@ namespace Catch { // There is no 1-1 mapping between signals and windows exceptions. // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { + static SignalDefs signalDefs[] = { { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, @@ -6881,7 +6411,7 @@ namespace Catch { int id; const char* name; }; - SignalDefs signalDefs[] = { + static SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGILL, "SIGILL - Illegal instruction signal" }, { SIGFPE, "SIGFPE - Floating point error signal" }, @@ -6891,7 +6421,7 @@ namespace Catch { }; void FatalConditionHandler::handleSignal( int sig ) { - std::string name = ""; + char const * name = ""; for (auto const& def : signalDefs) { if (sig == def.id) { name = def.name; @@ -6946,6 +6476,32 @@ namespace Catch { #endif // not Windows // end catch_fatal_condition.cpp +// start catch_interfaces_capture.cpp + +namespace Catch { + IResultCapture::~IResultCapture() = default; +} +// end catch_interfaces_capture.cpp +// start catch_interfaces_config.cpp + +namespace Catch { + IConfig::~IConfig() = default; +} +// end catch_interfaces_config.cpp +// start catch_interfaces_exception.cpp + +namespace Catch { + IExceptionTranslator::~IExceptionTranslator() = default; + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; +} +// end catch_interfaces_exception.cpp +// start catch_interfaces_registry_hub.cpp + +namespace Catch { + IRegistryHub::~IRegistryHub() = default; + IMutableRegistryHub::~IMutableRegistryHub() = default; +} +// end catch_interfaces_registry_hub.cpp // start catch_interfaces_reporter.cpp // start catch_reporter_multi.h @@ -6965,7 +6521,7 @@ namespace Catch { void noMatchingTestCases( std::string const& spec ) override; - static std::set getSupportedVerbosities(); + static std::set getSupportedVerbosities(); void testRunStarting( TestRunInfo const& testRunInfo ) override; void testGroupStarting( GroupInfo const& groupInfo ) override; @@ -6986,6 +6542,7 @@ namespace Catch { }; } // end namespace Catch + // end catch_reporter_multi.h namespace Catch { @@ -7028,6 +6585,8 @@ namespace Catch { } } + AssertionStats::~AssertionStats() = default; + SectionStats::SectionStats( SectionInfo const& _sectionInfo, Counts const& _assertions, double _durationInSeconds, @@ -7038,6 +6597,8 @@ namespace Catch { missingAssertions( _missingAssertions ) {} + SectionStats::~SectionStats() = default; + TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, Totals const& _totals, std::string const& _stdOut, @@ -7050,6 +6611,8 @@ namespace Catch { aborting( _aborting ) {} + TestCaseStats::~TestCaseStats() = default; + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, Totals const& _totals, bool _aborting ) @@ -7063,6 +6626,8 @@ namespace Catch { aborting( false ) {} + TestGroupStats::~TestGroupStats() = default; + TestRunStats::TestRunStats( TestRunInfo const& _runInfo, Totals const& _totals, bool _aborting ) @@ -7071,8 +6636,14 @@ namespace Catch { aborting( _aborting ) {} + TestRunStats::~TestRunStats() = default; + + void IStreamingReporter::fatalErrorEncountered( StringRef ) {} bool IStreamingReporter::isMulti() const { return false; } + IReporterFactory::~IReporterFactory() = default; + IReporterRegistry::~IReporterRegistry() = default; + void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { if( !existingReporter ) { @@ -7096,6 +6667,19 @@ namespace Catch { } // end namespace Catch // end catch_interfaces_reporter.cpp +// start catch_interfaces_runner.cpp + +namespace Catch { + IRunner::~IRunner() = default; +} +// end catch_interfaces_runner.cpp +// start catch_interfaces_testcase.cpp + +namespace Catch { + ITestInvoker::~ITestInvoker() = default; + ITestCaseRegistry::~ITestCaseRegistry() = default; +} +// end catch_interfaces_testcase.cpp // start catch_leak_detector.cpp namespace Catch { @@ -7124,6 +6708,40 @@ namespace Catch { // end catch_leak_detector.cpp // start catch_list.cpp +// start catch_list.h + +#include + +namespace Catch { + + std::size_t listTests( Config const& config ); + + std::size_t listTestsNamesOnly( Config const& config ); + + struct TagInfo { + void add( std::string const& spelling ); + std::string all() const; + + std::set spellings; + std::size_t count = 0; + }; + + std::size_t listTags( Config const& config ); + + std::size_t listReporters( Config const& /*config*/ ); + + Option list( Config const& config ); + +} // end namespace Catch + +// end catch_list.h +// start catch_text.h + +namespace Catch { + using namespace clara::TextFlow; +} + +// end catch_text.h #include #include #include @@ -7280,6 +6898,8 @@ namespace Matchers { return m_cachedToString; } + MatcherUntypedBase::~MatcherUntypedBase() = default; + } // namespace Impl } // namespace Matchers @@ -7417,28 +7037,63 @@ namespace Catch { } // end namespace Catch // end catch_message.cpp -// start catch_notimplemented_exception.cpp +// start catch_random_number_generator.cpp -#include +// start catch_random_number_generator.h + +#include namespace Catch { - NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) { - std::ostringstream oss; - oss << lineInfo << ": function "; - oss << "not implemented"; - m_what = oss.str(); + struct IConfig; + + void seedRng( IConfig const& config ); + + unsigned int rngSeed(); + + struct RandomNumberGenerator { + using result_type = std::ptrdiff_t; + + static constexpr result_type min() { return 0; } + static constexpr result_type max() { return 1000000; } + + result_type operator()( result_type n ) const; + result_type operator()() const; + + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; + std::shuffle( vector.begin(), vector.end(), rng ); + } + }; + +} + +// end catch_random_number_generator.h +#include + +namespace Catch { + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); } - const char* NotImplementedException::what() const noexcept { - return m_what.c_str(); + RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { + return std::rand() % n; + } + RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { + return std::rand() % max(); } -} // end namespace Catch -// end catch_notimplemented_exception.cpp +} +// end catch_random_number_generator.cpp // start catch_registry_hub.cpp -// start catch_test_case_registry_impl.hpp +// start catch_test_case_registry_impl.h #include #include @@ -7450,21 +7105,6 @@ namespace Catch { class TestCase; struct IConfig; - struct RandomNumberGenerator { - using result_type = std::ptrdiff_t; - - result_type operator()( result_type n ) const; - - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return 1000000; } - result_type operator()() const; - template - static void shuffle( V& vector ) { - RandomNumberGenerator rng; - std::shuffle( vector.begin(), vector.end(), rng ); - } - }; - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); @@ -7486,7 +7126,7 @@ namespace Catch { std::vector m_functions; mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; mutable std::vector m_sortedFunctions; - size_t m_unnamedCount = 0; + std::size_t m_unnamedCount = 0; std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; @@ -7506,8 +7146,8 @@ namespace Catch { } // end namespace Catch -// end catch_test_case_registry_impl.hpp -// start catch_reporter_registry.hpp +// end catch_test_case_registry_impl.h +// start catch_reporter_registry.h #include @@ -7517,28 +7157,15 @@ namespace Catch { public: - ~ReporterRegistry() override {} + ~ReporterRegistry() override; - IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override { - auto it = m_factories.find( name ); - if( it == m_factories.end() ) - return nullptr; - return it->second->create( ReporterConfig( config ) ); - } + IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; - void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { - m_factories.emplace(name, factory); - } - void registerListener( IReporterFactoryPtr const& factory ) { - m_listeners.push_back( factory ); - } + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); + void registerListener( IReporterFactoryPtr const& factory ); - FactoryMap const& getFactories() const override { - return m_factories; - } - Listeners const& getListeners() const override { - return m_listeners; - } + FactoryMap const& getFactories() const override; + Listeners const& getListeners() const override; private: FactoryMap m_factories; @@ -7546,7 +7173,7 @@ namespace Catch { }; } -// end catch_reporter_registry.hpp +// end catch_reporter_registry.h // start catch_tag_alias_registry.h // start catch_tag_alias.h @@ -7583,6 +7210,24 @@ namespace Catch { } // end namespace Catch // end catch_tag_alias_registry.h +// start catch_startup_exception_registry.h + +#include +#include + +namespace Catch { + + class StartupExceptionRegistry { + public: + void add(std::exception_ptr const& exception) noexcept; + std::vector const& getExceptions() const noexcept; + private: + std::vector m_exceptions; + }; + +} // end namespace Catch + +// end catch_startup_exception_registry.h namespace Catch { namespace { @@ -7591,8 +7236,7 @@ namespace Catch { private NonCopyable { public: // IRegistryHub - RegistryHub() { - } + RegistryHub() = default; IReporterRegistry const& getReporterRegistry() const override { return m_reporterRegistry; } @@ -7663,6 +7307,35 @@ namespace Catch { } // end namespace Catch // end catch_registry_hub.cpp +// start catch_reporter_registry.cpp + +namespace Catch { + + ReporterRegistry::~ReporterRegistry() = default; + + IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { + auto it = m_factories.find( name ); + if( it == m_factories.end() ) + return nullptr; + return it->second->create( ReporterConfig( config ) ); + } + + void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { + m_factories.emplace(name, factory); + } + void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { + m_listeners.push_back( factory ); + } + + IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { + return m_factories; + } + IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { + return m_listeners; + } + +} +// end catch_reporter_registry.cpp // start catch_result_type.cpp namespace Catch { @@ -7685,6 +7358,129 @@ namespace Catch { } // end namespace Catch // end catch_result_type.cpp // start catch_run_context.cpp +// start catch_run_context.h + +#include + +namespace Catch { + + struct IMutableContext; + + class StreamRedirect { + + public: + StreamRedirect(std::ostream& stream, std::string& targetString); + + ~StreamRedirect(); + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + // StdErr has two constituent streams in C++, std::cerr and std::clog + // This means that we need to redirect 2 streams into 1 to keep proper + // order of writes and cannot use StreamRedirect on its own + class StdErrRedirect { + public: + StdErrRedirect(std::string& targetString); + ~StdErrRedirect(); + private: + std::streambuf* m_cerrBuf; + std::streambuf* m_clogBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + public: + RunContext( RunContext const& ) = delete; + RunContext& operator =( RunContext const& ) = delete; + + explicit RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter); + + virtual ~RunContext(); + + void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount); + void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount); + + Totals runTest(TestCase const& testCase); + + IConfigPtr config() const; + IStreamingReporter& reporter() const; + + private: // IResultCapture + + void assertionStarting(AssertionInfo const& info) override; + void assertionEnded(AssertionResult const& result) override; + + bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; + bool testForMissingAssertions(Counts& assertions); + + void sectionEnded(SectionEndInfo const& endInfo) override; + void sectionEndedEarly(SectionEndInfo const& endInfo) override; + + void benchmarkStarting( BenchmarkInfo const& info ) override; + void benchmarkEnded( BenchmarkStats const& stats ) override; + + void pushScopedMessage(MessageInfo const& message) override; + void popScopedMessage(MessageInfo const& message) override; + + std::string getCurrentTestName() const override; + + const AssertionResult* getLastResult() const override; + + void exceptionEarlyReported() override; + + void handleFatalErrorCondition( StringRef message ) override; + + bool lastAssertionPassed() override; + + void assertionPassed() override; + + void assertionRun() override; + + public: + // !TBD We need to do this another way! + bool aborting() const override; + + private: + + void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr); + void invokeActiveTestCase(); + + private: + + void handleUnfinishedSections(); + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase = nullptr; + ITracker* m_testCaseTracker; + Option m_lastResult; + + IConfigPtr m_config; + Totals m_totals; + IStreamingReporterPtr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + std::size_t m_prevPassed = 0; + bool m_shouldReportUnexpected = true; + }; + + IResultCapture& getResultCapture(); + +} // end namespace Catch + +// end catch_run_context.h #include #include @@ -7889,11 +7685,13 @@ namespace Catch { m_shouldReportUnexpected = false; } - void RunContext::handleFatalErrorCondition(std::string const & message) { + void RunContext::handleFatalErrorCondition( StringRef message ) { + // First notify reporter that bad things happened + m_reporter->fatalErrorEncountered(message); + // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. - AssertionResultData tempResult( ResultWas::Unknown, { false } ); - tempResult.resultType = ResultWas::FatalErrorCondition; + AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); tempResult.message = message; AssertionResult result(m_lastAssertionInfo, tempResult); @@ -7902,7 +7700,7 @@ namespace Catch { handleUnfinishedSections(); // Recreate section for test case (as we will lose the one that was in scope) - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); Counts assertions; @@ -7910,7 +7708,7 @@ namespace Catch { SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); m_reporter->sectionEnded(testCaseSectionStats); - TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); + auto const& testInfo = m_activeTestCase->getTestCaseInfo(); Totals deltaTotals; deltaTotals.testCases.failed = 1; @@ -7944,7 +7742,7 @@ namespace Catch { } void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { - TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); m_reporter->sectionStarting(testCaseSection); Counts prevAssertions = m_totals.assertions; @@ -8006,7 +7804,7 @@ namespace Catch { } IResultCapture& getResultCapture() { - if (IResultCapture* capture = getCurrentContext().getResultCapture()) + if (auto* capture = getCurrentContext().getResultCapture()) return *capture; else CATCH_INTERNAL_ERROR("No result capture instance"); @@ -8067,6 +7865,320 @@ namespace Catch { } // end namespace Catch // end catch_section_info.cpp +// start catch_session.cpp + +// start catch_session.h + +#include + +namespace Catch { + + class Session : NonCopyable { + public: + + Session(); + ~Session() override; + + void showHelp() const; + void libIdentify(); + + int applyCommandLine( int argc, char* argv[] ); + + void useConfigData( ConfigData const& configData ); + + int run( int argc, char* argv[] ); + #if defined(WIN32) && defined(UNICODE) + int run( int argc, wchar_t* const argv[] ); + #endif + int run(); + + clara::Parser const& cli() const; + void cli( clara::Parser const& newParser ); + ConfigData& configData(); + Config& config(); + private: + int runInternal(); + + clara::Parser m_cli; + ConfigData m_configData; + std::shared_ptr m_config; + }; + +} // end namespace Catch + +// end catch_session.h +// start catch_version.h + +#include + +namespace Catch { + + // Versioning information + struct Version { + Version( Version const& ) = delete; + Version& operator=( Version const& ) = delete; + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + char const * const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + }; + + Version const& libraryVersion(); +} + +// end catch_version.h +#include +#include + +namespace { + const int MaxExitCode = 255; + using Catch::IStreamingReporterPtr; + using Catch::IConfigPtr; + using Catch::Config; + + IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { + auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); + CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); + + return reporter; + } + +#ifndef CATCH_CONFIG_DEFAULT_REPORTER +#define CATCH_CONFIG_DEFAULT_REPORTER "console" +#endif + + IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { + auto const& reporterNames = config->getReporterNames(); + if (reporterNames.empty()) + return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config); + + IStreamingReporterPtr reporter; + for (auto const& name : reporterNames) + addReporter(reporter, createReporter(name, config)); + return reporter; + } + +#undef CATCH_CONFIG_DEFAULT_REPORTER + + void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) { + auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); + for (auto const& listener : listeners) + addReporter(reporters, listener->create(Catch::ReporterConfig(config))); + } + + Catch::Totals runTests(std::shared_ptr const& config) { + using namespace Catch; + IStreamingReporterPtr reporter = makeReporter(config); + addListeners(reporter, config); + + RunContext context(config, std::move(reporter)); + + Totals totals; + + context.testGroupStarting(config->name(), 1, 1); + + TestSpec testSpec = config->testSpec(); + if (!testSpec.hasFilters()) + testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests + + auto const& allTestCases = getAllTestCasesSorted(*config); + for (auto const& testCase : allTestCases) { + if (!context.aborting() && matchTest(testCase, testSpec, *config)) + totals += context.runTest(testCase); + else + context.reporter().skipTest(testCase); + } + + context.testGroupEnded(config->name(), totals, 1, 1); + return totals; + } + + void applyFilenamesAsTags(Catch::IConfig const& config) { + using namespace Catch; + auto& tests = const_cast&>(getAllTestCasesSorted(config)); + for (auto& testCase : tests) { + auto tags = testCase.tags; + + std::string filename = testCase.lineInfo.file; + auto lastSlash = filename.find_last_of("\\/"); + if (lastSlash != std::string::npos) { + filename.erase(0, lastSlash); + filename[0] = '#'; + } + + auto lastDot = filename.find_last_of('.'); + if (lastDot != std::string::npos) { + filename.erase(lastDot); + } + + tags.push_back(std::move(filename)); + setTags(testCase, tags); + } + } + +} + +namespace Catch { + + Session::Session() { + static bool alreadyInstantiated = false; + if( alreadyInstantiated ) + CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); + alreadyInstantiated = true; + m_cli = makeCommandLineParser( m_configData ); + } + Session::~Session() { + Catch::cleanUp(); + } + + void Session::showHelp() const { + Catch::cout() + << "\nCatch v" << libraryVersion() << "\n" + << m_cli << std::endl + << "For more detailed usage please see the project docs\n" << std::endl; + } + void Session::libIdentify() { + Catch::cout() + << std::left << std::setw(16) << "description: " << "A Catch test executable\n" + << std::left << std::setw(16) << "category: " << "testframework\n" + << std::left << std::setw(16) << "framework: " << "Catch Test\n" + << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; + } + + int Session::applyCommandLine( int argc, char* argv[] ) { + auto result = m_cli.parse( clara::Args( argc, argv ) ); + if( !result ) { + Catch::cerr() + << Colour( Colour::Red ) + << "\nError(s) in input:\n" + << Column( result.errorMessage() ).indent( 2 ) + << "\n\n"; + Catch::cerr() << "Run with -? for usage\n" << std::endl; + return MaxExitCode; + } + + if( m_configData.showHelp ) + showHelp(); + if( m_configData.libIdentify ) + libIdentify(); + m_config.reset(); + return 0; + } + + void Session::useConfigData( ConfigData const& configData ) { + m_configData = configData; + m_config.reset(); + } + + int Session::run( int argc, char* argv[] ) { + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + Catch::cerr() << "Errors occured during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << ex.what() << '\n'; + } + } + return 1; + } + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + +#if defined(WIN32) && defined(UNICODE) + int Session::run( int argc, wchar_t* const argv[] ) { + + char **utf8Argv = new char *[ argc ]; + + for ( int i = 0; i < argc; ++i ) { + int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + + utf8Argv[ i ] = new char[ bufSize ]; + + WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); + } + + int returnCode = run( argc, utf8Argv ); + + for ( int i = 0; i < argc; ++i ) + delete [] utf8Argv[ i ]; + + delete [] utf8Argv; + + return returnCode; + } +#endif + int Session::run() { + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before starting" << std::endl; + static_cast(std::getchar()); + } + int exitCode = runInternal(); + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; + static_cast(std::getchar()); + } + return exitCode; + } + + clara::Parser const& Session::cli() const { + return m_cli; + } + void Session::cli( clara::Parser const& newParser ) { + m_cli = newParser; + } + ConfigData& Session::configData() { + return m_configData; + } + Config& Session::config() { + if( !m_config ) + m_config = std::make_shared( m_configData ); + return *m_config; + } + + int Session::runInternal() { + if( m_configData.showHelp || m_configData.libIdentify ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return (std::min)( MaxExitCode, static_cast( runTests( m_config ).assertions.failed ) ); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return MaxExitCode; + } + } + +} // end namespace Catch +// end catch_session.cpp // start catch_startup_exception_registry.cpp namespace Catch { @@ -8094,7 +8206,7 @@ namespace Catch { namespace Catch { - template + template class StreamBufImpl : public StreamBufBase { char data[bufferSize]; WriterF m_writer; @@ -8132,6 +8244,8 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// + Catch::IStream::~IStream() = default; + FileStream::FileStream( std::string const& filename ) { m_ofs.open( filename.c_str() ); CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); @@ -8180,8 +8294,90 @@ namespace Catch { #endif } // end catch_stream.cpp +// start catch_streambuf.cpp + +namespace Catch { + StreamBufBase::~StreamBufBase() = default; +} +// end catch_streambuf.cpp +// start catch_string_manip.cpp + +#include +#include +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); + } + bool startsWith( std::string const& s, char prefix ) { + return !s.empty() && s[0] == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); + } + bool endsWith( std::string const& s, char suffix ) { + return !s.empty() && s[s.size()-1] == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << 's'; + return os; + } + +} +// end catch_string_manip.cpp // start catch_stringref.cpp +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + #include #include #include @@ -8335,78 +8531,11 @@ namespace Catch { } } // namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif // end catch_stringref.cpp -// start catch_string_manip.cpp - -#include -#include -#include -#include - -namespace Catch { - - bool startsWith( std::string const& s, std::string const& prefix ) { - return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); - } - bool startsWith( std::string const& s, char prefix ) { - return !s.empty() && s[0] == prefix; - } - bool endsWith( std::string const& s, std::string const& suffix ) { - return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); - } - bool endsWith( std::string const& s, char suffix ) { - return !s.empty() && s[s.size()-1] == suffix; - } - bool contains( std::string const& s, std::string const& infix ) { - return s.find( infix ) != std::string::npos; - } - char toLowerCh(char c) { - return static_cast( std::tolower( c ) ); - } - void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); - } - std::string toLower( std::string const& s ) { - std::string lc = s; - toLowerInPlace( lc ); - return lc; - } - std::string trim( std::string const& str ) { - static char const* whitespaceChars = "\n\r\t "; - std::string::size_type start = str.find_first_not_of( whitespaceChars ); - std::string::size_type end = str.find_last_not_of( whitespaceChars ); - - return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); - } - - bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { - bool replaced = false; - std::size_t i = str.find( replaceThis ); - while( i != std::string::npos ) { - replaced = true; - str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); - if( i < str.size()-withThis.size() ) - i = str.find( replaceThis, i+withThis.size() ); - else - i = std::string::npos; - } - return replaced; - } - - pluralise::pluralise( std::size_t count, std::string const& label ) - : m_count( count ), - m_label( label ) - {} - - std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { - os << pluraliser.m_count << ' ' << pluraliser.m_label; - if( pluraliser.m_count != 1 ) - os << 's'; - return os; - } - -} -// end catch_string_manip.cpp // start catch_tag_alias.cpp namespace Catch { @@ -8594,7 +8723,7 @@ namespace Catch { std::string TestCaseInfo::tagsAsString() const { std::string ret; // '[' and ']' per tag - size_t full_size = 2 * tags.size(); + std::size_t full_size = 2 * tags.size(); for (const auto& tag : tags) { full_size += tag.size(); } @@ -8643,9 +8772,6 @@ namespace Catch { namespace Catch { - RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { return std::rand() % n; } - RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { return std::rand() % max(); } - std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { std::vector sorted = unsortedTestCases; @@ -8744,7 +8870,10 @@ namespace Catch { #include #include -CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif namespace Catch { namespace TestCaseTracking { @@ -8754,6 +8883,8 @@ namespace TestCaseTracking { location( _location ) {} + ITracker::~ITracker() = default; + TrackerContext& TrackerContext::instance() { static TrackerContext s_instance; return s_instance; @@ -9001,7 +9132,9 @@ using TestCaseTracking::IndexTracker; } // namespace Catch -CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS +#if defined(__clang__) +# pragma clang diagnostic pop +#endif // end catch_test_case_tracker.cpp // start catch_test_registry.cpp @@ -9028,6 +9161,8 @@ namespace Catch { getMutableRegistryHub().registerStartupException(); } } + + AutoReg::~AutoReg() = default; } // end catch_test_registry.cpp // start catch_test_spec.cpp @@ -9039,6 +9174,11 @@ namespace Catch { namespace Catch { + TestSpec::Pattern::~Pattern() = default; + TestSpec::NamePattern::~NamePattern() = default; + TestSpec::TagPattern::~TagPattern() = default; + TestSpec::ExcludedPattern::~ExcludedPattern() = default; + TestSpec::NamePattern::NamePattern( std::string const& name ) : m_wildcardPattern( toLower( name ), CaseSensitive::No ) {} @@ -9172,7 +9312,7 @@ namespace Catch { uint64_t sum = 0; static const uint64_t iterations = 1000000; - for( size_t i = 0; i < iterations; ++i ) { + for( std::size_t i = 0; i < iterations; ++i ) { uint64_t ticks; uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); @@ -9214,6 +9354,12 @@ namespace Catch { // end catch_timer.cpp // start catch_tostring.cpp +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + #include namespace Catch { @@ -9409,23 +9555,12 @@ std::string StringMaker::convert(double value) { return fpToString(value, 10); } -#ifdef __OBJC__ -std::string StringMaker::convert(NSString* nsstring) { - if (!nsstring) - return "nil"; - return "@" + toString([nsstring UTF8String]); -} -std::string StringMaker::convert(NSString* CATCH_ARC_STRONG nsstring) { - if (!nsstring) - return "nil"; - return "@" + toString([nsstring UTF8String]); -} -std::string StringMaker::convert(NSObject* nsObject) { - return ::Catch::Detail::stringify([nsObject description]); -} +} // end namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop #endif -} // end namespace Catch // end catch_tostring.cpp // start catch_totals.cpp @@ -9514,7 +9649,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 3 ); + static Version version( 2, 0, 0, "develop", 4 ); return version; } @@ -9561,7 +9696,7 @@ namespace Catch { // end catch_wildcard_pattern.cpp // start catch_xmlwriter.cpp -// start catch_xmlwriter.hpp +// start catch_xmlwriter.h #include #include @@ -9657,7 +9792,7 @@ namespace Catch { } -// end catch_xmlwriter.hpp +// end catch_xmlwriter.h #include namespace Catch { @@ -9859,7 +9994,7 @@ namespace Catch { // + 1 for decimal point // + 3 for the 3 decimal places // + 1 for null terminator - const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; char buffer[maxDoubleSize]; // Save previous errno, to prevent sprintf from overwriting it @@ -10182,179 +10317,179 @@ namespace Catch { #include #include -namespace { - std::size_t makeRatio( std::size_t number, std::size_t total ) { - std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; - return ( ratio == 0 && number > 0 ) ? 1 : ratio; - } - - std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { - if( i > j && i > k ) - return i; - else if( j > k ) - return j; - else - return k; - } - - struct ColumnInfo { - enum Justification { Left, Right }; - std::string name; - int width; - Justification justification; - }; - struct ColumnBreak {}; - struct RowBreak {}; - - class TablePrinter { - std::ostream& m_os; - std::vector m_columnInfos; - std::ostringstream m_oss; - int m_currentColumn = -1; - bool m_isOpen = false; - - public: - TablePrinter( std::ostream& os, std::vector const& columnInfos ) - : m_os( os ), - m_columnInfos( columnInfos ) - {} - - auto columnInfos() const -> std::vector const& { - return m_columnInfos; - } - - void open() { - if( !m_isOpen ) { - m_isOpen = true; - *this << RowBreak(); - for( auto const& info : m_columnInfos ) - *this << info.name << ColumnBreak(); - *this << RowBreak(); - m_os << Catch::getLineOfChars<'-'>() << "\n"; - } - } - void close() { - if( m_isOpen ) { - *this << RowBreak(); - m_os << std::endl; - m_isOpen = false; - } - } - - template - friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { - tp.m_oss << value; - return tp; - } - - friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { - auto colStr = tp.m_oss.str(); - // This takes account of utf8 encodings - auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); - tp.m_oss.str(""); - tp.open(); - if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { - tp.m_currentColumn = -1; - tp.m_os << "\n"; - } - tp.m_currentColumn++; - - auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; - auto padding = ( strSize+2 < static_cast( colInfo.width ) ) - ? std::string( colInfo.width-(strSize+2), ' ' ) - : std::string(); - if( colInfo.justification == ColumnInfo::Left ) - tp.m_os << colStr << padding << " "; - else - tp.m_os << padding << colStr << " "; - return tp; - } - - friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { - if( tp.m_currentColumn > 0 ) { - tp.m_os << "\n"; - tp.m_currentColumn = -1; - } - return tp; - } - }; - - class Duration { - enum class Unit { - Auto, - Nanoseconds, - Microseconds, - Milliseconds, - Seconds, - Minutes - }; - static const uint64_t s_nanosecondsInAMicrosecond = 1000; - static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; - static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; - static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; - - uint64_t m_inNanoseconds; - Unit m_units; - - public: - Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) - : m_inNanoseconds( inNanoseconds ), - m_units( units ) - { - if( m_units == Unit::Auto ) { - if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) - m_units = Unit::Nanoseconds; - else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) - m_units = Unit::Microseconds; - else if( m_inNanoseconds < s_nanosecondsInASecond ) - m_units = Unit::Milliseconds; - else if( m_inNanoseconds < s_nanosecondsInAMinute ) - m_units = Unit::Seconds; - else - m_units = Unit::Minutes; - } - - } - - auto value() const -> double { - switch( m_units ) { - case Unit::Microseconds: - return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); - case Unit::Milliseconds: - return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); - case Unit::Seconds: - return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); - case Unit::Minutes: - return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); - default: - return static_cast( m_inNanoseconds ); - } - } - auto unitsAsString() const -> std::string { - switch( m_units ) { - case Unit::Nanoseconds: - return "ns"; - case Unit::Microseconds: - return "µs"; - case Unit::Milliseconds: - return "ms"; - case Unit::Seconds: - return "s"; - case Unit::Minutes: - return "m"; - default: - return "** internal error **"; - } - - } - friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { - return os << duration.value() << " " << duration.unitsAsString(); - } - }; -} - namespace Catch { + namespace { + std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + + std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + struct ColumnInfo { + enum Justification { Left, Right }; + std::string name; + int width; + Justification justification; + }; + struct ColumnBreak {}; + struct RowBreak {}; + + class TablePrinter { + std::ostream& m_os; + std::vector m_columnInfos; + std::ostringstream m_oss; + int m_currentColumn = -1; + bool m_isOpen = false; + + public: + TablePrinter( std::ostream& os, std::vector const& columnInfos ) + : m_os( os ), + m_columnInfos( columnInfos ) + {} + + auto columnInfos() const -> std::vector const& { + return m_columnInfos; + } + + void open() { + if( !m_isOpen ) { + m_isOpen = true; + *this << RowBreak(); + for( auto const& info : m_columnInfos ) + *this << info.name << ColumnBreak(); + *this << RowBreak(); + m_os << Catch::getLineOfChars<'-'>() << "\n"; + } + } + void close() { + if( m_isOpen ) { + *this << RowBreak(); + m_os << std::endl; + m_isOpen = false; + } + } + + template + friend TablePrinter& operator << ( TablePrinter& tp, T const& value ) { + tp.m_oss << value; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, ColumnBreak ) { + auto colStr = tp.m_oss.str(); + // This takes account of utf8 encodings + auto strSize = Catch::StringRef( colStr ).numberOfCharacters(); + tp.m_oss.str(""); + tp.open(); + if( tp.m_currentColumn == static_cast(tp.m_columnInfos.size()-1) ) { + tp.m_currentColumn = -1; + tp.m_os << "\n"; + } + tp.m_currentColumn++; + + auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; + auto padding = ( strSize+2 < static_cast( colInfo.width ) ) + ? std::string( colInfo.width-(strSize+2), ' ' ) + : std::string(); + if( colInfo.justification == ColumnInfo::Left ) + tp.m_os << colStr << padding << " "; + else + tp.m_os << padding << colStr << " "; + return tp; + } + + friend TablePrinter& operator << ( TablePrinter& tp, RowBreak ) { + if( tp.m_currentColumn > 0 ) { + tp.m_os << "\n"; + tp.m_currentColumn = -1; + } + return tp; + } + }; + + class Duration { + enum class Unit { + Auto, + Nanoseconds, + Microseconds, + Milliseconds, + Seconds, + Minutes + }; + static const uint64_t s_nanosecondsInAMicrosecond = 1000; + static const uint64_t s_nanosecondsInAMillisecond = 1000*s_nanosecondsInAMicrosecond; + static const uint64_t s_nanosecondsInASecond = 1000*s_nanosecondsInAMillisecond; + static const uint64_t s_nanosecondsInAMinute = 60*s_nanosecondsInASecond; + + uint64_t m_inNanoseconds; + Unit m_units; + + public: + Duration( uint64_t inNanoseconds, Unit units = Unit::Auto ) + : m_inNanoseconds( inNanoseconds ), + m_units( units ) + { + if( m_units == Unit::Auto ) { + if( m_inNanoseconds < s_nanosecondsInAMicrosecond ) + m_units = Unit::Nanoseconds; + else if( m_inNanoseconds < s_nanosecondsInAMillisecond ) + m_units = Unit::Microseconds; + else if( m_inNanoseconds < s_nanosecondsInASecond ) + m_units = Unit::Milliseconds; + else if( m_inNanoseconds < s_nanosecondsInAMinute ) + m_units = Unit::Seconds; + else + m_units = Unit::Minutes; + } + + } + + auto value() const -> double { + switch( m_units ) { + case Unit::Microseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMicrosecond ); + case Unit::Milliseconds: + return m_inNanoseconds / static_cast( s_nanosecondsInAMillisecond ); + case Unit::Seconds: + return m_inNanoseconds / static_cast( s_nanosecondsInASecond ); + case Unit::Minutes: + return m_inNanoseconds / static_cast( s_nanosecondsInAMinute ); + default: + return static_cast( m_inNanoseconds ); + } + } + auto unitsAsString() const -> std::string { + switch( m_units ) { + case Unit::Nanoseconds: + return "ns"; + case Unit::Microseconds: + return "µs"; + case Unit::Milliseconds: + return "ms"; + case Unit::Seconds: + return "s"; + case Unit::Minutes: + return "m"; + default: + return "** internal error **"; + } + + } + friend auto operator << ( std::ostream& os, Duration const& duration ) -> std::ostream& { + return os << duration.value() << " " << duration.unitsAsString(); + } + }; + } // end anon namespace + struct ConsoleReporter : StreamingReporterBase { TablePrinter m_tablePrinter; @@ -10819,7 +10954,7 @@ namespace Catch { // Also, UTC only, again because of backward compatibility (%z is C++11) time_t rawtime; std::time(&rawtime); - const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); #ifdef _MSC_VER std::tm timeInfo = {}; @@ -11061,7 +11196,7 @@ namespace Catch { } std::set MultipleReporters::getSupportedVerbosities() { - return { }; + return std::set{ }; } void MultipleReporters::noMatchingTestCases( std::string const& spec ) { @@ -11348,26 +11483,6 @@ namespace Catch { namespace Catch { LeakDetector leakDetector; - - // These are all here to avoid warnings about not having any out of line - // virtual methods - NonCopyable::~NonCopyable() {} - IStream::~IStream() noexcept {} - FileStream::~FileStream() noexcept {} - CoutStream::~CoutStream() noexcept {} - DebugOutStream::~DebugOutStream() noexcept {} - StreamBufBase::~StreamBufBase() noexcept {} - IResultCapture::~IResultCapture() {} - ITestInvoker::~ITestInvoker() {} - ITestCaseRegistry::~ITestCaseRegistry() {} - IRegistryHub::~IRegistryHub() {} - IMutableRegistryHub::~IMutableRegistryHub() {} - IExceptionTranslator::~IExceptionTranslator() {} - IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} - IRunner::~IRunner() {} - IConfig::~IConfig() {} - - void Config::dummy() {} } #ifdef __clang__ @@ -11402,7 +11517,7 @@ int main (int argc, char * const argv[]) { #endif Catch::registerTestMethods(); - int result = Catch::Session().run( argc, (char* const*)argv ); + int result = Catch::Session().run( argc, (char**)argv ); #if !CATCH_ARC_ENABLED [pool drain]; diff --git a/test_package/conanfile.py b/test_package/conanfile.py index ebefc8ac..2311ab7f 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.0.0-develop.3@%s/%s" % (username, channel) + requires = "Catch/2.0.0-develop.4@%s/%s" % (username, channel) def build(self): cmake = CMake(self) From 3d49d83128f80b70edd5333729f5d8bc96a5b018 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 21 Sep 2017 09:32:46 +0100 Subject: [PATCH 348/398] Added benchmark support to MultiReporters - otherwise benchmarks are not reported if multiple reporters (usually reporter + listener(s)) are used --- include/reporters/catch_reporter_multi.cpp | 8 ++++++++ include/reporters/catch_reporter_multi.h | 3 +++ 2 files changed, 11 insertions(+) diff --git a/include/reporters/catch_reporter_multi.cpp b/include/reporters/catch_reporter_multi.cpp index 017b628d..23bb1603 100644 --- a/include/reporters/catch_reporter_multi.cpp +++ b/include/reporters/catch_reporter_multi.cpp @@ -28,6 +28,14 @@ namespace Catch { reporter->noMatchingTestCases( spec ); } + void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkStarting( benchmarkInfo ); + } + void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkEnded( benchmarkStats ); + } void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { for( auto const& reporter : m_reporters ) diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_multi.h index 02924c9c..985d442f 100644 --- a/include/reporters/catch_reporter_multi.h +++ b/include/reporters/catch_reporter_multi.h @@ -26,6 +26,9 @@ namespace Catch { static std::set getSupportedVerbosities(); + void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; + void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; + void testRunStarting( TestRunInfo const& testRunInfo ) override; void testGroupStarting( GroupInfo const& groupInfo ) override; void testCaseStarting( TestCaseInfo const& testInfo ) override; From 80bbce84248cc2e7fcfdbd3f50f3b0bbb6b20c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 26 Sep 2017 13:36:57 +0200 Subject: [PATCH 349/398] Reorganize release notes --- docs/release-notes.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index c134b3fa..fc4de69b 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -19,7 +19,9 @@ * This is most noticeable in `CHECK(throws())`, which would previously report failure, properly stringify the exception and continue. Now it will report failure and stop executing current section. * Removed deprecated matcher utility functions `Not`, `AllOf` and `AnyOf`. * They are superseded by operators `!`, `&&` and `||`, which are natural and do not have limited arity -* No longer accept non-const comparison operators +* Removed support for non-const comparison operators + * Non-const comparison operators are an abomination that should not exist + * They were breaking support for comparing function to function pointer ## Improvements @@ -48,13 +50,17 @@ * Exception translators are not registered * Reporters are not registered * Listeners are not registered -* More warnings are silenced -* Don't use console colour if running in XCode +* Reporters/Listeners are now notified of fatal errors + * This means specific signals or structured exceptions + * The Reporter/Listener interface provides default, empty, implementation to preserve backward compatibility + ## Fixes +* Don't use console colour if running in XCode * Explicit constructor in reporter base class -* Many fixes for building in Objective-C context -* Do not use SEH and console api under UWP +* Swept out `-Wweak-vtables`, `-Wexit-time-destructors`, `-Wglobal-constructors` warnings +* Compilation for Universal Windows Platform (UWP) is supported + * SEH handling and colorized output are disabled when compiling for UWP ## Internal changes * The development version now uses .cpp files instead of header files containing implementation. From 9541e89e6a91b89b45f222053d7131e0fe8dba93 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 25 Sep 2017 15:11:12 -0700 Subject: [PATCH 350/398] Changed embed script to just do direct regex substitution --- scripts/embed.py | 26 ++++++++------------------ scripts/embedClara.py | 2 +- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/scripts/embed.py b/scripts/embed.py index 85a7fcfb..23b157c8 100644 --- a/scripts/embed.py +++ b/scripts/embed.py @@ -22,27 +22,16 @@ class LineMapper: self.idMap = idMap self.outerNamespace = outerNamespace - def replaceId( self, lineNo, id ): - if not self.idMap.has_key( id ): - raise ValueError( "Unrecognised macro identifier: '{0}' on line: {1}".format( id, lineNo ) ) - subst = self.idMap[id] - if subst == "": - return id - else: - return subst - # TBD: # #if, #ifdef, comments after #else def mapLine( self, lineNo, line ): - m = ifndefRe.match( line ) - if m: - return "#ifndef " + self.replaceId( lineNo, m.group(1)) + "\n" - m = defineRe.match( line ) - if m: - return "#define {0}{1}{2}\n".format( self.replaceId( lineNo, m.group(1)), m.group(2), m.group(3) ) - m = endifRe.match( line ) - if m: - return "#endif // " + self.replaceId( lineNo, m.group(1)) + "\n" + for idFrom, idTo in self.idMap.iteritems(): + r = re.compile("(.*)" + idFrom + "(.*)") + + m = r.match( line ) + if m: + line = m.group(1) + idTo + m.group(2) + "\n" + m = nsCloseRe.match( line ) if m: originalNs = m.group(3) @@ -61,6 +50,7 @@ class LineMapper: if self.outerNamespace.has_key(originalNs): outerNs, innerNs = self.outerNamespace[originalNs] return "{0}{1} {{ namespace {2}{3}{4}\n".format( m.group(1), outerNs, innerNs, m.group(3), m.group(4) ) + return line def mapFile(self, filenameIn, filenameOut ): diff --git a/scripts/embedClara.py b/scripts/embedClara.py index 3a861549..e7bb9335 100644 --- a/scripts/embedClara.py +++ b/scripts/embedClara.py @@ -15,7 +15,7 @@ idMap = { "CLARA_CONFIG_CONSOLE_WIDTH": "CATCH_CLARA_CONFIG_CONSOLE_WIDTH", "CLARA_TEXTFLOW_HPP_INCLUDED": "CATCH_CLARA_TEXTFLOW_HPP_INCLUDED", "CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH": "CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH", - "CLARA_PLATFORM_WINDOWS": "" + "CLARA_PLATFORM_WINDOWS": "CATCH_PLATFORM_WINDOWS" } # outer namespace to add From 2a1f8ae684eb4d9ac6dda20261295c8d354a0ef9 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 25 Sep 2017 15:12:00 -0700 Subject: [PATCH 351/398] New version of Clara --- include/external/clara.hpp | 497 ++++++++++++------------- include/internal/catch_commandline.cpp | 54 +-- third_party/clara.hpp | 490 ++++++++++++------------ 3 files changed, 507 insertions(+), 534 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 4abcd16f..e46574b4 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -4,11 +4,13 @@ #ifndef CATCH_CLARA_HPP_INCLUDED #define CATCH_CLARA_HPP_INCLUDED - #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 #endif +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#endif // ----------- #included from clara_textflow.hpp ----------- @@ -24,7 +26,6 @@ #ifndef CATCH_CLARA_TEXTFLOW_HPP_INCLUDED #define CATCH_CLARA_TEXTFLOW_HPP_INCLUDED - #include #include #include @@ -350,9 +351,8 @@ namespace Catch { namespace clara { namespace TextFlow { #include #include -#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) -#define CLARA_PLATFORM_WINDOWS - +#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CATCH_PLATFORM_WINDOWS #endif namespace Catch { namespace clara { @@ -360,15 +360,15 @@ namespace detail { // Traits for extracting arg and return type of lambdas (for single argument lambdas) template - struct UnaryLambdaTraits : UnaryLambdaTraits {}; + struct UnaryLambdaTraits : UnaryLambdaTraits {}; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = false; }; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = true; using ArgType = typename std::remove_const::type>::type;; using ReturnType = ReturnT; @@ -383,13 +383,13 @@ namespace detail { std::vector m_args; public: - Args(int argc, char *argv[]) { + Args( int argc, char *argv[] ) { m_exeName = argv[0]; - for (int i = 1; i < argc; ++i) - m_args.push_back(argv[i]); + for( int i = 1; i < argc; ++i ) + m_args.push_back( argv[i] ); } - Args(std::initializer_list args) + Args( std::initializer_list args ) : m_exeName( *args.begin() ), m_args( args.begin()+1, args.end() ) {} @@ -417,40 +417,40 @@ namespace detail { std::vector m_tokenBuffer; void loadBuffer() { - m_tokenBuffer.resize(0); + m_tokenBuffer.resize( 0 ); // Skip any empty strings - while (it != itEnd && it->empty()) + while( it != itEnd && it->empty() ) ++it; - if (it != itEnd) { + if( it != itEnd ) { auto const &next = *it; - if (next[0] == '-' || next[0] == '/') { - auto delimiterPos = next.find_first_of(" :="); - if (delimiterPos != std::string::npos) { - m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)}); - m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)}); + if( next[0] == '-' || next[0] == '/' ) { + auto delimiterPos = next.find_first_of( " :=" ); + if( delimiterPos != std::string::npos ) { + m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); + m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); } else { - if (next[1] != '-' && next.size() > 2) { + if( next[1] != '-' && next.size() > 2 ) { std::string opt = "- "; - for (size_t i = 1; i < next.size(); ++i) { + for( size_t i = 1; i < next.size(); ++i ) { opt[1] = next[i]; - m_tokenBuffer.push_back({TokenType::Option, opt}); + m_tokenBuffer.push_back( { TokenType::Option, opt } ); } } else { - m_tokenBuffer.push_back({TokenType::Option, next}); + m_tokenBuffer.push_back( { TokenType::Option, next } ); } } } else { - m_tokenBuffer.push_back({TokenType::Argument, next}); + m_tokenBuffer.push_back( { TokenType::Argument, next } ); } } } public: - explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} + explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} - TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { loadBuffer(); } @@ -461,20 +461,20 @@ namespace detail { auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } auto operator*() const -> Token { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return m_tokenBuffer.front(); } auto operator->() const -> Token const * { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return &m_tokenBuffer.front(); } auto operator++() -> TokenStream & { - if (m_tokenBuffer.size() >= 2) { - m_tokenBuffer.erase(m_tokenBuffer.begin()); + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); } else { - if (it != itEnd) + if( it != itEnd ) ++it; loadBuffer(); } @@ -490,7 +490,7 @@ namespace detail { }; protected: - ResultBase(Type type) : m_type(type) {} + ResultBase( Type type ) : m_type( type ) {} virtual ~ResultBase() = default; virtual void enforceOk() const = 0; @@ -507,28 +507,28 @@ namespace detail { } protected: - ResultValueBase(Type type) : ResultBase(type) {} + ResultValueBase( Type type ) : ResultBase( type ) {} - ResultValueBase(ResultValueBase const &other) : ResultBase(other) { - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); } - ResultValueBase(Type, T const &value) : ResultBase(Ok) { - new(&m_value) T(value); + ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { + new( &m_value ) T( value ); } - auto operator=(ResultValueBase const &other) -> ResultValueBase & { - if (m_type == ResultBase::Ok) + auto operator=( ResultValueBase const &other ) -> ResultValueBase & { + if( m_type == ResultBase::Ok ) m_value.~T(); ResultBase::operator=(other); - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); return *this; } ~ResultValueBase() { - if (m_type == Ok) + if( m_type == Ok ) m_value.~T(); } @@ -547,37 +547,31 @@ namespace detail { class BasicResult : public ResultValueBase { public: template - explicit BasicResult(BasicResult const &other) - : ResultValueBase(other.type()), - m_errorMessage(other.errorMessage()) { - assert(type() != ResultBase::Ok); + explicit BasicResult( BasicResult const &other ) + : ResultValueBase( other.type() ), + m_errorMessage( other.errorMessage() ) + { + assert( type() != ResultBase::Ok ); } - static auto ok() -> BasicResult { return {ResultBase::Ok}; } - template - static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; } - - static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; } - - static auto runtimeError(std::string const &message) -> BasicResult { - return {ResultBase::RuntimeError, message}; - } + static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } + static auto ok() -> BasicResult { return { ResultBase::Ok }; } + static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } + static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } explicit operator bool() const { return m_type == ResultBase::Ok; } - auto type() const -> ResultBase::Type { return m_type; } - auto errorMessage() const -> std::string { return m_errorMessage; } protected: virtual void enforceOk() const { // !TBD: If no exceptions, std::terminate here or something - switch (m_type) { + switch( m_type ) { case ResultBase::LogicError: - throw std::logic_error(m_errorMessage); + throw std::logic_error( m_errorMessage ); case ResultBase::RuntimeError: - throw std::runtime_error(m_errorMessage); + throw std::runtime_error( m_errorMessage ); case ResultBase::Ok: break; } @@ -585,10 +579,11 @@ namespace detail { std::string m_errorMessage; // Only populated if resultType is an error - BasicResult(ResultBase::Type type, std::string const &message) - : ResultValueBase(type), - m_errorMessage(message) { - assert(m_type != ResultBase::Ok); + BasicResult( ResultBase::Type type, std::string const &message ) + : ResultValueBase(type), + m_errorMessage(message) + { + assert( m_type != ResultBase::Ok ); } using ResultValueBase::ResultValueBase; @@ -602,12 +597,12 @@ namespace detail { class ParseState { public: - ParseState(ParseResultType type, TokenStream const &remainingTokens) - : m_type(type), - m_remainingTokens(remainingTokens) {} + ParseState( ParseResultType type, TokenStream const &remainingTokens ) + : m_type(type), + m_remainingTokens( remainingTokens ) + {} auto type() const -> ParseResultType { return m_type; } - auto remainingTokens() const -> TokenStream { return m_remainingTokens; } private: @@ -625,69 +620,62 @@ namespace detail { }; template - inline auto convertInto(std::string const &source, T& target) -> ParserResult { + inline auto convertInto( std::string const &source, T& target ) -> ParserResult { std::stringstream ss; ss << source; ss >> target; - if (ss.fail()) - return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type"); + if( ss.fail() ) + return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); else - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - inline auto convertInto(std::string const &source, std::string& target) -> ParserResult { + inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { target = source; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - inline auto convertInto(std::string const &source, bool &target) -> ParserResult { + inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { std::string srcLC = source; - std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast( ::tolower(c) ); } ); + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } ); if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") target = true; else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") target = false; else - return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'"); - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); + return ParserResult::ok( ParseResultType::Matched ); } struct BoundRefBase { BoundRefBase() = default; - - BoundRefBase(BoundRefBase const &) = delete; - - BoundRefBase(BoundRefBase &&) = delete; - - BoundRefBase &operator=(BoundRefBase const &) = delete; - - BoundRefBase &operator=(BoundRefBase &&) = delete; + BoundRefBase( BoundRefBase const & ) = delete; + BoundRefBase( BoundRefBase && ) = delete; + BoundRefBase &operator=( BoundRefBase const & ) = delete; + BoundRefBase &operator=( BoundRefBase && ) = delete; virtual ~BoundRefBase() = default; virtual auto isFlag() const -> bool = 0; - virtual auto isContainer() const -> bool { return false; } - - virtual auto setValue(std::string const &arg) -> ParserResult = 0; - - virtual auto setFlag(bool flag) -> ParserResult = 0; + virtual auto setValue( std::string const &arg ) -> ParserResult = 0; + virtual auto setFlag( bool flag ) -> ParserResult = 0; }; struct BoundValueRefBase : BoundRefBase { auto isFlag() const -> bool override { return false; } - auto setFlag(bool) -> ParserResult override { - return ParserResult::logicError("Flags can only be set on boolean fields"); + auto setFlag( bool ) -> ParserResult override { + return ParserResult::logicError( "Flags can only be set on boolean fields" ); } }; struct BoundFlagRefBase : BoundRefBase { auto isFlag() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { bool flag; - auto result = convertInto(arg, flag); - if (result) - setFlag(flag); + auto result = convertInto( arg, flag ); + if( result ) + setFlag( flag ); return result; } }; @@ -696,10 +684,10 @@ namespace detail { struct BoundRef : BoundValueRefBase { T &m_ref; - explicit BoundRef(T &ref) : m_ref(ref) {} + explicit BoundRef( T &ref ) : m_ref( ref ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return convertInto(arg, m_ref); + auto setValue( std::string const &arg ) -> ParserResult override { + return convertInto( arg, m_ref ); } }; @@ -707,15 +695,15 @@ namespace detail { struct BoundRef> : BoundValueRefBase { std::vector &m_ref; - explicit BoundRef(std::vector &ref) : m_ref(ref) {} + explicit BoundRef( std::vector &ref ) : m_ref( ref ) {} auto isContainer() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { T temp; - auto result = convertInto(arg, temp); - if (result) - m_ref.push_back(temp); + auto result = convertInto( arg, temp ); + if( result ) + m_ref.push_back( temp ); return result; } }; @@ -723,40 +711,40 @@ namespace detail { struct BoundFlagRef : BoundFlagRefBase { bool &m_ref; - explicit BoundFlagRef(bool &ref) : m_ref(ref) {} + explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} - auto setFlag(bool flag) -> ParserResult override { + auto setFlag( bool flag ) -> ParserResult override { m_ref = flag; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } }; template struct LambdaInvoker { - static_assert(std::is_same::value, "Lambda must return void or clara::ParserResult"); + static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - return lambda(arg); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + return lambda( arg ); } }; template<> struct LambdaInvoker { template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - lambda(arg); - return ParserResult::ok(ParseResultType::Matched); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + lambda( arg ); + return ParserResult::ok( ParseResultType::Matched ); } }; template - inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { + inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { ArgType temp; - auto result = convertInto(arg, temp); + auto result = convertInto( arg, temp ); return !result - ? result - : LambdaInvoker::ReturnType>::invoke(lambda, temp); + ? result + : LambdaInvoker::ReturnType>::invoke( lambda, temp ); }; @@ -765,10 +753,10 @@ namespace detail { L m_lambda; static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return invokeLambda::ArgType>(m_lambda, arg); + auto setValue( std::string const &arg ) -> ParserResult override { + return invokeLambda::ArgType>( m_lambda, arg ); } }; @@ -779,16 +767,14 @@ namespace detail { static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); - explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setFlag(bool flag) -> ParserResult override { - return LambdaInvoker::ReturnType>::invoke(m_lambda, flag); + auto setFlag( bool flag ) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); } }; - enum class Optionality { - Optional, Required - }; + enum class Optionality { Optional, Required }; struct Parser; @@ -799,8 +785,8 @@ namespace detail { virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; virtual auto cardinality() const -> size_t { return 1; } - auto parse(Args const &args) const -> InternalParseResult { - return parse( args.exeName(), TokenStream(args)); + auto parse( Args const &args ) const -> InternalParseResult { + return parse( args.exeName(), TokenStream( args ) ); } }; @@ -808,7 +794,7 @@ namespace detail { class ComposableParserImpl : public ParserBase { public: template - auto operator+(T const &other) const -> Parser; + auto operator|( T const &other ) const -> Parser; }; // Common code and state for Args and Opts @@ -820,17 +806,22 @@ namespace detail { std::string m_hint; std::string m_description; - explicit ParserRefImpl(std::shared_ptr const &ref) : m_ref(ref) {} + explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} public: template - ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), m_hint(hint) {} + ParserRefImpl( T &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint( hint ) + {} template - ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), - m_hint(hint) {} + ParserRefImpl( LambdaT const &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint(hint) + {} - auto operator()(std::string const &description) -> DerivedT & { + auto operator()( std::string const &description ) -> DerivedT & { m_description = description; return static_cast( *this ); } @@ -850,7 +841,7 @@ namespace detail { } auto cardinality() const -> size_t override { - if (m_ref->isContainer()) + if( m_ref->isContainer() ) return 0; else return 1; @@ -865,13 +856,13 @@ namespace detail { template static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { - return std::make_shared>(lambda); + return std::make_shared>( lambda) ; } public: - ExeName() : m_name(std::make_shared("")) {} + ExeName() : m_name( std::make_shared( "" ) ) {} - explicit ExeName(std::string &ref) : ExeName() { + explicit ExeName( std::string &ref ) : ExeName() { m_ref = std::make_shared>( ref ); } @@ -882,14 +873,14 @@ namespace detail { // The exe name is not parsed out of the normal tokens, but is handled specially auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); } auto name() const -> std::string { return *m_name; } auto set( std::string const& newName ) -> ParserResult { auto lastSlash = newName.find_last_of( "\\/" ); - auto filename = (lastSlash == std::string::npos) + auto filename = ( lastSlash == std::string::npos ) ? newName : newName.substr( lastSlash+1 ); @@ -905,27 +896,27 @@ namespace detail { public: using ParserRefImpl::ParserRefImpl; - auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { + auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; auto const &token = *remainingTokens; - if (token.type != TokenType::Argument) - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + if( token.type != TokenType::Argument ) + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - auto result = m_ref->setValue(remainingTokens->token); - if (!result) - return InternalParseResult(result); + auto result = m_ref->setValue( remainingTokens->token ); + if( !result ) + return InternalParseResult( result ); else - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } }; - inline auto normaliseOpt(std::string const &optName) -> std::string { - if (optName[0] == '/') - return "-" + optName.substr(1); + inline auto normaliseOpt( std::string const &optName ) -> std::string { + if( optName[0] == '/' ) + return "-" + optName.substr( 1 ); else return optName; } @@ -936,9 +927,9 @@ namespace detail { public: template - explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} + explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} - explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} template Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} @@ -946,34 +937,34 @@ namespace detail { template Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - auto operator[](std::string const &optName) -> Opt & { - m_optNames.push_back(optName); + auto operator[]( std::string const &optName ) -> Opt & { + m_optNames.push_back( optName ); return *this; } auto getHelpColumns() const -> std::vector { std::ostringstream oss; bool first = true; - for (auto const &opt : m_optNames) { + for( auto const &opt : m_optNames ) { if (first) first = false; else oss << ", "; oss << opt; } - if (!m_hint.empty()) + if( !m_hint.empty() ) oss << " <" << m_hint << ">"; - return {{oss.str(), m_description}}; + return { { oss.str(), m_description } }; } - auto isMatch(std::string const &optToken) const -> bool { -#ifdef CLARA_PLATFORM_WINDOWS + auto isMatch( std::string const &optToken ) const -> bool { +#ifdef CATCH_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); #else auto const &normalisedToken = optToken; #endif - for (auto const &name : m_optNames) { - if (normaliseOpt(name) == normalisedToken) + for( auto const &name : m_optNames ) { + if( normaliseOpt( name ) == normalisedToken ) return true; } return false; @@ -983,46 +974,46 @@ namespace detail { auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; - if (remainingTokens && remainingTokens->type == TokenType::Option) { + if( remainingTokens && remainingTokens->type == TokenType::Option ) { auto const &token = *remainingTokens; - if (isMatch(token.token)) { - if (m_ref->isFlag()) { - auto result = m_ref->setFlag(true); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( isMatch(token.token ) ) { + if( m_ref->isFlag() ) { + auto result = m_ref->setFlag( true ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } else { ++remainingTokens; - if (!remainingTokens) - return InternalParseResult::runtimeError("Expected argument following " + token.token); + if( !remainingTokens ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); auto const &argToken = *remainingTokens; - if (argToken.type != TokenType::Argument) - return InternalParseResult::runtimeError("Expected argument following " + token.token); - auto result = m_ref->setValue(argToken.token); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( argToken.type != TokenType::Argument ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto result = m_ref->setValue( argToken.token ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } } - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); } auto validate() const -> Result override { - if (m_optNames.empty()) - return Result::logicError("No options supplied to Opt"); - for (auto const &name : m_optNames) { - if (name.empty()) - return Result::logicError("Option name cannot be empty"); - if (name[0] != '-' && name[0] != '/') - return Result::logicError("Option name must begin with '-' or '/'"); + if( m_optNames.empty() ) + return Result::logicError( "No options supplied to Opt" ); + for( auto const &name : m_optNames ) { + if( name.empty() ) + return Result::logicError( "Option name cannot be empty" ); + if( name[0] != '-' && name[0] != '/' ) + return Result::logicError( "Option name must begin with '-' or '/'" ); } return ParserRefImpl::validate(); } @@ -1031,11 +1022,11 @@ namespace detail { struct Help : Opt { Help( bool &showHelpFlag ) : Opt([&]( bool flag ) { - showHelpFlag = flag; - return ParserResult::ok(ParseResultType::ShortCircuitAll); + showHelpFlag = flag; + return ParserResult::ok( ParseResultType::ShortCircuitAll ); }) { - static_cast(*this) + static_cast( *this ) ("display usage information") ["-?"]["-h"]["--help"] .optional(); @@ -1049,61 +1040,61 @@ namespace detail { std::vector m_options; std::vector m_args; - auto operator+=(ExeName const &exeName) -> Parser & { + auto operator|=( ExeName const &exeName ) -> Parser & { m_exeName = exeName; return *this; } - auto operator+=(Arg const &arg) -> Parser & { + auto operator|=( Arg const &arg ) -> Parser & { m_args.push_back(arg); return *this; } - auto operator+=(Opt const &opt) -> Parser & { + auto operator|=( Opt const &opt ) -> Parser & { m_options.push_back(opt); return *this; } - auto operator+=(Parser const &other) -> Parser & { + auto operator|=( Parser const &other ) -> Parser & { m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); return *this; } template - auto operator+(T const &other) const -> Parser { - return Parser(*this) += other; + auto operator|( T const &other ) const -> Parser { + return Parser( *this ) |= other; } auto getHelpColumns() const -> std::vector { std::vector cols; for (auto const &o : m_options) { auto childCols = o.getHelpColumns(); - cols.insert(cols.end(), childCols.begin(), childCols.end()); + cols.insert( cols.end(), childCols.begin(), childCols.end() ); } return cols; } - void writeToStream(std::ostream &os) const { + void writeToStream( std::ostream &os ) const { if (!m_exeName.name().empty()) { os << "usage:\n" << " " << m_exeName.name() << " "; bool required = true, first = true; - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { if (first) first = false; else os << " "; - if (arg.isOptional() && required) { + if( arg.isOptional() && required ) { os << "["; required = false; } os << "<" << arg.hint() << ">"; - if (arg.cardinality() == 0) + if( arg.cardinality() == 0 ) os << " ... "; } - if (!required) + if( !required ) os << "]"; - if (!m_options.empty()) + if( !m_options.empty() ) os << " options"; os << "\n\nwhere options are:" << std::endl; } @@ -1111,32 +1102,32 @@ namespace detail { auto rows = getHelpColumns(); size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; - for (auto const &cols : rows) + for( auto const &cols : rows ) optWidth = std::max(optWidth, cols.left.size() + 2); - for (auto const &cols : rows) { + for( auto const &cols : rows ) { auto row = - TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + TextFlow::Spacer(4) + - TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); + TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); os << row << std::endl; } } - friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { - parser.writeToStream(os); + friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { + parser.writeToStream( os ); return os; } auto validate() const -> Result override { - for (auto const &opt : m_options) { + for( auto const &opt : m_options ) { auto result = opt.validate(); - if (!result) + if( !result ) return result; } - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { auto result = arg.validate(); - if (!result) + if( !result ) return result; } return Result::ok(); @@ -1144,47 +1135,41 @@ namespace detail { using ParserBase::parse; - auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override { - std::vector allParsers; - allParsers.reserve(m_args.size() + m_options.size()); - std::set requiredParsers; + auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { - for (auto const &opt : m_options) { - allParsers.push_back(&opt); - if (!opt.isOptional()) - requiredParsers.insert(&opt); - } - - size_t optionalArgs = 0; - for (auto const &arg : m_args) { - allParsers.push_back(&arg); - if (!arg.isOptional()) { - if (optionalArgs > 0) - return InternalParseResult::logicError( - "Required arguments must preceed any optional arguments"); - else - ++optionalArgs; - requiredParsers.insert(&arg); - } - } + struct ParserInfo { + ParserBase const* parser = nullptr; + size_t count = 0; + }; + const size_t totalParsers = m_options.size() + m_args.size(); + ParserInfo parseInfos[totalParsers]; + size_t i = 0; + for( auto const& opt : m_options ) parseInfos[i++].parser = &opt; + for( auto const& arg : m_args ) parseInfos[i++].parser = &arg; m_exeName.set( exeName ); - auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); - while (result.value().remainingTokens()) { - auto remainingTokenCount = result.value().remainingTokens().count(); - for (auto parser : allParsers) { - result = parser->parse( exeName, result.value().remainingTokens() ); - if (!result || result.value().type() != ParseResultType::NoMatch) { - if (parser->cardinality() == 1) - allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser), - allParsers.end()); - requiredParsers.erase(parser); - break; + auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + while( result.value().remainingTokens() ) { + bool tokenParsed = false; + + for( auto& parseInfo : parseInfos ) { + if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { + result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); + if (!result) + return result; + if (result.value().type() != ParseResultType::NoMatch) { + tokenParsed = true; + ++parseInfo.count; + break; + } } } - if (!result || remainingTokenCount == result.value().remainingTokens().count()) + + if( result.value().type() == ParseResultType::ShortCircuitAll ) return result; + if( !tokenParsed ) + return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); } // !TBD Check missing required options return result; @@ -1193,8 +1178,8 @@ namespace detail { template template - auto ComposableParserImpl::operator+(T const &other) const -> Parser { - return Parser() + static_cast( *this ) + other; + auto ComposableParserImpl::operator|( T const &other ) const -> Parser { + return Parser() | static_cast( *this ) | other; } } // namespace detail diff --git a/include/internal/catch_commandline.cpp b/include/internal/catch_commandline.cpp index 89329032..c0231d1a 100644 --- a/include/internal/catch_commandline.cpp +++ b/include/internal/catch_commandline.cpp @@ -98,84 +98,84 @@ namespace Catch { auto cli = ExeName( config.processName ) - + Help( config.showHelp ) - + Opt( config.listTests ) + | Help( config.showHelp ) + | Opt( config.listTests ) ["-l"]["--list-tests"] ( "list all/matching test cases" ) - + Opt( config.listTags ) + | Opt( config.listTags ) ["-t"]["--list-tags"] ( "list all/matching tags" ) - + Opt( config.showSuccessfulTests ) + | Opt( config.showSuccessfulTests ) ["-s"]["--success"] ( "include successful tests in output" ) - + Opt( config.shouldDebugBreak ) + | Opt( config.shouldDebugBreak ) ["-b"]["--break"] ( "break into debugger on failure" ) - + Opt( config.noThrow ) + | Opt( config.noThrow ) ["-e"]["--nothrow"] ( "skip exception tests" ) - + Opt( config.showInvisibles ) + | Opt( config.showInvisibles ) ["-i"]["--invisibles"] ( "show invisibles (tabs, newlines)" ) - + Opt( config.outputFilename, "filename" ) + | Opt( config.outputFilename, "filename" ) ["-o"]["--out"] ( "output filename" ) - + Opt( config.reporterNames, "name" ) + | Opt( config.reporterNames, "name" ) ["-r"]["--reporter"] ( "reporter to use (defaults to console)" ) - + Opt( config.name, "name" ) + | Opt( config.name, "name" ) ["-n"]["--name"] ( "suite name" ) - + Opt( [&]( bool ){ config.abortAfter = 1; } ) + | Opt( [&]( bool ){ config.abortAfter = 1; } ) ["-a"]["--abort"] ( "abort at first failure" ) - + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) ["-x"]["--abortx"] ( "abort after x failures" ) - + Opt( setWarning, "warning name" ) + | Opt( setWarning, "warning name" ) ["-w"]["--warn"] ( "enable warnings" ) - + Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) + | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) ["-d"]["--durations"] ( "show test durations" ) - + Opt( loadTestNamesFromFile, "filename" ) + | Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] ( "load test names to run from a file" ) - + Opt( config.filenamesAsTags ) + | Opt( config.filenamesAsTags ) ["-#"]["--filenames-as-tags"] ( "adds a tag for the filename" ) - + Opt( config.sectionsToRun, "section name" ) + | Opt( config.sectionsToRun, "section name" ) ["-c"]["--section"] ( "specify section to run" ) - + Opt( setVerbosity, "quiet|normal|high" ) + | Opt( setVerbosity, "quiet|normal|high" ) ["-v"]["--verbosity"] ( "set output verbosity" ) - + Opt( config.listTestNamesOnly ) + | Opt( config.listTestNamesOnly ) ["--list-test-names-only"] ( "list all/matching test cases names only" ) - + Opt( config.listReporters ) + | Opt( config.listReporters ) ["--list-reporters"] ( "list all reporters" ) - + Opt( setTestOrder, "decl|lex|rand" ) + | Opt( setTestOrder, "decl|lex|rand" ) ["--order"] ( "test case order (defaults to decl)" ) - + Opt( setRngSeed, "'time'|number" ) + | Opt( setRngSeed, "'time'|number" ) ["--rng-seed"] ( "set a specific seed for random numbers" ) - + Opt( setColourUsage, "yes|no" ) + | Opt( setColourUsage, "yes|no" ) ["--use-colour"] ( "should output be colourised" ) - + Opt( config.libIdentify ) + | Opt( config.libIdentify ) ["--libidentify"] ( "report name and version according to libidentify standard" ) - + Opt( setWaitForKeypress, "start|exit|both" ) + | Opt( setWaitForKeypress, "start|exit|both" ) ["--wait-for-keypress"] ( "waits for a keypress before exiting" ) - + Opt( config.benchmarkResolutionMultiple, "multiplier" ) + | Opt( config.benchmarkResolutionMultiple, "multiplier" ) ["--benchmark-resolution-multiple"] ( "multiple of clock resolution to run benchmarks" ) - + Arg( config.testsOrTags, "test name|pattern|tags" ) + | Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); return cli; diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 509c9b5a..5778c562 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -8,6 +8,9 @@ #define CLARA_CONFIG_CONSOLE_WIDTH 80 #endif +#ifndef CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#endif // ----------- #included from clara_textflow.hpp ----------- @@ -133,7 +136,7 @@ namespace clara { namespace TextFlow { auto operator *() const -> std::string { assert( m_stringIndex < m_column.m_strings.size() ); - assert( m_pos < m_end ); + assert( m_pos <= m_end ); if( m_pos + m_column.m_width < m_end ) return addIndentAndSuffix(line().substr(m_pos, m_len)); else @@ -357,15 +360,15 @@ namespace detail { // Traits for extracting arg and return type of lambdas (for single argument lambdas) template - struct UnaryLambdaTraits : UnaryLambdaTraits {}; + struct UnaryLambdaTraits : UnaryLambdaTraits {}; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = false; }; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = true; using ArgType = typename std::remove_const::type>::type;; using ReturnType = ReturnT; @@ -380,13 +383,13 @@ namespace detail { std::vector m_args; public: - Args(int argc, char *argv[]) { + Args( int argc, char *argv[] ) { m_exeName = argv[0]; - for (int i = 1; i < argc; ++i) - m_args.push_back(argv[i]); + for( int i = 1; i < argc; ++i ) + m_args.push_back( argv[i] ); } - Args(std::initializer_list args) + Args( std::initializer_list args ) : m_exeName( *args.begin() ), m_args( args.begin()+1, args.end() ) {} @@ -414,40 +417,40 @@ namespace detail { std::vector m_tokenBuffer; void loadBuffer() { - m_tokenBuffer.resize(0); + m_tokenBuffer.resize( 0 ); // Skip any empty strings - while (it != itEnd && it->empty()) + while( it != itEnd && it->empty() ) ++it; - if (it != itEnd) { + if( it != itEnd ) { auto const &next = *it; - if (next[0] == '-' || next[0] == '/') { - auto delimiterPos = next.find_first_of(" :="); - if (delimiterPos != std::string::npos) { - m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)}); - m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)}); + if( next[0] == '-' || next[0] == '/' ) { + auto delimiterPos = next.find_first_of( " :=" ); + if( delimiterPos != std::string::npos ) { + m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); + m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); } else { - if (next[1] != '-' && next.size() > 2) { + if( next[1] != '-' && next.size() > 2 ) { std::string opt = "- "; - for (size_t i = 1; i < next.size(); ++i) { + for( size_t i = 1; i < next.size(); ++i ) { opt[1] = next[i]; - m_tokenBuffer.push_back({TokenType::Option, opt}); + m_tokenBuffer.push_back( { TokenType::Option, opt } ); } } else { - m_tokenBuffer.push_back({TokenType::Option, next}); + m_tokenBuffer.push_back( { TokenType::Option, next } ); } } } else { - m_tokenBuffer.push_back({TokenType::Argument, next}); + m_tokenBuffer.push_back( { TokenType::Argument, next } ); } } } public: - explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} + explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} - TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { loadBuffer(); } @@ -458,20 +461,20 @@ namespace detail { auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } auto operator*() const -> Token { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return m_tokenBuffer.front(); } auto operator->() const -> Token const * { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return &m_tokenBuffer.front(); } auto operator++() -> TokenStream & { - if (m_tokenBuffer.size() >= 2) { - m_tokenBuffer.erase(m_tokenBuffer.begin()); + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); } else { - if (it != itEnd) + if( it != itEnd ) ++it; loadBuffer(); } @@ -487,7 +490,7 @@ namespace detail { }; protected: - ResultBase(Type type) : m_type(type) {} + ResultBase( Type type ) : m_type( type ) {} virtual ~ResultBase() = default; virtual void enforceOk() const = 0; @@ -504,28 +507,28 @@ namespace detail { } protected: - ResultValueBase(Type type) : ResultBase(type) {} + ResultValueBase( Type type ) : ResultBase( type ) {} - ResultValueBase(ResultValueBase const &other) : ResultBase(other) { - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); } - ResultValueBase(Type, T const &value) : ResultBase(Ok) { - new(&m_value) T(value); + ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { + new( &m_value ) T( value ); } - auto operator=(ResultValueBase const &other) -> ResultValueBase & { - if (m_type == ResultBase::Ok) + auto operator=( ResultValueBase const &other ) -> ResultValueBase & { + if( m_type == ResultBase::Ok ) m_value.~T(); ResultBase::operator=(other); - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); return *this; } ~ResultValueBase() { - if (m_type == Ok) + if( m_type == Ok ) m_value.~T(); } @@ -544,37 +547,31 @@ namespace detail { class BasicResult : public ResultValueBase { public: template - explicit BasicResult(BasicResult const &other) - : ResultValueBase(other.type()), - m_errorMessage(other.errorMessage()) { - assert(type() != ResultBase::Ok); + explicit BasicResult( BasicResult const &other ) + : ResultValueBase( other.type() ), + m_errorMessage( other.errorMessage() ) + { + assert( type() != ResultBase::Ok ); } - static auto ok() -> BasicResult { return {ResultBase::Ok}; } - template - static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; } - - static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; } - - static auto runtimeError(std::string const &message) -> BasicResult { - return {ResultBase::RuntimeError, message}; - } + static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } + static auto ok() -> BasicResult { return { ResultBase::Ok }; } + static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } + static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } explicit operator bool() const { return m_type == ResultBase::Ok; } - auto type() const -> ResultBase::Type { return m_type; } - auto errorMessage() const -> std::string { return m_errorMessage; } protected: virtual void enforceOk() const { // !TBD: If no exceptions, std::terminate here or something - switch (m_type) { + switch( m_type ) { case ResultBase::LogicError: - throw std::logic_error(m_errorMessage); + throw std::logic_error( m_errorMessage ); case ResultBase::RuntimeError: - throw std::runtime_error(m_errorMessage); + throw std::runtime_error( m_errorMessage ); case ResultBase::Ok: break; } @@ -582,10 +579,11 @@ namespace detail { std::string m_errorMessage; // Only populated if resultType is an error - BasicResult(ResultBase::Type type, std::string const &message) - : ResultValueBase(type), - m_errorMessage(message) { - assert(m_type != ResultBase::Ok); + BasicResult( ResultBase::Type type, std::string const &message ) + : ResultValueBase(type), + m_errorMessage(message) + { + assert( m_type != ResultBase::Ok ); } using ResultValueBase::ResultValueBase; @@ -599,12 +597,12 @@ namespace detail { class ParseState { public: - ParseState(ParseResultType type, TokenStream const &remainingTokens) - : m_type(type), - m_remainingTokens(remainingTokens) {} + ParseState( ParseResultType type, TokenStream const &remainingTokens ) + : m_type(type), + m_remainingTokens( remainingTokens ) + {} auto type() const -> ParseResultType { return m_type; } - auto remainingTokens() const -> TokenStream { return m_remainingTokens; } private: @@ -622,69 +620,62 @@ namespace detail { }; template - inline auto convertInto(std::string const &source, T& target) -> ParserResult { + inline auto convertInto( std::string const &source, T& target ) -> ParserResult { std::stringstream ss; ss << source; ss >> target; - if (ss.fail()) - return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type"); + if( ss.fail() ) + return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); else - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - inline auto convertInto(std::string const &source, std::string& target) -> ParserResult { + inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { target = source; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - inline auto convertInto(std::string const &source, bool &target) -> ParserResult { + inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { std::string srcLC = source; - std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast( ::tolower(c) ); } ); + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } ); if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") target = true; else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") target = false; else - return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'"); - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); + return ParserResult::ok( ParseResultType::Matched ); } struct BoundRefBase { BoundRefBase() = default; - - BoundRefBase(BoundRefBase const &) = delete; - - BoundRefBase(BoundRefBase &&) = delete; - - BoundRefBase &operator=(BoundRefBase const &) = delete; - - BoundRefBase &operator=(BoundRefBase &&) = delete; + BoundRefBase( BoundRefBase const & ) = delete; + BoundRefBase( BoundRefBase && ) = delete; + BoundRefBase &operator=( BoundRefBase const & ) = delete; + BoundRefBase &operator=( BoundRefBase && ) = delete; virtual ~BoundRefBase() = default; virtual auto isFlag() const -> bool = 0; - virtual auto isContainer() const -> bool { return false; } - - virtual auto setValue(std::string const &arg) -> ParserResult = 0; - - virtual auto setFlag(bool flag) -> ParserResult = 0; + virtual auto setValue( std::string const &arg ) -> ParserResult = 0; + virtual auto setFlag( bool flag ) -> ParserResult = 0; }; struct BoundValueRefBase : BoundRefBase { auto isFlag() const -> bool override { return false; } - auto setFlag(bool) -> ParserResult override { - return ParserResult::logicError("Flags can only be set on boolean fields"); + auto setFlag( bool ) -> ParserResult override { + return ParserResult::logicError( "Flags can only be set on boolean fields" ); } }; struct BoundFlagRefBase : BoundRefBase { auto isFlag() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { bool flag; - auto result = convertInto(arg, flag); - if (result) - setFlag(flag); + auto result = convertInto( arg, flag ); + if( result ) + setFlag( flag ); return result; } }; @@ -693,10 +684,10 @@ namespace detail { struct BoundRef : BoundValueRefBase { T &m_ref; - explicit BoundRef(T &ref) : m_ref(ref) {} + explicit BoundRef( T &ref ) : m_ref( ref ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return convertInto(arg, m_ref); + auto setValue( std::string const &arg ) -> ParserResult override { + return convertInto( arg, m_ref ); } }; @@ -704,15 +695,15 @@ namespace detail { struct BoundRef> : BoundValueRefBase { std::vector &m_ref; - explicit BoundRef(std::vector &ref) : m_ref(ref) {} + explicit BoundRef( std::vector &ref ) : m_ref( ref ) {} auto isContainer() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { T temp; - auto result = convertInto(arg, temp); - if (result) - m_ref.push_back(temp); + auto result = convertInto( arg, temp ); + if( result ) + m_ref.push_back( temp ); return result; } }; @@ -720,40 +711,40 @@ namespace detail { struct BoundFlagRef : BoundFlagRefBase { bool &m_ref; - explicit BoundFlagRef(bool &ref) : m_ref(ref) {} + explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} - auto setFlag(bool flag) -> ParserResult override { + auto setFlag( bool flag ) -> ParserResult override { m_ref = flag; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } }; template struct LambdaInvoker { - static_assert(std::is_same::value, "Lambda must return void or clara::ParserResult"); + static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - return lambda(arg); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + return lambda( arg ); } }; template<> struct LambdaInvoker { template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - lambda(arg); - return ParserResult::ok(ParseResultType::Matched); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + lambda( arg ); + return ParserResult::ok( ParseResultType::Matched ); } }; template - inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { + inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { ArgType temp; - auto result = convertInto(arg, temp); + auto result = convertInto( arg, temp ); return !result - ? result - : LambdaInvoker::ReturnType>::invoke(lambda, temp); + ? result + : LambdaInvoker::ReturnType>::invoke( lambda, temp ); }; @@ -762,10 +753,10 @@ namespace detail { L m_lambda; static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return invokeLambda::ArgType>(m_lambda, arg); + auto setValue( std::string const &arg ) -> ParserResult override { + return invokeLambda::ArgType>( m_lambda, arg ); } }; @@ -776,16 +767,14 @@ namespace detail { static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); - explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setFlag(bool flag) -> ParserResult override { - return LambdaInvoker::ReturnType>::invoke(m_lambda, flag); + auto setFlag( bool flag ) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); } }; - enum class Optionality { - Optional, Required - }; + enum class Optionality { Optional, Required }; struct Parser; @@ -796,8 +785,8 @@ namespace detail { virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; virtual auto cardinality() const -> size_t { return 1; } - auto parse(Args const &args) const -> InternalParseResult { - return parse( args.exeName(), TokenStream(args)); + auto parse( Args const &args ) const -> InternalParseResult { + return parse( args.exeName(), TokenStream( args ) ); } }; @@ -805,7 +794,7 @@ namespace detail { class ComposableParserImpl : public ParserBase { public: template - auto operator+(T const &other) const -> Parser; + auto operator|( T const &other ) const -> Parser; }; // Common code and state for Args and Opts @@ -817,17 +806,22 @@ namespace detail { std::string m_hint; std::string m_description; - explicit ParserRefImpl(std::shared_ptr const &ref) : m_ref(ref) {} + explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} public: template - ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), m_hint(hint) {} + ParserRefImpl( T &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint( hint ) + {} template - ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), - m_hint(hint) {} + ParserRefImpl( LambdaT const &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint(hint) + {} - auto operator()(std::string const &description) -> DerivedT & { + auto operator()( std::string const &description ) -> DerivedT & { m_description = description; return static_cast( *this ); } @@ -847,7 +841,7 @@ namespace detail { } auto cardinality() const -> size_t override { - if (m_ref->isContainer()) + if( m_ref->isContainer() ) return 0; else return 1; @@ -862,13 +856,13 @@ namespace detail { template static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { - return std::make_shared>(lambda); + return std::make_shared>( lambda) ; } public: - ExeName() : m_name(std::make_shared("")) {} + ExeName() : m_name( std::make_shared( "" ) ) {} - explicit ExeName(std::string &ref) : ExeName() { + explicit ExeName( std::string &ref ) : ExeName() { m_ref = std::make_shared>( ref ); } @@ -879,14 +873,14 @@ namespace detail { // The exe name is not parsed out of the normal tokens, but is handled specially auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); } auto name() const -> std::string { return *m_name; } auto set( std::string const& newName ) -> ParserResult { auto lastSlash = newName.find_last_of( "\\/" ); - auto filename = (lastSlash == std::string::npos) + auto filename = ( lastSlash == std::string::npos ) ? newName : newName.substr( lastSlash+1 ); @@ -902,27 +896,27 @@ namespace detail { public: using ParserRefImpl::ParserRefImpl; - auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { + auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; auto const &token = *remainingTokens; - if (token.type != TokenType::Argument) - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + if( token.type != TokenType::Argument ) + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - auto result = m_ref->setValue(remainingTokens->token); - if (!result) - return InternalParseResult(result); + auto result = m_ref->setValue( remainingTokens->token ); + if( !result ) + return InternalParseResult( result ); else - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } }; - inline auto normaliseOpt(std::string const &optName) -> std::string { - if (optName[0] == '/') - return "-" + optName.substr(1); + inline auto normaliseOpt( std::string const &optName ) -> std::string { + if( optName[0] == '/' ) + return "-" + optName.substr( 1 ); else return optName; } @@ -933,9 +927,9 @@ namespace detail { public: template - explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} + explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} - explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} template Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} @@ -943,34 +937,34 @@ namespace detail { template Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - auto operator[](std::string const &optName) -> Opt & { - m_optNames.push_back(optName); + auto operator[]( std::string const &optName ) -> Opt & { + m_optNames.push_back( optName ); return *this; } auto getHelpColumns() const -> std::vector { std::ostringstream oss; bool first = true; - for (auto const &opt : m_optNames) { + for( auto const &opt : m_optNames ) { if (first) first = false; else oss << ", "; oss << opt; } - if (!m_hint.empty()) + if( !m_hint.empty() ) oss << " <" << m_hint << ">"; - return {{oss.str(), m_description}}; + return { { oss.str(), m_description } }; } - auto isMatch(std::string const &optToken) const -> bool { + auto isMatch( std::string const &optToken ) const -> bool { #ifdef CLARA_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); #else auto const &normalisedToken = optToken; #endif - for (auto const &name : m_optNames) { - if (normaliseOpt(name) == normalisedToken) + for( auto const &name : m_optNames ) { + if( normaliseOpt( name ) == normalisedToken ) return true; } return false; @@ -980,46 +974,46 @@ namespace detail { auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; - if (remainingTokens && remainingTokens->type == TokenType::Option) { + if( remainingTokens && remainingTokens->type == TokenType::Option ) { auto const &token = *remainingTokens; - if (isMatch(token.token)) { - if (m_ref->isFlag()) { - auto result = m_ref->setFlag(true); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( isMatch(token.token ) ) { + if( m_ref->isFlag() ) { + auto result = m_ref->setFlag( true ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } else { ++remainingTokens; - if (!remainingTokens) - return InternalParseResult::runtimeError("Expected argument following " + token.token); + if( !remainingTokens ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); auto const &argToken = *remainingTokens; - if (argToken.type != TokenType::Argument) - return InternalParseResult::runtimeError("Expected argument following " + token.token); - auto result = m_ref->setValue(argToken.token); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( argToken.type != TokenType::Argument ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto result = m_ref->setValue( argToken.token ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } } - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); } auto validate() const -> Result override { - if (m_optNames.empty()) - return Result::logicError("No options supplied to Opt"); - for (auto const &name : m_optNames) { - if (name.empty()) - return Result::logicError("Option name cannot be empty"); - if (name[0] != '-' && name[0] != '/') - return Result::logicError("Option name must begin with '-' or '/'"); + if( m_optNames.empty() ) + return Result::logicError( "No options supplied to Opt" ); + for( auto const &name : m_optNames ) { + if( name.empty() ) + return Result::logicError( "Option name cannot be empty" ); + if( name[0] != '-' && name[0] != '/' ) + return Result::logicError( "Option name must begin with '-' or '/'" ); } return ParserRefImpl::validate(); } @@ -1028,11 +1022,11 @@ namespace detail { struct Help : Opt { Help( bool &showHelpFlag ) : Opt([&]( bool flag ) { - showHelpFlag = flag; - return ParserResult::ok(ParseResultType::ShortCircuitAll); + showHelpFlag = flag; + return ParserResult::ok( ParseResultType::ShortCircuitAll ); }) { - static_cast(*this) + static_cast( *this ) ("display usage information") ["-?"]["-h"]["--help"] .optional(); @@ -1046,61 +1040,61 @@ namespace detail { std::vector m_options; std::vector m_args; - auto operator+=(ExeName const &exeName) -> Parser & { + auto operator|=( ExeName const &exeName ) -> Parser & { m_exeName = exeName; return *this; } - auto operator+=(Arg const &arg) -> Parser & { + auto operator|=( Arg const &arg ) -> Parser & { m_args.push_back(arg); return *this; } - auto operator+=(Opt const &opt) -> Parser & { + auto operator|=( Opt const &opt ) -> Parser & { m_options.push_back(opt); return *this; } - auto operator+=(Parser const &other) -> Parser & { + auto operator|=( Parser const &other ) -> Parser & { m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); return *this; } template - auto operator+(T const &other) const -> Parser { - return Parser(*this) += other; + auto operator|( T const &other ) const -> Parser { + return Parser( *this ) |= other; } auto getHelpColumns() const -> std::vector { std::vector cols; for (auto const &o : m_options) { auto childCols = o.getHelpColumns(); - cols.insert(cols.end(), childCols.begin(), childCols.end()); + cols.insert( cols.end(), childCols.begin(), childCols.end() ); } return cols; } - void writeToStream(std::ostream &os) const { + void writeToStream( std::ostream &os ) const { if (!m_exeName.name().empty()) { os << "usage:\n" << " " << m_exeName.name() << " "; bool required = true, first = true; - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { if (first) first = false; else os << " "; - if (arg.isOptional() && required) { + if( arg.isOptional() && required ) { os << "["; required = false; } os << "<" << arg.hint() << ">"; - if (arg.cardinality() == 0) + if( arg.cardinality() == 0 ) os << " ... "; } - if (!required) + if( !required ) os << "]"; - if (!m_options.empty()) + if( !m_options.empty() ) os << " options"; os << "\n\nwhere options are:" << std::endl; } @@ -1108,32 +1102,32 @@ namespace detail { auto rows = getHelpColumns(); size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; - for (auto const &cols : rows) + for( auto const &cols : rows ) optWidth = std::max(optWidth, cols.left.size() + 2); - for (auto const &cols : rows) { + for( auto const &cols : rows ) { auto row = - TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + TextFlow::Spacer(4) + - TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); + TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); os << row << std::endl; } } - friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { - parser.writeToStream(os); + friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { + parser.writeToStream( os ); return os; } auto validate() const -> Result override { - for (auto const &opt : m_options) { + for( auto const &opt : m_options ) { auto result = opt.validate(); - if (!result) + if( !result ) return result; } - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { auto result = arg.validate(); - if (!result) + if( !result ) return result; } return Result::ok(); @@ -1141,47 +1135,41 @@ namespace detail { using ParserBase::parse; - auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override { - std::vector allParsers; - allParsers.reserve(m_args.size() + m_options.size()); - std::set requiredParsers; + auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { - for (auto const &opt : m_options) { - allParsers.push_back(&opt); - if (!opt.isOptional()) - requiredParsers.insert(&opt); - } - - size_t optionalArgs = 0; - for (auto const &arg : m_args) { - allParsers.push_back(&arg); - if (!arg.isOptional()) { - if (optionalArgs > 0) - return InternalParseResult::logicError( - "Required arguments must preceed any optional arguments"); - else - ++optionalArgs; - requiredParsers.insert(&arg); - } - } + struct ParserInfo { + ParserBase const* parser = nullptr; + size_t count = 0; + }; + const size_t totalParsers = m_options.size() + m_args.size(); + ParserInfo parseInfos[totalParsers]; + size_t i = 0; + for( auto const& opt : m_options ) parseInfos[i++].parser = &opt; + for( auto const& arg : m_args ) parseInfos[i++].parser = &arg; m_exeName.set( exeName ); - auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); - while (result.value().remainingTokens()) { - auto remainingTokenCount = result.value().remainingTokens().count(); - for (auto parser : allParsers) { - result = parser->parse( exeName, result.value().remainingTokens() ); - if (!result || result.value().type() != ParseResultType::NoMatch) { - if (parser->cardinality() == 1) - allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser), - allParsers.end()); - requiredParsers.erase(parser); - break; + auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + while( result.value().remainingTokens() ) { + bool tokenParsed = false; + + for( auto& parseInfo : parseInfos ) { + if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { + result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); + if (!result) + return result; + if (result.value().type() != ParseResultType::NoMatch) { + tokenParsed = true; + ++parseInfo.count; + break; + } } } - if (!result || remainingTokenCount == result.value().remainingTokens().count()) + + if( result.value().type() == ParseResultType::ShortCircuitAll ) return result; + if( !tokenParsed ) + return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); } // !TBD Check missing required options return result; @@ -1190,8 +1178,8 @@ namespace detail { template template - auto ComposableParserImpl::operator+(T const &other) const -> Parser { - return Parser() + static_cast( *this ) + other; + auto ComposableParserImpl::operator|( T const &other ) const -> Parser { + return Parser() | static_cast( *this ) | other; } } // namespace detail From c1416d55cbca4f71056dd781fd22157ef7bde819 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 26 Sep 2017 15:55:34 -0700 Subject: [PATCH 352/398] Backed out dynamic stack array (use fixed size for now) --- include/external/clara.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index e46574b4..b5947c8a 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -1142,7 +1142,9 @@ namespace detail { size_t count = 0; }; const size_t totalParsers = m_options.size() + m_args.size(); - ParserInfo parseInfos[totalParsers]; + assert( totalParsers < 512 ); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do + ParserInfo parseInfos[512]; size_t i = 0; for( auto const& opt : m_options ) parseInfos[i++].parser = &opt; for( auto const& arg : m_args ) parseInfos[i++].parser = &arg; @@ -1153,7 +1155,8 @@ namespace detail { while( result.value().remainingTokens() ) { bool tokenParsed = false; - for( auto& parseInfo : parseInfos ) { + for( size_t i = 0; i < totalParsers; ++i ) { + auto& parseInfo = parseInfos[i]; if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); if (!result) From 5fe19f73e72a2050af7ff4dbbdbd73bbaee76632 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 26 Sep 2017 16:06:48 -0700 Subject: [PATCH 353/398] Scoped parseInfos population so `i` can be reused --- include/external/clara.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index b5947c8a..668d9e48 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -1145,9 +1145,12 @@ namespace detail { assert( totalParsers < 512 ); // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do ParserInfo parseInfos[512]; - size_t i = 0; - for( auto const& opt : m_options ) parseInfos[i++].parser = &opt; - for( auto const& arg : m_args ) parseInfos[i++].parser = &arg; + + { + size_t i = 0; + for (auto const &opt : m_options) parseInfos[i++].parser = &opt; + for (auto const &arg : m_args) parseInfos[i++].parser = &arg; + } m_exeName.set( exeName ); From 11918b76d04de035b4e63f5556fb6ae1906e065b Mon Sep 17 00:00:00 2001 From: offa Date: Wed, 20 Sep 2017 18:28:33 +0200 Subject: [PATCH 354/398] Direct link to the single header file updated to latest release (dev.4). --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 523cb791..256b1c3a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=catch2)](https://travis-ci.org/philsquared/Catch?branch=catch2) [![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/catch2?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/catch2) -The latest version of the single header can be downloaded directly using this link +The latest version of the single header can be downloaded directly using this link ## What's the Catch? From 70e0d48978655010447b6e6ddef5aa6c781d844b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 28 Sep 2017 12:47:32 +0200 Subject: [PATCH 355/398] Replace throw; with std::rethrow_exception(std::current_exception()); This works around a bug in libcxxrt handling of active exception count that caused std::uncaught_exception() to return true even if there was none. Closes #1028 --- include/internal/catch_exception_translator_registry.cpp | 4 ++-- include/internal/catch_interfaces_exception.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/internal/catch_exception_translator_registry.cpp b/include/internal/catch_exception_translator_registry.cpp index ce45194b..77f74a88 100644 --- a/include/internal/catch_exception_translator_registry.cpp +++ b/include/internal/catch_exception_translator_registry.cpp @@ -37,7 +37,7 @@ namespace Catch { #endif } catch( TestFailureException& ) { - throw; + std::rethrow_exception(std::current_exception()); } catch( std::exception& ex ) { return ex.what(); @@ -55,7 +55,7 @@ namespace Catch { std::string ExceptionTranslatorRegistry::tryTranslators() const { if( m_translators.empty() ) - throw; + std::rethrow_exception(std::current_exception()); else return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index 40b7e59b..3473ff52 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -15,6 +15,7 @@ static std::string translatorName( signature ) #endif +#include #include #include @@ -47,7 +48,7 @@ namespace Catch { std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { try { if( it == itEnd ) - throw; + std::rethrow_exception(std::current_exception()); else return (*it)->translate( it+1, itEnd ); } From b80c5134f07ead770dc27525edc921f392b60e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 1 Oct 2017 17:03:06 +0200 Subject: [PATCH 356/398] Updated release notes --- docs/release-notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index fc4de69b..62faabdc 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -61,6 +61,9 @@ * Swept out `-Wweak-vtables`, `-Wexit-time-destructors`, `-Wglobal-constructors` warnings * Compilation for Universal Windows Platform (UWP) is supported * SEH handling and colorized output are disabled when compiling for UWP +* Implemented a workaround for `std::uncaught_exception` issues in libcxxrt + * These issues caused incorrect section traversals + * The workaround is only partial, user's test can still trigger the issue by using `throw;` to rethrow an exception ## Internal changes * The development version now uses .cpp files instead of header files containing implementation. From 7e9b53e40ca4b5f066613ee72b32c211b29e4266 Mon Sep 17 00:00:00 2001 From: Martin Moene Date: Tue, 29 Aug 2017 21:33:56 +0200 Subject: [PATCH 357/398] Add original markdown_toclify.py by Sebastian Raschk (@rasbt) - https://github.com/rasbt/markdown-toclify --- scripts/markdown_toclify.py | 400 ++++++++++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 scripts/markdown_toclify.py diff --git a/scripts/markdown_toclify.py b/scripts/markdown_toclify.py new file mode 100644 index 00000000..8278e215 --- /dev/null +++ b/scripts/markdown_toclify.py @@ -0,0 +1,400 @@ +#!/usr/bin/env python + +# +# Sebastian Raschka 2014-2015 +# +# Python script that inserts a table of contents +# into markdown documents and creates the required +# internal links. +# +# For more information about how internal links +# in HTML and Markdown documents work, please see +# +# Creating a table of contents with internal links in +# IPython Notebooks and Markdown documents: +# http://sebastianraschka.com/Articles/2014_ipython_internal_links.html +# +# Updates for this script will be available at +# https://github.com/rasbt/markdown-toclify +# +# for more information about the usage: +# markdown-toclify.py --help +# + +import argparse +import re + + +__version__ = '1.7.1' + +VALIDS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-&' + + +def read_lines(in_file): + """Returns a list of lines from a input markdown file.""" + + with open(in_file, 'r') as inf: + in_contents = inf.read().split('\n') + return in_contents + + +def remove_lines(lines, remove=('[[back to top]', ' tags.""" + + if not remove: + return lines[:] + + out = [] + for l in lines: + if l.startswith(remove): + continue + out.append(l) + return out + + +def dashify_headline(line): + """ + Takes a header line from a Markdown document and + returns a tuple of the + '#'-stripped version of the head line, + a string version for anchor tags, + and the level of the headline as integer. + E.g., + >>> dashify_headline('### some header lvl3') + ('Some header lvl3', 'some-header-lvl3', 3) + + """ + stripped_right = line.rstrip('#') + stripped_both = stripped_right.lstrip('#') + level = len(stripped_right) - len(stripped_both) + stripped_wspace = stripped_both.strip() + + # character replacements + replaced_colon = stripped_wspace.replace('.', '') + replaced_slash = replaced_colon.replace('/', '') + rem_nonvalids = ''.join([c if c in VALIDS + else '-' for c in replaced_slash]) + + lowered = rem_nonvalids.lower() + dashified = re.sub(r'(-)\1+', r'\1', lowered) # remove duplicate dashes + dashified = dashified.strip('-') # strip dashes from start and end + + # exception '&' (double-dash in github) + dashified = dashified.replace('-&-', '--') + + return [stripped_wspace, dashified, level] + + +def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None): + """ + Gets headlines from the markdown document and creates anchor tags. + + Keyword arguments: + lines: a list of sublists where every sublist + represents a line from a Markdown document. + id_tag: if true, creates inserts a the tags (not req. by GitHub) + back_links: if true, adds "back to top" links below each headline + exclude_h: header levels to exclude. E.g., [2, 3] + excludes level 2 and 3 headings. + + Returns a tuple of 2 lists: + 1st list: + A modified version of the input list where + anchor tags where inserted + above the header lines (if github is False). + + 2nd list: + A list of 3-value sublists, where the first value + represents the heading, the second value the string + that was inserted assigned to the IDs in the anchor tags, + and the third value is an integer that reprents the headline level. + E.g., + [['some header lvl3', 'some-header-lvl3', 3], ...] + + """ + out_contents = [] + headlines = [] + for l in lines: + saw_headline = False + + orig_len = len(l) + l = l.lstrip() + + if l.startswith(('# ', '## ', '### ', '#### ', '##### ', '###### ')): + + # comply with new markdown standards + + # not a headline if '#' not followed by whitespace '##no-header': + if not l.lstrip('#').startswith(' '): + continue + # not a headline if more than 6 '#': + if len(l) - len(l.lstrip('#')) > 6: + continue + # headers can be indented by at most 3 spaces: + if orig_len - len(l) > 3: + continue + + # ignore empty headers + if not set(l) - {'#', ' '}: + continue + + saw_headline = True + dashified = dashify_headline(l) + + if not exclude_h or not dashified[-1] in exclude_h: + if id_tag: + id_tag = ''\ + % (dashified[1]) + out_contents.append(id_tag) + headlines.append(dashified) + + out_contents.append(l) + if back_links and saw_headline: + out_contents.append('[[back to top](#table-of-contents)]') + return out_contents, headlines + + +def positioning_headlines(headlines): + """ + Strips unnecessary whitespaces/tabs if first header is not left-aligned + """ + left_just = False + for row in headlines: + if row[-1] == 1: + left_just = True + break + if not left_just: + for row in headlines: + row[-1] -= 1 + return headlines + + +def create_toc(headlines, hyperlink=True, top_link=False, no_toc_header=False): + """ + Creates the table of contents from the headline list + that was returned by the tag_and_collect function. + + Keyword Arguments: + headlines: list of lists + e.g., ['Some header lvl3', 'some-header-lvl3', 3] + hyperlink: Creates hyperlinks in Markdown format if True, + e.g., '- [Some header lvl1](#some-header-lvl1)' + top_link: if True, add a id tag for linking the table + of contents itself (for the back-to-top-links) + no_toc_header: suppresses TOC header if True. + + Returns a list of headlines for a table of contents + in Markdown format, + e.g., [' - [Some header lvl3](#some-header-lvl3)', ...] + + """ + processed = [] + if not no_toc_header: + if top_link: + processed.append('\n') + processed.append('# Table of Contents') + + for line in headlines: + if hyperlink: + item = '%s- [%s](#%s)' % ((line[2]-1)*' ', line[0], line[1]) + else: + item = '%s- %s' % ((line[2]-1)*' ', line[0]) + processed.append(item) + processed.append('\n') + return processed + + +def build_markdown(toc_headlines, body, spacer=0, placeholder=None): + """ + Returns a string with the Markdown output contents incl. + the table of contents. + + Keyword arguments: + toc_headlines: lines for the table of contents + as created by the create_toc function. + body: contents of the Markdown file including + ID-anchor tags as returned by the + tag_and_collect function. + spacer: Adds vertical space after the table + of contents. Height in pixels. + placeholder: If a placeholder string is provided, the placeholder + will be replaced by the TOC instead of inserting the TOC at + the top of the document + + """ + if spacer: + spacer_line = ['\n
\n' % (spacer)] + toc_markdown = "\n".join(toc_headlines + spacer_line) + else: + toc_markdown = "\n".join(toc_headlines) + + body_markdown = "\n".join(body).strip() + + if placeholder: + markdown = body_markdown.replace(placeholder, toc_markdown) + else: + markdown = toc_markdown + body_markdown + + return markdown + + +def output_markdown(markdown_cont, output_file): + """ + Writes to an output file if `outfile` is a valid path. + + """ + if output_file: + with open(output_file, 'w') as out: + out.write(markdown_cont) + + +def markdown_toclify(input_file, output_file=None, github=False, + back_to_top=False, nolink=False, + no_toc_header=False, spacer=0, placeholder=None, + exclude_h=None): + """ Function to add table of contents to markdown files. + + Parameters + ----------- + input_file: str + Path to the markdown input file. + + output_file: str (defaul: None) + Path to the markdown output file. + + github: bool (default: False) + Uses GitHub TOC syntax if True. + + back_to_top: bool (default: False) + Inserts back-to-top links below headings if True. + + nolink: bool (default: False) + Creates the table of contents without internal links if True. + + no_toc_header: bool (default: False) + Suppresses the Table of Contents header if True + + spacer: int (default: 0) + Inserts horizontal space (in pixels) after the table of contents. + + placeholder: str (default: None) + Inserts the TOC at the placeholder string instead + of inserting the TOC at the top of the document. + + exclude_h: list (default None) + Excludes header levels, e.g., if [2, 3], ignores header + levels 2 and 3 in the TOC. + + Returns + ----------- + cont: str + Markdown contents including the TOC. + + """ + raw_contents = read_lines(input_file) + cleaned_contents = remove_lines(raw_contents, remove=('[[back to top]', ' Date: Tue, 29 Aug 2017 21:34:43 +0200 Subject: [PATCH 358/398] Rename to updateDocumentToC.py and adapt for use with Catch adding missing GPL 3.0 license (thanks for noting @horenmar). --- ...rkdown_toclify.py => updateDocumentToC.py} | 318 ++++++++++-------- 1 file changed, 182 insertions(+), 136 deletions(-) rename scripts/{markdown_toclify.py => updateDocumentToC.py} (54%) diff --git a/scripts/markdown_toclify.py b/scripts/updateDocumentToC.py similarity index 54% rename from scripts/markdown_toclify.py rename to scripts/updateDocumentToC.py index 8278e215..b1ab6dd2 100644 --- a/scripts/markdown_toclify.py +++ b/scripts/updateDocumentToC.py @@ -1,44 +1,51 @@ #!/usr/bin/env python # -# Sebastian Raschka 2014-2015 +# updateDocumentToC.py # -# Python script that inserts a table of contents -# into markdown documents and creates the required -# internal links. +# Insert table of contents at top of Catch markdown documents. # -# For more information about how internal links -# in HTML and Markdown documents work, please see +# This script is distributed under the GNU General Public License v3.0 # -# Creating a table of contents with internal links in -# IPython Notebooks and Markdown documents: -# http://sebastianraschka.com/Articles/2014_ipython_internal_links.html -# -# Updates for this script will be available at +# It is based on markdown-toclify version 1.7.1 by Sebastian Raschka, # https://github.com/rasbt/markdown-toclify # -# for more information about the usage: -# markdown-toclify.py --help -# + +from __future__ import print_function +from scriptCommon import catchPath import argparse +import glob +import os import re +import sys +# Configuration: -__version__ = '1.7.1' +minTocEntries = 4 + +headingExcludeDefault = [1,3,4,5] # use level 2 headers for at default +headingExcludeRelease = [2,3,4,5] # use level 1 headers for release-notes.md + +documentsDefault = os.path.join(os.path.relpath(catchPath), 'docs/*.md') +releaseNotesName = 'release-notes.md' + +contentTitle = '**Contents** ' +contentLineNo = 4 +contentLineNdx = contentLineNo - 1 + +# End configuration VALIDS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-&' - -def read_lines(in_file): +def readLines(in_file): """Returns a list of lines from a input markdown file.""" with open(in_file, 'r') as inf: in_contents = inf.read().split('\n') return in_contents - -def remove_lines(lines, remove=('[[back to top]', ' tags.""" if not remove: @@ -51,8 +58,22 @@ def remove_lines(lines, remove=('[[back to top]', ' anchor tags, and the level of the headline as integer. E.g., - >>> dashify_headline('### some header lvl3') + >>> dashifyHeadline('### some header lvl3') ('Some header lvl3', 'some-header-lvl3', 3) """ @@ -84,8 +105,7 @@ def dashify_headline(line): return [stripped_wspace, dashified, level] - -def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None): +def tagAndCollect(lines, id_tag=True, back_links=False, exclude_h=None): """ Gets headlines from the markdown document and creates anchor tags. @@ -118,9 +138,9 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None): saw_headline = False orig_len = len(l) - l = l.lstrip() + l_stripped = l.lstrip() - if l.startswith(('# ', '## ', '### ', '#### ', '##### ', '###### ')): + if l_stripped.startswith(('# ', '## ', '### ', '#### ', '##### ', '###### ')): # comply with new markdown standards @@ -131,7 +151,7 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None): if len(l) - len(l.lstrip('#')) > 6: continue # headers can be indented by at most 3 spaces: - if orig_len - len(l) > 3: + if orig_len - len(l_stripped) > 3: continue # ignore empty headers @@ -139,7 +159,7 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None): continue saw_headline = True - dashified = dashify_headline(l) + dashified = dashifyHeadline(l) if not exclude_h or not dashified[-1] in exclude_h: if id_tag: @@ -153,8 +173,7 @@ def tag_and_collect(lines, id_tag=True, back_links=False, exclude_h=None): out_contents.append('[[back to top](#table-of-contents)]') return out_contents, headlines - -def positioning_headlines(headlines): +def positioningHeadlines(headlines): """ Strips unnecessary whitespaces/tabs if first header is not left-aligned """ @@ -168,11 +187,10 @@ def positioning_headlines(headlines): row[-1] -= 1 return headlines - -def create_toc(headlines, hyperlink=True, top_link=False, no_toc_header=False): +def createToc(headlines, hyperlink=True, top_link=False, no_toc_header=False): """ Creates the table of contents from the headline list - that was returned by the tag_and_collect function. + that was returned by the tagAndCollect function. Keyword Arguments: headlines: list of lists @@ -192,29 +210,28 @@ def create_toc(headlines, hyperlink=True, top_link=False, no_toc_header=False): if not no_toc_header: if top_link: processed.append('\n') - processed.append('# Table of Contents') + processed.append(contentTitle) for line in headlines: if hyperlink: - item = '%s- [%s](#%s)' % ((line[2]-1)*' ', line[0], line[1]) + item = '[%s](#%s) ' % (line[0], line[1]) else: item = '%s- %s' % ((line[2]-1)*' ', line[0]) processed.append(item) processed.append('\n') return processed - -def build_markdown(toc_headlines, body, spacer=0, placeholder=None): +def buildMarkdown(toc_headlines, body, spacer=0, placeholder=None): """ Returns a string with the Markdown output contents incl. the table of contents. Keyword arguments: toc_headlines: lines for the table of contents - as created by the create_toc function. + as created by the createToc function. body: contents of the Markdown file including ID-anchor tags as returned by the - tag_and_collect function. + tagAndCollect function. spacer: Adds vertical space after the table of contents. Height in pixels. placeholder: If a placeholder string is provided, the placeholder @@ -228,17 +245,17 @@ def build_markdown(toc_headlines, body, spacer=0, placeholder=None): else: toc_markdown = "\n".join(toc_headlines) - body_markdown = "\n".join(body).strip() - if placeholder: + body_markdown = "\n".join(body) markdown = body_markdown.replace(placeholder, toc_markdown) else: - markdown = toc_markdown + body_markdown + body_markdown_p1 = "\n".join(body[:contentLineNdx ]) + '\n' + body_markdown_p2 = "\n".join(body[ contentLineNdx:]) + markdown = body_markdown_p1 + toc_markdown + body_markdown_p2 return markdown - -def output_markdown(markdown_cont, output_file): +def outputMarkdown(markdown_cont, output_file): """ Writes to an output file if `outfile` is a valid path. @@ -247,11 +264,17 @@ def output_markdown(markdown_cont, output_file): with open(output_file, 'w') as out: out.write(markdown_cont) - -def markdown_toclify(input_file, output_file=None, github=False, - back_to_top=False, nolink=False, - no_toc_header=False, spacer=0, placeholder=None, - exclude_h=None): +def markdownToclify( + input_file, + output_file=None, + min_toc_len=2, + github=False, + back_to_top=False, + nolink=False, + no_toc_header=False, + spacer=0, + placeholder=None, + exclude_h=None): """ Function to add table of contents to markdown files. Parameters @@ -262,6 +285,9 @@ def markdown_toclify(input_file, output_file=None, github=False, output_file: str (defaul: None) Path to the markdown output file. + min_toc_len: int (default: 2) + Miniumum number of entries to create a table of contents for. + github: bool (default: False) Uses GitHub TOC syntax if True. @@ -287,114 +313,134 @@ def markdown_toclify(input_file, output_file=None, github=False, Returns ----------- - cont: str - Markdown contents including the TOC. + changed: Boolean + True if the file has been updated, False otherwise. """ - raw_contents = read_lines(input_file) - cleaned_contents = remove_lines(raw_contents, remove=('[[back to top]', '= (3, 3): + os.replace(output_file, input_file) + else: + os.remove(input_file) + os.rename(output_file, input_file) + + return 1 + +def updateDocumentToC(paths, min_toc_len, verbose): + """Add or update table of contents to specified paths. Return number of changed files""" + n = 0 + for g in paths: + for f in glob.glob(g): + if os.path.isfile(f): + n = n + updateSingleDocumentToC(input_file=f, min_toc_len=min_toc_len, verbose=verbose) + return n + +def updateDocumentToCMain(): + """Add or update table of contents to specified paths.""" parser = argparse.ArgumentParser( - description='Python script that inserts a table of contents\n'\ - 'into markdown documents and creates the required internal links.', - epilog=""" Example: - markdown-toclify.py ~/Desktop/input.md -o ~/Desktop/output.md + description='Add or update table of contents in markdown documents.', + epilog="""""", + formatter_class=argparse.RawTextHelpFormatter) - For more information about how internal links in - HTML and Markdown documents work - please see: - "Creating a table of contents with internal - links in IPython Notebooks and Markdown documents" - (http://sebastianraschka.com/Articles/2014_ipython_internal_links.html) + parser.add_argument( + 'Input', + metavar='file', + type=str, + nargs=argparse.REMAINDER, + help='files to process, at default: docs/*.md') - Updates for this script will be available at - https://github.com/rasbt/markdown-toclify + parser.add_argument( + '-v', '--verbose', + action='store_true', + help='report the name of the file being processed') - """, - formatter_class=argparse.RawTextHelpFormatter - ) + parser.add_argument( + '--min-toc-entries', + dest='minTocEntries', + default=minTocEntries, + type=int, + metavar='N', + help='the minimum number of entries to create a table of contents for [{deflt}]'.format(deflt=minTocEntries)) - parser.add_argument('InputFile', - metavar='input.md', - help='path to the Markdown input file') - parser.add_argument('-o', '--output', - metavar='output.md', - default=None, - help='path to the Markdown output file') - parser.add_argument('-b', '--back_to_top', - action='store_true', - help='add [back to top] links.') - parser.add_argument('-g', '--github', - action='store_true', - help='omits id-anchor tags (recommended for GitHub)') - parser.add_argument('-s', '--spacer', - default=0, - type=int, - metavar='pixels', - help='add horizontal space (in pixels) after the table of contents') - parser.add_argument('-n', '--nolink', - action='store_true', - help='create the table of contents without internal links') - parser.add_argument('-e', '--exclude_h', - type=str, - default='', - help='exclude eading levels, e.g., "2,3" to exclude all level 2 and 3 headings') - parser.add_argument('--placeholder', - type=str, - help='inserts TOC at the placeholder string instead of inserting it on top of the document') - parser.add_argument('--no_toc_header', - action='store_true', - help='suppresses the Table of Contents header') - parser.add_argument('-v', '--version', - action='version', - version='%s' % __version__) + parser.add_argument( + '--remove-toc', + action='store_const', + dest='minTocEntries', + const=99, + help='remove all tables of contents') args = parser.parse_args() - if args.exclude_h: - exclude_h = [int(i) for i in args.exclude_h.split(',')] + paths = args.Input if len(args.Input) > 0 else [documentsDefault] + + changedFiles = updateDocumentToC(paths=paths, min_toc_len=args.minTocEntries, verbose=args.verbose) + + if changedFiles > 0: + print( "Processed table of contents in " + str(changedFiles) + " file(s)" ) else: - exclude_h = None - - cont = markdown_toclify(input_file=args.InputFile, - output_file=args.output, - github=args.github, - back_to_top=args.back_to_top, - nolink=args.nolink, - no_toc_header=args.no_toc_header, - spacer=args.spacer, - placeholder=args.placeholder, - exclude_h=exclude_h) - - if not args.output: - print(cont) + print( "No table of contents added or updated" ) if __name__ == '__main__': - commandline() + updateDocumentToCMain() + +# end of file From f9727327370abbee50f99d3fcd26f0b114a21887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 3 Oct 2017 18:31:51 +0200 Subject: [PATCH 359/398] Workaround for stitching issue in #1020 Closes #1020 --- include/catch.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/catch.hpp b/include/catch.hpp index 118337c9..377cb31e 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -62,6 +62,10 @@ #endif #ifdef CATCH_IMPL + #ifdef CATCH_PLATFORM_WINDOWS + #include "internal/catch_windows_h_proxy.h" + #endif + #include "internal/catch_impl.hpp" #endif From 79b405fd3f752bd61a077d03798001c4e9d711b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 9 Oct 2017 12:31:22 +0200 Subject: [PATCH 360/398] Add stringification for std::chrono::{duration,time_point} Also hides std::chrono, std::pair and std::chrono::* behind new configuration macros, CATCH_CONFIG_ENABLE_*_STRINGMAKER to avoid dragging in , and in common path, unless requested. --- CMakeLists.txt | 1 + docs/configuration.md | 28 ++- docs/release-notes.md | 7 +- include/internal/catch_tostring.h | 193 +++++++++++++++--- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 82 +++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 6 +- .../SelfTest/Baselines/xml.sw.approved.txt | 86 +++++++- projects/SelfTest/ToStringChrono.cpp | 41 ++++ projects/SelfTest/ToStringPair.cpp | 1 + projects/SelfTest/ToStringTuple.cpp | 1 + scripts/approvalTests.py | 6 +- 12 files changed, 408 insertions(+), 48 deletions(-) create mode 100644 projects/SelfTest/ToStringChrono.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c8a17f18..17248cfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,7 @@ set(TEST_SOURCES ${SELF_TEST_DIR}/PartTrackerTests.cpp ${SELF_TEST_DIR}/TagAliasTests.cpp ${SELF_TEST_DIR}/TestMain.cpp + ${SELF_TEST_DIR}/ToStringChrono.cpp ${SELF_TEST_DIR}/ToStringGeneralTests.cpp ${SELF_TEST_DIR}/ToStringPair.cpp ${SELF_TEST_DIR}/ToStringTuple.cpp diff --git a/docs/configuration.md b/docs/configuration.md index 937e6122..bbb27ac0 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,14 +1,15 @@ # Compile-time configuration -**Contents** -[main()/ implementation](#main-implementation) -[Prefixing Catch macros](#prefixing-catch-macros) -[Terminal colour](#terminal-colour) -[Console width](#console-width) -[stdout](#stdout) -[Other toggles](#other-toggles) -[Windows header clutter](#windows-header-clutter) +**Contents** +[main()/ implementation](#main-implementation) +[Prefixing Catch macros](#prefixing-catch-macros) +[Terminal colour](#terminal-colour) +[Console width](#console-width) +[stdout](#stdout) +[Other toggles](#other-toggles) +[Windows header clutter](#windows-header-clutter) +[Enabling stringification](#enabling-stringification) Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). @@ -121,6 +122,17 @@ On Windows Catch includes `windows.h`. To minimize global namespace clutter in t CATCH_CONFIG_NO_NOMINMAX // Stops Catch from using NOMINMAX macro CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN // Stops Catch from using WIN32_LEAN_AND_MEAN macro + +## Enabling stringification + +By default, Catch does not stringify some types from the standard library. This is done to avoid dragging in various standard library headers by default. However, Catch does contain these and can be configured to provide them, using these macros: + + CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER // Provide StringMaker specialization for std::pair + CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER // Provide StringMaker specialization for std::tuple + CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER // Provide StringMaker specialization for std::chrono::duration, std::chrono::timepoint + CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS // Defines all of the above + + --- [Home](Readme.md#top) diff --git a/docs/release-notes.md b/docs/release-notes.md index 62faabdc..3c7a97ea 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -22,7 +22,9 @@ * Removed support for non-const comparison operators * Non-const comparison operators are an abomination that should not exist * They were breaking support for comparing function to function pointer - +* `std::pair` and `std::tuple` are no longer stringified by default + * This is done to avoid dragging in `` and `` headers in common path + * Their stringification can be enabled per-file via new configuration macros ## Improvements * Reporters and Listeners can be defined in files different from the main file @@ -53,7 +55,8 @@ * Reporters/Listeners are now notified of fatal errors * This means specific signals or structured exceptions * The Reporter/Listener interface provides default, empty, implementation to preserve backward compatibility - +* Stringification of `std::chrono::duration` and `std::chrono::time_point` is now supported + * Needs to be enabled by a per-file compile time configuration option ## Fixes * Don't use console colour if running in XCode diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index b5d31397..568232ba 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -57,7 +56,7 @@ namespace Catch { public: static const bool value = decltype(test(0))::value; }; - + } // namespace Detail // If we decide for C++14, change these to enable_if_ts @@ -241,7 +240,53 @@ namespace Catch { } }; - // === Pair === + template + struct EnumStringMaker { + static std::string convert(const T& t) { + return ::Catch::Detail::stringify(static_cast::type>(t)); + } + }; + +#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]); + } + + }; + namespace Detail { + inline std::string stringify( NSString* nsstring ) { + return StringMaker::convert( nsstring ); + } + + } // namespace Detail +#endif // __OBJC__ + +} // namespace Catch + +////////////////////////////////////////////////////// +// Separate std-lib types stringification, so it can be selectively enabled +// This means that we do not bring in + +#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) +# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +# define CATCH_CONFIG_ENABLE_CHRONO_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) { @@ -254,9 +299,13 @@ namespace Catch { return oss.str(); } }; +} +#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER - - +// Separate std::tuple specialization +#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) +#include +namespace Catch { namespace Detail { template< typename Tuple, @@ -292,40 +341,126 @@ namespace Catch { return os.str(); } }; +} +#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER - template - struct EnumStringMaker { - static std::string convert(const T& t) { - return ::Catch::Detail::stringify(static_cast::type>(t)); +// Separate std::chrono::duration specialization +#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#include + +#include + +template +struct ratio_string { + static std::string symbol(); +}; + +template +std::string ratio_string::symbol() { + std::ostringstream oss; + oss << '[' << Ratio::num << '/' + << Ratio::den << ']'; + return oss.str(); +} +template <> +struct ratio_string { + static std::string symbol() { return "a"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "f"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "p"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "n"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "u"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "m"; } +}; + +namespace Catch { + //////////// + // std::chrono::duration specializations + template + struct StringMaker> { + static std::string convert(std::chrono::duration const& duration) { + std::ostringstream oss; + oss << duration.count() << ' ' << ratio_string::symbol() << 's'; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " s"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " m"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " h"; + return oss.str(); } }; -#ifdef __OBJC__ - template<> - struct StringMaker { - static std::string convert(NSString * nsstring) { - if (!nsstring) - return "nil"; - return std::string("@") + [nsstring UTF8String]; + //////////// + // std::chrono::time_point specialization + // Generic time_point cannot be specialized, only std::chrono::time_point + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; } }; - template<> - struct StringMaker { - static std::string convert(NSObject* nsObject) { - return ::Catch::Detail::stringify([nsObject description]); - } + // std::chrono::time_point specialization + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + auto converted = std::chrono::system_clock::to_time_t(time_point); +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &converted); +#else + std::tm* timeInfo = std::gmtime(&converted); +#endif + + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } }; - namespace Detail { - inline std::string stringify( NSString* nsstring ) { - return StringMaker::convert( nsstring ); - } +} +#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER - } // namespace Detail -#endif // __OBJC__ - -} // namespace Catch #ifdef _MSC_VER #pragma warning(pop) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 9b2defd5..939d0d89 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 176 | 125 passed | 47 failed | 4 failed as expected -assertions: 878 | 761 passed | 96 failed | 21 failed as expected +test cases: 180 | 129 passed | 47 failed | 4 failed as expected +assertions: 886 | 769 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index be582975..5441de43 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -4613,6 +4613,84 @@ PASSED: with expansion: 11 == 11 +------------------------------------------------------------------------------- +Stringifying std::chrono::duration helpers +------------------------------------------------------------------------------- +ToStringChrono.cpp: +............................................................................... + +ToStringChrono.cpp:: +PASSED: + REQUIRE( minute == seconds ) +with expansion: + 1 m == 60 s + +ToStringChrono.cpp:: +PASSED: + REQUIRE( hour != seconds ) +with expansion: + 1 h != 60 s + +ToStringChrono.cpp:: +PASSED: + REQUIRE( micro != milli ) +with expansion: + 1 us != 1 ms + +ToStringChrono.cpp:: +PASSED: + REQUIRE( nano != micro ) +with expansion: + 1 ns != 1 us + +------------------------------------------------------------------------------- +Stringifying std::chrono::duration with weird ratios +------------------------------------------------------------------------------- +ToStringChrono.cpp: +............................................................................... + +ToStringChrono.cpp:: +PASSED: + REQUIRE( half_minute != femto_second ) +with expansion: + 1 [30/1]s != 1 fs + +------------------------------------------------------------------------------- +Stringifying std::chrono::time_point +------------------------------------------------------------------------------- +ToStringChrono.cpp: +............................................................................... + +ToStringChrono.cpp:: +PASSED: + REQUIRE( now != later ) +with expansion: + {iso8601-timestamp} + != + {iso8601-timestamp} + +ToStringChrono.cpp:: +PASSED: + REQUIRE( now2 != later2 ) +with expansion: + {since-epoch-report} + != + {since-epoch-report} + +------------------------------------------------------------------------------- +Stringifying std::chrono::time_point +------------------------------------------------------------------------------- +ToStringChrono.cpp: +............................................................................... + +ToStringChrono.cpp:: +PASSED: + REQUIRE( now != later ) +with expansion: + {iso8601-timestamp} + != + {iso8601-timestamp} + ------------------------------------------------------------------------------- Tabs and newlines show in output ------------------------------------------------------------------------------- @@ -7434,6 +7512,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 176 | 123 passed | 49 failed | 4 failed as expected -assertions: 877 | 757 passed | 99 failed | 21 failed as expected +test cases: 180 | 127 passed | 49 failed | 4 failed as expected +assertions: 885 | 765 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 9c0c8204..0dd6ab60 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -519,6 +519,10 @@ StringRef.tests.cpp: + + + + + + + + minute == seconds + + + 1 m == 60 s + + + + + hour != seconds + + + 1 h != 60 s + + + + + micro != milli + + + 1 us != 1 ms + + + + + nano != micro + + + 1 ns != 1 us + + + + + + + + half_minute != femto_second + + + 1 [30/1]s != 1 fs + + + + + + + + now != later + + + {iso8601-timestamp} +!= +{iso8601-timestamp} + + + + + now2 != later2 + + + {since-epoch-report} +!= +{since-epoch-report} + + + + + + + + now != later + + + {iso8601-timestamp} +!= +{iso8601-timestamp} + + + + @@ -8209,7 +8291,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/ToStringChrono.cpp b/projects/SelfTest/ToStringChrono.cpp new file mode 100644 index 00000000..1716ce64 --- /dev/null +++ b/projects/SelfTest/ToStringChrono.cpp @@ -0,0 +1,41 @@ +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#include "catch.hpp" + +#include +#include + +TEST_CASE("Stringifying std::chrono::duration helpers", "[toString][chrono]") { + // No literals because we still support c++11 + auto hour = std::chrono::hours(1); + auto minute = std::chrono::minutes(1); + auto seconds = std::chrono::seconds(60); + auto micro = std::chrono::microseconds(1); + auto milli = std::chrono::milliseconds(1); + auto nano = std::chrono::nanoseconds(1); + REQUIRE(minute == seconds); + REQUIRE(hour != seconds); + REQUIRE(micro != milli); + REQUIRE(nano != micro); +} + +TEST_CASE("Stringifying std::chrono::duration with weird ratios", "[toString][chrono]") { + std::chrono::duration> half_minute(1); + std::chrono::duration> femto_second(1); + REQUIRE(half_minute != femto_second); +} + +TEST_CASE("Stringifying std::chrono::time_point", "[toString][chrono]") { + auto now = std::chrono::system_clock::now(); + auto later = now + std::chrono::minutes(2); + REQUIRE(now != later); +} + +TEST_CASE("Stringifying std::chrono::time_point", "[toString][chrono]") { + auto now = std::chrono::high_resolution_clock::now(); + auto later = now + std::chrono::minutes(2); + REQUIRE(now != later); + + auto now2 = std::chrono::steady_clock::now(); + auto later2 = now2 + std::chrono::minutes(2); + REQUIRE(now2 != later2); +} diff --git a/projects/SelfTest/ToStringPair.cpp b/projects/SelfTest/ToStringPair.cpp index 38f30854..1445c54f 100644 --- a/projects/SelfTest/ToStringPair.cpp +++ b/projects/SelfTest/ToStringPair.cpp @@ -1,3 +1,4 @@ +#define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER #include "catch.hpp" TEST_CASE( "std::pair -> toString", "[toString][pair]" ) { diff --git a/projects/SelfTest/ToStringTuple.cpp b/projects/SelfTest/ToStringTuple.cpp index 330e427e..fe19ce01 100644 --- a/projects/SelfTest/ToStringTuple.cpp +++ b/projects/SelfTest/ToStringTuple.cpp @@ -1,3 +1,4 @@ +#define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER #include "catch.hpp" #include diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py index 5c0c63ec..a963531b 100755 --- a/scripts/approvalTests.py +++ b/scripts/approvalTests.py @@ -24,7 +24,7 @@ filelocParser = re.compile(r''' lineNumberParser = re.compile(r' line="[0-9]*"') hexParser = re.compile(r'\b(0[xX][0-9a-fA-F]+)\b') durationsParser = re.compile(r' time="[0-9]*\.[0-9]*"') -timestampsParser = re.compile(r' timestamp="\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z"') +timestampsParser = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}Z') versionParser = re.compile(r'Catch v[0-9]+\.[0-9]+\.[0-9]+(-develop\.[0-9]+)?') nullParser = re.compile(r'\b(__null|nullptr)\b') exeNameParser = re.compile(r''' @@ -44,6 +44,7 @@ errnoParser = re.compile(r''' | \(\*_errno\(\)\) ''', re.VERBOSE) +sinceEpochParser = re.compile(r'\d+ .+ since epoch') if len(sys.argv) == 2: cmdPath = sys.argv[1] @@ -97,9 +98,10 @@ def filterLine(line): # strip durations and timestamps line = durationsParser.sub(' time="{duration}"', line) - line = timestampsParser.sub(' timestamp="{iso8601-timestamp}"', line) + line = timestampsParser.sub('{iso8601-timestamp}', line) line = specialCaseParser.sub('file:\g<1>', line) line = errnoParser.sub('errno', line) + line = sinceEpochParser.sub('{since-epoch-report}', line) return line From 760a25e8135e23b7f8d2d925e84bd6bbce9e9247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 9 Oct 2017 13:12:50 +0200 Subject: [PATCH 361/398] Fix baseline for file where std::pair stringification is not enabled --- projects/SelfTest/Baselines/console.sw.approved.txt | 2 +- projects/SelfTest/Baselines/xml.sw.approved.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 5441de43..13da430d 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3336,7 +3336,7 @@ TrickyTests.cpp:: PASSED: REQUIRE( (std::pair( 1, 2 )) == aNicePair ) with expansion: - { 1, 2 } == { 1, 2 } + {?} == {?} ------------------------------------------------------------------------------- Pointers can be compared to null diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index b05dd463..c4b7ac38 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -3853,7 +3853,7 @@ (std::pair<int, int>( 1, 2 )) == aNicePair - { 1, 2 } == { 1, 2 } + {?} == {?} From 4899d891d3946b8f43b31130330ce387caf316f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 9 Oct 2017 13:13:30 +0200 Subject: [PATCH 362/398] Fix MSVC compilation when stringifying std::chrono::time_point --- include/internal/catch_tostring.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 568232ba..8348c825 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -347,9 +347,9 @@ namespace Catch { // Separate std::chrono::duration specialization #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -#include - +#include #include +#include template struct ratio_string { From 17cdf209683de2a9da8469a81ae48def45624944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 9 Oct 2017 14:54:37 +0200 Subject: [PATCH 363/398] Mark part of std::chrono stringification tests nonportable --- .../Baselines/console.std.approved.txt | 4 +-- .../Baselines/console.sw.approved.txt | 26 ++---------------- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +-- .../SelfTest/Baselines/xml.sw.approved.txt | 27 ++----------------- projects/SelfTest/ToStringChrono.cpp | 2 +- 5 files changed, 8 insertions(+), 54 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 939d0d89..6aaa7ed1 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 180 | 129 passed | 47 failed | 4 failed as expected -assertions: 886 | 769 passed | 96 failed | 21 failed as expected +test cases: 179 | 128 passed | 47 failed | 4 failed as expected +assertions: 884 | 767 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 13da430d..10b6fc35 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -4655,28 +4655,6 @@ PASSED: with expansion: 1 [30/1]s != 1 fs -------------------------------------------------------------------------------- -Stringifying std::chrono::time_point -------------------------------------------------------------------------------- -ToStringChrono.cpp: -............................................................................... - -ToStringChrono.cpp:: -PASSED: - REQUIRE( now != later ) -with expansion: - {iso8601-timestamp} - != - {iso8601-timestamp} - -ToStringChrono.cpp:: -PASSED: - REQUIRE( now2 != later2 ) -with expansion: - {since-epoch-report} - != - {since-epoch-report} - ------------------------------------------------------------------------------- Stringifying std::chrono::time_point ------------------------------------------------------------------------------- @@ -7512,6 +7490,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 180 | 127 passed | 49 failed | 4 failed as expected -assertions: 885 | 765 passed | 99 failed | 21 failed as expected +test cases: 179 | 126 passed | 49 failed | 4 failed as expected +assertions: 883 | 763 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 0dd6ab60..b306b393 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -521,7 +521,6 @@ StringRef.tests.cpp: - - - - - now != later - - - {iso8601-timestamp} -!= -{iso8601-timestamp} - - - - - now2 != later2 - - - {since-epoch-report} -!= -{since-epoch-report} - - - - @@ -8291,7 +8268,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/ToStringChrono.cpp b/projects/SelfTest/ToStringChrono.cpp index 1716ce64..97d0c1cb 100644 --- a/projects/SelfTest/ToStringChrono.cpp +++ b/projects/SelfTest/ToStringChrono.cpp @@ -30,7 +30,7 @@ TEST_CASE("Stringifying std::chrono::time_point", "[toString][chro REQUIRE(now != later); } -TEST_CASE("Stringifying std::chrono::time_point", "[toString][chrono]") { +TEST_CASE("Stringifying std::chrono::time_point", "[toString][chrono][!nonportable]") { auto now = std::chrono::high_resolution_clock::now(); auto later = now + std::chrono::minutes(2); REQUIRE(now != later); From cc0b093c20180ff847956522641fdbb63fd2cd49 Mon Sep 17 00:00:00 2001 From: philsquared Date: Wed, 11 Oct 2017 14:58:20 +0100 Subject: [PATCH 364/398] unconditional windows proxy --- include/catch.hpp | 5 +---- include/internal/catch_windows_h_proxy.h | 17 +++++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 377cb31e..edb588d1 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -62,10 +62,7 @@ #endif #ifdef CATCH_IMPL - #ifdef CATCH_PLATFORM_WINDOWS - #include "internal/catch_windows_h_proxy.h" - #endif - +#include "internal/catch_windows_h_proxy.h" #include "internal/catch_impl.hpp" #endif diff --git a/include/internal/catch_windows_h_proxy.h b/include/internal/catch_windows_h_proxy.h index bbb1ee82..a7a19c8e 100644 --- a/include/internal/catch_windows_h_proxy.h +++ b/include/internal/catch_windows_h_proxy.h @@ -11,14 +11,14 @@ #include "catch_platform.h" #if defined(CATCH_PLATFORM_WINDOWS) -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX -# define NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif + +#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +#endif +#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN #endif #ifdef __AFXDLL @@ -34,5 +34,6 @@ # undef WIN32_LEAN_AND_MEAN #endif +#endif // defined(CATCH_PLATFORM_WINDOWS) #endif // TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED From 927f520a9731d5a10ec1a16deb15759ee6609528 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 12 Oct 2017 10:37:03 +0100 Subject: [PATCH 365/398] Moved windows proxy inclusion outside of CATCH_CONFIG_COLOUR_WINDOWS guard, so workaround early inclusion can be removed --- include/catch.hpp | 1 - include/internal/catch_console_colour.cpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index edb588d1..118337c9 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -62,7 +62,6 @@ #endif #ifdef CATCH_IMPL -#include "internal/catch_windows_h_proxy.h" #include "internal/catch_impl.hpp" #endif diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp index 946e2903..8b055b33 100644 --- a/include/internal/catch_console_colour.cpp +++ b/include/internal/catch_console_colour.cpp @@ -21,6 +21,7 @@ #include "catch_context.h" #include "catch_platform.h" #include "catch_debugger.h" +#include "catch_windows_h_proxy.h" namespace Catch { namespace { @@ -53,8 +54,6 @@ namespace Catch { #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// -#include "catch_windows_h_proxy.h" - namespace Catch { namespace { From 355ab78f4a89736171d34d6ce271aa36a0ce155d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 12 Oct 2017 13:06:41 +0100 Subject: [PATCH 366/398] dev build 5 --- conanfile.py | 2 +- include/internal/catch_version.cpp | 2 +- single_include/catch.hpp | 825 +++++++++++++++++------------ test_package/conanfile.py | 2 +- 4 files changed, 488 insertions(+), 343 deletions(-) diff --git a/conanfile.py b/conanfile.py index d1dfa81d..5c7d9931 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.0.0-develop.4" + version = "2.0.0-develop.5" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index b635800b..e684f3f9 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 4 ); + static Version version( 2, 0, 0, "develop", 5 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index e5ae6198..f9568b0c 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.0.0-develop.4 - * Generated: 2017-09-19 17:37:34.480115 + * Catch v2.0.0-develop.5 + * Generated: 2017-10-12 13:05:08.135067 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. @@ -480,7 +480,6 @@ struct AutoReg : NonCopyable { #include #include #include -#include #include #include @@ -749,7 +748,53 @@ namespace Catch { } }; - // === Pair === + template + struct EnumStringMaker { + static std::string convert(const T& t) { + return ::Catch::Detail::stringify(static_cast::type>(t)); + } + }; + +#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]); + } + + }; + namespace Detail { + inline std::string stringify( NSString* nsstring ) { + return StringMaker::convert( nsstring ); + } + + } // namespace Detail +#endif // __OBJC__ + +} // namespace Catch + +////////////////////////////////////////////////////// +// Separate std-lib types stringification, so it can be selectively enabled +// This means that we do not bring in + +#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) +# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +# define CATCH_CONFIG_ENABLE_CHRONO_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) { @@ -762,7 +807,13 @@ namespace Catch { return oss.str(); } }; +} +#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +// Separate std::tuple specialization +#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) +#include +namespace Catch { namespace Detail { template< typename Tuple, @@ -797,39 +848,124 @@ namespace Catch { return os.str(); } }; +} +#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER - template - struct EnumStringMaker { - static std::string convert(const T& t) { - return ::Catch::Detail::stringify(static_cast::type>(t)); +// Separate std::chrono::duration specialization +#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#include +#include +#include + +template +struct ratio_string { + static std::string symbol(); +}; + +template +std::string ratio_string::symbol() { + std::ostringstream oss; + oss << '[' << Ratio::num << '/' + << Ratio::den << ']'; + return oss.str(); +} +template <> +struct ratio_string { + static std::string symbol() { return "a"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "f"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "p"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "n"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "u"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "m"; } +}; + +namespace Catch { + //////////// + // std::chrono::duration specializations + template + struct StringMaker> { + static std::string convert(std::chrono::duration const& duration) { + std::ostringstream oss; + oss << duration.count() << ' ' << ratio_string::symbol() << 's'; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " s"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " m"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " h"; + return oss.str(); } }; -#ifdef __OBJC__ - template<> - struct StringMaker { - static std::string convert(NSString * nsstring) { - if (!nsstring) - return "nil"; - return std::string("@") + [nsstring UTF8String]; + //////////// + // std::chrono::time_point specialization + // Generic time_point cannot be specialized, only std::chrono::time_point + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; } }; - template<> - struct StringMaker { - static std::string convert(NSObject* nsObject) { - return ::Catch::Detail::stringify([nsObject description]); - } + // std::chrono::time_point specialization + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + auto converted = std::chrono::system_clock::to_time_t(time_point); +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &converted); +#else + std::tm* timeInfo = std::gmtime(&converted); +#endif + + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } }; - namespace Detail { - inline std::string stringify( NSString* nsstring ) { - return StringMaker::convert( nsstring ); - } - - } // namespace Detail -#endif // __OBJC__ - -} // namespace Catch +} +#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER #ifdef _MSC_VER #pragma warning(pop) @@ -1614,6 +1750,7 @@ namespace Catch { static std::string translatorName( signature ) #endif +#include #include #include @@ -1646,7 +1783,7 @@ namespace Catch { std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { try { if( it == itEnd ) - throw; + std::rethrow_exception(std::current_exception()); else return (*it)->translate( it+1, itEnd ); } @@ -4205,6 +4342,10 @@ namespace Catch { #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 #endif +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#endif + // ----------- #included from clara_textflow.hpp ----------- // TextFlowCpp @@ -4538,9 +4679,8 @@ namespace Catch { namespace clara { namespace TextFlow { #include #include -#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) -#define CLARA_PLATFORM_WINDOWS - +#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CATCH_PLATFORM_WINDOWS #endif namespace Catch { namespace clara { @@ -4548,15 +4688,15 @@ namespace detail { // Traits for extracting arg and return type of lambdas (for single argument lambdas) template - struct UnaryLambdaTraits : UnaryLambdaTraits {}; + struct UnaryLambdaTraits : UnaryLambdaTraits {}; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = false; }; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = true; using ArgType = typename std::remove_const::type>::type;; using ReturnType = ReturnT; @@ -4571,13 +4711,13 @@ namespace detail { std::vector m_args; public: - Args(int argc, char *argv[]) { + Args( int argc, char *argv[] ) { m_exeName = argv[0]; - for (int i = 1; i < argc; ++i) - m_args.push_back(argv[i]); + for( int i = 1; i < argc; ++i ) + m_args.push_back( argv[i] ); } - Args(std::initializer_list args) + Args( std::initializer_list args ) : m_exeName( *args.begin() ), m_args( args.begin()+1, args.end() ) {} @@ -4605,40 +4745,40 @@ namespace detail { std::vector m_tokenBuffer; void loadBuffer() { - m_tokenBuffer.resize(0); + m_tokenBuffer.resize( 0 ); // Skip any empty strings - while (it != itEnd && it->empty()) + while( it != itEnd && it->empty() ) ++it; - if (it != itEnd) { + if( it != itEnd ) { auto const &next = *it; - if (next[0] == '-' || next[0] == '/') { - auto delimiterPos = next.find_first_of(" :="); - if (delimiterPos != std::string::npos) { - m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)}); - m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)}); + if( next[0] == '-' || next[0] == '/' ) { + auto delimiterPos = next.find_first_of( " :=" ); + if( delimiterPos != std::string::npos ) { + m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); + m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); } else { - if (next[1] != '-' && next.size() > 2) { + if( next[1] != '-' && next.size() > 2 ) { std::string opt = "- "; - for (size_t i = 1; i < next.size(); ++i) { + for( size_t i = 1; i < next.size(); ++i ) { opt[1] = next[i]; - m_tokenBuffer.push_back({TokenType::Option, opt}); + m_tokenBuffer.push_back( { TokenType::Option, opt } ); } } else { - m_tokenBuffer.push_back({TokenType::Option, next}); + m_tokenBuffer.push_back( { TokenType::Option, next } ); } } } else { - m_tokenBuffer.push_back({TokenType::Argument, next}); + m_tokenBuffer.push_back( { TokenType::Argument, next } ); } } } public: - explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} + explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} - TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { loadBuffer(); } @@ -4649,20 +4789,20 @@ namespace detail { auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } auto operator*() const -> Token { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return m_tokenBuffer.front(); } auto operator->() const -> Token const * { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return &m_tokenBuffer.front(); } auto operator++() -> TokenStream & { - if (m_tokenBuffer.size() >= 2) { - m_tokenBuffer.erase(m_tokenBuffer.begin()); + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); } else { - if (it != itEnd) + if( it != itEnd ) ++it; loadBuffer(); } @@ -4677,7 +4817,7 @@ namespace detail { }; protected: - ResultBase(Type type) : m_type(type) {} + ResultBase( Type type ) : m_type( type ) {} virtual ~ResultBase() = default; virtual void enforceOk() const = 0; @@ -4694,28 +4834,28 @@ namespace detail { } protected: - ResultValueBase(Type type) : ResultBase(type) {} + ResultValueBase( Type type ) : ResultBase( type ) {} - ResultValueBase(ResultValueBase const &other) : ResultBase(other) { - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); } - ResultValueBase(Type, T const &value) : ResultBase(Ok) { - new(&m_value) T(value); + ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { + new( &m_value ) T( value ); } - auto operator=(ResultValueBase const &other) -> ResultValueBase & { - if (m_type == ResultBase::Ok) + auto operator=( ResultValueBase const &other ) -> ResultValueBase & { + if( m_type == ResultBase::Ok ) m_value.~T(); ResultBase::operator=(other); - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); return *this; } ~ResultValueBase() { - if (m_type == Ok) + if( m_type == Ok ) m_value.~T(); } @@ -4734,37 +4874,31 @@ namespace detail { class BasicResult : public ResultValueBase { public: template - explicit BasicResult(BasicResult const &other) - : ResultValueBase(other.type()), - m_errorMessage(other.errorMessage()) { - assert(type() != ResultBase::Ok); + explicit BasicResult( BasicResult const &other ) + : ResultValueBase( other.type() ), + m_errorMessage( other.errorMessage() ) + { + assert( type() != ResultBase::Ok ); } - static auto ok() -> BasicResult { return {ResultBase::Ok}; } - template - static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; } - - static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; } - - static auto runtimeError(std::string const &message) -> BasicResult { - return {ResultBase::RuntimeError, message}; - } + static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } + static auto ok() -> BasicResult { return { ResultBase::Ok }; } + static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } + static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } explicit operator bool() const { return m_type == ResultBase::Ok; } - auto type() const -> ResultBase::Type { return m_type; } - auto errorMessage() const -> std::string { return m_errorMessage; } protected: virtual void enforceOk() const { // !TBD: If no exceptions, std::terminate here or something - switch (m_type) { + switch( m_type ) { case ResultBase::LogicError: - throw std::logic_error(m_errorMessage); + throw std::logic_error( m_errorMessage ); case ResultBase::RuntimeError: - throw std::runtime_error(m_errorMessage); + throw std::runtime_error( m_errorMessage ); case ResultBase::Ok: break; } @@ -4772,10 +4906,11 @@ namespace detail { std::string m_errorMessage; // Only populated if resultType is an error - BasicResult(ResultBase::Type type, std::string const &message) - : ResultValueBase(type), - m_errorMessage(message) { - assert(m_type != ResultBase::Ok); + BasicResult( ResultBase::Type type, std::string const &message ) + : ResultValueBase(type), + m_errorMessage(message) + { + assert( m_type != ResultBase::Ok ); } using ResultValueBase::ResultValueBase; @@ -4789,12 +4924,12 @@ namespace detail { class ParseState { public: - ParseState(ParseResultType type, TokenStream const &remainingTokens) - : m_type(type), - m_remainingTokens(remainingTokens) {} + ParseState( ParseResultType type, TokenStream const &remainingTokens ) + : m_type(type), + m_remainingTokens( remainingTokens ) + {} auto type() const -> ParseResultType { return m_type; } - auto remainingTokens() const -> TokenStream { return m_remainingTokens; } private: @@ -4812,69 +4947,62 @@ namespace detail { }; template - inline auto convertInto(std::string const &source, T& target) -> ParserResult { + inline auto convertInto( std::string const &source, T& target ) -> ParserResult { std::stringstream ss; ss << source; ss >> target; - if (ss.fail()) - return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type"); + if( ss.fail() ) + return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); else - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - inline auto convertInto(std::string const &source, std::string& target) -> ParserResult { + inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { target = source; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - inline auto convertInto(std::string const &source, bool &target) -> ParserResult { + inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { std::string srcLC = source; - std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast( ::tolower(c) ); } ); + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } ); if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") target = true; else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") target = false; else - return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'"); - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); + return ParserResult::ok( ParseResultType::Matched ); } struct BoundRefBase { BoundRefBase() = default; - - BoundRefBase(BoundRefBase const &) = delete; - - BoundRefBase(BoundRefBase &&) = delete; - - BoundRefBase &operator=(BoundRefBase const &) = delete; - - BoundRefBase &operator=(BoundRefBase &&) = delete; + BoundRefBase( BoundRefBase const & ) = delete; + BoundRefBase( BoundRefBase && ) = delete; + BoundRefBase &operator=( BoundRefBase const & ) = delete; + BoundRefBase &operator=( BoundRefBase && ) = delete; virtual ~BoundRefBase() = default; virtual auto isFlag() const -> bool = 0; - virtual auto isContainer() const -> bool { return false; } - - virtual auto setValue(std::string const &arg) -> ParserResult = 0; - - virtual auto setFlag(bool flag) -> ParserResult = 0; + virtual auto setValue( std::string const &arg ) -> ParserResult = 0; + virtual auto setFlag( bool flag ) -> ParserResult = 0; }; struct BoundValueRefBase : BoundRefBase { auto isFlag() const -> bool override { return false; } - auto setFlag(bool) -> ParserResult override { - return ParserResult::logicError("Flags can only be set on boolean fields"); + auto setFlag( bool ) -> ParserResult override { + return ParserResult::logicError( "Flags can only be set on boolean fields" ); } }; struct BoundFlagRefBase : BoundRefBase { auto isFlag() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { bool flag; - auto result = convertInto(arg, flag); - if (result) - setFlag(flag); + auto result = convertInto( arg, flag ); + if( result ) + setFlag( flag ); return result; } }; @@ -4883,10 +5011,10 @@ namespace detail { struct BoundRef : BoundValueRefBase { T &m_ref; - explicit BoundRef(T &ref) : m_ref(ref) {} + explicit BoundRef( T &ref ) : m_ref( ref ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return convertInto(arg, m_ref); + auto setValue( std::string const &arg ) -> ParserResult override { + return convertInto( arg, m_ref ); } }; @@ -4894,15 +5022,15 @@ namespace detail { struct BoundRef> : BoundValueRefBase { std::vector &m_ref; - explicit BoundRef(std::vector &ref) : m_ref(ref) {} + explicit BoundRef( std::vector &ref ) : m_ref( ref ) {} auto isContainer() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { T temp; - auto result = convertInto(arg, temp); - if (result) - m_ref.push_back(temp); + auto result = convertInto( arg, temp ); + if( result ) + m_ref.push_back( temp ); return result; } }; @@ -4910,40 +5038,40 @@ namespace detail { struct BoundFlagRef : BoundFlagRefBase { bool &m_ref; - explicit BoundFlagRef(bool &ref) : m_ref(ref) {} + explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} - auto setFlag(bool flag) -> ParserResult override { + auto setFlag( bool flag ) -> ParserResult override { m_ref = flag; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } }; template struct LambdaInvoker { - static_assert(std::is_same::value, "Lambda must return void or clara::ParserResult"); + static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - return lambda(arg); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + return lambda( arg ); } }; template<> struct LambdaInvoker { template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - lambda(arg); - return ParserResult::ok(ParseResultType::Matched); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + lambda( arg ); + return ParserResult::ok( ParseResultType::Matched ); } }; template - inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { + inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { ArgType temp; - auto result = convertInto(arg, temp); + auto result = convertInto( arg, temp ); return !result - ? result - : LambdaInvoker::ReturnType>::invoke(lambda, temp); + ? result + : LambdaInvoker::ReturnType>::invoke( lambda, temp ); }; template @@ -4951,10 +5079,10 @@ namespace detail { L m_lambda; static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return invokeLambda::ArgType>(m_lambda, arg); + auto setValue( std::string const &arg ) -> ParserResult override { + return invokeLambda::ArgType>( m_lambda, arg ); } }; @@ -4965,16 +5093,14 @@ namespace detail { static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); - explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setFlag(bool flag) -> ParserResult override { - return LambdaInvoker::ReturnType>::invoke(m_lambda, flag); + auto setFlag( bool flag ) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); } }; - enum class Optionality { - Optional, Required - }; + enum class Optionality { Optional, Required }; struct Parser; @@ -4985,8 +5111,8 @@ namespace detail { virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; virtual auto cardinality() const -> size_t { return 1; } - auto parse(Args const &args) const -> InternalParseResult { - return parse( args.exeName(), TokenStream(args)); + auto parse( Args const &args ) const -> InternalParseResult { + return parse( args.exeName(), TokenStream( args ) ); } }; @@ -4994,7 +5120,7 @@ namespace detail { class ComposableParserImpl : public ParserBase { public: template - auto operator+(T const &other) const -> Parser; + auto operator|( T const &other ) const -> Parser; }; // Common code and state for Args and Opts @@ -5006,17 +5132,22 @@ namespace detail { std::string m_hint; std::string m_description; - explicit ParserRefImpl(std::shared_ptr const &ref) : m_ref(ref) {} + explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} public: template - ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), m_hint(hint) {} + ParserRefImpl( T &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint( hint ) + {} template - ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), - m_hint(hint) {} + ParserRefImpl( LambdaT const &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint(hint) + {} - auto operator()(std::string const &description) -> DerivedT & { + auto operator()( std::string const &description ) -> DerivedT & { m_description = description; return static_cast( *this ); } @@ -5036,7 +5167,7 @@ namespace detail { } auto cardinality() const -> size_t override { - if (m_ref->isContainer()) + if( m_ref->isContainer() ) return 0; else return 1; @@ -5051,13 +5182,13 @@ namespace detail { template static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { - return std::make_shared>(lambda); + return std::make_shared>( lambda) ; } public: - ExeName() : m_name(std::make_shared("")) {} + ExeName() : m_name( std::make_shared( "" ) ) {} - explicit ExeName(std::string &ref) : ExeName() { + explicit ExeName( std::string &ref ) : ExeName() { m_ref = std::make_shared>( ref ); } @@ -5068,14 +5199,14 @@ namespace detail { // The exe name is not parsed out of the normal tokens, but is handled specially auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); } auto name() const -> std::string { return *m_name; } auto set( std::string const& newName ) -> ParserResult { auto lastSlash = newName.find_last_of( "\\/" ); - auto filename = (lastSlash == std::string::npos) + auto filename = ( lastSlash == std::string::npos ) ? newName : newName.substr( lastSlash+1 ); @@ -5091,27 +5222,27 @@ namespace detail { public: using ParserRefImpl::ParserRefImpl; - auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { + auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; auto const &token = *remainingTokens; - if (token.type != TokenType::Argument) - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + if( token.type != TokenType::Argument ) + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - auto result = m_ref->setValue(remainingTokens->token); - if (!result) - return InternalParseResult(result); + auto result = m_ref->setValue( remainingTokens->token ); + if( !result ) + return InternalParseResult( result ); else - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } }; - inline auto normaliseOpt(std::string const &optName) -> std::string { - if (optName[0] == '/') - return "-" + optName.substr(1); + inline auto normaliseOpt( std::string const &optName ) -> std::string { + if( optName[0] == '/' ) + return "-" + optName.substr( 1 ); else return optName; } @@ -5122,9 +5253,9 @@ namespace detail { public: template - explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} + explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} - explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} template Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} @@ -5132,34 +5263,34 @@ namespace detail { template Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - auto operator[](std::string const &optName) -> Opt & { - m_optNames.push_back(optName); + auto operator[]( std::string const &optName ) -> Opt & { + m_optNames.push_back( optName ); return *this; } auto getHelpColumns() const -> std::vector { std::ostringstream oss; bool first = true; - for (auto const &opt : m_optNames) { + for( auto const &opt : m_optNames ) { if (first) first = false; else oss << ", "; oss << opt; } - if (!m_hint.empty()) + if( !m_hint.empty() ) oss << " <" << m_hint << ">"; - return {{oss.str(), m_description}}; + return { { oss.str(), m_description } }; } - auto isMatch(std::string const &optToken) const -> bool { -#ifdef CLARA_PLATFORM_WINDOWS + auto isMatch( std::string const &optToken ) const -> bool { +#ifdef CATCH_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); #else auto const &normalisedToken = optToken; #endif - for (auto const &name : m_optNames) { - if (normaliseOpt(name) == normalisedToken) + for( auto const &name : m_optNames ) { + if( normaliseOpt( name ) == normalisedToken ) return true; } return false; @@ -5169,46 +5300,46 @@ namespace detail { auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; - if (remainingTokens && remainingTokens->type == TokenType::Option) { + if( remainingTokens && remainingTokens->type == TokenType::Option ) { auto const &token = *remainingTokens; - if (isMatch(token.token)) { - if (m_ref->isFlag()) { - auto result = m_ref->setFlag(true); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( isMatch(token.token ) ) { + if( m_ref->isFlag() ) { + auto result = m_ref->setFlag( true ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } else { ++remainingTokens; - if (!remainingTokens) - return InternalParseResult::runtimeError("Expected argument following " + token.token); + if( !remainingTokens ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); auto const &argToken = *remainingTokens; - if (argToken.type != TokenType::Argument) - return InternalParseResult::runtimeError("Expected argument following " + token.token); - auto result = m_ref->setValue(argToken.token); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( argToken.type != TokenType::Argument ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto result = m_ref->setValue( argToken.token ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } } - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); } auto validate() const -> Result override { - if (m_optNames.empty()) - return Result::logicError("No options supplied to Opt"); - for (auto const &name : m_optNames) { - if (name.empty()) - return Result::logicError("Option name cannot be empty"); - if (name[0] != '-' && name[0] != '/') - return Result::logicError("Option name must begin with '-' or '/'"); + if( m_optNames.empty() ) + return Result::logicError( "No options supplied to Opt" ); + for( auto const &name : m_optNames ) { + if( name.empty() ) + return Result::logicError( "Option name cannot be empty" ); + if( name[0] != '-' && name[0] != '/' ) + return Result::logicError( "Option name must begin with '-' or '/'" ); } return ParserRefImpl::validate(); } @@ -5217,11 +5348,11 @@ namespace detail { struct Help : Opt { Help( bool &showHelpFlag ) : Opt([&]( bool flag ) { - showHelpFlag = flag; - return ParserResult::ok(ParseResultType::ShortCircuitAll); + showHelpFlag = flag; + return ParserResult::ok( ParseResultType::ShortCircuitAll ); }) { - static_cast(*this) + static_cast( *this ) ("display usage information") ["-?"]["-h"]["--help"] .optional(); @@ -5234,61 +5365,61 @@ namespace detail { std::vector m_options; std::vector m_args; - auto operator+=(ExeName const &exeName) -> Parser & { + auto operator|=( ExeName const &exeName ) -> Parser & { m_exeName = exeName; return *this; } - auto operator+=(Arg const &arg) -> Parser & { + auto operator|=( Arg const &arg ) -> Parser & { m_args.push_back(arg); return *this; } - auto operator+=(Opt const &opt) -> Parser & { + auto operator|=( Opt const &opt ) -> Parser & { m_options.push_back(opt); return *this; } - auto operator+=(Parser const &other) -> Parser & { + auto operator|=( Parser const &other ) -> Parser & { m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); return *this; } template - auto operator+(T const &other) const -> Parser { - return Parser(*this) += other; + auto operator|( T const &other ) const -> Parser { + return Parser( *this ) |= other; } auto getHelpColumns() const -> std::vector { std::vector cols; for (auto const &o : m_options) { auto childCols = o.getHelpColumns(); - cols.insert(cols.end(), childCols.begin(), childCols.end()); + cols.insert( cols.end(), childCols.begin(), childCols.end() ); } return cols; } - void writeToStream(std::ostream &os) const { + void writeToStream( std::ostream &os ) const { if (!m_exeName.name().empty()) { os << "usage:\n" << " " << m_exeName.name() << " "; bool required = true, first = true; - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { if (first) first = false; else os << " "; - if (arg.isOptional() && required) { + if( arg.isOptional() && required ) { os << "["; required = false; } os << "<" << arg.hint() << ">"; - if (arg.cardinality() == 0) + if( arg.cardinality() == 0 ) os << " ... "; } - if (!required) + if( !required ) os << "]"; - if (!m_options.empty()) + if( !m_options.empty() ) os << " options"; os << "\n\nwhere options are:" << std::endl; } @@ -5296,32 +5427,32 @@ namespace detail { auto rows = getHelpColumns(); size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; - for (auto const &cols : rows) + for( auto const &cols : rows ) optWidth = std::max(optWidth, cols.left.size() + 2); - for (auto const &cols : rows) { + for( auto const &cols : rows ) { auto row = - TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + TextFlow::Spacer(4) + - TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); + TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); os << row << std::endl; } } - friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { - parser.writeToStream(os); + friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { + parser.writeToStream( os ); return os; } auto validate() const -> Result override { - for (auto const &opt : m_options) { + for( auto const &opt : m_options ) { auto result = opt.validate(); - if (!result) + if( !result ) return result; } - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { auto result = arg.validate(); - if (!result) + if( !result ) return result; } return Result::ok(); @@ -5329,47 +5460,47 @@ namespace detail { using ParserBase::parse; - auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override { - std::vector allParsers; - allParsers.reserve(m_args.size() + m_options.size()); - std::set requiredParsers; + auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { - for (auto const &opt : m_options) { - allParsers.push_back(&opt); - if (!opt.isOptional()) - requiredParsers.insert(&opt); - } + struct ParserInfo { + ParserBase const* parser = nullptr; + size_t count = 0; + }; + const size_t totalParsers = m_options.size() + m_args.size(); + assert( totalParsers < 512 ); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do + ParserInfo parseInfos[512]; - size_t optionalArgs = 0; - for (auto const &arg : m_args) { - allParsers.push_back(&arg); - if (!arg.isOptional()) { - if (optionalArgs > 0) - return InternalParseResult::logicError( - "Required arguments must preceed any optional arguments"); - else - ++optionalArgs; - requiredParsers.insert(&arg); - } + { + size_t i = 0; + for (auto const &opt : m_options) parseInfos[i++].parser = &opt; + for (auto const &arg : m_args) parseInfos[i++].parser = &arg; } m_exeName.set( exeName ); - auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); - while (result.value().remainingTokens()) { - auto remainingTokenCount = result.value().remainingTokens().count(); - for (auto parser : allParsers) { - result = parser->parse( exeName, result.value().remainingTokens() ); - if (!result || result.value().type() != ParseResultType::NoMatch) { - if (parser->cardinality() == 1) - allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser), - allParsers.end()); - requiredParsers.erase(parser); - break; + auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + while( result.value().remainingTokens() ) { + bool tokenParsed = false; + + for( size_t i = 0; i < totalParsers; ++i ) { + auto& parseInfo = parseInfos[i]; + if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { + result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); + if (!result) + return result; + if (result.value().type() != ParseResultType::NoMatch) { + tokenParsed = true; + ++parseInfo.count; + break; + } } } - if (!result || remainingTokenCount == result.value().remainingTokens().count()) + + if( result.value().type() == ParseResultType::ShortCircuitAll ) return result; + if( !tokenParsed ) + return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); } // !TBD Check missing required options return result; @@ -5378,8 +5509,8 @@ namespace detail { template template - auto ComposableParserImpl::operator+(T const &other) const -> Parser { - return Parser() + static_cast( *this ) + other; + auto ComposableParserImpl::operator|( T const &other ) const -> Parser { + return Parser() | static_cast( *this ) | other; } } // namespace detail @@ -5516,84 +5647,84 @@ namespace Catch { auto cli = ExeName( config.processName ) - + Help( config.showHelp ) - + Opt( config.listTests ) + | Help( config.showHelp ) + | Opt( config.listTests ) ["-l"]["--list-tests"] ( "list all/matching test cases" ) - + Opt( config.listTags ) + | Opt( config.listTags ) ["-t"]["--list-tags"] ( "list all/matching tags" ) - + Opt( config.showSuccessfulTests ) + | Opt( config.showSuccessfulTests ) ["-s"]["--success"] ( "include successful tests in output" ) - + Opt( config.shouldDebugBreak ) + | Opt( config.shouldDebugBreak ) ["-b"]["--break"] ( "break into debugger on failure" ) - + Opt( config.noThrow ) + | Opt( config.noThrow ) ["-e"]["--nothrow"] ( "skip exception tests" ) - + Opt( config.showInvisibles ) + | Opt( config.showInvisibles ) ["-i"]["--invisibles"] ( "show invisibles (tabs, newlines)" ) - + Opt( config.outputFilename, "filename" ) + | Opt( config.outputFilename, "filename" ) ["-o"]["--out"] ( "output filename" ) - + Opt( config.reporterNames, "name" ) + | Opt( config.reporterNames, "name" ) ["-r"]["--reporter"] ( "reporter to use (defaults to console)" ) - + Opt( config.name, "name" ) + | Opt( config.name, "name" ) ["-n"]["--name"] ( "suite name" ) - + Opt( [&]( bool ){ config.abortAfter = 1; } ) + | Opt( [&]( bool ){ config.abortAfter = 1; } ) ["-a"]["--abort"] ( "abort at first failure" ) - + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) ["-x"]["--abortx"] ( "abort after x failures" ) - + Opt( setWarning, "warning name" ) + | Opt( setWarning, "warning name" ) ["-w"]["--warn"] ( "enable warnings" ) - + Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) + | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) ["-d"]["--durations"] ( "show test durations" ) - + Opt( loadTestNamesFromFile, "filename" ) + | Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] ( "load test names to run from a file" ) - + Opt( config.filenamesAsTags ) + | Opt( config.filenamesAsTags ) ["-#"]["--filenames-as-tags"] ( "adds a tag for the filename" ) - + Opt( config.sectionsToRun, "section name" ) + | Opt( config.sectionsToRun, "section name" ) ["-c"]["--section"] ( "specify section to run" ) - + Opt( setVerbosity, "quiet|normal|high" ) + | Opt( setVerbosity, "quiet|normal|high" ) ["-v"]["--verbosity"] ( "set output verbosity" ) - + Opt( config.listTestNamesOnly ) + | Opt( config.listTestNamesOnly ) ["--list-test-names-only"] ( "list all/matching test cases names only" ) - + Opt( config.listReporters ) + | Opt( config.listReporters ) ["--list-reporters"] ( "list all reporters" ) - + Opt( setTestOrder, "decl|lex|rand" ) + | Opt( setTestOrder, "decl|lex|rand" ) ["--order"] ( "test case order (defaults to decl)" ) - + Opt( setRngSeed, "'time'|number" ) + | Opt( setRngSeed, "'time'|number" ) ["--rng-seed"] ( "set a specific seed for random numbers" ) - + Opt( setColourUsage, "yes|no" ) + | Opt( setColourUsage, "yes|no" ) ["--use-colour"] ( "should output be colourised" ) - + Opt( config.libIdentify ) + | Opt( config.libIdentify ) ["--libidentify"] ( "report name and version according to libidentify standard" ) - + Opt( setWaitForKeypress, "start|exit|both" ) + | Opt( setWaitForKeypress, "start|exit|both" ) ["--wait-for-keypress"] ( "waits for a keypress before exiting" ) - + Opt( config.benchmarkResolutionMultiple, "multiplier" ) + | Opt( config.benchmarkResolutionMultiple, "multiplier" ) ["--benchmark-resolution-multiple"] ( "multiple of clock resolution to run benchmarks" ) - + Arg( config.testsOrTags, "test name|pattern|tags" ) + | Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); return cli; @@ -5731,6 +5862,36 @@ namespace Catch { } // end catch_errno_guard.h +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) + +#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +#endif +#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINED_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +#endif // defined(CATCH_PLATFORM_WINDOWS) + +// end catch_windows_h_proxy.h namespace Catch { namespace { @@ -5761,34 +5922,6 @@ namespace Catch { #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// -// start catch_windows_h_proxy.h - - -#if defined(CATCH_PLATFORM_WINDOWS) -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX -# define NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINED_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - -// end catch_windows_h_proxy.h namespace Catch { namespace { @@ -6220,7 +6353,7 @@ namespace Catch { #endif } catch( TestFailureException& ) { - throw; + std::rethrow_exception(std::current_exception()); } catch( std::exception& ex ) { return ex.what(); @@ -6238,7 +6371,7 @@ namespace Catch { std::string ExceptionTranslatorRegistry::tryTranslators() const { if( m_translators.empty() ) - throw; + std::rethrow_exception(std::current_exception()); else return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } @@ -6523,6 +6656,9 @@ namespace Catch { static std::set getSupportedVerbosities(); + void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; + void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; + void testRunStarting( TestRunInfo const& testRunInfo ) override; void testGroupStarting( GroupInfo const& groupInfo ) override; void testCaseStarting( TestCaseInfo const& testInfo ) override; @@ -9649,7 +9785,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 4 ); + static Version version( 2, 0, 0, "develop", 5 ); return version; } @@ -11204,6 +11340,15 @@ namespace Catch { reporter->noMatchingTestCases( spec ); } + void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkStarting( benchmarkInfo ); + } + void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkEnded( benchmarkStats ); + } + void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { for( auto const& reporter : m_reporters ) reporter->testRunStarting( testRunInfo ); diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 2311ab7f..96d93985 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.0.0-develop.4@%s/%s" % (username, channel) + requires = "Catch/2.0.0-develop.5@%s/%s" % (username, channel) def build(self): cmake = CMake(self) From c7d9f02d5b723183fb170209e740c7c097c2af04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 12 Oct 2017 21:42:09 +0200 Subject: [PATCH 367/398] Add pkg-config support Closes #1032 --- CMakeLists.txt | 15 +++++++++++++++ catch.pc.in | 10 ++++++++++ scripts/releaseCommon.py | 13 +++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 catch.pc.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 17248cfa..f25f47fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark) set(HEADER_DIR ${CATCH_DIR}/include) +set(CATCH_VERSION_NUMBER 2.0.0) if(USE_CPP14) message(STATUS "Enabling C++14") @@ -331,3 +332,17 @@ endif() # !NO_SELFTEST install(DIRECTORY "single_include/" DESTINATION "include/catch") + +## Provide some pkg-config integration +# Don't bother on Windows +if(NOT WIN32 OR NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows) + + set(PKGCONFIG_INSTALL_DIR + "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" + CACHE PATH "Path where catch.pc is installed" + ) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/catch.pc.in ${CMAKE_CURRENT_BINARY_DIR}/catch.pc @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/catch.pc DESTINATION ${PKGCONFIG_INSTALL_DIR}) + +endif() diff --git a/catch.pc.in b/catch.pc.in new file mode 100644 index 00000000..de6fdfea --- /dev/null +++ b/catch.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} + +Name: Catch +Description: Testing library for C++ +Requires: +Version: @CATCH_VERSION_NUMBER@ +Libs: +Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@ + diff --git a/scripts/releaseCommon.py b/scripts/releaseCommon.py index 6ec175f6..2acd4869 100644 --- a/scripts/releaseCommon.py +++ b/scripts/releaseCommon.py @@ -15,6 +15,7 @@ versionPath = os.path.join( rootPath, "internal/catch_version.cpp" ) readmePath = os.path.join( catchPath, "README.md" ) conanPath = os.path.join(catchPath, 'conanfile.py') conanTestPath = os.path.join(catchPath, 'test_package', 'conanfile.py') +cmakePath = os.path.join(catchPath, 'CMakeLists.txt') class Version: def __init__(self): @@ -126,6 +127,17 @@ def updateConanTestFile(version): for line in lines: f.write( line + "\n" ) +def updateCmakeFile(version): + cmakeParser = re.compile(r'set(CATCH_VERSION_NUMBER \d+\.\d+\.\d+)') + with open(cmakePath, 'r') as file: + lines = file.readlines() + with open(cmakePath, 'w') as file: + for line in lines: + if 'set(CATCH_VERSION_NUMBER ' in line: + file.write('set(CATCH_VERSION_NUMBER {0})\n'.format(version.getVersionString())) + else: + file.write(line) + def performUpdates(version): # First update version file, so we can regenerate single header and # have it ready for upload to wandbox, when updating readme @@ -134,3 +146,4 @@ def performUpdates(version): updateReadmeFile(version) updateConanFile(version) updateConanTestFile(version) + updateCmakeFile(version) From 276393e4e59b8be4c1a5fc14c19749fee3eb28ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 13 Oct 2017 11:14:37 +0200 Subject: [PATCH 368/398] Change ToC script to use
instead of trailing spaces Also updated docs that contain ToC. Fixes #1048 --- docs/assertions.md | 10 ++++---- docs/command-line.md | 46 ++++++++++++++++++------------------ docs/configuration.md | 18 +++++++------- docs/slow-compiles.md | 10 ++++---- docs/tutorial.md | 16 ++++++------- scripts/updateDocumentToC.py | 8 +++---- 6 files changed, 54 insertions(+), 54 deletions(-) diff --git a/docs/assertions.md b/docs/assertions.md index 66d127bb..3a9d898e 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -1,11 +1,11 @@ # Assertion Macros -**Contents** -[Natural Expressions](#natural-expressions) -[Exceptions](#exceptions) -[Matcher expressions](#matcher-expressions) -[Thread Safety](#thread-safety) +**Contents**
+[Natural Expressions](#natural-expressions)
+[Exceptions](#exceptions)
+[Matcher expressions](#matcher-expressions)
+[Thread Safety](#thread-safety)
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc). diff --git a/docs/command-line.md b/docs/command-line.md index 00d55852..8afcb7d4 100644 --- a/docs/command-line.md +++ b/docs/command-line.md @@ -1,29 +1,29 @@ # Command line -**Contents** -[Specifying which tests to run](#specifying-which-tests-to-run) -[Choosing a reporter to use](#choosing-a-reporter-to-use) -[Breaking into the debugger](#breaking-into-the-debugger) -[Showing results for successful tests](#showing-results-for-successful-tests) -[Aborting after a certain number of failures](#aborting-after-a-certain-number-of-failures) -[Listing available tests, tags or reporters](#listing-available-tests-tags-or-reporters) -[Sending output to a file](#sending-output-to-a-file) -[Naming a test run](#naming-a-test-run) -[Eliding assertions expected to throw](#eliding-assertions-expected-to-throw) -[Make whitespace visible](#make-whitespace-visible) -[Warnings](#warnings) -[Reporting timings](#reporting-timings) -[Load test names to run from a file](#load-test-names-to-run-from-a-file) -[Just test names](#just-test-names) -[Specify the order test cases are run](#specify-the-order-test-cases-are-run) -[Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator) -[Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard) -[Wait for key before continuing](#wait-for-key-before-continuing) -[Specify multiples of clock resolution to run benchmarks for](#specify-multiples-of-clock-resolution-to-run-benchmarks-for) -[Usage](#usage) -[Specify the section to run](#specify-the-section-to-run) -[Filenames as tags](#filenames-as-tags) +**Contents**
+[Specifying which tests to run](#specifying-which-tests-to-run)
+[Choosing a reporter to use](#choosing-a-reporter-to-use)
+[Breaking into the debugger](#breaking-into-the-debugger)
+[Showing results for successful tests](#showing-results-for-successful-tests)
+[Aborting after a certain number of failures](#aborting-after-a-certain-number-of-failures)
+[Listing available tests, tags or reporters](#listing-available-tests-tags-or-reporters)
+[Sending output to a file](#sending-output-to-a-file)
+[Naming a test run](#naming-a-test-run)
+[Eliding assertions expected to throw](#eliding-assertions-expected-to-throw)
+[Make whitespace visible](#make-whitespace-visible)
+[Warnings](#warnings)
+[Reporting timings](#reporting-timings)
+[Load test names to run from a file](#load-test-names-to-run-from-a-file)
+[Just test names](#just-test-names)
+[Specify the order test cases are run](#specify-the-order-test-cases-are-run)
+[Specify a seed for the Random Number Generator](#specify-a-seed-for-the-random-number-generator)
+[Identify framework and version according to the libIdentify standard](#identify-framework-and-version-according-to-the-libidentify-standard)
+[Wait for key before continuing](#wait-for-key-before-continuing)
+[Specify multiples of clock resolution to run benchmarks for](#specify-multiples-of-clock-resolution-to-run-benchmarks-for)
+[Usage](#usage)
+[Specify the section to run](#specify-the-section-to-run)
+[Filenames as tags](#filenames-as-tags)
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available. Click one of the followings links to take you straight to that option - or scroll on to browse the available options. diff --git a/docs/configuration.md b/docs/configuration.md index bbb27ac0..56d2327b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,15 +1,15 @@ # Compile-time configuration -**Contents** -[main()/ implementation](#main-implementation) -[Prefixing Catch macros](#prefixing-catch-macros) -[Terminal colour](#terminal-colour) -[Console width](#console-width) -[stdout](#stdout) -[Other toggles](#other-toggles) -[Windows header clutter](#windows-header-clutter) -[Enabling stringification](#enabling-stringification) +**Contents**
+[main()/ implementation](#main-implementation)
+[Prefixing Catch macros](#prefixing-catch-macros)
+[Terminal colour](#terminal-colour)
+[Console width](#console-width)
+[stdout](#stdout)
+[Other toggles](#other-toggles)
+[Windows header clutter](#windows-header-clutter)
+[Enabling stringification](#enabling-stringification)
Catch is designed to "just work" as much as possible. For most people the only configuration needed is telling Catch which source file should host all the implementation code (```CATCH_CONFIG_MAIN```). diff --git a/docs/slow-compiles.md b/docs/slow-compiles.md index 9696757d..0853b661 100644 --- a/docs/slow-compiles.md +++ b/docs/slow-compiles.md @@ -1,11 +1,11 @@ # Why do my tests take so long to compile? -**Contents** -[Short answer](#short-answer) -[Long answer](#long-answer) -[Practical example](#practical-example) -[Other possible solutions](#other-possible-solutions) +**Contents**
+[Short answer](#short-answer)
+[Long answer](#long-answer)
+[Practical example](#practical-example)
+[Other possible solutions](#other-possible-solutions)
Several people have reported that test code written with Catch takes much longer to compile than they would expect. Why is that? diff --git a/docs/tutorial.md b/docs/tutorial.md index ebc20fd2..1b55bcf1 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -1,14 +1,14 @@ # Tutorial -**Contents** -[Getting Catch](#getting-catch) -[Where to put it?](#where-to-put-it) -[Writing tests](#writing-tests) -[Test cases and sections](#test-cases-and-sections) -[BDD-Style](#bdd-style) -[Scaling up](#scaling-up) -[Next steps](#next-steps) +**Contents**
+[Getting Catch](#getting-catch)
+[Where to put it?](#where-to-put-it)
+[Writing tests](#writing-tests)
+[Test cases and sections](#test-cases-and-sections)
+[BDD-Style](#bdd-style)
+[Scaling up](#scaling-up)
+[Next steps](#next-steps)
## Getting Catch diff --git a/scripts/updateDocumentToC.py b/scripts/updateDocumentToC.py index b1ab6dd2..948e5e1d 100644 --- a/scripts/updateDocumentToC.py +++ b/scripts/updateDocumentToC.py @@ -30,7 +30,7 @@ headingExcludeRelease = [2,3,4,5] # use level 1 headers for release-notes.md documentsDefault = os.path.join(os.path.relpath(catchPath), 'docs/*.md') releaseNotesName = 'release-notes.md' -contentTitle = '**Contents** ' +contentTitle = '**Contents**' contentLineNo = 4 contentLineNdx = contentLineNo - 1 @@ -210,14 +210,14 @@ def createToc(headlines, hyperlink=True, top_link=False, no_toc_header=False): if not no_toc_header: if top_link: processed.append('\n') - processed.append(contentTitle) + processed.append(contentTitle + '
') for line in headlines: if hyperlink: - item = '[%s](#%s) ' % (line[0], line[1]) + item = '[%s](#%s)' % (line[0], line[1]) else: item = '%s- %s' % ((line[2]-1)*' ', line[0]) - processed.append(item) + processed.append(item + '
') processed.append('\n') return processed From 2eb93f47f7523146b3a10a22034c3525fde92bbe Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 12 Oct 2017 16:00:04 +0100 Subject: [PATCH 369/398] enclosed more min/ max in parentheses to default MFC macros --- include/internal/catch_approx.cpp | 2 +- include/internal/catch_approx.h | 5 +++-- include/internal/catch_random_number_generator.cpp | 2 +- include/internal/catch_random_number_generator.h | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp index 51f4b243..ca3ac94a 100644 --- a/include/internal/catch_approx.cpp +++ b/include/internal/catch_approx.cpp @@ -13,7 +13,7 @@ namespace Catch { namespace Detail { - double max(double lhs, double rhs) { + double dmax(double lhs, double rhs) { if (lhs < rhs) { return rhs; } diff --git a/include/internal/catch_approx.h b/include/internal/catch_approx.h index 2185b8f6..a2af9c86 100644 --- a/include/internal/catch_approx.h +++ b/include/internal/catch_approx.h @@ -17,7 +17,7 @@ namespace Catch { namespace Detail { - double max(double lhs, double rhs); + double dmax(double lhs, double rhs); class Approx { public: @@ -43,7 +43,8 @@ namespace Detail { friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula auto lhs_v = static_cast(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); + bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + + dmax(std::fabs(lhs_v), std::fabs(rhs.m_value))); if (relativeOK) { return true; } diff --git a/include/internal/catch_random_number_generator.cpp b/include/internal/catch_random_number_generator.cpp index 7149a58b..412faeba 100644 --- a/include/internal/catch_random_number_generator.cpp +++ b/include/internal/catch_random_number_generator.cpp @@ -25,7 +25,7 @@ namespace Catch { return std::rand() % n; } RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { - return std::rand() % max(); + return std::rand() % (max)(); } } diff --git a/include/internal/catch_random_number_generator.h b/include/internal/catch_random_number_generator.h index 859e6cdf..1a61202d 100644 --- a/include/internal/catch_random_number_generator.h +++ b/include/internal/catch_random_number_generator.h @@ -22,8 +22,8 @@ namespace Catch { struct RandomNumberGenerator { using result_type = std::ptrdiff_t; - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return 1000000; } + static constexpr result_type (min)() { return 0; } + static constexpr result_type (max)() { return 1000000; } result_type operator()( result_type n ) const; result_type operator()() const; From ba6845a865c6d198557dede3f556214bf926942f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 12 Oct 2017 16:06:40 +0100 Subject: [PATCH 370/398] Version of Clara with (std::max) --- include/external/clara.hpp | 2 +- third_party/clara.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 668d9e48..3f2d13bf 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -1103,7 +1103,7 @@ namespace detail { size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; for( auto const &cols : rows ) - optWidth = std::max(optWidth, cols.left.size() + 2); + optWidth = (std::max)(optWidth, cols.left.size() + 2); for( auto const &cols : rows ) { auto row = diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 5778c562..83c4c514 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -1103,7 +1103,7 @@ namespace detail { size_t consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; for( auto const &cols : rows ) - optWidth = std::max(optWidth, cols.left.size() + 2); + optWidth = (std::max)(optWidth, cols.left.size() + 2); for( auto const &cols : rows ) { auto row = From c2b7bd15c092e2528f52bf26046e3c55ca629392 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 13 Oct 2017 14:16:14 +0100 Subject: [PATCH 371/398] Changed rhs expression capture from universal ref to const ref. - addresses #1027 --- include/internal/catch_decomposer.h | 26 +++++++++---------- .../Baselines/console.std.approved.txt | 4 +-- .../Baselines/console.sw.approved.txt | 22 ++++++++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 3 ++- .../SelfTest/Baselines/xml.sw.approved.txt | 23 ++++++++++++++-- projects/SelfTest/TrickyTests.cpp | 11 +++++++- 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index 786a052e..fee24e72 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -77,7 +77,7 @@ namespace Catch { // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template - auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; + auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; }; template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } template @@ -106,36 +106,36 @@ namespace Catch { ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} template - auto operator == ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); + auto operator == ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); } auto operator == ( bool rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs == rhs, m_lhs, "==", rhs ); } template - auto operator != ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); + auto operator != ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); } auto operator != ( bool rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs != rhs, m_lhs, "!=", rhs ); } template - auto operator > ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); + auto operator > ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); } template - auto operator < ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); + auto operator < ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); } template - auto operator >= ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); + auto operator >= ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); } template - auto operator <= ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); + auto operator <= ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); } auto makeUnaryExpr() const -> UnaryExpr { diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 6aaa7ed1..939d0d89 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 179 | 128 passed | 47 failed | 4 failed as expected -assertions: 884 | 767 passed | 96 failed | 21 failed as expected +test cases: 180 | 129 passed | 47 failed | 4 failed as expected +assertions: 886 | 769 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 10b6fc35..1d64df20 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -738,6 +738,24 @@ PASSED: with expansion: true +------------------------------------------------------------------------------- +Bitfields can be captured (#1027) +------------------------------------------------------------------------------- +TrickyTests.cpp: +............................................................................... + +TrickyTests.cpp:: +PASSED: + REQUIRE( y.v == 0 ) +with expansion: + 0 == 0 + +TrickyTests.cpp:: +PASSED: + REQUIRE( 0 == y.v ) +with expansion: + 0 == 0 + ------------------------------------------------------------------------------- Capture and info messages Capture should stringify like assertions @@ -7490,6 +7508,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 179 | 126 passed | 49 failed | 4 failed as expected -assertions: 883 | 763 passed | 99 failed | 21 failed as expected +test cases: 180 | 127 passed | 49 failed | 4 failed as expected +assertions: 885 | 765 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index b306b393..508b9206 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -109,6 +109,7 @@ ExceptionTests.cpp: + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index da12285d..72b7c1b6 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -750,6 +750,25 @@
+ + + + y.v == 0 + + + 0 == 0 + + + + + 0 == y.v + + + 0 == 0 + + + +
@@ -8268,7 +8287,7 @@ loose text artifact
- + - + diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 78f7052f..820d2fbd 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -168,7 +168,7 @@ namespace ObjectWithConversions { struct Object { - operator unsigned int() {return 0xc0000000;} + operator unsigned int() const {return 0xc0000000;} }; /////////////////////////////////////////////////////////////////////////////// @@ -436,3 +436,12 @@ TEST_CASE("#925: comparing function pointer to function address failed to compil TestClass test; REQUIRE(utility::synchronizing_callback != test.testMethod_uponComplete_arg); } + +TEST_CASE( "Bitfields can be captured (#1027)" ) { + struct Y { + uint32_t v : 1; + }; + Y y{ 0 }; + REQUIRE( y.v == 0 ); + REQUIRE( 0 == y.v ); +} From 05b1ca28844d2b2770b929415393653474866a3d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 13 Oct 2017 19:45:19 +0100 Subject: [PATCH 372/398] Fixed expansion of _FALSE binary expression - see #1051 --- include/internal/catch_assertionresult.cpp | 4 +-- .../Baselines/console.std.approved.txt | 4 +-- .../Baselines/console.sw.approved.txt | 8 +++--- .../Baselines/console.swa4.approved.txt | 2 ++ .../SelfTest/Baselines/xml.sw.approved.txt | 26 +++++++++---------- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/include/internal/catch_assertionresult.cpp b/include/internal/catch_assertionresult.cpp index 7a3a2e08..3af40dfc 100644 --- a/include/internal/catch_assertionresult.cpp +++ b/include/internal/catch_assertionresult.cpp @@ -54,8 +54,8 @@ namespace Catch { } std::string AssertionResult::getExpression() const { - if (isFalseTest(m_info.resultDisposition)) - return '!' + std::string(m_info.capturedExpression); + if( isFalseTest( m_info.resultDisposition ) ) + return "!(" + std::string(m_info.capturedExpression) + ")"; else return m_info.capturedExpression; } diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 939d0d89..cc23a7dd 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -58,6 +58,8 @@ with expansion: ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) +with expansion: + !true ConditionTests.cpp:: FAILED: CHECK( !trueValue ) @@ -76,8 +78,6 @@ with expansion: ConditionTests.cpp:: FAILED: CHECK_FALSE( 1 == 1 ) -with expansion: - !(1 == 1) ------------------------------------------------------------------------------- A METHOD_AS_TEST_CASE based test run that fails diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 1d64df20..e32d6f72 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -235,6 +235,8 @@ with expansion: ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) +with expansion: + !true ConditionTests.cpp:: FAILED: CHECK( !trueValue ) @@ -253,8 +255,6 @@ with expansion: ConditionTests.cpp:: FAILED: CHECK_FALSE( 1 == 1 ) -with expansion: - !(1 == 1) ------------------------------------------------------------------------------- 'Not' checks that should succeed @@ -279,6 +279,8 @@ with expansion: ConditionTests.cpp:: PASSED: REQUIRE_FALSE( false ) +with expansion: + !false ConditionTests.cpp:: PASSED: @@ -301,8 +303,6 @@ with expansion: ConditionTests.cpp:: PASSED: REQUIRE_FALSE( 1 == 2 ) -with expansion: - !(1 == 2) ------------------------------------------------------------------------------- (unimplemented) static bools can be evaluated diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt index 06c24e86..eacf34e1 100644 --- a/projects/SelfTest/Baselines/console.swa4.approved.txt +++ b/projects/SelfTest/Baselines/console.swa4.approved.txt @@ -235,6 +235,8 @@ with expansion: ConditionTests.cpp:: FAILED: CHECK_FALSE( true ) +with expansion: + !true =============================================================================== test cases: 9 | 6 passed | 1 failed | 2 failed as expected diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 72b7c1b6..04c6f986 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -214,7 +214,7 @@ - !true + !(true) !true @@ -230,7 +230,7 @@ - !trueValue + !(trueValue) !true @@ -246,7 +246,7 @@ - !1 == 1 + !(1 == 1) !(1 == 1) @@ -281,7 +281,7 @@ - !false + !(false) !false @@ -297,7 +297,7 @@ - !falseValue + !(falseValue) !false @@ -313,7 +313,7 @@ - !1 == 2 + !(1 == 2) !(1 == 2) @@ -393,7 +393,7 @@ - !is_true<false>::value + !(is_true<false>::value) !false @@ -975,7 +975,7 @@ - !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + !(std::vector<int>{1, 2} == std::vector<int>{1, 2, 3}) !({ 1, 2 } == { 1, 2, 3 }) @@ -983,7 +983,7 @@ - !std::vector<int>{1, 2} == std::vector<int>{1, 2, 3} + !(std::vector<int>{1, 2} == std::vector<int>{1, 2, 3}) !({ 1, 2 } == { 1, 2, 3 }) @@ -1813,7 +1813,7 @@ - !d >= Approx( 1.24 ) + !(d >= Approx( 1.24 )) !(1.23 >= Approx( 1.24 )) @@ -2230,7 +2230,7 @@ - !d <= Approx( 1.22 ) + !(d <= Approx( 1.22 )) !(1.23 <= Approx( 1.22 )) @@ -2373,7 +2373,7 @@ - !False + !(False) !{?} @@ -7633,7 +7633,7 @@ loose text artifact
- !Catch::replaceInPlace( letters, "x", "z" ) + !(Catch::replaceInPlace( letters, "x", "z" )) !false From 5af918eefd708d4264d351c7fd70757636f8a9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 17 Oct 2017 17:04:37 +0200 Subject: [PATCH 373/398] Fix-up pkg-config provided include path Related to #1032 --- catch.pc.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/catch.pc.in b/catch.pc.in index de6fdfea..4a7b2545 100644 --- a/catch.pc.in +++ b/catch.pc.in @@ -6,5 +6,4 @@ Description: Testing library for C++ Requires: Version: @CATCH_VERSION_NUMBER@ Libs: -Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@ - +Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@/include From 75a77b6f8cf439c8ad57e6e7d922ec186665067e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 21 Oct 2017 09:16:38 +0200 Subject: [PATCH 374/398] embedded v1.0-develop.2 of Clara, which addresses / prefixed options, which should impact non-windows platforms See #1054 --- include/external/clara.hpp | 23 ++++++++++++++++------ third_party/clara.hpp | 39 +++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 3f2d13bf..88a5e9fe 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -1,4 +1,4 @@ -// v1.0 +// v1.0-develop.2 // See https://github.com/philsquared/Clara #ifndef CATCH_CLARA_HPP_INCLUDED @@ -409,6 +409,14 @@ namespace detail { std::string token; }; + inline auto isOptPrefix( char c ) -> bool { + return c == '-' +#ifdef CATCH_PLATFORM_WINDOWS + || c == '/' +#endif + ; + } + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled class TokenStream { using Iterator = std::vector::const_iterator; @@ -425,7 +433,7 @@ namespace detail { if( it != itEnd ) { auto const &next = *it; - if( next[0] == '-' || next[0] == '/' ) { + if( isOptPrefix( next[0] ) ) { auto delimiterPos = next.find_first_of( " :=" ); if( delimiterPos != std::string::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); @@ -915,9 +923,11 @@ namespace detail { }; inline auto normaliseOpt( std::string const &optName ) -> std::string { +#ifdef CATCH_PLATFORM_WINDOWS if( optName[0] == '/' ) return "-" + optName.substr( 1 ); else +#endif return optName; } @@ -958,11 +968,7 @@ namespace detail { } auto isMatch( std::string const &optToken ) const -> bool { -#ifdef CATCH_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); -#else - auto const &normalisedToken = optToken; -#endif for( auto const &name : m_optNames ) { if( normaliseOpt( name ) == normalisedToken ) return true; @@ -1012,8 +1018,13 @@ namespace detail { for( auto const &name : m_optNames ) { if( name.empty() ) return Result::logicError( "Option name cannot be empty" ); +#ifdef CATCH_PLATFORM_WINDOWS if( name[0] != '-' && name[0] != '/' ) return Result::logicError( "Option name must begin with '-' or '/'" ); +#else + if( name[0] != '-' ) + return Result::logicError( "Option name must begin with '-'" ); +#endif } return ParserRefImpl::validate(); } diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 83c4c514..aa429e7a 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -1,4 +1,4 @@ -// v1.0 +// v1.0-develop.2 // See https://github.com/philsquared/Clara #ifndef CLARA_HPP_INCLUDED @@ -409,6 +409,14 @@ namespace detail { std::string token; }; + inline auto isOptPrefix( char c ) -> bool { + return c == '-' +#ifdef CLARA_PLATFORM_WINDOWS + || c == '/' +#endif + ; + } + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled class TokenStream { using Iterator = std::vector::const_iterator; @@ -425,7 +433,7 @@ namespace detail { if( it != itEnd ) { auto const &next = *it; - if( next[0] == '-' || next[0] == '/' ) { + if( isOptPrefix( next[0] ) ) { auto delimiterPos = next.find_first_of( " :=" ); if( delimiterPos != std::string::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); @@ -915,9 +923,11 @@ namespace detail { }; inline auto normaliseOpt( std::string const &optName ) -> std::string { +#ifdef CLARA_PLATFORM_WINDOWS if( optName[0] == '/' ) return "-" + optName.substr( 1 ); else +#endif return optName; } @@ -958,11 +968,7 @@ namespace detail { } auto isMatch( std::string const &optToken ) const -> bool { -#ifdef CLARA_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); -#else - auto const &normalisedToken = optToken; -#endif for( auto const &name : m_optNames ) { if( normaliseOpt( name ) == normalisedToken ) return true; @@ -1012,8 +1018,13 @@ namespace detail { for( auto const &name : m_optNames ) { if( name.empty() ) return Result::logicError( "Option name cannot be empty" ); +#ifdef CLARA_PLATFORM_WINDOWS if( name[0] != '-' && name[0] != '/' ) return Result::logicError( "Option name must begin with '-' or '/'" ); +#else + if( name[0] != '-' ) + return Result::logicError( "Option name must begin with '-'" ); +#endif } return ParserRefImpl::validate(); } @@ -1142,10 +1153,15 @@ namespace detail { size_t count = 0; }; const size_t totalParsers = m_options.size() + m_args.size(); - ParserInfo parseInfos[totalParsers]; - size_t i = 0; - for( auto const& opt : m_options ) parseInfos[i++].parser = &opt; - for( auto const& arg : m_args ) parseInfos[i++].parser = &arg; + assert( totalParsers < 512 ); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do + ParserInfo parseInfos[512]; + + { + size_t i = 0; + for (auto const &opt : m_options) parseInfos[i++].parser = &opt; + for (auto const &arg : m_args) parseInfos[i++].parser = &arg; + } m_exeName.set( exeName ); @@ -1153,7 +1169,8 @@ namespace detail { while( result.value().remainingTokens() ) { bool tokenParsed = false; - for( auto& parseInfo : parseInfos ) { + for( size_t i = 0; i < totalParsers; ++i ) { + auto& parseInfo = parseInfos[i]; if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); if (!result) From 57b4e0b64ce00c7e6d43e509071127debf4d12f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 30 Oct 2017 09:27:00 +0100 Subject: [PATCH 375/398] Fix missing pragma warning(pop) and other warnings under MSVC Fixes #1072 --- include/internal/catch_compiler_capabilities.h | 2 +- include/internal/catch_decomposer.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index e7d506ed..96ddd800 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -82,7 +82,7 @@ // Universal Windows platform does not support SEH // Or console colours (or console at all...) -# if (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) # define CATCH_CONFIG_COLOUR_NONE # else # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH diff --git a/include/internal/catch_decomposer.h b/include/internal/catch_decomposer.h index fee24e72..38b62f45 100644 --- a/include/internal/catch_decomposer.h +++ b/include/internal/catch_decomposer.h @@ -162,4 +162,8 @@ namespace Catch { } // end namespace Catch +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED From c67251297910982586e2db79748d23ff02b773c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 30 Oct 2017 12:14:20 +0100 Subject: [PATCH 376/398] Fix C4601 and enable C4602 warning for internal builds Related to #1072 --- CMakeLists.txt | 2 +- include/reporters/catch_reporter_console.cpp | 12 ++++++++++++ include/reporters/catch_reporter_xml.cpp | 11 +++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f25f47fe..bda4b293 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -310,7 +310,7 @@ if (NOT NO_SELFTEST) target_compile_options( SelfTest PRIVATE -Wweak-vtables -Wexit-time-destructors -Wglobal-constructors -Wmissing-noreturn ) endif() if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) - target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX ) + target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX /w44061 /w44062 ) target_compile_options( Benchmark PRIVATE /W4 ) endif() diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp index 31a46bd9..68eb3b94 100644 --- a/include/reporters/catch_reporter_console.cpp +++ b/include/reporters/catch_reporter_console.cpp @@ -17,6 +17,14 @@ #include #include +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + + namespace Catch { namespace { @@ -639,3 +647,7 @@ namespace Catch { ConsoleReporter::~ConsoleReporter() {} } // end namespace Catch + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/include/reporters/catch_reporter_xml.cpp b/include/reporters/catch_reporter_xml.cpp index abdfbce5..36f169fd 100644 --- a/include/reporters/catch_reporter_xml.cpp +++ b/include/reporters/catch_reporter_xml.cpp @@ -13,6 +13,13 @@ #include "internal/catch_xmlwriter.h" #include "../internal/catch_timer.h" +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + namespace Catch { class XmlReporter : public StreamingReporterBase { public: @@ -223,3 +230,7 @@ namespace Catch { CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif From 3049445d7811248c3b2d42db0f4f4034e2995756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 30 Oct 2017 12:25:57 +0100 Subject: [PATCH 377/398] Remove benchmark binary from main cmake list We can give it a separate CMakeLists.txt later, but there is no point in building it every time. --- CMakeLists.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bda4b293..4d5bc600 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -276,17 +276,9 @@ set(HEADERS ${REPORTER_HEADERS} ) - -set(BENCH_SOURCES - ${BENCHMARK_DIR}/BenchMain.cpp - ${BENCHMARK_DIR}/StringificationBench.cpp - ) -CheckFileList(BENCH_SOURCES ${BENCHMARK_DIR}) - # Provide some groupings for IDEs SOURCE_GROUP("Tests" FILES ${TEST_SOURCES}) SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES}) -SOURCE_GROUP("Benchmarks" FILES ${BENCH_SOURCES}) # configure the executable include_directories(${HEADER_DIR}) @@ -297,12 +289,10 @@ add_definitions( -DCATCH_CONFIG_FULL_PROJECT ) # without building all of our selftests. if (NOT NO_SELFTEST) add_executable(SelfTest ${TEST_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${SURROGATE_SOURCES} ${HEADERS}) - add_executable(Benchmark ${BENCH_SOURCES} ${IMPL_SOURCES} ${REPORTER_SOURCES} ${HEADERS}) # Add desired warnings if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang|AppleClang|GNU" ) target_compile_options( SelfTest PRIVATE -Wall -Wextra -Wunreachable-code ) - target_compile_options( Benchmark PRIVATE -Wall -Wextra -Wunreachable-code ) endif() # Clang specific warning go here if ( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) @@ -311,7 +301,6 @@ if (NOT NO_SELFTEST) endif() if ( CMAKE_CXX_COMPILER_ID MATCHES "MSVC" ) target_compile_options( SelfTest PRIVATE /W4 /w44265 /WX /w44061 /w44062 ) - target_compile_options( Benchmark PRIVATE /W4 ) endif() From 601b2888ec6951a4adff224979d530f607a566df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 30 Oct 2017 12:27:14 +0100 Subject: [PATCH 378/398] Remove superfluous define from cmake project --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d5bc600..c9d15dc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,8 +283,6 @@ SOURCE_GROUP("Surrogates" FILES ${SURROGATE_SOURCES}) # configure the executable include_directories(${HEADER_DIR}) -add_definitions( -DCATCH_CONFIG_FULL_PROJECT ) - # Projects consuming Catch via ExternalProject_Add might want to use install step # without building all of our selftests. if (NOT NO_SELFTEST) From eea9e1efd7b9f790fd382c70c10e997ba3fd3aba Mon Sep 17 00:00:00 2001 From: solvingj Date: Sat, 26 Aug 2017 13:53:03 -0400 Subject: [PATCH 379/398] Minor - added header-only flag in conan See header-only guidelines: http://conanio.readthedocs.io/en/latest/howtos/header_only.html?highlight=header%20only Its borderline cosmetic, but it does have a purpose. --- conanfile.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conanfile.py b/conanfile.py index 5c7d9931..f1825814 100644 --- a/conanfile.py +++ b/conanfile.py @@ -14,3 +14,6 @@ class CatchConan(ConanFile): def package(self): self.copy(pattern="catch.hpp", src="single_include", dst="include") + + def package_id(self): + self.info.header_only() From 44244713f10e772e9d8fcf011941f326099c1c9a Mon Sep 17 00:00:00 2001 From: Dmitry Kozhevnikov Date: Mon, 4 Sep 2017 19:43:32 +0300 Subject: [PATCH 380/398] Update handling of __JETBRAINS_IDE__ macro 1. Use it to conditionally define CATCH_INTERNAL_CONFIG_COUNTER, not CATCH_CONFIG_COUNTER, as __JETBRAINS_IDE__ is similar to compiler-provided macros, not to user-provided ones. 2. Since __COUNTER__ will work starting with CLion 2017.3, use it when possible (and hopefully remove this check altogether at some point). --- .../internal/catch_compiler_capabilities.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index 96ddd800..88180af2 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -92,17 +92,16 @@ //////////////////////////////////////////////////////////////////////////////// -// All supported compilers support COUNTER macro, -//but user still might want to turn it off -#define CATCH_INTERNAL_CONFIG_COUNTER +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// 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 +#endif - -// Now set the actual defines based on the above + anything the user has configured - -// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for -// analytics) because, at time of writing, __COUNTER__ is not properly handled by it. -// This does not affect compilation -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) +#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) From 88e912b4d13b5e22c4e91323372597e4c4f667d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 14 Oct 2017 08:36:44 +0200 Subject: [PATCH 381/398] Fix documentation crosslink in configuration.md --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index 56d2327b..3e59e763 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -106,7 +106,7 @@ When `CATCH_CONFIG_DISABLE_MATCHERS` is defined, all mentions of Catch's Matcher _Note: If you define `CATCH_CONFIG_DISABLE_MATCHERS` in the same file as Catch's main is implemented, your test executable will fail to link if you use Matchers anywhere._ ### `CATCH_CONFIG_DISABLE_STRINGIFICATION` -This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#Visual Studio 2017 -- raw string literal in assert fails to compile) +This toggle enables a workaround for VS 2017 bug. For details see [known limitations](limitations.md#visual-studio-2017----raw-string-literal-in-assert-fails-to-compile). ### `CATCH_CONFIG_DISABLE` This toggle removes most of Catch from given file. This means that `TEST_CASE`s are not registered and assertions are turned into no-ops. Useful for keeping tests within implementation files (ie for functions with internal linkage), instead of in external files. From e68485e19664d0388c98db0bb7bc8e985a3a42cd Mon Sep 17 00:00:00 2001 From: dvirtz Date: Wed, 11 Oct 2017 15:01:06 +0300 Subject: [PATCH 382/398] added PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS option --- contrib/ParseAndAddCatchTests.cmake | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contrib/ParseAndAddCatchTests.cmake b/contrib/ParseAndAddCatchTests.cmake index 700357fd..cb2846d0 100644 --- a/contrib/ParseAndAddCatchTests.cmake +++ b/contrib/ParseAndAddCatchTests.cmake @@ -36,6 +36,8 @@ # -- adds fixture class name to the test name # # PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) # # -- adds cmake target name to the test name # +# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) # +# -- causes CMake to rerun when file with tests changes so that new tests will be discovered # # # #==================================================================================================# @@ -45,6 +47,7 @@ option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OF option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF) option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON) option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON) +option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF) function(PrintDebugMessage) if(PARSE_CATCH_TESTS_VERBOSE) @@ -85,6 +88,15 @@ function(ParseFile SourceFile TestTarget) # Find definition of test names string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}") + if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests) + PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property") + set_property( + DIRECTORY + APPEND + PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile} + ) + endif() + foreach(TestName ${Tests}) # Strip newlines string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}") From 96c5de678d538e4e9b95c7f06afa03e3d0a0b15e Mon Sep 17 00:00:00 2001 From: Sebastian Grottel Date: Sun, 15 Oct 2017 18:30:40 +0200 Subject: [PATCH 383/398] `RandomNumberGenerator::result_type` should be unsigned (#1050) `result_type` must be unsigned: http://en.cppreference.com/w/cpp/concept/UniformRandomBitGenerator Using a signed type causes an infinite loop working with MS Visual Studio 2017, targetting: v140, WindowsTargetPlatformVersion 10.0.15063.0, Debug, x64 --- include/internal/catch_random_number_generator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_random_number_generator.h b/include/internal/catch_random_number_generator.h index 1a61202d..2395bd39 100644 --- a/include/internal/catch_random_number_generator.h +++ b/include/internal/catch_random_number_generator.h @@ -20,7 +20,7 @@ namespace Catch { unsigned int rngSeed(); struct RandomNumberGenerator { - using result_type = std::ptrdiff_t; + using result_type = unsigned int; static constexpr result_type (min)() { return 0; } static constexpr result_type (max)() { return 1000000; } From c1a91caf004be65b3e6c68376b552a38742aa43e Mon Sep 17 00:00:00 2001 From: Sebastian Grottel Date: Mon, 16 Oct 2017 08:55:51 +0200 Subject: [PATCH 384/398] adds flushes to the output stream of teamcity reporter, making the test output more responsive. --- include/reporters/catch_reporter_teamcity.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index d17026a8..6c7b3d18 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -133,6 +133,7 @@ namespace Catch { << "]\n"; } } + stream.flush(); return true; } @@ -146,6 +147,7 @@ namespace Catch { StreamingReporterBase::testCaseStarting( testInfo ); stream << "##teamcity[testStarted name='" << escape( testInfo.name ) << "']\n"; + stream.flush(); } void testCaseEnded( TestCaseStats const& testCaseStats ) override { @@ -161,6 +163,7 @@ namespace Catch { stream << "##teamcity[testFinished name='" << escape( testCaseStats.testInfo.name ) << "' duration='" << m_testTimer.getElapsedMilliseconds() << "']\n"; + stream.flush(); } private: From 4220f2eef2a3de7b82f1994de3c4dd648be9c11e Mon Sep 17 00:00:00 2001 From: Pfiffikus <2845742+Pfiffikus@users.noreply.github.com> Date: Tue, 24 Oct 2017 19:04:47 +0200 Subject: [PATCH 385/398] Update build-systems.md typo correction --- docs/build-systems.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build-systems.md b/docs/build-systems.md index 2f7953ca..20711d37 100644 --- a/docs/build-systems.md +++ b/docs/build-systems.md @@ -16,7 +16,7 @@ The XML Reporter writes in an XML format that is specific to Catch. The advantage of this format is that it corresponds well to the way Catch works (especially the more unusual features, such as nested sections) and is a fully streaming format - that is it writes output as it goes, without having to store up all its results before it can start writing. -The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could covert it to, say, HTML - although this loses the streaming advantage, of course. +The disadvantage is that, being specific to Catch, no existing build servers understand the format natively. It can be used as input to an XSLT transformation that could convert it to, say, HTML - although this loses the streaming advantage, of course. ### JUnit Reporter ```-r junit``` From c43ce854167b2b6231648a4bd072172ee69a5712 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Mon, 23 Oct 2017 21:18:57 +0100 Subject: [PATCH 386/398] Fix very minor typo it's -> its --- docs/opensource-users.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/opensource-users.md b/docs/opensource-users.md index d23f4140..c7171ed4 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -1,7 +1,7 @@ # Open Source projects using Catch -Catch is great for open source. With it's [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution +Catch is great for open source. With its [liberal license](../LICENSE.txt) and single-header, dependency-free, distribution it's easy to just drop the header into your project and start writing tests - what's not to like? As a result Catch is now being used in many Open Source projects, including some quite well known ones. From c3ddd4a7e286c768d5c0af0752c3e9ee328f5e34 Mon Sep 17 00:00:00 2001 From: Pfiffikus <2845742+Pfiffikus@users.noreply.github.com> Date: Thu, 26 Oct 2017 11:37:18 +0200 Subject: [PATCH 387/398] Update test-cases-and-sections.md some clarification and typo correction --- docs/test-cases-and-sections.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md index 0e5cc466..68944f51 100644 --- a/docs/test-cases-and-sections.md +++ b/docs/test-cases-and-sections.md @@ -39,13 +39,13 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch. * `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be excluded when running with `-e` or `--nothrow`. -* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests. +* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in your tests. * `[!shouldfail]` - like `[!mayfail]` but *fails* the test if it *passes*. This can be useful if you want to be notified of accidental, or third-party, fixes. * `[!nonportable]` - Indicates that behaviour may vary between platforms or compilers. -* `[#]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`. +* `[#]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped), as a tag to all contained tests, e.g. tests in testfile.cpp would all be tagged `[#testfile]`. * `[@]` - tag aliases all begin with `@` (see below). @@ -53,7 +53,7 @@ All tag names beginning with non-alphanumeric characters are reserved by Catch. ## Tag aliases -Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form: +Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. This can be done, in code, using the following form: CATCH_REGISTER_TAG_ALIAS( , ) From 11f716f28d6621d1e54cf13374f8b5dd1a7489f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 30 Oct 2017 15:25:48 +0100 Subject: [PATCH 388/398] Make Approx::margin inclusive Fixes #952, related to #980 --- include/internal/catch_approx.h | 4 +- projects/SelfTest/ApproxTests.cpp | 20 +++++ .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 70 ++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 4 +- .../SelfTest/Baselines/xml.sw.approved.txt | 90 ++++++++++++++++++- 6 files changed, 184 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_approx.h b/include/internal/catch_approx.h index a2af9c86..69428c8a 100644 --- a/include/internal/catch_approx.h +++ b/include/internal/catch_approx.h @@ -8,6 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED +#include "catch_enforce.h" #include "catch_tostring.h" #include @@ -48,7 +49,7 @@ namespace Detail { if (relativeOK) { return true; } - return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; + return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin; } template ::value>::type> @@ -95,6 +96,7 @@ namespace Detail { template ::value>::type> Approx& margin( T const& newMargin ) { m_margin = static_cast(newMargin); + CATCH_ENFORCE(m_margin >= 0, "Invalid Approx::margin: " << m_margin << ", Approx::Margin has to be non-negative."); return *this; } diff --git a/projects/SelfTest/ApproxTests.cpp b/projects/SelfTest/ApproxTests.cpp index bb6abffe..208be8e4 100644 --- a/projects/SelfTest/ApproxTests.cpp +++ b/projects/SelfTest/ApproxTests.cpp @@ -24,6 +24,8 @@ TEST_CASE REQUIRE( Approx( d ) == 1.23 ); REQUIRE( Approx( d ) != 1.22 ); REQUIRE( Approx( d ) != 1.24 ); + + REQUIRE( 0 == Approx(0) ); } /////////////////////////////////////////////////////////////////////////////// @@ -146,11 +148,29 @@ TEST_CASE( "Approximate PI", "[Approx][PI]" ) TEST_CASE( "Absolute margin", "[Approx]" ) { REQUIRE( 104.0 != Approx(100.0) ); REQUIRE( 104.0 == Approx(100.0).margin(5) ); + REQUIRE( 104.0 == Approx(100.0).margin(4) ); REQUIRE( 104.0 != Approx(100.0).margin(3) ); REQUIRE( 100.3 != Approx(100.0) ); REQUIRE( 100.3 == Approx(100.0).margin(0.5) ); } +TEST_CASE("Approx with exactly-representable margin", "[Approx]") { + CHECK( 0.25f == Approx(0.0f).margin(0.25f) ); + + CHECK( 0.0f == Approx(0.25f).margin(0.25f) ); + CHECK( 0.5f == Approx(0.25f).margin(0.25f) ); + + CHECK( 245.0f == Approx(245.25f).margin(0.25f) ); + CHECK( 245.5f == Approx(245.25f).margin(0.25f) ); +} + +TEST_CASE("Approx setters validate their arguments", "[Approx]") { + REQUIRE_NOTHROW(Approx(0).margin(0)); + REQUIRE_NOTHROW(Approx(0).margin(1234656)); + + REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error); +} + //////////////////////////////////////////////////////////////////////////////// class StrongDoubleTypedef diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index cc23a7dd..d15e5ab8 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 180 | 129 passed | 47 failed | 4 failed as expected -assertions: 886 | 769 passed | 96 failed | 21 failed as expected +test cases: 182 | 131 passed | 47 failed | 4 failed as expected +assertions: 896 | 779 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index e32d6f72..f47b7329 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -490,6 +490,12 @@ PASSED: with expansion: 104.0 == Approx( 100.0 ) +ApproxTests.cpp:: +PASSED: + REQUIRE( 104.0 == Approx(100.0).margin(4) ) +with expansion: + 104.0 == Approx( 100.0 ) + ApproxTests.cpp:: PASSED: REQUIRE( 104.0 != Approx(100.0).margin(3) ) @@ -552,6 +558,60 @@ PASSED: with message: anonymous test case +------------------------------------------------------------------------------- +Approx setters validate their arguments +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE_NOTHROW( Approx(0).margin(0) ) + +ApproxTests.cpp:: +PASSED: + REQUIRE_NOTHROW( Approx(0).margin(1234656) ) + +ApproxTests.cpp:: +PASSED: + REQUIRE_THROWS_AS( Approx(0).margin(-2), std::domain_error ) + +------------------------------------------------------------------------------- +Approx with exactly-representable margin +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + CHECK( 0.25f == Approx(0.0f).margin(0.25f) ) +with expansion: + 0.25f == Approx( 0.0 ) + +ApproxTests.cpp:: +PASSED: + CHECK( 0.0f == Approx(0.25f).margin(0.25f) ) +with expansion: + 0.0f == Approx( 0.25 ) + +ApproxTests.cpp:: +PASSED: + CHECK( 0.5f == Approx(0.25f).margin(0.25f) ) +with expansion: + 0.5f == Approx( 0.25 ) + +ApproxTests.cpp:: +PASSED: + CHECK( 245.0f == Approx(245.25f).margin(0.25f) ) +with expansion: + 245.0f == Approx( 245.25 ) + +ApproxTests.cpp:: +PASSED: + CHECK( 245.5f == Approx(245.25f).margin(0.25f) ) +with expansion: + 245.5f == Approx( 245.25 ) + ------------------------------------------------------------------------------- Approximate PI ------------------------------------------------------------------------------- @@ -4201,6 +4261,12 @@ PASSED: with expansion: Approx( 1.23 ) != 1.24 +ApproxTests.cpp:: +PASSED: + REQUIRE( 0 == Approx(0) ) +with expansion: + 0 == Approx( 0.0 ) + Message from section one ------------------------------------------------------------------------------- Standard output from all sections is reported @@ -7508,6 +7574,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 180 | 127 passed | 49 failed | 4 failed as expected -assertions: 885 | 765 passed | 99 failed | 21 failed as expected +test cases: 182 | 129 passed | 49 failed | 4 failed as expected +assertions: 895 | 775 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 508b9206..8c186f0c 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -100,6 +100,8 @@ ExceptionTests.cpp: + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 04c6f986..07eb6a52 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -495,6 +495,14 @@ 104.0 == Approx( 100.0 ) + + + 104.0 == Approx(100.0).margin(4) + + + 104.0 == Approx( 100.0 ) + + 104.0 != Approx(100.0).margin(3) @@ -568,6 +576,76 @@ + + + + Approx(0).margin(0) + + + Approx(0).margin(0) + + + + + Approx(0).margin(1234656) + + + Approx(0).margin(1234656) + + + + + Approx(0).margin(-2), std::domain_error + + + Approx(0).margin(-2), std::domain_error + + + + + + + + 0.25f == Approx(0.0f).margin(0.25f) + + + 0.25f == Approx( 0.0 ) + + + + + 0.0f == Approx(0.25f).margin(0.25f) + + + 0.0f == Approx( 0.25 ) + + + + + 0.5f == Approx(0.25f).margin(0.25f) + + + 0.5f == Approx( 0.25 ) + + + + + 245.0f == Approx(245.25f).margin(0.25f) + + + 245.0f == Approx( 245.25 ) + + + + + 245.5f == Approx(245.25f).margin(0.25f) + + + 245.5f == Approx( 245.25 ) + + + + @@ -4795,6 +4873,14 @@ A string sent directly to stderr Approx( 1.23 ) != 1.24 + + + 0 == Approx(0) + + + 0 == Approx( 0.0 ) + + @@ -8287,7 +8373,7 @@ loose text artifact
- + - + From ae21020640e6137acac027177d86c08083225dc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Tue, 31 Oct 2017 15:17:21 +0100 Subject: [PATCH 389/398] dev build 6 --- CMakeLists.txt | 2 +- README.md | 2 +- conanfile.py | 4 +- docs/release-notes.md | 4 + include/internal/catch_version.cpp | 2 +- single_include/catch.hpp | 155 ++++++++++++++++++----------- test_package/conanfile.py | 2 +- 7 files changed, 107 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9d15dc8..92a55dae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark) set(HEADER_DIR ${CATCH_DIR}/include) -set(CATCH_VERSION_NUMBER 2.0.0) +set(CATCH_VERSION_NUMBER 2.0.0-develop.6) if(USE_CPP14) message(STATUS "Enabling C++14") diff --git a/README.md b/README.md index 256b1c3a..0d1b9649 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=catch2)](https://travis-ci.org/philsquared/Catch?branch=catch2) [![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/catch2?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/catch2) -The latest version of the single header can be downloaded directly using this link +The latest version of the single header can be downloaded directly using this link ## What's the Catch? diff --git a/conanfile.py b/conanfile.py index f1825814..5e6886ca 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.0.0-develop.5" + version = "2.0.0-develop.6" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" @@ -14,6 +14,6 @@ class CatchConan(ConanFile): def package(self): self.copy(pattern="catch.hpp", src="single_include", dst="include") - + def package_id(self): self.info.header_only() diff --git a/docs/release-notes.md b/docs/release-notes.md index 3c7a97ea..65444980 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -57,6 +57,8 @@ * The Reporter/Listener interface provides default, empty, implementation to preserve backward compatibility * Stringification of `std::chrono::duration` and `std::chrono::time_point` is now supported * Needs to be enabled by a per-file compile time configuration option +* Add `pkg-config` support to CMake install command + ## Fixes * Don't use console colour if running in XCode @@ -67,6 +69,8 @@ * Implemented a workaround for `std::uncaught_exception` issues in libcxxrt * These issues caused incorrect section traversals * The workaround is only partial, user's test can still trigger the issue by using `throw;` to rethrow an exception +* Suppressed C4061 warning under MSVC + ## Internal changes * The development version now uses .cpp files instead of header files containing implementation. diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index e684f3f9..699a4843 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 5 ); + static Version version( 2, 0, 0, "develop", 6 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index f9568b0c..bc9e447d 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.0.0-develop.5 - * Generated: 2017-10-12 13:05:08.135067 + * Catch v2.0.0-develop.6 + * Generated: 2017-10-31 15:09:47.277913 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. @@ -155,7 +155,7 @@ // Universal Windows platform does not support SEH // Or console colours (or console at all...) -# if (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) # define CATCH_CONFIG_COLOUR_NONE # else # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH @@ -165,16 +165,16 @@ //////////////////////////////////////////////////////////////////////////////// -// All supported compilers support COUNTER macro, -//but user still might want to turn it off -#define CATCH_INTERNAL_CONFIG_COUNTER +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// 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 +#endif -// Now set the actual defines based on the above + anything the user has configured - -// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for -// analytics) because, at time of writing, __COUNTER__ is not properly handled by it. -// This does not affect compilation -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) +#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) @@ -1037,7 +1037,7 @@ namespace Catch { // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) template - auto compareEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; + auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return lhs == rhs; }; template auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } template @@ -1065,36 +1065,36 @@ namespace Catch { ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} template - auto operator == ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); + auto operator == ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); } auto operator == ( bool rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs == rhs, m_lhs, "==", rhs ); } template - auto operator != ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); + auto operator != ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); } auto operator != ( bool rhs ) -> BinaryExpr const { return BinaryExpr( m_lhs != rhs, m_lhs, "!=", rhs ); } template - auto operator > ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); + auto operator > ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs > rhs, m_lhs, ">", rhs ); } template - auto operator < ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); + auto operator < ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs < rhs, m_lhs, "<", rhs ); } template - auto operator >= ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); + auto operator >= ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs >= rhs, m_lhs, ">=", rhs ); } template - auto operator <= ( RhsT&& rhs ) -> BinaryExpr const { - return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); + auto operator <= ( RhsT const& rhs ) -> BinaryExpr const { + return BinaryExpr( m_lhs <= rhs, m_lhs, "<=", rhs ); } auto makeUnaryExpr() const -> UnaryExpr { @@ -1121,6 +1121,10 @@ namespace Catch { } // end namespace Catch +#ifdef _MSC_VER +#pragma warning(pop) +#endif + // end catch_decomposer.h // start catch_assertioninfo.h @@ -1816,6 +1820,21 @@ namespace Catch { // end catch_interfaces_exception.h // start catch_approx.h +// start catch_enforce.h + +#include +#include + +#define CATCH_PREPARE_EXCEPTION( type, msg ) \ + type( static_cast( std::ostringstream() << msg ).str() ) +#define CATCH_INTERNAL_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); +#define CATCH_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) +#define CATCH_ENFORCE( condition, msg ) \ + do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) + +// end catch_enforce.h #include #include @@ -1823,7 +1842,7 @@ namespace Catch { namespace Catch { namespace Detail { - double max(double lhs, double rhs); + double dmax(double lhs, double rhs); class Approx { public: @@ -1848,11 +1867,12 @@ namespace Detail { friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula auto lhs_v = static_cast(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); + bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + + dmax(std::fabs(lhs_v), std::fabs(rhs.m_value))); if (relativeOK) { return true; } - return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; + return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin; } template ::value>::type> @@ -1899,6 +1919,7 @@ namespace Detail { template ::value>::type> Approx& margin( T const& newMargin ) { m_margin = static_cast(newMargin); + CATCH_ENFORCE(m_margin >= 0, "Invalid Approx::margin: " << m_margin << ", Approx::Margin has to be non-negative."); return *this; } @@ -2643,21 +2664,6 @@ return @ desc; \ // start catch_reporter_bases.hpp -// start catch_enforce.h - -#include -#include - -#define CATCH_PREPARE_EXCEPTION( type, msg ) \ - type( static_cast( std::ostringstream() << msg ).str() ) -#define CATCH_INTERNAL_ERROR( msg ) \ - throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); -#define CATCH_ERROR( msg ) \ - throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) -#define CATCH_ENFORCE( condition, msg ) \ - do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) - -// end catch_enforce.h // start catch_interfaces_reporter.h // start catch_config.hpp @@ -3979,7 +3985,7 @@ namespace Catch { namespace Catch { namespace Detail { - double max(double lhs, double rhs) { + double dmax(double lhs, double rhs) { if (lhs < rhs) { return rhs; } @@ -4226,8 +4232,8 @@ namespace Catch { } std::string AssertionResult::getExpression() const { - if (isFalseTest(m_info.resultDisposition)) - return '!' + std::string(m_info.capturedExpression); + if( isFalseTest( m_info.resultDisposition ) ) + return "!(" + std::string(m_info.capturedExpression) + ")"; else return m_info.capturedExpression; } @@ -4334,7 +4340,7 @@ namespace Catch { #endif // start clara.hpp -// v1.0 +// v1.0-develop.2 // See https://github.com/philsquared/Clara @@ -4737,6 +4743,14 @@ namespace detail { std::string token; }; + inline auto isOptPrefix( char c ) -> bool { + return c == '-' +#ifdef CATCH_PLATFORM_WINDOWS + || c == '/' +#endif + ; + } + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled class TokenStream { using Iterator = std::vector::const_iterator; @@ -4753,7 +4767,7 @@ namespace detail { if( it != itEnd ) { auto const &next = *it; - if( next[0] == '-' || next[0] == '/' ) { + if( isOptPrefix( next[0] ) ) { auto delimiterPos = next.find_first_of( " :=" ); if( delimiterPos != std::string::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); @@ -5241,9 +5255,11 @@ namespace detail { }; inline auto normaliseOpt( std::string const &optName ) -> std::string { +#ifdef CATCH_PLATFORM_WINDOWS if( optName[0] == '/' ) return "-" + optName.substr( 1 ); else +#endif return optName; } @@ -5284,11 +5300,7 @@ namespace detail { } auto isMatch( std::string const &optToken ) const -> bool { -#ifdef CATCH_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); -#else - auto const &normalisedToken = optToken; -#endif for( auto const &name : m_optNames ) { if( normaliseOpt( name ) == normalisedToken ) return true; @@ -5338,8 +5350,13 @@ namespace detail { for( auto const &name : m_optNames ) { if( name.empty() ) return Result::logicError( "Option name cannot be empty" ); +#ifdef CATCH_PLATFORM_WINDOWS if( name[0] != '-' && name[0] != '/' ) return Result::logicError( "Option name must begin with '-' or '/'" ); +#else + if( name[0] != '-' ) + return Result::logicError( "Option name must begin with '-'" ); +#endif } return ParserRefImpl::validate(); } @@ -5428,7 +5445,7 @@ namespace detail { size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; for( auto const &cols : rows ) - optWidth = std::max(optWidth, cols.left.size() + 2); + optWidth = (std::max)(optWidth, cols.left.size() + 2); for( auto const &cols : rows ) { auto row = @@ -7188,10 +7205,10 @@ namespace Catch { unsigned int rngSeed(); struct RandomNumberGenerator { - using result_type = std::ptrdiff_t; + using result_type = unsigned int; - static constexpr result_type min() { return 0; } - static constexpr result_type max() { return 1000000; } + static constexpr result_type (min)() { return 0; } + static constexpr result_type (max)() { return 1000000; } result_type operator()( result_type n ) const; result_type operator()() const; @@ -7222,7 +7239,7 @@ namespace Catch { return std::rand() % n; } RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { - return std::rand() % max(); + return std::rand() % (max)(); } } @@ -9785,7 +9802,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 5 ); + static Version version( 2, 0, 0, "develop", 6 ); return version; } @@ -10453,6 +10470,13 @@ namespace Catch { #include #include +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + namespace Catch { namespace { @@ -11074,6 +11098,10 @@ namespace Catch { ConsoleReporter::~ConsoleReporter() {} } // end namespace Catch + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif // end catch_reporter_console.cpp // start catch_reporter_junit.cpp @@ -11415,6 +11443,13 @@ namespace Catch { // end catch_reporter_multi.cpp // start catch_reporter_xml.cpp +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + namespace Catch { class XmlReporter : public StreamingReporterBase { public: @@ -11624,6 +11659,10 @@ namespace Catch { CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif // end catch_reporter_xml.cpp namespace Catch { diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 96d93985..ec99f3bc 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.0.0-develop.5@%s/%s" % (username, channel) + requires = "Catch/2.0.0-develop.6@%s/%s" % (username, channel) def build(self): cmake = CMake(self) From 00af677577973758b3b35e1c94ab4142c45c3f67 Mon Sep 17 00:00:00 2001 From: Pfiffikus <2845742+Pfiffikus@users.noreply.github.com> Date: Thu, 26 Oct 2017 09:19:57 +0200 Subject: [PATCH 390/398] Approx rework: default scale == 0, epsilon applies to Approx::value Also adds check to Approx::epsilon that the new epsilon has a valid (ie one between 0 and 1) Based on http://realtimecollisiondetection.net/blog/?p=89 https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html https://en.wikipedia.org/wiki/Approximation_error#Formal_Definition The given epsilon should refer to the target value, otherwise the result would be unexpected, e.g. 101.02 == Approx(100).epsilon(0.01) is true. The default scale should be invisible, thus, e.g. 101.01 == Approx(100).epsilon(0.01) gets false. Finally even 101.000001 == Approx(100).epsilon(0.01) is false --- include/internal/catch_approx.cpp | 2 +- include/internal/catch_approx.h | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp index ca3ac94a..826a1049 100644 --- a/include/internal/catch_approx.cpp +++ b/include/internal/catch_approx.cpp @@ -23,7 +23,7 @@ namespace Detail { Approx::Approx ( double value ) : m_epsilon( std::numeric_limits::epsilon()*100 ), m_margin( 0.0 ), - m_scale( 1.0 ), + m_scale( 0.0 ), m_value( value ) {} diff --git a/include/internal/catch_approx.h b/include/internal/catch_approx.h index 69428c8a..8ca7f315 100644 --- a/include/internal/catch_approx.h +++ b/include/internal/catch_approx.h @@ -44,8 +44,9 @@ namespace Detail { friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula auto lhs_v = static_cast(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + - dmax(std::fabs(lhs_v), std::fabs(rhs.m_value))); + + bool relativeOK = std::fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + std::fabs(rhs.m_value) ); + if (relativeOK) { return true; } @@ -89,7 +90,11 @@ namespace Detail { template ::value>::type> Approx& epsilon( T const& newEpsilon ) { - m_epsilon = static_cast(newEpsilon); + double asDouble = static_cast(newEpsilon); + CATCH_ENFORCE(asDouble >= 0 && asDouble <= 1.0, + "Invalid Approx::epsilon: " << m_epsilon << + ", Approx::epsilon has to be between 0 and 1"); + m_epsilon = asDouble; return *this; } From 22ac9d2184b3868cccfd635eb631d0eee1529121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 1 Nov 2017 07:30:11 +0100 Subject: [PATCH 391/398] Approx cleanup: More tests, INFINITY handling, etc --- include/internal/catch_approx.cpp | 24 ++++-- include/internal/catch_approx.h | 33 ++++---- projects/SelfTest/ApproxTests.cpp | 29 +++++-- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 68 +++++++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 5 +- .../SelfTest/Baselines/xml.sw.approved.txt | 83 +++++++++++++++++-- scripts/approvalTests.py | 6 ++ 8 files changed, 207 insertions(+), 45 deletions(-) diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp index 826a1049..82c6ff12 100644 --- a/include/internal/catch_approx.cpp +++ b/include/internal/catch_approx.cpp @@ -8,18 +8,22 @@ #include "catch_approx.h" +#include #include +namespace { + +// Performs equivalent check of std::fabs(lhs - rhs) <= margin +// But without the subtraction to allow for INFINITY in comparison +bool marginComparison(double lhs, double rhs, double margin) { + return (lhs + margin >= rhs) && (rhs + margin >= lhs); +} + +} + namespace Catch { namespace Detail { - double dmax(double lhs, double rhs) { - if (lhs < rhs) { - return rhs; - } - return lhs; - } - Approx::Approx ( double value ) : m_epsilon( std::numeric_limits::epsilon()*100 ), m_margin( 0.0 ), @@ -37,6 +41,12 @@ namespace Detail { return oss.str(); } + bool Approx::equalityComparisonImpl(const double other) const { + // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value + // Thanks to Richard Harris for his help refining the scaled margin value + return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); + } + } // end namespace Detail std::string StringMaker::convert(Catch::Detail::Approx const& value) { diff --git a/include/internal/catch_approx.h b/include/internal/catch_approx.h index 8ca7f315..64f92db7 100644 --- a/include/internal/catch_approx.h +++ b/include/internal/catch_approx.h @@ -11,16 +11,15 @@ #include "catch_enforce.h" #include "catch_tostring.h" -#include - #include namespace Catch { namespace Detail { - double dmax(double lhs, double rhs); - class Approx { + private: + bool equalityComparisonImpl(double other) const; + public: explicit Approx ( double value ); @@ -42,15 +41,8 @@ namespace Detail { template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula auto lhs_v = static_cast(lhs); - - bool relativeOK = std::fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + std::fabs(rhs.m_value) ); - - if (relativeOK) { - return true; - } - return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin; + return rhs.equalityComparisonImpl(lhs_v); } template ::value>::type> @@ -90,18 +82,21 @@ namespace Detail { template ::value>::type> Approx& epsilon( T const& newEpsilon ) { - double asDouble = static_cast(newEpsilon); - CATCH_ENFORCE(asDouble >= 0 && asDouble <= 1.0, - "Invalid Approx::epsilon: " << m_epsilon << - ", Approx::epsilon has to be between 0 and 1"); - m_epsilon = asDouble; + double epsilonAsDouble = static_cast(newEpsilon); + CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0, + "Invalid Approx::epsilon: " << epsilonAsDouble + << ", Approx::epsilon has to be between 0 and 1"); + m_epsilon = epsilonAsDouble; return *this; } template ::value>::type> Approx& margin( T const& newMargin ) { - m_margin = static_cast(newMargin); - CATCH_ENFORCE(m_margin >= 0, "Invalid Approx::margin: " << m_margin << ", Approx::Margin has to be non-negative."); + double marginAsDouble = static_cast(newMargin); + CATCH_ENFORCE(marginAsDouble >= 0, + "Invalid Approx::margin: " << marginAsDouble + << ", Approx::Margin has to be non-negative."); + m_margin = marginAsDouble; return *this; } diff --git a/projects/SelfTest/ApproxTests.cpp b/projects/SelfTest/ApproxTests.cpp index 208be8e4..09008e5a 100644 --- a/projects/SelfTest/ApproxTests.cpp +++ b/projects/SelfTest/ApproxTests.cpp @@ -8,6 +8,8 @@ #include "catch.hpp" +#include + /////////////////////////////////////////////////////////////////////////////// TEST_CASE ( @@ -25,7 +27,7 @@ TEST_CASE REQUIRE( Approx( d ) != 1.22 ); REQUIRE( Approx( d ) != 1.24 ); - REQUIRE( 0 == Approx(0) ); + REQUIRE(INFINITY == Approx(INFINITY)); } /////////////////////////////////////////////////////////////////////////////// @@ -106,7 +108,7 @@ TEST_CASE REQUIRE( 1.0f == Approx( 1 ) ); REQUIRE( 0 == Approx( dZero) ); - REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ); + REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) ); REQUIRE( 1.234f == Approx( dMedium ) ); REQUIRE( dMedium == Approx( 1.234f ) ); } @@ -120,7 +122,7 @@ TEST_CASE { double d = 1.23; - Approx approx = Approx::custom().epsilon( 0.005 ); + Approx approx = Approx::custom().epsilon( 0.01 ); REQUIRE( d == approx( 1.23 ) ); REQUIRE( d == approx( 1.22 ) ); @@ -169,9 +171,26 @@ TEST_CASE("Approx setters validate their arguments", "[Approx]") { REQUIRE_NOTHROW(Approx(0).margin(1234656)); REQUIRE_THROWS_AS(Approx(0).margin(-2), std::domain_error); + + REQUIRE_NOTHROW(Approx(0).epsilon(0)); + REQUIRE_NOTHROW(Approx(0).epsilon(1)); + + REQUIRE_THROWS_AS(Approx(0).epsilon(-0.001), std::domain_error); + REQUIRE_THROWS_AS(Approx(0).epsilon(1.0001), std::domain_error); } -//////////////////////////////////////////////////////////////////////////////// +TEST_CASE("Default scale is invisible to comparison", "[Approx]") { + REQUIRE(101.000001 != Approx(100).epsilon(0.01)); + REQUIRE(std::pow(10, -5) != Approx(std::pow(10, -7))); +} + +TEST_CASE("Epsilon only applies to Approx's value", "[Approx]") { + REQUIRE(101.01 != Approx(100).epsilon(0.01)); +} + +TEST_CASE("Assorted miscellaneous tests", "[Approx]") { + REQUIRE(INFINITY == Approx(INFINITY)); +} class StrongDoubleTypedef { @@ -207,5 +226,3 @@ TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" ) REQUIRE(Approx(11.0) >= td); } - -//////////////////////////////////////////////////////////////////////////////// diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index d15e5ab8..f0791caf 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -1003,6 +1003,6 @@ with expansion: "{?}" == "1" =============================================================================== -test cases: 182 | 131 passed | 47 failed | 4 failed as expected -assertions: 896 | 779 passed | 96 failed | 21 failed as expected +test cases: 185 | 134 passed | 47 failed | 4 failed as expected +assertions: 904 | 787 passed | 96 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index f47b7329..2c205275 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -576,6 +576,22 @@ ApproxTests.cpp:: PASSED: REQUIRE_THROWS_AS( Approx(0).margin(-2), std::domain_error ) +ApproxTests.cpp:: +PASSED: + REQUIRE_NOTHROW( Approx(0).epsilon(0) ) + +ApproxTests.cpp:: +PASSED: + REQUIRE_NOTHROW( Approx(0).epsilon(1) ) + +ApproxTests.cpp:: +PASSED: + REQUIRE_THROWS_AS( Approx(0).epsilon(-0.001), std::domain_error ) + +ApproxTests.cpp:: +PASSED: + REQUIRE_THROWS_AS( Approx(0).epsilon(1.0001), std::domain_error ) + ------------------------------------------------------------------------------- Approx with exactly-representable margin ------------------------------------------------------------------------------- @@ -704,7 +720,7 @@ with expansion: ApproxTests.cpp:: PASSED: - REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ) + REQUIRE( 0 == Approx( dSmall ).margin( 0.001 ) ) with expansion: 0 == Approx( 0.00001 ) @@ -798,6 +814,18 @@ PASSED: with expansion: true +------------------------------------------------------------------------------- +Assorted miscellaneous tests +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( INFINITY == Approx(INFINITY) ) +with expansion: + inff == Approx( inf ) + ------------------------------------------------------------------------------- Bitfields can be captured (#1027) ------------------------------------------------------------------------------- @@ -1293,6 +1321,24 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: custom std exception +------------------------------------------------------------------------------- +Default scale is invisible to comparison +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 101.000001 != Approx(100).epsilon(0.01) ) +with expansion: + 101.000001 != Approx( 100.0 ) + +ApproxTests.cpp:: +PASSED: + REQUIRE( std::pow(10, -5) != Approx(std::pow(10, -7)) ) +with expansion: + 0.00001 != Approx( 0.0000001 ) + ------------------------------------------------------------------------------- EndsWith string matcher ------------------------------------------------------------------------------- @@ -1304,6 +1350,18 @@ MatchersTests.cpp:: FAILED: with expansion: "this string contains 'abc' as a substring" ends with: "this" +------------------------------------------------------------------------------- +Epsilon only applies to Approx's value +------------------------------------------------------------------------------- +ApproxTests.cpp: +............................................................................... + +ApproxTests.cpp:: +PASSED: + REQUIRE( 101.01 != Approx(100).epsilon(0.01) ) +with expansion: + 101.01 != Approx( 100.0 ) + ------------------------------------------------------------------------------- Equality checks that should fail ------------------------------------------------------------------------------- @@ -4263,9 +4321,9 @@ with expansion: ApproxTests.cpp:: PASSED: - REQUIRE( 0 == Approx(0) ) + REQUIRE( INFINITY == Approx(INFINITY) ) with expansion: - 0 == Approx( 0.0 ) + inff == Approx( inf ) Message from section one ------------------------------------------------------------------------------- @@ -7574,6 +7632,6 @@ MiscTests.cpp:: PASSED: =============================================================================== -test cases: 182 | 129 passed | 49 failed | 4 failed as expected -assertions: 895 | 775 passed | 99 failed | 21 failed as expected +test cases: 185 | 132 passed | 49 failed | 4 failed as expected +assertions: 903 | 783 passed | 99 failed | 21 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 8c186f0c..0aba9725 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -111,6 +111,7 @@ ExceptionTests.cpp: + @@ -146,11 +147,13 @@ custom std exception ExceptionTests.cpp: + MatchersTests.cpp: + ConditionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 07eb6a52..d3ef33c9 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -601,6 +601,38 @@ Approx(0).margin(-2), std::domain_error + + + Approx(0).epsilon(0) + + + Approx(0).epsilon(0) + + + + + Approx(0).epsilon(1) + + + Approx(0).epsilon(1) + + + + + Approx(0).epsilon(-0.001), std::domain_error + + + Approx(0).epsilon(-0.001), std::domain_error + + + + + Approx(0).epsilon(1.0001), std::domain_error + + + Approx(0).epsilon(1.0001), std::domain_error + + @@ -741,7 +773,7 @@ - 0 == Approx( dSmall ).epsilon( 0.001 ) + 0 == Approx( dSmall ).margin( 0.001 ) 0 == Approx( 0.00001 ) @@ -828,6 +860,17 @@
+ + + + INFINITY == Approx(INFINITY) + + + inff == Approx( inf ) + + + + @@ -1433,6 +1476,25 @@ + + + + 101.000001 != Approx(100).epsilon(0.01) + + + 101.000001 != Approx( 100.0 ) + + + + + std::pow(10, -5) != Approx(std::pow(10, -7)) + + + 0.00001 != Approx( 0.0000001 ) + + + + @@ -1444,6 +1506,17 @@ + + + + 101.01 != Approx(100).epsilon(0.01) + + + 101.01 != Approx( 100.0 ) + + + + @@ -4875,10 +4948,10 @@ A string sent directly to stderr - 0 == Approx(0) + INFINITY == Approx(INFINITY) - 0 == Approx( 0.0 ) + inff == Approx( inf ) @@ -8373,7 +8446,7 @@ loose text artifact
- + - + diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py index a963531b..7f9447b9 100755 --- a/scripts/approvalTests.py +++ b/scripts/approvalTests.py @@ -45,6 +45,11 @@ errnoParser = re.compile(r''' \(\*_errno\(\)\) ''', re.VERBOSE) sinceEpochParser = re.compile(r'\d+ .+ since epoch') +infParser = re.compile(r''' + \(\(float\)\(1e\+300\ \*\ 1e\+300\)\) # MSVC INFINITY macro + | + \(__builtin_inff\(\)\) # Clang INFINITY macro +''', re.VERBOSE) if len(sys.argv) == 2: cmdPath = sys.argv[1] @@ -102,6 +107,7 @@ def filterLine(line): line = specialCaseParser.sub('file:\g<1>', line) line = errnoParser.sub('errno', line) line = sinceEpochParser.sub('{since-epoch-report}', line) + line = infParser.sub('INFINITY', line) return line From accf9859b412425158b9976ed984c2bf82971b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 1 Nov 2017 08:46:49 +0100 Subject: [PATCH 392/398] Add OSX specific INFINITE macro parsing in approval tests --- scripts/approvalTests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py index 7f9447b9..8194c422 100755 --- a/scripts/approvalTests.py +++ b/scripts/approvalTests.py @@ -48,7 +48,9 @@ sinceEpochParser = re.compile(r'\d+ .+ since epoch') infParser = re.compile(r''' \(\(float\)\(1e\+300\ \*\ 1e\+300\)\) # MSVC INFINITY macro | - \(__builtin_inff\(\)\) # Clang INFINITY macro + \(__builtin_inff\(\)\) # Linux (ubuntu) INFINITY macro + | + __builtin_huge_valf\(\) # OSX macro ''', re.VERBOSE) if len(sys.argv) == 2: From a49e6fdc2779f4427549b784f8f6c72d3cffdbce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 1 Nov 2017 13:45:21 +0100 Subject: [PATCH 393/398] Update Approx documentation --- docs/assertions.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/assertions.md b/docs/assertions.md index 3a9d898e..93f88c41 100644 --- a/docs/assertions.md +++ b/docs/assertions.md @@ -64,7 +64,7 @@ This way `Approx` is constructed with reasonable defaults, covering most simple * __epsilon__ - epsilon serves to set the percentage by which a result can be erroneous, before it is rejected. By default set to `std::numeric_limits::epsilon()*100`. * __margin__ - margin serves to set the the absolute value by which a result can be erroneous before it is rejected. By default set to `0.0`. -* __scale__ - scale serves to adjust the base for comparison used by epsilon, can be used when By default set to `1.0`. +* __scale__ - scale serves to adjust the epsilon's multiplicator. By default set to `0.0`. #### epsilon example ```cpp @@ -84,7 +84,12 @@ Approx target = Approx(100).margin(5); ``` #### scale -Scale can be useful if the computation leading to the result worked on different scale, than is used by the results (and thus expected errors are on a different scale than would be expected based on the results alone). +Scale can be useful if the computation leading to the result worked +on different scale than is used by the results. Since allowed difference +between Approx's value and compared value is based primarily on Approx's value +(the allowed difference is computed as +`(Approx::scale + Approx::value) * epsilon`), the resulting comparison could +need rescaling to be correct. ## Exceptions From 31cc62e6b7c7de4d019bfa7653dcc4bece566611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 1 Nov 2017 22:25:17 +0100 Subject: [PATCH 394/398] Updated release notes with Approx changes --- docs/release-notes.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 65444980..92659884 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -25,6 +25,11 @@ * `std::pair` and `std::tuple` are no longer stringified by default * This is done to avoid dragging in `` and `` headers in common path * Their stringification can be enabled per-file via new configuration macros +* `Approx` is subtly different and hopefully behaves more as users would expect + * `Approx::scale` defaults to `0.0` + * `Approx::epsilon` no longer applies to the larger of the two compared values, but only to the `Approx`'s value + * `INFINITY == Approx(INFINITY)` returns true + ## Improvements * Reporters and Listeners can be defined in files different from the main file From fe05062f9e3b00251b86fb76b3dab9732e1e7787 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 2 Nov 2017 17:57:52 +0000 Subject: [PATCH 395/398] Print any start-up exceptions in Session's constructor, so custom main's don't need to worry about them --- include/internal/catch_session.cpp | 41 ++++++++++++++++++++---------- include/internal/catch_session.h | 1 + 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp index d799b9ea..5a6a8434 100644 --- a/include/internal/catch_session.cpp +++ b/include/internal/catch_session.cpp @@ -116,8 +116,26 @@ namespace Catch { Session::Session() { static bool alreadyInstantiated = false; - if( alreadyInstantiated ) - CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); + if( alreadyInstantiated ) { + try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } + catch(...) { getMutableRegistryHub().registerStartupException(); } + } + + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + m_startupExceptions = true; + Colour colourGuard( Colour::Red ); + Catch::cerr() << "Errors occured during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; + } + } + } + alreadyInstantiated = true; m_cli = makeCommandLineParser( m_configData ); } @@ -140,6 +158,9 @@ namespace Catch { } int Session::applyCommandLine( int argc, char* argv[] ) { + if( m_startupExceptions ) + return 1; + auto result = m_cli.parse( clara::Args( argc, argv ) ); if( !result ) { Catch::cerr() @@ -165,19 +186,8 @@ namespace Catch { } int Session::run( int argc, char* argv[] ) { - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - Catch::cerr() << "Errors occured during startup!" << '\n'; - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch ( std::exception const& ex ) { - Catch::cerr() << ex.what() << '\n'; - } - } + if( m_startupExceptions ) return 1; - } int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); @@ -236,6 +246,9 @@ namespace Catch { } int Session::runInternal() { + if( m_startupExceptions ) + return 1; + if( m_configData.showHelp || m_configData.libIdentify ) return 0; diff --git a/include/internal/catch_session.h b/include/internal/catch_session.h index dca8a051..b814aa6a 100644 --- a/include/internal/catch_session.h +++ b/include/internal/catch_session.h @@ -45,6 +45,7 @@ namespace Catch { clara::Parser m_cli; ConfigData m_configData; std::shared_ptr m_config; + bool m_startupExceptions = false; }; } // end namespace Catch From 8b40c264341f25b57f9deea73975244008492c0b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 2 Nov 2017 18:01:09 +0000 Subject: [PATCH 396/398] Removed handling of start-up exceptions from custom main docs --- docs/own-main.md | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/docs/own-main.md b/docs/own-main.md index 23f472e2..b1f3269f 100644 --- a/docs/own-main.md +++ b/docs/own-main.md @@ -39,34 +39,20 @@ If you still want Catch to process the command line, but you want to programatic int main( int argc, char* argv[] ) { Catch::Session session; // There must be exactly one instance - + // writing to session.configData() here sets defaults // this is the preferred way to set them - - // Verify that all tests, aliases, etc registered properly - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch (std::exception const& ex) { - Catch::cerr() << ex.what(); - } - } - // Indicate that an error occured before main - return 1; - } - + int returnCode = session.applyCommandLine( argc, argv ); if( returnCode != 0 ) // Indicates a command line error - return returnCode; - + return returnCode; + // writing to session.configData() or session.Config() here // overrides command line args // only do this if you know you need to int numFailed = session.run(); + // numFailed is clamped to 255 as some unices only use the lower 8 bits. // This clamping has already been applied, so just return it here // You can also do any post run clean-up here From 1c43fb64c14d9a6be7826ca9f34adfed755a8ba8 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 2 Nov 2017 17:14:32 +0000 Subject: [PATCH 397/398] Added docs for extending command line with Clara --- docs/own-main.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/docs/own-main.md b/docs/own-main.md index b1f3269f..fbaff591 100644 --- a/docs/own-main.md +++ b/docs/own-main.md @@ -66,7 +66,44 @@ To take full control of the config simply omit the call to ```applyCommandLine() ## Adding your own command line options -Catch embeds a powerful command line parser which you can also use to parse your own options out. This capability is still in active development but will be documented here when it is ready. +Catch embeds a powerful command line parser called [Clara](https://github.com/philsquared/Clara). +As of Catch2 (and Clara 1.0) Clara allows you to write _composable_ option and argument parsers, +so extending Catch's own command line options is now easy. + +```c++ +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" + +int main( int argc, char* argv[] ) +{ + Catch::Session session; // There must be exactly one instance + + int height = 0; // Some user variable you want to be able to set + + // Build a new parser on top of Catch's + auto cli + = session.cli() // Get Catch's composite command line parser + | Opt( height, "height" ) // bind variable to a new option, with a hint string + ["-g"]["--height"] // the option names it will respond to + ("how high?"); // description string for the help output + + // Now pass the new composite back to Catch so it uses that + session.cli( cli ); + + // Let Catch (using Clara) parse the command line + int returnCode = session.applyCommandLine( argc, argv ); + if( returnCode != 0 ) // Indicates a command line error + return returnCode; + + // if set on the command line then 'height' is now set at this point + if( height > 0 ) + std::cout << "height: " << height << std::endl; + + return session.run(); +} +``` + +See the [Clara documentation](https://github.com/philsquared/Clara/blob/master/README.md) for more details. --- From b119ebdde15ae4b092f22766fcd652307b42cdf2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 3 Nov 2017 12:01:52 +0000 Subject: [PATCH 398/398] v2.0.1 release --- CMakeLists.txt | 2 +- conanfile.py | 2 +- docs/release-notes.md | 2 +- include/internal/catch_version.cpp | 2 +- single_include/catch.hpp | 102 ++++++++++++++++++----------- test_package/conanfile.py | 2 +- 6 files changed, 68 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 92a55dae..41d2f44a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(CATCH_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(SELF_TEST_DIR ${CATCH_DIR}/projects/SelfTest) set(BENCHMARK_DIR ${CATCH_DIR}/projects/Benchmark) set(HEADER_DIR ${CATCH_DIR}/include) -set(CATCH_VERSION_NUMBER 2.0.0-develop.6) +set(CATCH_VERSION_NUMBER 2.0.1) if(USE_CPP14) message(STATUS "Enabling C++14") diff --git a/conanfile.py b/conanfile.py index 5e6886ca..b4993b71 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.0.0-develop.6" + version = "2.0.1" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/docs/release-notes.md b/docs/release-notes.md index 92659884..f51f68fb 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,5 +1,5 @@ -# 2.0.0 (in progress) +# 2.0.1 ## Breaking changes * Removed C++98 support diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index 699a4843..a9dc64e6 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 6 ); + static Version version( 2, 0, 1, "", 0 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index bc9e447d..362f8693 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.0.0-develop.6 - * Generated: 2017-10-31 15:09:47.277913 + * Catch v2.0.1 + * Generated: 2017-11-03 11:53:39.642003 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. @@ -1835,16 +1835,15 @@ namespace Catch { do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) // end catch_enforce.h -#include - #include namespace Catch { namespace Detail { - double dmax(double lhs, double rhs); - class Approx { + private: + bool equalityComparisonImpl(double other) const; + public: explicit Approx ( double value ); @@ -1865,14 +1864,8 @@ namespace Detail { template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { - // Thanks to Richard Harris for his help refining this formula auto lhs_v = static_cast(lhs); - bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + - dmax(std::fabs(lhs_v), std::fabs(rhs.m_value))); - if (relativeOK) { - return true; - } - return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin; + return rhs.equalityComparisonImpl(lhs_v); } template ::value>::type> @@ -1912,14 +1905,21 @@ namespace Detail { template ::value>::type> Approx& epsilon( T const& newEpsilon ) { - m_epsilon = static_cast(newEpsilon); + double epsilonAsDouble = static_cast(newEpsilon); + CATCH_ENFORCE(epsilonAsDouble >= 0 && epsilonAsDouble <= 1.0, + "Invalid Approx::epsilon: " << epsilonAsDouble + << ", Approx::epsilon has to be between 0 and 1"); + m_epsilon = epsilonAsDouble; return *this; } template ::value>::type> Approx& margin( T const& newMargin ) { - m_margin = static_cast(newMargin); - CATCH_ENFORCE(m_margin >= 0, "Invalid Approx::margin: " << m_margin << ", Approx::Margin has to be non-negative."); + double marginAsDouble = static_cast(newMargin); + CATCH_ENFORCE(marginAsDouble >= 0, + "Invalid Approx::margin: " << marginAsDouble + << ", Approx::Margin has to be non-negative."); + m_margin = marginAsDouble; return *this; } @@ -3980,22 +3980,26 @@ namespace Catch { // Cpp files will be included in the single-header file here // start catch_approx.cpp +#include #include +namespace { + +// Performs equivalent check of std::fabs(lhs - rhs) <= margin +// But without the subtraction to allow for INFINITY in comparison +bool marginComparison(double lhs, double rhs, double margin) { + return (lhs + margin >= rhs) && (rhs + margin >= lhs); +} + +} + namespace Catch { namespace Detail { - double dmax(double lhs, double rhs) { - if (lhs < rhs) { - return rhs; - } - return lhs; - } - Approx::Approx ( double value ) : m_epsilon( std::numeric_limits::epsilon()*100 ), m_margin( 0.0 ), - m_scale( 1.0 ), + m_scale( 0.0 ), m_value( value ) {} @@ -4009,6 +4013,12 @@ namespace Detail { return oss.str(); } + bool Approx::equalityComparisonImpl(const double other) const { + // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value + // Thanks to Richard Harris for his help refining the scaled margin value + return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); + } + } // end namespace Detail std::string StringMaker::convert(Catch::Detail::Approx const& value) { @@ -8055,6 +8065,7 @@ namespace Catch { clara::Parser m_cli; ConfigData m_configData; std::shared_ptr m_config; + bool m_startupExceptions = false; }; } // end namespace Catch @@ -8186,8 +8197,26 @@ namespace Catch { Session::Session() { static bool alreadyInstantiated = false; - if( alreadyInstantiated ) - CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); + if( alreadyInstantiated ) { + try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } + catch(...) { getMutableRegistryHub().registerStartupException(); } + } + + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + m_startupExceptions = true; + Colour colourGuard( Colour::Red ); + Catch::cerr() << "Errors occured during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; + } + } + } + alreadyInstantiated = true; m_cli = makeCommandLineParser( m_configData ); } @@ -8210,6 +8239,9 @@ namespace Catch { } int Session::applyCommandLine( int argc, char* argv[] ) { + if( m_startupExceptions ) + return 1; + auto result = m_cli.parse( clara::Args( argc, argv ) ); if( !result ) { Catch::cerr() @@ -8235,19 +8267,8 @@ namespace Catch { } int Session::run( int argc, char* argv[] ) { - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - Catch::cerr() << "Errors occured during startup!" << '\n'; - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch ( std::exception const& ex ) { - Catch::cerr() << ex.what() << '\n'; - } - } + if( m_startupExceptions ) return 1; - } int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); @@ -8306,6 +8327,9 @@ namespace Catch { } int Session::runInternal() { + if( m_startupExceptions ) + return 1; + if( m_configData.showHelp || m_configData.libIdentify ) return 0; @@ -9802,7 +9826,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 6 ); + static Version version( 2, 0, 1, "", 0 ); return version; } diff --git a/test_package/conanfile.py b/test_package/conanfile.py index ec99f3bc..207c480e 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.0.0-develop.6@%s/%s" % (username, channel) + requires = "Catch/2.0.1@%s/%s" % (username, channel) def build(self): cmake = CMake(self)