From 338572a4f72d1c2791157b12a77d6e04ab3646ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 7 Feb 2020 09:25:34 +0100 Subject: [PATCH] Move TAP reporter implementation to a cpp file --- src/catch2/reporters/catch_reporter_tap.cpp | 210 +++++++++++++++++++ src/catch2/reporters/catch_reporter_tap.hpp | 212 +------------------- 2 files changed, 215 insertions(+), 207 deletions(-) diff --git a/src/catch2/reporters/catch_reporter_tap.cpp b/src/catch2/reporters/catch_reporter_tap.cpp index 98cc58be..9eb39957 100644 --- a/src/catch2/reporters/catch_reporter_tap.cpp +++ b/src/catch2/reporters/catch_reporter_tap.cpp @@ -4,9 +4,219 @@ */ #include +#include + +#include namespace Catch { + namespace { + class TapAssertionPrinter { + static constexpr StringRef failedString = "not ok"_sr; + static constexpr StringRef passedString = "ok"_sr; + public: + TapAssertionPrinter& operator= (TapAssertionPrinter const&) = delete; + TapAssertionPrinter(TapAssertionPrinter const&) = delete; + TapAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter) + : stream(_stream) + , result(_stats.assertionResult) + , messages(_stats.infoMessages) + , itMessage(_stats.infoMessages.begin()) + , printInfoMessages(true) + , counter(_counter) {} + + void print() { + itMessage = messages.begin(); + + switch (result.getResultType()) { + case ResultWas::Ok: + printResultType(passedString); + printOriginalExpression(); + printReconstructedExpression(); + if (!result.hasExpression()) + printRemainingMessages(Colour::None); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if (result.isOk()) { + printResultType(passedString); + } else { + printResultType(failedString); + } + printOriginalExpression(); + printReconstructedExpression(); + if (result.isOk()) { + printIssue(" # TODO"); + } + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType(failedString); + printIssue("unexpected exception with message:"_sr); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType(failedString); + printIssue("fatal error condition with message:"_sr); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType(failedString); + printIssue("expected exception, got none"_sr); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType("info"_sr); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType("warning"_sr); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType(failedString); + printIssue("explicitly"_sr); + printRemainingMessages(Colour::None); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType("** internal error **"_sr); + break; + } + } + + private: + static Colour::Code dimColour() { return Colour::FileName; } + + void printSourceInfo() const { + Colour colourGuard(dimColour()); + stream << result.getSourceInfo() << ':'; + } + + void printResultType(StringRef passOrFail) const { + if (!passOrFail.empty()) { + stream << passOrFail << ' ' << counter << " -"; + } + } + + void printIssue(StringRef issue) const { + stream << ' ' << issue; + } + + void printExpressionWas() { + if (result.hasExpression()) { + stream << ';'; + { + Colour colour(dimColour()); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if (result.hasExpression()) { + stream << ' ' << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if (result.hasExpandedExpression()) { + { + Colour colour(dimColour()); + stream << " for: "; + } + std::string expr = result.getExpandedExpression(); + std::replace(expr.begin(), expr.end(), '\n', ' '); + stream << expr; + } + } + + void printMessage() { + if (itMessage != messages.end()) { + stream << " '" << itMessage->message << '\''; + ++itMessage; + } + } + + void printRemainingMessages(Colour::Code colour = dimColour()) { + if (itMessage == messages.end()) { + return; + } + + // using messages.end() directly (or auto) yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast(std::distance(itMessage, itEnd)); + + { + Colour colourGuard(colour); + stream << " with " << pluralise(N, "message") << ':'; + } + + for (; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if (printInfoMessages || itMessage->type != ResultWas::Info) { + stream << " '" << itMessage->message << '\''; + if (++itMessage != itEnd) { + Colour colourGuard(dimColour()); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + std::size_t counter; + }; + + constexpr StringRef TapAssertionPrinter::failedString; + constexpr StringRef TapAssertionPrinter::passedString; + + } // End anonymous namespace + TAPReporter::~TAPReporter() {} + void TAPReporter::noMatchingTestCases(std::string const& spec) { + stream << "# No test cases matched '" << spec << "'\n"; + } + + bool TAPReporter::assertionEnded(AssertionStats const& _assertionStats) { + ++counter; + + stream << "# " << currentTestCaseInfo->name << '\n'; + TapAssertionPrinter printer(stream, _assertionStats, counter); + printer.print(); + + stream << '\n' << std::flush; + return true; + } + + void TAPReporter::testRunEnded(TestRunStats const& _testRunStats) { + if (_testRunStats.totals.testCases.total() == 0) { + stream << "1..0 # Skipped: No tests ran."; + } else { + stream << "1.." << counter; + } + stream << "\n\n" << std::flush; + StreamingReporterBase::testRunEnded(_testRunStats); + } + + + + } // end namespace Catch diff --git a/src/catch2/reporters/catch_reporter_tap.hpp b/src/catch2/reporters/catch_reporter_tap.hpp index a9b72dcb..1ede76fb 100644 --- a/src/catch2/reporters/catch_reporter_tap.hpp +++ b/src/catch2/reporters/catch_reporter_tap.hpp @@ -1,18 +1,12 @@ /* - * Created by Colton Wolkins on 2015-08-15. - * Copyright 2015 Martin Moene. 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_REPORTER_TAP_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED -#include #include -#include - namespace Catch { struct TAPReporter : StreamingReporterBase { @@ -22,220 +16,24 @@ namespace Catch { ~TAPReporter() override; static std::string getDescription() { - return "Reports test results in TAP format, suitable for test harnesses"; + using namespace std::string_literals; + return "Reports test results in TAP format, suitable for test harnesses"s; } ReporterPreferences getPreferences() const override { return m_reporterPrefs; } - void noMatchingTestCases( std::string const& spec ) override { - stream << "# No test cases matched '" << spec << "'" << std::endl; - } + void noMatchingTestCases(std::string const& spec) override; void assertionStarting( AssertionInfo const& ) override {} - bool assertionEnded( AssertionStats const& _assertionStats ) override { - ++counter; + bool assertionEnded(AssertionStats const& _assertionStats) override; - stream << "# " << currentTestCaseInfo->name << std::endl; - AssertionPrinter printer( stream, _assertionStats, counter ); - printer.print(); - - stream << std::endl; - return true; - } - - void testRunEnded( TestRunStats const& _testRunStats ) override { - printTotals( _testRunStats.totals ); - stream << "\n" << std::endl; - StreamingReporterBase::testRunEnded( _testRunStats ); - } + void testRunEnded(TestRunStats const& _testRunStats) override; private: std::size_t counter = 0; - class AssertionPrinter { - public: - AssertionPrinter& operator= ( AssertionPrinter const& ) = delete; - AssertionPrinter( AssertionPrinter const& ) = delete; - AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter ) - : stream( _stream ) - , result( _stats.assertionResult ) - , messages( _stats.infoMessages ) - , itMessage( _stats.infoMessages.begin() ) - , printInfoMessages( true ) - , counter(_counter) - {} - - void print() { - itMessage = messages.begin(); - - switch( result.getResultType() ) { - case ResultWas::Ok: - printResultType( passedString() ); - printOriginalExpression(); - printReconstructedExpression(); - if ( ! result.hasExpression() ) - printRemainingMessages( Colour::None ); - else - printRemainingMessages(); - break; - case ResultWas::ExpressionFailed: - if (result.isOk()) { - printResultType(passedString()); - } else { - printResultType(failedString()); - } - printOriginalExpression(); - printReconstructedExpression(); - if (result.isOk()) { - printIssue(" # TODO"); - } - printRemainingMessages(); - break; - case ResultWas::ThrewException: - printResultType( failedString() ); - printIssue( "unexpected exception with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::FatalErrorCondition: - printResultType( failedString() ); - printIssue( "fatal error condition with message:" ); - printMessage(); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::DidntThrowException: - printResultType( failedString() ); - printIssue( "expected exception, got none" ); - printExpressionWas(); - printRemainingMessages(); - break; - case ResultWas::Info: - printResultType( "info" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::Warning: - printResultType( "warning" ); - printMessage(); - printRemainingMessages(); - break; - case ResultWas::ExplicitFailure: - printResultType( failedString() ); - printIssue( "explicitly" ); - printRemainingMessages( Colour::None ); - break; - // These cases are here to prevent compiler warnings - case ResultWas::Unknown: - case ResultWas::FailureBit: - case ResultWas::Exception: - printResultType( "** internal error **" ); - break; - } - } - - private: - static Colour::Code dimColour() { return Colour::FileName; } - - static const char* failedString() { return "not ok"; } - static const char* passedString() { return "ok"; } - - void printSourceInfo() const { - Colour colourGuard( dimColour() ); - stream << result.getSourceInfo() << ":"; - } - - void printResultType( std::string const& passOrFail ) const { - if( !passOrFail.empty() ) { - stream << passOrFail << ' ' << counter << " -"; - } - } - - void printIssue( std::string const& issue ) const { - stream << " " << issue; - } - - void printExpressionWas() { - if( result.hasExpression() ) { - stream << ";"; - { - Colour colour( dimColour() ); - stream << " expression was:"; - } - printOriginalExpression(); - } - } - - void printOriginalExpression() const { - if( result.hasExpression() ) { - stream << " " << result.getExpression(); - } - } - - void printReconstructedExpression() const { - if( result.hasExpandedExpression() ) { - { - Colour colour( dimColour() ); - stream << " for: "; - } - std::string expr = result.getExpandedExpression(); - std::replace( expr.begin(), expr.end(), '\n', ' '); - stream << expr; - } - } - - void printMessage() { - if ( itMessage != messages.end() ) { - stream << " '" << itMessage->message << "'"; - ++itMessage; - } - } - - void printRemainingMessages( Colour::Code colour = dimColour() ) { - if (itMessage == messages.end()) { - return; - } - - // using messages.end() directly (or auto) yields compilation error: - std::vector::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); - - { - Colour colourGuard( colour ); - stream << " with " << pluralise( N, "message" ) << ":"; - } - - for(; itMessage != itEnd; ) { - // If this assertion is a warning ignore any INFO messages - if( printInfoMessages || itMessage->type != ResultWas::Info ) { - stream << " '" << itMessage->message << "'"; - if ( ++itMessage != itEnd ) { - Colour colourGuard( dimColour() ); - stream << " and"; - } - } - } - } - - private: - std::ostream& stream; - AssertionResult const& result; - std::vector messages; - std::vector::const_iterator itMessage; - bool printInfoMessages; - std::size_t counter; - }; - - void printTotals( const Totals& totals ) const { - if( totals.testCases.total() == 0 ) { - stream << "1..0 # Skipped: No tests ran."; - } else { - stream << "1.." << counter; - } - } }; } // end namespace Catch