mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Move session to internal, split apart implementation
This commit is contained in:
		| @@ -36,8 +36,8 @@ namespace Catch { | ||||
|         NonCopyable& operator = ( NonCopyable && )     = delete; | ||||
|  | ||||
|     protected: | ||||
|         NonCopyable() {} | ||||
|         virtual ~NonCopyable(); | ||||
|         NonCopyable()          = default; | ||||
|         virtual ~NonCopyable() = default; | ||||
|     }; | ||||
|  | ||||
|     struct SourceLineInfo { | ||||
|   | ||||
| @@ -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 <memory> | ||||
| #include <vector> | ||||
| #include <string> | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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() {} | ||||
|   | ||||
							
								
								
									
										251
									
								
								include/internal/catch_session.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								include/internal/catch_session.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <cstdlib> | ||||
| #include <iomanip> | ||||
|  | ||||
| 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<Config> 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<Config> 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<TestCase> 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<std::vector<TestCase>&>( 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<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::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<Config>( 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<std::size_t> listed = list( config() ) ) | ||||
|                 return static_cast<int>( *listed ); | ||||
|  | ||||
|             return (std::min)( MaxExitCode, static_cast<int>( runTests( m_config ).assertions.failed ) ); | ||||
|         } | ||||
|         catch( std::exception& ex ) { | ||||
|             Catch::cerr() << ex.what() << std::endl; | ||||
|             return MaxExitCode; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } // end namespace Catch | ||||
							
								
								
									
										52
									
								
								include/internal/catch_session.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								include/internal/catch_session.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <memory> | ||||
|  | ||||
| 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<Config> m_config; | ||||
|     }; | ||||
|  | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED | ||||
| @@ -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; | ||||
|   | ||||
| @@ -16,7 +16,7 @@ namespace Catch { | ||||
|  | ||||
|     class StreamBufBase : public std::streambuf { | ||||
|     public: | ||||
|         virtual ~StreamBufBase() noexcept; | ||||
|         virtual ~StreamBufBase() = default; | ||||
|     }; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský