mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Removed zombie files
These files were removed from the Catch2 branch, and crept back in when Catch2 merged with master
This commit is contained in:
		| @@ -1,272 +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_list.hpp" | ||||
| #include "internal/catch_run_context.hpp" | ||||
| #include "internal/catch_test_spec.hpp" | ||||
| #include "internal/catch_version.h" | ||||
| #include "internal/catch_text.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <stdlib.h> | ||||
| #include <limits> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) { | ||||
|         Ptr<IStreamingReporter> 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; | ||||
|     } | ||||
|  | ||||
| #if !defined(CATCH_CONFIG_DEFAULT_REPORTER) | ||||
| #define CATCH_CONFIG_DEFAULT_REPORTER "console" | ||||
| #endif | ||||
|  | ||||
|     Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) { | ||||
|         std::vector<std::string> reporters = config->getReporterNames(); | ||||
|         if( reporters.empty() ) | ||||
|             reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER ); | ||||
|  | ||||
|         Ptr<IStreamingReporter> reporter; | ||||
|         for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end(); | ||||
|                 it != itEnd; | ||||
|                 ++it ) | ||||
|             reporter = addReporter( reporter, createReporter( *it, config ) ); | ||||
|         return reporter; | ||||
|     } | ||||
|     Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> 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<Config> const& config ) { | ||||
|  | ||||
|         Ptr<IConfig const> iconfig = config.get(); | ||||
|  | ||||
|         Ptr<IStreamingReporter> 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<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig ); | ||||
|         for( std::vector<TestCase>::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<TestCase> const& tests = getAllTestCasesSorted( config ); | ||||
|         for(std::size_t i = 0; i < tests.size(); ++i ) { | ||||
|             TestCase& test = const_cast<TestCase&>( tests[i] ); | ||||
|             std::set<std::string> 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; | ||||
|         } | ||||
|         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 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 ); | ||||
|                 if( m_configData.libIdentify ) | ||||
|                     libIdentify(); | ||||
|                 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<int>::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; | ||||
|         } | ||||
|  | ||||
|     #if defined(WIN32) && defined(UNICODE) | ||||
|         int run( int argc, wchar_t const* const* 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 = applyCommandLine( argc, utf8Argv ); | ||||
|             if( returnCode == 0 ) | ||||
|                 returnCode = run(); | ||||
|  | ||||
|             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<void>(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<void>(std::getchar()); | ||||
|             } | ||||
|             return exitCode; | ||||
|         } | ||||
|  | ||||
|         Clara::CommandLine<ConfigData> const& cli() const { | ||||
|             return m_cli; | ||||
|         } | ||||
|         std::vector<Clara::Parser::Token> 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: | ||||
|  | ||||
|         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<std::size_t> listed = list( config() ) ) | ||||
|                     return static_cast<int>( *listed ); | ||||
|  | ||||
|                 return static_cast<int>( runTests( m_config ).assertions.failed ); | ||||
|             } | ||||
|             catch( std::exception& ex ) { | ||||
|                 Catch::cerr() << ex.what() << std::endl; | ||||
|                 return (std::numeric_limits<int>::max)(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Clara::CommandLine<ConfigData> m_cli; | ||||
|         std::vector<Clara::Parser::Token> m_unusedTokens; | ||||
|         ConfigData m_configData; | ||||
|         Ptr<Config> m_config; | ||||
|     }; | ||||
|  | ||||
|     bool Session::alreadyInstantiated = false; | ||||
|  | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED | ||||
| @@ -1,202 +0,0 @@ | ||||
| /* | ||||
|  *  Created by Phil on 28/04/2011. | ||||
|  *  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_APPROX_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_tostring.h" | ||||
|  | ||||
| #include <cmath> | ||||
| #include <limits> | ||||
|  | ||||
| #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) | ||||
| #include <type_traits> | ||||
| #endif | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Detail { | ||||
|  | ||||
|     class Approx { | ||||
|     public: | ||||
|         explicit Approx ( double value ) | ||||
|         :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ), | ||||
|             m_margin( 0.0 ), | ||||
|             m_scale( 1.0 ), | ||||
|             m_value( value ) | ||||
|         {} | ||||
|  | ||||
|         static Approx custom() { | ||||
|             return Approx( 0 ); | ||||
|         } | ||||
|  | ||||
| #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         Approx operator()( T value ) { | ||||
|             Approx approx( static_cast<double>(value) ); | ||||
|             approx.epsilon( m_epsilon ); | ||||
|             approx.margin( m_margin ); | ||||
|             approx.scale( m_scale ); | ||||
|             return approx; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         explicit Approx( T value ): Approx(static_cast<double>(value)) | ||||
|         {} | ||||
|  | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::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 <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator == ( Approx const& lhs, const T& rhs ) { | ||||
|             return operator==( rhs, lhs ); | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator != ( T lhs, Approx const& rhs ) { | ||||
|             return !operator==( lhs, rhs ); | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator != ( Approx const& lhs, T rhs ) { | ||||
|             return !operator==( rhs, lhs ); | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator <= ( T lhs, Approx const& rhs ) { | ||||
|             return double(lhs) < rhs.m_value || lhs == rhs; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator <= ( Approx const& lhs, T rhs ) { | ||||
|             return lhs.m_value < double(rhs) || lhs == rhs; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator >= ( T lhs, Approx const& rhs ) { | ||||
|             return double(lhs) > rhs.m_value || lhs == rhs; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         friend bool operator >= ( Approx const& lhs, T rhs ) { | ||||
|             return lhs.m_value > double(rhs) || lhs == rhs; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         Approx& epsilon( T newEpsilon ) { | ||||
|             m_epsilon = double(newEpsilon); | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> | ||||
|         Approx& margin( T newMargin ) { | ||||
|             m_margin = double(newMargin); | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::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>( Detail::Approx const& value ) { | ||||
|     return value.toString(); | ||||
| } | ||||
|  | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED | ||||
| @@ -1,109 +0,0 @@ | ||||
| /* | ||||
|  *  Created by Phil on 8/8/12 | ||||
|  *  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_ASSERTIONRESULT_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_assertionresult.h" | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|  | ||||
|     AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){} | ||||
|  | ||||
|     AssertionInfo::AssertionInfo(   char const * _macroName, | ||||
|                                     SourceLineInfo const& _lineInfo, | ||||
|                                     char const * _capturedExpression, | ||||
|                                     ResultDisposition::Flags _resultDisposition, | ||||
|                                     char const * _secondArg) | ||||
|     :   macroName( _macroName ), | ||||
|         lineInfo( _lineInfo ), | ||||
|         capturedExpression( _capturedExpression ), | ||||
|         resultDisposition( _resultDisposition ), | ||||
|         secondArg( _secondArg ) | ||||
|     {} | ||||
|  | ||||
|     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[0] != 0; | ||||
|     } | ||||
|  | ||||
|     bool AssertionResult::hasMessage() const { | ||||
|         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 "!(" + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + ")"; | ||||
|         else | ||||
|             return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); | ||||
|     } | ||||
|     std::string AssertionResult::getExpressionInMacro() const { | ||||
|         if( m_info.macroName[0] == 0 ) | ||||
|             return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); | ||||
|         else | ||||
|             return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; | ||||
|     } | ||||
|  | ||||
|     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 | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED | ||||
| @@ -1,240 +0,0 @@ | ||||
| /* | ||||
|  *  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) | ||||
|  */ | ||||
| #ifndef TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_config.hpp" | ||||
| #include "catch_common.h" | ||||
| #include "catch_clara.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <ctime> | ||||
|  | ||||
| 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<WarnAbout::What>( 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<unsigned int>( 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<Verbosity::Level>( 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 setWaitForKeypress( ConfigData& config, std::string const& keypress ) { | ||||
|         std::string 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 | ||||
|             throw std::runtime_error( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     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<ConfigData> makeCommandLineParser() { | ||||
|  | ||||
|         using namespace Clara; | ||||
|         CommandLine<ConfigData> 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-extra-info"] | ||||
|             .describe( "list all/matching test cases with more info" ) | ||||
|             .bind( &ConfigData::listExtraInfo ); | ||||
|  | ||||
|         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" ); | ||||
|  | ||||
|         cli["--libidentify"] | ||||
|             .describe( "report name and version according to libidentify standard" ) | ||||
|             .bind( &ConfigData::libIdentify ); | ||||
|  | ||||
|         cli["--wait-for-keypress"] | ||||
|                 .describe( "waits for a keypress before exiting" ) | ||||
|                 .bind( &setWaitForKeypress, "start|exit|both" ); | ||||
|  | ||||
|         return cli; | ||||
|     } | ||||
|  | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED | ||||
| @@ -1,147 +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 <cstddef> | ||||
|  | ||||
| namespace Catch { | ||||
| namespace Internal { | ||||
|  | ||||
|     enum Operator { | ||||
|         IsEqualTo, | ||||
|         IsNotEqualTo, | ||||
|         IsLessThan, | ||||
|         IsGreaterThan, | ||||
|         IsLessThanOrEqualTo, | ||||
|         IsGreaterThanOrEqualTo | ||||
|     }; | ||||
|  | ||||
|     template<Operator Op> struct OperatorTraits             { static const char* getName(){ return "*error*"; } }; | ||||
|     template<> struct OperatorTraits<IsEqualTo>             { static const char* getName(){ return "=="; } }; | ||||
|     template<> struct OperatorTraits<IsNotEqualTo>          { static const char* getName(){ return "!="; } }; | ||||
|     template<> struct OperatorTraits<IsLessThan>            { static const char* getName(){ return "<"; } }; | ||||
|     template<> struct OperatorTraits<IsGreaterThan>         { static const char* getName(){ return ">"; } }; | ||||
|     template<> struct OperatorTraits<IsLessThanOrEqualTo>   { static const char* getName(){ return "<="; } }; | ||||
|     template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; | ||||
|  | ||||
|     template<typename T> | ||||
|     T& removeConst(T const &t) { return const_cast<T&>(t); } | ||||
| #ifdef CATCH_CONFIG_CPP11_NULLPTR | ||||
|     inline std::nullptr_t removeConst(std::nullptr_t) { return nullptr; } | ||||
| #endif | ||||
|  | ||||
|  | ||||
|     // 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<typename T1, typename T2, Operator Op> | ||||
|     struct Evaluator{}; | ||||
|  | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsEqualTo> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs) { | ||||
|             return bool(removeConst(lhs) == removeConst(rhs) ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsNotEqualTo> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool(removeConst(lhs) != removeConst(rhs) ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsLessThan> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool(removeConst(lhs) < removeConst(rhs) ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsGreaterThan> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool(removeConst(lhs) > removeConst(rhs) ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { | ||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { | ||||
|             return bool(removeConst(lhs) >= removeConst(rhs) ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T1, typename T2> | ||||
|     struct Evaluator<T1, T2, IsLessThanOrEqualTo> { | ||||
|         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<typename T> | ||||
|     struct Evaluator<int const&, T* const&, IsEqualTo> { | ||||
|         static bool evaluate( int lhs, T* rhs) { | ||||
|             return reinterpret_cast<void const*>( lhs ) ==  rhs; | ||||
|         } | ||||
|     }; | ||||
|     template<typename T> | ||||
|     struct Evaluator<T* const&, int const&, IsEqualTo> { | ||||
|         static bool evaluate( T* lhs, int rhs) { | ||||
|             return lhs == reinterpret_cast<void const*>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T> | ||||
|     struct Evaluator<int const&, T* const&, IsNotEqualTo> { | ||||
|         static bool evaluate( int lhs, T* rhs) { | ||||
|             return reinterpret_cast<void const*>( lhs ) !=  rhs; | ||||
|         } | ||||
|     }; | ||||
|     template<typename T> | ||||
|     struct Evaluator<T* const&, int const&, IsNotEqualTo> { | ||||
|         static bool evaluate( T* lhs, int rhs) { | ||||
|             return lhs != reinterpret_cast<void const*>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     template<typename T> | ||||
|     struct Evaluator<long const&, T* const&, IsEqualTo> { | ||||
|         static bool evaluate( long lhs, T* rhs) { | ||||
|             return reinterpret_cast<void const*>( lhs ) ==  rhs; | ||||
|         } | ||||
|     }; | ||||
|     template<typename T> | ||||
|     struct Evaluator<T* const&, long const&, IsEqualTo> { | ||||
|         static bool evaluate( T* lhs, long rhs) { | ||||
|             return lhs == reinterpret_cast<void const*>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|     template<typename T> | ||||
|     struct Evaluator<long const&, T* const&, IsNotEqualTo> { | ||||
|         static bool evaluate( long lhs, T* rhs) { | ||||
|             return reinterpret_cast<void const*>( lhs ) !=  rhs; | ||||
|         } | ||||
|     }; | ||||
|     template<typename T> | ||||
|     struct Evaluator<T* const&, long const&, IsNotEqualTo> { | ||||
|         static bool evaluate( T* lhs, long rhs) { | ||||
|             return lhs != reinterpret_cast<void const*>( rhs ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| } // end of namespace Internal | ||||
| } // end of namespace Catch | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #pragma warning(pop) | ||||
| #endif | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED | ||||
| @@ -1,174 +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<typename LhsT, Internal::Operator Op, typename RhsT> | ||||
| class BinaryExpression; | ||||
|  | ||||
| template<typename ArgT, typename MatcherT> | ||||
| class MatchExpression; | ||||
|  | ||||
| // Wraps the LHS of an expression and overloads comparison operators | ||||
| // for also capturing those and RHS (if any) | ||||
| template<typename T> | ||||
| class ExpressionLhs : public DecomposedExpression { | ||||
| public: | ||||
|     ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} | ||||
|  | ||||
|     ExpressionLhs& operator = ( const ExpressionLhs& ); | ||||
|  | ||||
|     template<typename RhsT> | ||||
|     BinaryExpression<T, Internal::IsEqualTo, RhsT const&> | ||||
|     operator == ( RhsT const& rhs ) { | ||||
|         return captureExpression<Internal::IsEqualTo>( rhs ); | ||||
|     } | ||||
|  | ||||
|     template<typename RhsT> | ||||
|     BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&> | ||||
|     operator != ( RhsT const& rhs ) { | ||||
|         return captureExpression<Internal::IsNotEqualTo>( rhs ); | ||||
|     } | ||||
|  | ||||
|     template<typename RhsT> | ||||
|     BinaryExpression<T, Internal::IsLessThan, RhsT const&> | ||||
|     operator < ( RhsT const& rhs ) { | ||||
|         return captureExpression<Internal::IsLessThan>( rhs ); | ||||
|     } | ||||
|  | ||||
|     template<typename RhsT> | ||||
|     BinaryExpression<T, Internal::IsGreaterThan, RhsT const&> | ||||
|     operator > ( RhsT const& rhs ) { | ||||
|         return captureExpression<Internal::IsGreaterThan>( rhs ); | ||||
|     } | ||||
|  | ||||
|     template<typename RhsT> | ||||
|     BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&> | ||||
|     operator <= ( RhsT const& rhs ) { | ||||
|         return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); | ||||
|     } | ||||
|  | ||||
|     template<typename RhsT> | ||||
|     BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&> | ||||
|     operator >= ( RhsT const& rhs ) { | ||||
|         return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); | ||||
|     } | ||||
|  | ||||
|     BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) { | ||||
|         return captureExpression<Internal::IsEqualTo>( rhs ); | ||||
|     } | ||||
|  | ||||
|     BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) { | ||||
|         return captureExpression<Internal::IsNotEqualTo>( 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_lhs ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     template<Internal::Operator Op, typename RhsT> | ||||
|     BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const { | ||||
|         return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs ); | ||||
|     } | ||||
|  | ||||
|     template<Internal::Operator Op> | ||||
|     BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const { | ||||
|         return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     ResultBuilder& m_rb; | ||||
|     T m_lhs; | ||||
|     bool m_truthy; | ||||
| }; | ||||
|  | ||||
| template<typename LhsT, Internal::Operator Op, typename RhsT> | ||||
| 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::Evaluator<LhsT, RhsT, Op>::evaluate( 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<Op>::getName(); | ||||
|         dest += delim; | ||||
|         dest += rhs; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     ResultBuilder& m_rb; | ||||
|     LhsT m_lhs; | ||||
|     RhsT m_rhs; | ||||
| }; | ||||
|  | ||||
| template<typename ArgT, typename MatcherT> | ||||
| 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 | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED | ||||
| @@ -1,419 +0,0 @@ | ||||
|  /* | ||||
|  *  Created by Phil on 22/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_IMPL_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_interfaces_runner.h" | ||||
| #include "catch_interfaces_reporter.h" | ||||
| #include "catch_interfaces_exception.h" | ||||
| #include "catch_config.hpp" | ||||
| #include "catch_test_registry.hpp" | ||||
| #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_timer.h" | ||||
| #include "catch_result_builder.h" | ||||
| #include "catch_fatal_condition.hpp" | ||||
|  | ||||
|  | ||||
| #include <set> | ||||
| #include <string> | ||||
|  | ||||
| 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; | ||||
|     }; | ||||
|  | ||||
|     // 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) | ||||
|         :m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()), | ||||
|         m_targetString(targetString){ | ||||
|             cerr().rdbuf(m_oss.rdbuf()); | ||||
|             clog().rdbuf(m_oss.rdbuf()); | ||||
|         } | ||||
|         ~StdErrRedirect() { | ||||
|             m_targetString += m_oss.str(); | ||||
|             cerr().rdbuf(m_cerrBuf); | ||||
|             clog().rdbuf(m_clogBuf); | ||||
|         } | ||||
|     private: | ||||
|         std::streambuf* m_cerrBuf; | ||||
|         std::streambuf* m_clogBuf; | ||||
|         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<IConfig const> const& _config, Ptr<IStreamingReporter> 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<SectionTracker&>( 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<IConfig const> 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() ) { | ||||
|                 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 | ||||
|             // and should be let to clear themselves out. | ||||
|             static_cast<void>(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 lastAssertionPassed() | ||||
|         { | ||||
|             return m_totals.assertions.passed == (m_prevPassed + 1); | ||||
|         } | ||||
|  | ||||
|         virtual void assertionPassed() | ||||
|         { | ||||
|             m_totals.assertions.passed++; | ||||
|             m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"; | ||||
|             m_lastAssertionInfo.macroName = ""; | ||||
|         } | ||||
|  | ||||
|         virtual void assertionRun() | ||||
|         { | ||||
|             m_prevPassed = m_totals.assertions.passed; | ||||
|         } | ||||
|  | ||||
|         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; | ||||
|             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 ) ); | ||||
|         } | ||||
|  | ||||
|     public: | ||||
|         // !TBD We need to do this another way! | ||||
|         bool aborting() const { | ||||
|             return m_totals.assertions.failed == static_cast<std::size_t>( 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, "", ResultDisposition::Normal ); | ||||
|  | ||||
|                 seedRng( *m_config ); | ||||
|  | ||||
|                 Timer timer; | ||||
|                 timer.start(); | ||||
|                 if( m_reporter->getPreferences().shouldRedirectStdOut ) { | ||||
|                     StreamRedirect coutRedir( Catch::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) { | ||||
|                     makeUnexpectedResultBuilder().useActiveException(); | ||||
|                 } | ||||
|             } | ||||
|             m_testCaseTracker->close(); | ||||
|             handleUnfinishedSections(); | ||||
|             m_messages.clear(); | ||||
|  | ||||
|             Counts assertions = m_totals.assertions - prevAssertions; | ||||
|             bool missingAssertions = testForMissingAssertions( assertions ); | ||||
|  | ||||
|             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, | ||||
|                                     m_lastAssertionInfo.lineInfo, | ||||
|                                     m_lastAssertionInfo.capturedExpression, | ||||
|                                     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<SectionEndInfo>::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<IConfig const> m_config; | ||||
|         Totals m_totals; | ||||
|         Ptr<IStreamingReporter> m_reporter; | ||||
|         std::vector<MessageInfo> m_messages; | ||||
|         AssertionInfo m_lastAssertionInfo; | ||||
|         std::vector<SectionEndInfo> m_unfinishedSections; | ||||
|         std::vector<ITracker*> m_activeSections; | ||||
|         TrackerContext m_trackerContext; | ||||
|         size_t m_prevPassed; | ||||
|         bool m_shouldReportUnexpected; | ||||
|     }; | ||||
|  | ||||
|     IResultCapture& getResultCapture() { | ||||
|         if( IResultCapture* capture = getCurrentContext().getResultCapture() ) | ||||
|             return *capture; | ||||
|         else | ||||
|             throw std::logic_error( "No result capture instance" ); | ||||
|     } | ||||
|  | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED | ||||
| @@ -1,207 +0,0 @@ | ||||
| /* | ||||
|  *  Created by Phil on 7/1/2011 | ||||
|  *  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_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED | ||||
| #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 <vector> | ||||
| #include <set> | ||||
| #include <sstream> | ||||
| #include <algorithm> | ||||
|  | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     struct RandomNumberGenerator { | ||||
|         typedef unsigned int 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<typename V> | ||||
|         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<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { | ||||
|  | ||||
|         std::vector<TestCase> 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<TestCase> const& functions ) { | ||||
|         std::set<TestCase> seenFunctions; | ||||
|         for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end(); | ||||
|             it != itEnd; | ||||
|             ++it ) { | ||||
|             std::pair<std::set<TestCase>::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<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { | ||||
|         std::vector<TestCase> filtered; | ||||
|         filtered.reserve( testCases.size() ); | ||||
|         for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end(); | ||||
|                 it != itEnd; | ||||
|                 ++it ) | ||||
|             if( matchTest( *it, testSpec, config ) ) | ||||
|                 filtered.push_back( *it ); | ||||
|         return filtered; | ||||
|     } | ||||
|     std::vector<TestCase> 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<TestCase> const& getAllTests() const { | ||||
|             return m_functions; | ||||
|         } | ||||
|         virtual std::vector<TestCase> 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<TestCase> m_functions; | ||||
|         mutable RunTests::InWhatOrder m_currentSortOrder; | ||||
|         mutable std::vector<TestCase> m_sortedFunctions; | ||||
|         size_t m_unnamedCount; | ||||
|         std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised | ||||
|     }; | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|     class FreeFunctionTestCase : public SharedImpl<ITestCase> { | ||||
|     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 | ||||
|  | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash