diff --git a/CMakeLists.txt b/CMakeLists.txt index aa4b5f23..db830904 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -265,7 +265,7 @@ set(REPORTER_HEADERS ${HEADER_DIR}/reporters/catch_reporter_compact.h ${HEADER_DIR}/reporters/catch_reporter_console.h ${HEADER_DIR}/reporters/catch_reporter_junit.h - ${HEADER_DIR}/reporters/catch_reporter_multi.h + ${HEADER_DIR}/reporters/catch_reporter_listening.h ${HEADER_DIR}/reporters/catch_reporter_tap.hpp ${HEADER_DIR}/reporters/catch_reporter_teamcity.hpp ${HEADER_DIR}/reporters/catch_reporter_xml.h @@ -275,7 +275,7 @@ set(REPORTER_SOURCES ${HEADER_DIR}/reporters/catch_reporter_compact.cpp ${HEADER_DIR}/reporters/catch_reporter_console.cpp ${HEADER_DIR}/reporters/catch_reporter_junit.cpp - ${HEADER_DIR}/reporters/catch_reporter_multi.cpp + ${HEADER_DIR}/reporters/catch_reporter_listening.cpp ${HEADER_DIR}/reporters/catch_reporter_xml.cpp ) set(REPORTER_FILES ${REPORTER_HEADERS} ${REPORTER_SOURCES}) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 9d5e772e..7bafc9c3 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -54,14 +54,12 @@ namespace Catch { std::string outputFilename; std::string name; std::string processName; - #ifndef CATCH_CONFIG_DEFAULT_REPORTER #define CATCH_CONFIG_DEFAULT_REPORTER "console" #endif std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; #undef CATCH_CONFIG_DEFAULT_REPORTER - std::vector testsOrTags; std::vector sectionsToRun; }; diff --git a/include/internal/catch_interfaces_reporter.cpp b/include/internal/catch_interfaces_reporter.cpp index 129a5f4d..0c367c5b 100644 --- a/include/internal/catch_interfaces_reporter.cpp +++ b/include/internal/catch_interfaces_reporter.cpp @@ -6,7 +6,7 @@ */ #include "catch_interfaces_reporter.h" -#include "../reporters/catch_reporter_multi.h" +#include "../reporters/catch_reporter_listening.h" namespace Catch { @@ -111,25 +111,4 @@ namespace Catch { IReporterFactory::~IReporterFactory() = default; IReporterRegistry::~IReporterRegistry() = default; - void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) { - - if( !existingReporter ) { - existingReporter = std::move( additionalReporter ); - return; - } - - MultipleReporters* multi = nullptr; - - if( existingReporter->isMulti() ) { - multi = static_cast( existingReporter.get() ); - } - else { - auto newMulti = std::unique_ptr( new MultipleReporters ); - newMulti->add( std::move( existingReporter ) ); - multi = newMulti.get(); - existingReporter = std::move( newMulti ); - } - multi->add( std::move( additionalReporter ) ); - } - } // end namespace Catch diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index b620abb6..76f5fd5a 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -226,8 +226,6 @@ namespace Catch { virtual Listeners const& getListeners() const = 0; }; - void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ); - } // end namespace Catch #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp index a7ae19db..2c5fe08e 100644 --- a/include/internal/catch_session.cpp +++ b/include/internal/catch_session.cpp @@ -20,6 +20,7 @@ #include "catch_text.h" #include "catch_stream.h" #include "catch_windows_h_proxy.h" +#include "../reporters/catch_reporter_listening.h" #include #include @@ -36,22 +37,26 @@ namespace Catch { return reporter; } - IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { - return createReporter(config->getReporterName(), config); - } + if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { + return createReporter(config->getReporterName(), config); + } + auto multi = std::unique_ptr(new ListeningReporter); - void addListeners(IStreamingReporterPtr& reporters, IConfigPtr const& config) { auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); - for (auto const& listener : listeners) - addReporter(reporters, listener->create(Catch::ReporterConfig(config))); + for (auto const& listener : listeners) { + multi->addListener(listener->create(Catch::ReporterConfig(config))); + } + multi->addReporter(createReporter(config->getReporterName(), config)); + return std::move(multi); } Catch::Totals runTests(std::shared_ptr const& config) { - IStreamingReporterPtr reporter = makeReporter(config); - addListeners(reporter, config); + // FixMe: Add listeners in order first, then add reporters. + + auto reporter = makeReporter(config); RunContext context(config, std::move(reporter)); diff --git a/include/reporters/catch_reporter_listening.cpp b/include/reporters/catch_reporter_listening.cpp new file mode 100644 index 00000000..cd625154 --- /dev/null +++ b/include/reporters/catch_reporter_listening.cpp @@ -0,0 +1,136 @@ +/* + * Created by Phil on 5/08/2015. + * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + + #include "catch_reporter_listening.h" +#include + +namespace Catch { + + void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { + m_listeners.push_back( std::move( listener ) ); + } + + void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { + assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); + m_reporter = std::move( reporter ); + } + + ReporterPreferences ListeningReporter::getPreferences() const { + return m_reporter->getPreferences(); + } + + std::set ListeningReporter::getSupportedVerbosities() { + return std::set{ }; + } + + + void ListeningReporter::noMatchingTestCases( std::string const& spec ) { + for ( auto const& listener : m_listeners ) { + listener->noMatchingTestCases( spec ); + } + m_reporter->noMatchingTestCases( spec ); + } + + void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { + for ( auto const& listener : m_listeners ) { + listener->benchmarkStarting( benchmarkInfo ); + } + m_reporter->benchmarkStarting( benchmarkInfo ); + } + void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { + for ( auto const& listener : m_listeners ) { + listener->benchmarkEnded( benchmarkStats ); + } + m_reporter->benchmarkEnded( benchmarkStats ); + } + + void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { + for ( auto const& listener : m_listeners ) { + listener->testRunStarting( testRunInfo ); + } + m_reporter->testRunStarting( testRunInfo ); + } + + void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { + for ( auto const& listener : m_listeners ) { + listener->testGroupStarting( groupInfo ); + } + m_reporter->testGroupStarting( groupInfo ); + } + + + void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { + for ( auto const& listener : m_listeners ) { + listener->testCaseStarting( testInfo ); + } + m_reporter->testCaseStarting( testInfo ); + } + + void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { + for ( auto const& listener : m_listeners ) { + listener->sectionStarting( sectionInfo ); + } + m_reporter->sectionStarting( sectionInfo ); + } + + void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { + for ( auto const& listener : m_listeners ) { + listener->assertionStarting( assertionInfo ); + } + m_reporter->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { + for( auto const& listener : m_listeners ) { + static_cast( listener->assertionEnded( assertionStats ) ); + } + return m_reporter->assertionEnded( assertionStats ); + } + + void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { + for ( auto const& listener : m_listeners ) { + listener->sectionEnded( sectionStats ); + } + m_reporter->sectionEnded( sectionStats ); + } + + void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { + for ( auto const& listener : m_listeners ) { + listener->testCaseEnded( testCaseStats ); + } + m_reporter->testCaseEnded( testCaseStats ); + } + + void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { + for ( auto const& listener : m_listeners ) { + listener->testGroupEnded( testGroupStats ); + } + m_reporter->testGroupEnded( testGroupStats ); + } + + void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { + for ( auto const& listener : m_listeners ) { + listener->testRunEnded( testRunStats ); + } + m_reporter->testRunEnded( testRunStats ); + } + + + void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { + for ( auto const& listener : m_listeners ) { + listener->skipTest( testInfo ); + } + m_reporter->skipTest( testInfo ); + } + + bool ListeningReporter::isMulti() const { + return true; + } + +} // end namespace Catch diff --git a/include/reporters/catch_reporter_multi.h b/include/reporters/catch_reporter_listening.h similarity index 87% rename from include/reporters/catch_reporter_multi.h rename to include/reporters/catch_reporter_listening.h index 985d442f..bf97edef 100644 --- a/include/reporters/catch_reporter_multi.h +++ b/include/reporters/catch_reporter_listening.h @@ -11,12 +11,14 @@ namespace Catch { - class MultipleReporters : public IStreamingReporter { + class ListeningReporter : public IStreamingReporter { using Reporters = std::vector; - Reporters m_reporters; + Reporters m_listeners; + IStreamingReporterPtr m_reporter = nullptr; public: - void add( IStreamingReporterPtr&& reporter ); + void addListener( IStreamingReporterPtr&& listener ); + void addReporter( IStreamingReporterPtr&& reporter ); public: // IStreamingReporter diff --git a/include/reporters/catch_reporter_multi.cpp b/include/reporters/catch_reporter_multi.cpp deleted file mode 100644 index 23bb1603..00000000 --- a/include/reporters/catch_reporter_multi.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Created by Phil on 5/08/2015. - * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ - - #include "catch_reporter_multi.h" - -namespace Catch { - - void MultipleReporters::add( IStreamingReporterPtr&& reporter ) { - m_reporters.push_back( std::move( reporter ) ); - } - - ReporterPreferences MultipleReporters::getPreferences() const { - return m_reporters[0]->getPreferences(); - } - - std::set MultipleReporters::getSupportedVerbosities() { - return std::set{ }; - } - - - void MultipleReporters::noMatchingTestCases( std::string const& spec ) { - for( auto const& reporter : m_reporters ) - reporter->noMatchingTestCases( spec ); - } - - void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { - for( auto const& reporter : m_reporters ) - reporter->benchmarkStarting( benchmarkInfo ); - } - void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { - for( auto const& reporter : m_reporters ) - reporter->benchmarkEnded( benchmarkStats ); - } - - void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { - for( auto const& reporter : m_reporters ) - reporter->testRunStarting( testRunInfo ); - } - - void MultipleReporters::testGroupStarting( GroupInfo const& groupInfo ) { - for( auto const& reporter : m_reporters ) - reporter->testGroupStarting( groupInfo ); - } - - - void MultipleReporters::testCaseStarting( TestCaseInfo const& testInfo ) { - for( auto const& reporter : m_reporters ) - reporter->testCaseStarting( testInfo ); - } - - void MultipleReporters::sectionStarting( SectionInfo const& sectionInfo ) { - for( auto const& reporter : m_reporters ) - reporter->sectionStarting( sectionInfo ); - } - - void MultipleReporters::assertionStarting( AssertionInfo const& assertionInfo ) { - for( auto const& reporter : m_reporters ) - reporter->assertionStarting( assertionInfo ); - } - - // The return value indicates if the messages buffer should be cleared: - bool MultipleReporters::assertionEnded( AssertionStats const& assertionStats ) { - bool clearBuffer = false; - for( auto const& reporter : m_reporters ) - clearBuffer |= reporter->assertionEnded( assertionStats ); - return clearBuffer; - } - - void MultipleReporters::sectionEnded( SectionStats const& sectionStats ) { - for( auto const& reporter : m_reporters ) - reporter->sectionEnded( sectionStats ); - } - - void MultipleReporters::testCaseEnded( TestCaseStats const& testCaseStats ) { - for( auto const& reporter : m_reporters ) - reporter->testCaseEnded( testCaseStats ); - } - - void MultipleReporters::testGroupEnded( TestGroupStats const& testGroupStats ) { - for( auto const& reporter : m_reporters ) - reporter->testGroupEnded( testGroupStats ); - } - - void MultipleReporters::testRunEnded( TestRunStats const& testRunStats ) { - for( auto const& reporter : m_reporters ) - reporter->testRunEnded( testRunStats ); - } - - - void MultipleReporters::skipTest( TestCaseInfo const& testInfo ) { - for( auto const& reporter : m_reporters ) - reporter->skipTest( testInfo ); - } - - bool MultipleReporters::isMulti() const { - return true; - } - -} // end namespace Catch