diff options
Diffstat (limited to 'include/internal/catch_session.cpp')
-rw-r--r-- | include/internal/catch_session.cpp | 313 |
1 files changed, 0 insertions, 313 deletions
diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp deleted file mode 100644 index 24ebe4de..00000000 --- a/include/internal/catch_session.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * 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.h" -#include "catch_console_colour.h" -#include "catch_enforce.h" -#include "catch_list.h" -#include "catch_context.h" -#include "catch_run_context.h" -#include "catch_stream.h" -#include "catch_test_spec.h" -#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 "catch_stream.h" -#include "catch_windows_h_proxy.h" -#include "../reporters/catch_reporter_listening.h" - -#include <cstdlib> -#include <iomanip> -#include <set> -#include <iterator> - -namespace Catch { - - namespace { - const int MaxExitCode = 255; - - IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { - auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); - CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); - - return reporter; - } - - IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) { - if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { - return createReporter(config->getReporterName(), config); - } - - // On older platforms, returning std::unique_ptr<ListeningReporter> - // when the return type is std::unique_ptr<IStreamingReporter> - // doesn't compile without a std::move call. However, this causes - // a warning on newer platforms. Thus, we have to work around - // it a bit and downcast the pointer manually. - auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter); - auto& multi = static_cast<ListeningReporter&>(*ret); - auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); - for (auto const& listener : listeners) { - multi.addListener(listener->create(Catch::ReporterConfig(config))); - } - multi.addReporter(createReporter(config->getReporterName(), config)); - return ret; - } - - class TestGroup { - public: - explicit TestGroup(std::shared_ptr<Config> const& config) - : m_config{config} - , m_context{config, makeReporter(config)} - { - auto const& allTestCases = getAllTestCasesSorted(*m_config); - m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config); - auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); - - if (m_matches.empty() && invalidArgs.empty()) { - for (auto const& test : allTestCases) - if (!test.isHidden()) - m_tests.emplace(&test); - } else { - for (auto const& match : m_matches) - m_tests.insert(match.tests.begin(), match.tests.end()); - } - } - - Totals execute() { - auto const& invalidArgs = m_config->testSpec().getInvalidArgs(); - Totals totals; - m_context.testGroupStarting(m_config->name(), 1, 1); - for (auto const& testCase : m_tests) { - if (!m_context.aborting()) - totals += m_context.runTest(*testCase); - else - m_context.reporter().skipTest(*testCase); - } - - for (auto const& match : m_matches) { - if (match.tests.empty()) { - m_context.reporter().noMatchingTestCases(match.name); - totals.error = -1; - } - } - - if (!invalidArgs.empty()) { - for (auto const& invalidArg: invalidArgs) - m_context.reporter().reportInvalidArguments(invalidArg); - } - - m_context.testGroupEnded(m_config->name(), totals, 1, 1); - return totals; - } - - private: - using Tests = std::set<TestCase const*>; - - std::shared_ptr<Config> m_config; - RunContext m_context; - Tests m_tests; - TestSpec::Matches m_matches; - }; - - void applyFilenamesAsTags(Catch::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; - auto lastSlash = filename.find_last_of("\\/"); - if (lastSlash != std::string::npos) { - filename.erase(0, lastSlash); - filename[0] = '#'; - } - - auto lastDot = filename.find_last_of('.'); - if (lastDot != std::string::npos) { - filename.erase(lastDot); - } - - tags.push_back(std::move(filename)); - setTags(testCase, tags); - } - } - - } // anon namespace - - Session::Session() { - static bool alreadyInstantiated = false; - if( alreadyInstantiated ) { - CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } - CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); } - } - - // There cannot be exceptions at startup in no-exception mode. -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); - if ( !exceptions.empty() ) { - config(); - getCurrentMutableContext().setConfig(m_config); - - m_startupExceptions = true; - Colour colourGuard( Colour::Red ); - Catch::cerr() << "Errors occurred during startup!" << '\n'; - // iterate over all exceptions and notify user - for ( const auto& ex_ptr : exceptions ) { - try { - std::rethrow_exception(ex_ptr); - } catch ( std::exception const& ex ) { - Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; - } - } - } -#endif - - 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 Catch2 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 const * const * argv ) { - if( m_startupExceptions ) - return 1; - - auto result = m_cli.parse( clara::Args( argc, argv ) ); - if( !result ) { - config(); - getCurrentMutableContext().setConfig(m_config); - 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; - } - -#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE) - int Session::applyCommandLine( int argc, wchar_t const * const * argv ) { - - char **utf8Argv = new char *[ argc ]; - - for ( int i = 0; i < argc; ++i ) { - int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr ); - - utf8Argv[ i ] = new char[ bufSize ]; - - WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr ); - } - - int returnCode = applyCommandLine( argc, utf8Argv ); - - for ( int i = 0; i < argc; ++i ) - delete [] utf8Argv[ i ]; - - delete [] utf8Argv; - - return returnCode; - } -#endif - - void Session::useConfigData( ConfigData const& configData ) { - m_configData = configData; - m_config.reset(); - } - - 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_startupExceptions ) - return 1; - - if (m_configData.showHelp || m_configData.libIdentify) { - return 0; - } - - CATCH_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( m_config ) ) - return static_cast<int>( *listed ); - - TestGroup tests { m_config }; - auto const totals = tests.execute(); - - if( m_config->warnAboutNoTests() && totals.error == -1 ) - return 2; - - // Note that on unices only the lower 8 bits are usually used, clamping - // the return value to 255 prevents false negative when some multiple - // of 256 tests has failed - return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed))); - } -#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) - catch( std::exception& ex ) { - Catch::cerr() << ex.what() << std::endl; - return MaxExitCode; - } -#endif - } - -} // end namespace Catch |