catch_reporter_multi.cpp
1 2 // Copyright Catch2 Authors 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE.txt or copy at 5 // https://www.boost.org/LICENSE_1_0.txt) 6 7 // SPDX-License-Identifier: BSL-1.0 8 #include <catch2/reporters/catch_reporter_multi.hpp> 9 10 #include <catch2/catch_config.hpp> 11 #include <catch2/internal/catch_move_and_forward.hpp> 12 #include <catch2/internal/catch_stdstreams.hpp> 13 14 #include <ostream> 15 16 namespace Catch { 17 void MultiReporter::updatePreferences(IEventListener const& reporterish) { 18 m_preferences.shouldRedirectStdOut |= 19 reporterish.getPreferences().shouldRedirectStdOut; 20 m_preferences.shouldReportAllAssertions |= 21 reporterish.getPreferences().shouldReportAllAssertions; 22 } 23 24 void MultiReporter::addListener( IEventListenerPtr&& listener ) { 25 updatePreferences(*listener); 26 m_reporterLikes.insert(m_reporterLikes.begin() + m_insertedListeners, CATCH_MOVE(listener) ); 27 ++m_insertedListeners; 28 } 29 30 void MultiReporter::addReporter( IEventListenerPtr&& reporter ) { 31 updatePreferences(*reporter); 32 33 // We will need to output the captured stdout if there are reporters 34 // that do not want it captured. 35 // We do not consider listeners, because it is generally assumed that 36 // listeners are output-transparent, even though they can ask for stdout 37 // capture to do something with it. 38 m_haveNoncapturingReporters |= !reporter->getPreferences().shouldRedirectStdOut; 39 40 // Reporters can always be placed to the back without breaking the 41 // reporting order 42 m_reporterLikes.push_back( CATCH_MOVE( reporter ) ); 43 } 44 45 void MultiReporter::noMatchingTestCases( StringRef unmatchedSpec ) { 46 for ( auto& reporterish : m_reporterLikes ) { 47 reporterish->noMatchingTestCases( unmatchedSpec ); 48 } 49 } 50 51 void MultiReporter::fatalErrorEncountered( StringRef error ) { 52 for ( auto& reporterish : m_reporterLikes ) { 53 reporterish->fatalErrorEncountered( error ); 54 } 55 } 56 57 void MultiReporter::reportInvalidTestSpec( StringRef arg ) { 58 for ( auto& reporterish : m_reporterLikes ) { 59 reporterish->reportInvalidTestSpec( arg ); 60 } 61 } 62 63 void MultiReporter::benchmarkPreparing( StringRef name ) { 64 for (auto& reporterish : m_reporterLikes) { 65 reporterish->benchmarkPreparing(name); 66 } 67 } 68 void MultiReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { 69 for ( auto& reporterish : m_reporterLikes ) { 70 reporterish->benchmarkStarting( benchmarkInfo ); 71 } 72 } 73 void MultiReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) { 74 for ( auto& reporterish : m_reporterLikes ) { 75 reporterish->benchmarkEnded( benchmarkStats ); 76 } 77 } 78 79 void MultiReporter::benchmarkFailed( StringRef error ) { 80 for (auto& reporterish : m_reporterLikes) { 81 reporterish->benchmarkFailed(error); 82 } 83 } 84 85 void MultiReporter::testRunStarting( TestRunInfo const& testRunInfo ) { 86 for ( auto& reporterish : m_reporterLikes ) { 87 reporterish->testRunStarting( testRunInfo ); 88 } 89 } 90 91 void MultiReporter::testCaseStarting( TestCaseInfo const& testInfo ) { 92 for ( auto& reporterish : m_reporterLikes ) { 93 reporterish->testCaseStarting( testInfo ); 94 } 95 } 96 97 void 98 MultiReporter::testCasePartialStarting( TestCaseInfo const& testInfo, 99 uint64_t partNumber ) { 100 for ( auto& reporterish : m_reporterLikes ) { 101 reporterish->testCasePartialStarting( testInfo, partNumber ); 102 } 103 } 104 105 void MultiReporter::sectionStarting( SectionInfo const& sectionInfo ) { 106 for ( auto& reporterish : m_reporterLikes ) { 107 reporterish->sectionStarting( sectionInfo ); 108 } 109 } 110 111 void MultiReporter::assertionStarting( AssertionInfo const& assertionInfo ) { 112 for ( auto& reporterish : m_reporterLikes ) { 113 reporterish->assertionStarting( assertionInfo ); 114 } 115 } 116 117 void MultiReporter::assertionEnded( AssertionStats const& assertionStats ) { 118 const bool reportByDefault = 119 assertionStats.assertionResult.getResultType() != ResultWas::Ok || 120 m_config->includeSuccessfulResults(); 121 122 for ( auto & reporterish : m_reporterLikes ) { 123 if ( reportByDefault || 124 reporterish->getPreferences().shouldReportAllAssertions ) { 125 reporterish->assertionEnded( assertionStats ); 126 } 127 } 128 } 129 130 void MultiReporter::sectionEnded( SectionStats const& sectionStats ) { 131 for ( auto& reporterish : m_reporterLikes ) { 132 reporterish->sectionEnded( sectionStats ); 133 } 134 } 135 136 void MultiReporter::testCasePartialEnded( TestCaseStats const& testStats, 137 uint64_t partNumber ) { 138 if ( m_preferences.shouldRedirectStdOut && 139 m_haveNoncapturingReporters ) { 140 if ( !testStats.stdOut.empty() ) { 141 Catch::cout() << testStats.stdOut << std::flush; 142 } 143 if ( !testStats.stdErr.empty() ) { 144 Catch::cerr() << testStats.stdErr << std::flush; 145 } 146 } 147 148 for ( auto& reporterish : m_reporterLikes ) { 149 reporterish->testCasePartialEnded( testStats, partNumber ); 150 } 151 } 152 153 void MultiReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { 154 for ( auto& reporterish : m_reporterLikes ) { 155 reporterish->testCaseEnded( testCaseStats ); 156 } 157 } 158 159 void MultiReporter::testRunEnded( TestRunStats const& testRunStats ) { 160 for ( auto& reporterish : m_reporterLikes ) { 161 reporterish->testRunEnded( testRunStats ); 162 } 163 } 164 165 166 void MultiReporter::skipTest( TestCaseInfo const& testInfo ) { 167 for ( auto& reporterish : m_reporterLikes ) { 168 reporterish->skipTest( testInfo ); 169 } 170 } 171 172 void MultiReporter::listReporters(std::vector<ReporterDescription> const& descriptions) { 173 for (auto& reporterish : m_reporterLikes) { 174 reporterish->listReporters(descriptions); 175 } 176 } 177 178 void MultiReporter::listListeners( 179 std::vector<ListenerDescription> const& descriptions ) { 180 for ( auto& reporterish : m_reporterLikes ) { 181 reporterish->listListeners( descriptions ); 182 } 183 } 184 185 void MultiReporter::listTests(std::vector<TestCaseHandle> const& tests) { 186 for (auto& reporterish : m_reporterLikes) { 187 reporterish->listTests(tests); 188 } 189 } 190 191 void MultiReporter::listTags(std::vector<TagInfo> const& tags) { 192 for (auto& reporterish : m_reporterLikes) { 193 reporterish->listTags(tags); 194 } 195 } 196 197 } // end namespace Catch