Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Created by Phil on 5/12/2012. |
| 3 | * Copyright 2012 Two Blue Cubes Ltd. All rights reserved. |
| 4 | * |
| 5 | * Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 6 | * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 7 | */ |
| 8 | #ifndef TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED |
| 9 | #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED |
| 10 | |
Phil Nash | c4a089c | 2013-12-03 18:52:41 +0000 | [diff] [blame] | 11 | #include "catch_reporter_bases.hpp" |
| 12 | |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 13 | #include "../internal/catch_reporter_registrars.hpp" |
| 14 | #include "../internal/catch_console_colour.hpp" |
| 15 | |
Martin Hořeňovský | 061a183 | 2017-02-27 11:34:15 +0100 | [diff] [blame] | 16 | #include <cfloat> |
| 17 | #include <cstdio> |
| 18 | |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 19 | namespace Catch { |
| 20 | |
Martin Hořeňovský | 061a183 | 2017-02-27 11:34:15 +0100 | [diff] [blame] | 21 | |
Phil Nash | bcf722e | 2013-01-03 09:04:46 +0000 | [diff] [blame] | 22 | struct ConsoleReporter : StreamingReporterBase { |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 23 | ConsoleReporter( ReporterConfig const& _config ) |
Phil Nash | bcf722e | 2013-01-03 09:04:46 +0000 | [diff] [blame] | 24 | : StreamingReporterBase( _config ), |
Phil Nash | 94a1acf | 2014-07-03 19:06:59 +0100 | [diff] [blame] | 25 | m_headerPrinted( false ) |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 26 | {} |
| 27 | |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 28 | virtual ~ConsoleReporter() CATCH_OVERRIDE; |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 29 | static std::string getDescription() { |
| 30 | return "Reports test results as plain lines of text"; |
| 31 | } |
Phil Nash | 7542685 | 2013-03-12 19:06:40 +0000 | [diff] [blame] | 32 | |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 33 | virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 34 | stream << "No test cases matched '" << spec << '\'' << std::endl; |
Phil Nash | 7542685 | 2013-03-12 19:06:40 +0000 | [diff] [blame] | 35 | } |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 36 | |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 37 | virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 38 | } |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 39 | |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 40 | virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { |
Phil Nash | bcf722e | 2013-01-03 09:04:46 +0000 | [diff] [blame] | 41 | AssertionResult const& result = _assertionStats.assertionResult; |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 42 | |
Phil Nash | f9db24a | 2017-03-03 14:19:41 +0000 | [diff] [blame] | 43 | bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); |
Phil Nash | 4f57c8c | 2013-11-13 08:07:38 +0000 | [diff] [blame] | 44 | |
Phil Nash | f9db24a | 2017-03-03 14:19:41 +0000 | [diff] [blame] | 45 | // Drop out if result was successful but we're not printing them. |
| 46 | if( !includeResults && result.getResultType() != ResultWas::Warning ) |
| 47 | return false; |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 48 | |
Phil Nash | e6d1c98 | 2012-12-09 11:20:46 +0000 | [diff] [blame] | 49 | lazyPrint(); |
| 50 | |
Phil Nash | f9db24a | 2017-03-03 14:19:41 +0000 | [diff] [blame] | 51 | AssertionPrinter printer( stream, _assertionStats, includeResults ); |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 52 | printer.print(); |
Phil Nash | 42aef1d | 2013-01-13 21:51:44 +0000 | [diff] [blame] | 53 | stream << std::endl; |
Phil Nash | 0d35730 | 2013-06-28 16:25:49 +0100 | [diff] [blame] | 54 | return true; |
Phil Nash | 42aef1d | 2013-01-13 21:51:44 +0000 | [diff] [blame] | 55 | } |
Phil Nash | 603002c | 2013-01-26 20:17:52 +0000 | [diff] [blame] | 56 | |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 57 | virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { |
Phil Nash | b7ff995 | 2013-03-06 20:40:16 +0100 | [diff] [blame] | 58 | m_headerPrinted = false; |
Phil Nash | 603002c | 2013-01-26 20:17:52 +0000 | [diff] [blame] | 59 | StreamingReporterBase::sectionStarting( _sectionInfo ); |
| 60 | } |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 61 | virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 62 | if( _sectionStats.missingAssertions ) { |
| 63 | lazyPrint(); |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 64 | Colour colour( Colour::ResultError ); |
Phil Nash | 29ccaa6 | 2013-08-08 08:05:19 +0100 | [diff] [blame] | 65 | if( m_sectionStack.size() > 1 ) |
Phil Nash | b80280f | 2013-07-26 19:19:44 +0100 | [diff] [blame] | 66 | stream << "\nNo assertions in section"; |
| 67 | else |
| 68 | stream << "\nNo assertions in test case"; |
| 69 | stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 70 | } |
Martin Hořeňovský | 9bab7c8 | 2017-02-17 14:07:56 +0000 | [diff] [blame] | 71 | if( m_config->showDurations() == ShowDurations::Always ) { |
Martin Hořeňovský | 061a183 | 2017-02-27 11:34:15 +0100 | [diff] [blame] | 72 | stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; |
Phil Nash | f41fad7 | 2013-08-16 18:57:41 +0100 | [diff] [blame] | 73 | } |
Martin Hořeňovský | 9bab7c8 | 2017-02-17 14:07:56 +0000 | [diff] [blame] | 74 | if( m_headerPrinted ) { |
| 75 | m_headerPrinted = false; |
Phil Nash | f7378ee | 2013-09-07 12:07:38 +0100 | [diff] [blame] | 76 | } |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 77 | StreamingReporterBase::sectionEnded( _sectionStats ); |
| 78 | } |
| 79 | |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 80 | virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 81 | StreamingReporterBase::testCaseEnded( _testCaseStats ); |
Phil Nash | b7ff995 | 2013-03-06 20:40:16 +0100 | [diff] [blame] | 82 | m_headerPrinted = false; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 83 | } |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 84 | virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { |
Phil Nash | 1f519dd | 2013-08-08 08:24:37 +0100 | [diff] [blame] | 85 | if( currentGroupInfo.used ) { |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 86 | printSummaryDivider(); |
| 87 | stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; |
| 88 | printTotals( _testGroupStats.totals ); |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 89 | stream << '\n' << std::endl; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 90 | } |
| 91 | StreamingReporterBase::testGroupEnded( _testGroupStats ); |
| 92 | } |
Phil Nash | 368714e | 2015-08-07 08:20:56 +0100 | [diff] [blame] | 93 | virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 94 | printTotalsDivider( _testRunStats.totals ); |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 95 | printTotals( _testRunStats.totals ); |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 96 | stream << std::endl; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 97 | StreamingReporterBase::testRunEnded( _testRunStats ); |
| 98 | } |
| 99 | |
| 100 | private: |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 101 | |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 102 | class AssertionPrinter { |
Phil Nash | 503d5d0 | 2013-07-03 08:25:11 +0100 | [diff] [blame] | 103 | void operator= ( AssertionPrinter const& ); |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 104 | public: |
Phil Nash | 4f57c8c | 2013-11-13 08:07:38 +0000 | [diff] [blame] | 105 | AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 106 | : stream( _stream ), |
| 107 | stats( _stats ), |
| 108 | result( _stats.assertionResult ), |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 109 | colour( Colour::None ), |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 110 | message( result.getMessage() ), |
Phil Nash | 4f57c8c | 2013-11-13 08:07:38 +0000 | [diff] [blame] | 111 | messages( _stats.infoMessages ), |
| 112 | printInfoMessages( _printInfoMessages ) |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 113 | { |
| 114 | switch( result.getResultType() ) { |
| 115 | case ResultWas::Ok: |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 116 | colour = Colour::Success; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 117 | passOrFail = "PASSED"; |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 118 | //if( result.hasMessage() ) |
| 119 | if( _stats.infoMessages.size() == 1 ) |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 120 | messageLabel = "with message"; |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 121 | if( _stats.infoMessages.size() > 1 ) |
| 122 | messageLabel = "with messages"; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 123 | break; |
| 124 | case ResultWas::ExpressionFailed: |
| 125 | if( result.isOk() ) { |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 126 | colour = Colour::Success; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 127 | passOrFail = "FAILED - but was ok"; |
| 128 | } |
| 129 | else { |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 130 | colour = Colour::Error; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 131 | passOrFail = "FAILED"; |
| 132 | } |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 133 | if( _stats.infoMessages.size() == 1 ) |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 134 | messageLabel = "with message"; |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 135 | if( _stats.infoMessages.size() > 1 ) |
| 136 | messageLabel = "with messages"; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 137 | break; |
| 138 | case ResultWas::ThrewException: |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 139 | colour = Colour::Error; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 140 | passOrFail = "FAILED"; |
| 141 | messageLabel = "due to unexpected exception with message"; |
| 142 | break; |
Phil Nash | c1a8e1c | 2014-08-22 08:07:39 +0100 | [diff] [blame] | 143 | case ResultWas::FatalErrorCondition: |
| 144 | colour = Colour::Error; |
| 145 | passOrFail = "FAILED"; |
| 146 | messageLabel = "due to a fatal error condition"; |
| 147 | break; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 148 | case ResultWas::DidntThrowException: |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 149 | colour = Colour::Error; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 150 | passOrFail = "FAILED"; |
| 151 | messageLabel = "because no exception was thrown where one was expected"; |
| 152 | break; |
| 153 | case ResultWas::Info: |
| 154 | messageLabel = "info"; |
| 155 | break; |
| 156 | case ResultWas::Warning: |
| 157 | messageLabel = "warning"; |
| 158 | break; |
| 159 | case ResultWas::ExplicitFailure: |
| 160 | passOrFail = "FAILED"; |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 161 | colour = Colour::Error; |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 162 | if( _stats.infoMessages.size() == 1 ) |
| 163 | messageLabel = "explicitly with message"; |
| 164 | if( _stats.infoMessages.size() > 1 ) |
| 165 | messageLabel = "explicitly with messages"; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 166 | break; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 167 | // These cases are here to prevent compiler warnings |
| 168 | case ResultWas::Unknown: |
| 169 | case ResultWas::FailureBit: |
Phil Nash | 3bd4241 | 2013-04-08 12:05:32 +0100 | [diff] [blame] | 170 | case ResultWas::Exception: |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 171 | passOrFail = "** internal error **"; |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 172 | colour = Colour::Error; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 173 | break; |
| 174 | } |
| 175 | } |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 176 | |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 177 | void print() const { |
Phil Nash | 767f158 | 2013-03-04 12:19:15 +0100 | [diff] [blame] | 178 | printSourceInfo(); |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 179 | if( stats.totals.assertions.total() > 0 ) { |
Phil Nash | 767f158 | 2013-03-04 12:19:15 +0100 | [diff] [blame] | 180 | if( result.isOk() ) |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 181 | stream << '\n'; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 182 | printResultType(); |
| 183 | printOriginalExpression(); |
| 184 | printReconstructedExpression(); |
| 185 | } |
Phil Nash | 767f158 | 2013-03-04 12:19:15 +0100 | [diff] [blame] | 186 | else { |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 187 | stream << '\n'; |
Phil Nash | 767f158 | 2013-03-04 12:19:15 +0100 | [diff] [blame] | 188 | } |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 189 | printMessage(); |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 190 | } |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 191 | |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 192 | private: |
| 193 | void printResultType() const { |
| 194 | if( !passOrFail.empty() ) { |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 195 | Colour colourGuard( colour ); |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 196 | stream << passOrFail << ":\n"; |
| 197 | } |
| 198 | } |
| 199 | void printOriginalExpression() const { |
| 200 | if( result.hasExpression() ) { |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 201 | Colour colourGuard( Colour::OriginalExpression ); |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 202 | stream << " "; |
Phil Nash | d430537 | 2013-05-17 19:35:33 +0100 | [diff] [blame] | 203 | stream << result.getExpressionInMacro(); |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 204 | stream << '\n'; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 205 | } |
| 206 | } |
| 207 | void printReconstructedExpression() const { |
| 208 | if( result.hasExpandedExpression() ) { |
| 209 | stream << "with expansion:\n"; |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 210 | Colour colourGuard( Colour::ReconstructedExpression ); |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 211 | stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 212 | } |
| 213 | } |
| 214 | void printMessage() const { |
| 215 | if( !messageLabel.empty() ) |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 216 | stream << messageLabel << ':' << '\n'; |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 217 | for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end(); |
| 218 | it != itEnd; |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 219 | ++it ) { |
Phil Nash | 4f57c8c | 2013-11-13 08:07:38 +0000 | [diff] [blame] | 220 | // If this assertion is a warning ignore any INFO messages |
| 221 | if( printInfoMessages || it->type != ResultWas::Info ) |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 222 | stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 223 | } |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 224 | } |
| 225 | void printSourceInfo() const { |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 226 | Colour colourGuard( Colour::FileName ); |
Phil Nash | 767f158 | 2013-03-04 12:19:15 +0100 | [diff] [blame] | 227 | stream << result.getSourceInfo() << ": "; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 228 | } |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 229 | |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 230 | std::ostream& stream; |
| 231 | AssertionStats const& stats; |
| 232 | AssertionResult const& result; |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 233 | Colour::Code colour; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 234 | std::string passOrFail; |
| 235 | std::string messageLabel; |
| 236 | std::string message; |
Phil Nash | 207b27b | 2013-02-02 19:58:04 +0000 | [diff] [blame] | 237 | std::vector<MessageInfo> messages; |
Phil Nash | 4f57c8c | 2013-11-13 08:07:38 +0000 | [diff] [blame] | 238 | bool printInfoMessages; |
Phil Nash | 3682433 | 2013-01-18 17:50:21 +0000 | [diff] [blame] | 239 | }; |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 240 | |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 241 | void lazyPrint() { |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 242 | |
Phil Nash | 1f519dd | 2013-08-08 08:24:37 +0100 | [diff] [blame] | 243 | if( !currentTestRunInfo.used ) |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 244 | lazyPrintRunInfo(); |
Phil Nash | 1f519dd | 2013-08-08 08:24:37 +0100 | [diff] [blame] | 245 | if( !currentGroupInfo.used ) |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 246 | lazyPrintGroupInfo(); |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 247 | |
Phil Nash | b7ff995 | 2013-03-06 20:40:16 +0100 | [diff] [blame] | 248 | if( !m_headerPrinted ) { |
| 249 | printTestCaseAndSectionHeader(); |
| 250 | m_headerPrinted = true; |
| 251 | } |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 252 | } |
| 253 | void lazyPrintRunInfo() { |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 254 | stream << '\n' << getLineOfChars<'~'>() << '\n'; |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 255 | Colour colour( Colour::SecondaryText ); |
Phil Nash | 1f519dd | 2013-08-08 08:24:37 +0100 | [diff] [blame] | 256 | stream << currentTestRunInfo->name |
Kevin Ushey | e04dc51 | 2017-03-16 11:17:45 -0700 | [diff] [blame^] | 257 | << " is a Catch v" << libraryVersion() << " host application.\n" |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 258 | << "Run with -? for options\n\n"; |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 259 | |
Phil Nash | fa0122b | 2014-09-15 18:39:31 +0100 | [diff] [blame] | 260 | if( m_config->rngSeed() != 0 ) |
| 261 | stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; |
| 262 | |
Phil Nash | 1f519dd | 2013-08-08 08:24:37 +0100 | [diff] [blame] | 263 | currentTestRunInfo.used = true; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 264 | } |
| 265 | void lazyPrintGroupInfo() { |
Phil Nash | 1f519dd | 2013-08-08 08:24:37 +0100 | [diff] [blame] | 266 | if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { |
| 267 | printClosedHeader( "Group: " + currentGroupInfo->name ); |
| 268 | currentGroupInfo.used = true; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 269 | } |
| 270 | } |
Phil Nash | b7ff995 | 2013-03-06 20:40:16 +0100 | [diff] [blame] | 271 | void printTestCaseAndSectionHeader() { |
Phil Nash | 29ccaa6 | 2013-08-08 08:05:19 +0100 | [diff] [blame] | 272 | assert( !m_sectionStack.empty() ); |
Phil Nash | 1f519dd | 2013-08-08 08:24:37 +0100 | [diff] [blame] | 273 | printOpenHeader( currentTestCaseInfo->name ); |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 274 | |
Phil Nash | 29ccaa6 | 2013-08-08 08:05:19 +0100 | [diff] [blame] | 275 | if( m_sectionStack.size() > 1 ) { |
| 276 | Colour colourGuard( Colour::Headers ); |
| 277 | |
Phil Nash | 2ddb9d3 | 2013-08-15 18:39:55 +0100 | [diff] [blame] | 278 | std::vector<SectionInfo>::const_iterator |
Phil Nash | 29ccaa6 | 2013-08-08 08:05:19 +0100 | [diff] [blame] | 279 | it = m_sectionStack.begin()+1, // Skip first section (test case) |
| 280 | itEnd = m_sectionStack.end(); |
| 281 | for( ; it != itEnd; ++it ) |
Phil Nash | 2ddb9d3 | 2013-08-15 18:39:55 +0100 | [diff] [blame] | 282 | printHeaderString( it->name, 2 ); |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 283 | } |
Phil Nash | 29ccaa6 | 2013-08-08 08:05:19 +0100 | [diff] [blame] | 284 | |
Phil Nash | ab44fb6 | 2017-02-10 11:56:46 +0000 | [diff] [blame] | 285 | SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 286 | |
Phil Nash | bd5910e | 2013-04-17 00:05:25 +0100 | [diff] [blame] | 287 | if( !lineInfo.empty() ){ |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 288 | stream << getLineOfChars<'-'>() << '\n'; |
Phil Nash | bd5910e | 2013-04-17 00:05:25 +0100 | [diff] [blame] | 289 | Colour colourGuard( Colour::FileName ); |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 290 | stream << lineInfo << '\n'; |
Phil Nash | bd5910e | 2013-04-17 00:05:25 +0100 | [diff] [blame] | 291 | } |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 292 | stream << getLineOfChars<'.'>() << '\n' << std::endl; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 293 | } |
Phil Nash | 0a87795 | 2013-01-16 09:39:08 +0000 | [diff] [blame] | 294 | |
Phil Nash | b7ff995 | 2013-03-06 20:40:16 +0100 | [diff] [blame] | 295 | void printClosedHeader( std::string const& _name ) { |
| 296 | printOpenHeader( _name ); |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 297 | stream << getLineOfChars<'.'>() << '\n'; |
Phil Nash | b7ff995 | 2013-03-06 20:40:16 +0100 | [diff] [blame] | 298 | } |
Phil Nash | 7059c6e | 2013-04-19 19:08:32 +0100 | [diff] [blame] | 299 | void printOpenHeader( std::string const& _name ) { |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 300 | stream << getLineOfChars<'-'>() << '\n'; |
Phil Nash | 2c90533 | 2013-04-01 11:25:54 +0100 | [diff] [blame] | 301 | { |
Phil Nash | f186a91 | 2013-04-05 07:59:28 +0100 | [diff] [blame] | 302 | Colour colourGuard( Colour::Headers ); |
Phil Nash | 7059c6e | 2013-04-19 19:08:32 +0100 | [diff] [blame] | 303 | printHeaderString( _name ); |
Phil Nash | 2c90533 | 2013-04-01 11:25:54 +0100 | [diff] [blame] | 304 | } |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 305 | } |
Phil Nash | 7059c6e | 2013-04-19 19:08:32 +0100 | [diff] [blame] | 306 | |
Phil Nash | 4746caa | 2013-04-05 20:55:57 +0100 | [diff] [blame] | 307 | // if string has a : in first line will set indent to follow it on |
| 308 | // subsequent lines |
Phil Nash | 7059c6e | 2013-04-19 19:08:32 +0100 | [diff] [blame] | 309 | void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { |
Phil Nash | 4746caa | 2013-04-05 20:55:57 +0100 | [diff] [blame] | 310 | std::size_t i = _string.find( ": " ); |
| 311 | if( i != std::string::npos ) |
| 312 | i+=2; |
| 313 | else |
| 314 | i = 0; |
Phil Nash | b3acf45 | 2013-04-20 19:36:40 +0100 | [diff] [blame] | 315 | stream << Text( _string, TextAttributes() |
| 316 | .setIndent( indent+i) |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 317 | .setInitialIndent( indent ) ) << '\n'; |
Phil Nash | 4746caa | 2013-04-05 20:55:57 +0100 | [diff] [blame] | 318 | } |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 319 | |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 320 | struct SummaryColumn { |
| 321 | |
| 322 | SummaryColumn( std::string const& _label, Colour::Code _colour ) |
| 323 | : label( _label ), |
| 324 | colour( _colour ) |
| 325 | {} |
| 326 | SummaryColumn addRow( std::size_t count ) { |
| 327 | std::ostringstream oss; |
| 328 | oss << count; |
| 329 | std::string row = oss.str(); |
| 330 | for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) { |
| 331 | while( it->size() < row.size() ) |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 332 | *it = ' ' + *it; |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 333 | while( it->size() > row.size() ) |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 334 | row = ' ' + row; |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 335 | } |
| 336 | rows.push_back( row ); |
| 337 | return *this; |
| 338 | } |
| 339 | |
| 340 | std::string label; |
| 341 | Colour::Code colour; |
| 342 | std::vector<std::string> rows; |
| 343 | |
| 344 | }; |
| 345 | |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 346 | void printTotals( Totals const& totals ) { |
Phil Nash | 2f086ae | 2013-11-12 19:06:08 +0000 | [diff] [blame] | 347 | if( totals.testCases.total() == 0 ) { |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 348 | stream << Colour( Colour::Warning ) << "No tests ran\n"; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 349 | } |
Phil Nash | 447f53e | 2016-03-14 19:13:34 +0000 | [diff] [blame] | 350 | else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 351 | stream << Colour( Colour::ResultSuccess ) << "All tests passed"; |
| 352 | stream << " (" |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 353 | << pluralise( totals.assertions.passed, "assertion" ) << " in " |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 354 | << pluralise( totals.testCases.passed, "test case" ) << ')' |
| 355 | << '\n'; |
Phil Nash | 60ed3c1 | 2013-01-14 18:51:49 +0000 | [diff] [blame] | 356 | } |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 357 | else { |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 358 | |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 359 | std::vector<SummaryColumn> columns; |
| 360 | columns.push_back( SummaryColumn( "", Colour::None ) |
| 361 | .addRow( totals.testCases.total() ) |
| 362 | .addRow( totals.assertions.total() ) ); |
| 363 | columns.push_back( SummaryColumn( "passed", Colour::Success ) |
| 364 | .addRow( totals.testCases.passed ) |
| 365 | .addRow( totals.assertions.passed ) ); |
| 366 | columns.push_back( SummaryColumn( "failed", Colour::ResultError ) |
| 367 | .addRow( totals.testCases.failed ) |
| 368 | .addRow( totals.assertions.failed ) ); |
| 369 | columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) |
| 370 | .addRow( totals.testCases.failedButOk ) |
| 371 | .addRow( totals.assertions.failedButOk ) ); |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 372 | |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 373 | printSummaryRow( "test cases", columns, 0 ); |
| 374 | printSummaryRow( "assertions", columns, 1 ); |
Phil Nash | 6fb8260 | 2012-12-11 08:27:21 +0000 | [diff] [blame] | 375 | } |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 376 | } |
| 377 | void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) { |
| 378 | for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) { |
| 379 | std::string value = it->rows[row]; |
| 380 | if( it->label.empty() ) { |
| 381 | stream << label << ": "; |
| 382 | if( value != "0" ) |
| 383 | stream << value; |
| 384 | else |
| 385 | stream << Colour( Colour::Warning ) << "- none -"; |
| 386 | } |
| 387 | else if( value != "0" ) { |
| 388 | stream << Colour( Colour::LightGrey ) << " | "; |
| 389 | stream << Colour( it->colour ) |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 390 | << value << ' ' << it->label; |
Phil Nash | 76f80a6 | 2014-07-09 19:20:24 +0100 | [diff] [blame] | 391 | } |
| 392 | } |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 393 | stream << '\n'; |
Phil Nash | ff03cdf | 2012-12-06 08:44:51 +0000 | [diff] [blame] | 394 | } |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 395 | |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 396 | static std::size_t makeRatio( std::size_t number, std::size_t total ) { |
| 397 | std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; |
| 398 | return ( ratio == 0 && number > 0 ) ? 1 : ratio; |
| 399 | } |
| 400 | static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { |
| 401 | if( i > j && i > k ) |
| 402 | return i; |
| 403 | else if( j > k ) |
| 404 | return j; |
| 405 | else |
| 406 | return k; |
| 407 | } |
| 408 | |
| 409 | void printTotalsDivider( Totals const& totals ) { |
| 410 | if( totals.testCases.total() > 0 ) { |
| 411 | std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); |
| 412 | std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); |
| 413 | std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); |
| 414 | while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) |
| 415 | findMax( failedRatio, failedButOkRatio, passedRatio )++; |
| 416 | while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) |
| 417 | findMax( failedRatio, failedButOkRatio, passedRatio )--; |
| 418 | |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 419 | stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); |
| 420 | stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); |
Phil Nash | cab9141 | 2014-07-09 18:24:24 +0100 | [diff] [blame] | 421 | if( totals.testCases.allPassed() ) |
| 422 | stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); |
| 423 | else |
| 424 | stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); |
Phil Nash | 9c1f9a8 | 2014-07-03 08:09:57 +0100 | [diff] [blame] | 425 | } |
| 426 | else { |
| 427 | stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); |
| 428 | } |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 429 | stream << '\n'; |
Phil Nash | a7079a2 | 2012-12-13 12:46:47 +0000 | [diff] [blame] | 430 | } |
Phil Nash | 42aef1d | 2013-01-13 21:51:44 +0000 | [diff] [blame] | 431 | void printSummaryDivider() { |
Martin Hořeňovský | bcaa2f9 | 2017-01-29 23:07:15 +0100 | [diff] [blame] | 432 | stream << getLineOfChars<'-'>() << '\n'; |
Phil Nash | a7079a2 | 2012-12-13 12:46:47 +0000 | [diff] [blame] | 433 | } |
Phil Nash | f3d1f08 | 2013-07-03 19:14:59 +0100 | [diff] [blame] | 434 | |
Phil Nash | 42aef1d | 2013-01-13 21:51:44 +0000 | [diff] [blame] | 435 | private: |
Phil Nash | b7ff995 | 2013-03-06 20:40:16 +0100 | [diff] [blame] | 436 | bool m_headerPrinted; |
Phil Nash | fe98123 | 2012-12-05 08:40:53 +0000 | [diff] [blame] | 437 | }; |
| 438 | |
| 439 | INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) |
| 440 | |
| 441 | } // end namespace Catch |
| 442 | |
| 443 | #endif // TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED |