Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
catch_reporter_tap.hpp
Go to the documentation of this file.
1/*
2 * Created by Colton Wolkins on 2015-08-15.
3 * Copyright 2015 Martin Moene. 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_TAP_HPP_INCLUDED
9#define TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED
10
11
12// Don't #include any Catch headers here - we can assume they are already
13// included before this header.
14// This is not good practice in general but is necessary in this case so this
15// file can be distributed as a single header that works with the main
16// Catch single header.
17
18#include <algorithm>
19
20namespace Catch {
21
22 struct TAPReporter : StreamingReporterBase<TAPReporter> {
23
25
26 ~TAPReporter() override;
27
28 static std::string getDescription() {
29 return "Reports test results in TAP format, suitable for test harnesses";
30 }
31
33 return m_reporterPrefs;
34 }
35
36 void noMatchingTestCases( std::string const& spec ) override {
37 stream << "# No test cases matched '" << spec << "'" << std::endl;
38 }
39
40 void assertionStarting( AssertionInfo const& ) override {}
41
42 bool assertionEnded( AssertionStats const& _assertionStats ) override {
43 ++counter;
44
45 stream << "# " << currentTestCaseInfo->name << std::endl;
46 AssertionPrinter printer( stream, _assertionStats, counter );
47 printer.print();
48
49 stream << std::endl;
50 return true;
51 }
52
53 void testRunEnded( TestRunStats const& _testRunStats ) override {
54 printTotals( _testRunStats.totals );
55 stream << "\n" << std::endl;
57 }
58
59 private:
60 std::size_t counter = 0;
61 class AssertionPrinter {
62 public:
63 AssertionPrinter& operator= ( AssertionPrinter const& ) = delete;
64 AssertionPrinter( AssertionPrinter const& ) = delete;
65 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, std::size_t _counter )
66 : stream( _stream )
67 , result( _stats.assertionResult )
68 , messages( _stats.infoMessages )
69 , itMessage( _stats.infoMessages.begin() )
70 , printInfoMessages( true )
71 , counter(_counter)
72 {}
73
74 void print() {
75 itMessage = messages.begin();
76
77 switch( result.getResultType() ) {
78 case ResultWas::Ok:
79 printResultType( passedString() );
80 printOriginalExpression();
81 printReconstructedExpression();
82 if ( ! result.hasExpression() )
83 printRemainingMessages( Colour::None );
84 else
85 printRemainingMessages();
86 break;
88 if (result.isOk()) {
89 printResultType(passedString());
90 } else {
91 printResultType(failedString());
92 }
93 printOriginalExpression();
94 printReconstructedExpression();
95 if (result.isOk()) {
96 printIssue(" # TODO");
97 }
98 printRemainingMessages();
99 break;
101 printResultType( failedString() );
102 printIssue( "unexpected exception with message:" );
103 printMessage();
104 printExpressionWas();
105 printRemainingMessages();
106 break;
108 printResultType( failedString() );
109 printIssue( "fatal error condition with message:" );
110 printMessage();
111 printExpressionWas();
112 printRemainingMessages();
113 break;
115 printResultType( failedString() );
116 printIssue( "expected exception, got none" );
117 printExpressionWas();
118 printRemainingMessages();
119 break;
120 case ResultWas::Info:
121 printResultType( "info" );
122 printMessage();
123 printRemainingMessages();
124 break;
126 printResultType( "warning" );
127 printMessage();
128 printRemainingMessages();
129 break;
131 printResultType( failedString() );
132 printIssue( "explicitly" );
133 printRemainingMessages( Colour::None );
134 break;
135 // These cases are here to prevent compiler warnings
139 printResultType( "** internal error **" );
140 break;
141 }
142 }
143
144 private:
145 static Colour::Code dimColour() { return Colour::FileName; }
146
147 static const char* failedString() { return "not ok"; }
148 static const char* passedString() { return "ok"; }
149
150 void printSourceInfo() const {
151 Colour colourGuard( dimColour() );
152 stream << result.getSourceInfo() << ":";
153 }
154
155 void printResultType( std::string const& passOrFail ) const {
156 if( !passOrFail.empty() ) {
157 stream << passOrFail << ' ' << counter << " -";
158 }
159 }
160
161 void printIssue( std::string const& issue ) const {
162 stream << " " << issue;
163 }
164
165 void printExpressionWas() {
166 if( result.hasExpression() ) {
167 stream << ";";
168 {
169 Colour colour( dimColour() );
170 stream << " expression was:";
171 }
172 printOriginalExpression();
173 }
174 }
175
176 void printOriginalExpression() const {
177 if( result.hasExpression() ) {
178 stream << " " << result.getExpression();
179 }
180 }
181
182 void printReconstructedExpression() const {
183 if( result.hasExpandedExpression() ) {
184 {
185 Colour colour( dimColour() );
186 stream << " for: ";
187 }
188 std::string expr = result.getExpandedExpression();
189 std::replace( expr.begin(), expr.end(), '\n', ' ');
190 stream << expr;
191 }
192 }
193
194 void printMessage() {
195 if ( itMessage != messages.end() ) {
196 stream << " '" << itMessage->message << "'";
197 ++itMessage;
198 }
199 }
200
201 void printRemainingMessages( Colour::Code colour = dimColour() ) {
202 if (itMessage == messages.end()) {
203 return;
204 }
205
206 // using messages.end() directly (or auto) yields compilation error:
207 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
208 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
209
210 {
211 Colour colourGuard( colour );
212 stream << " with " << pluralise( N, "message" ) << ":";
213 }
214
215 for(; itMessage != itEnd; ) {
216 // If this assertion is a warning ignore any INFO messages
217 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
218 stream << " '" << itMessage->message << "'";
219 if ( ++itMessage != itEnd ) {
220 Colour colourGuard( dimColour() );
221 stream << " and";
222 }
223 }
224 }
225 }
226
227 private:
228 std::ostream& stream;
229 AssertionResult const& result;
230 std::vector<MessageInfo> messages;
231 std::vector<MessageInfo>::const_iterator itMessage;
232 bool printInfoMessages;
233 std::size_t counter;
234 };
235
236 void printTotals( const Totals& totals ) const {
237 if( totals.testCases.total() == 0 ) {
238 stream << "1..0 # Skipped: No tests ran.";
239 } else {
240 stream << "1.." << counter;
241 }
242 }
243 };
244
245#ifdef CATCH_IMPL
247#endif
248
249 CATCH_REGISTER_REPORTER( "tap", TAPReporter )
250
251} // end namespace Catch
252
253#endif // TWOBLUECUBES_CATCH_REPORTER_TAP_HPP_INCLUDED
#define CATCH_REGISTER_REPORTER(name, reporterType)
std::string getExpression() const
SourceLineInfo getSourceInfo() const
std::string getExpandedExpression() const
ResultWas::OfType getResultType() const
const int N
Definition quantize.cpp:54
void testRunEnded(TestRunStats const &) override
StreamingReporterBase(ReporterConfig const &_config)
ReporterPreferences getPreferences() const override
static std::string getDescription()
void testRunEnded(TestRunStats const &_testRunStats) override
void noMatchingTestCases(std::string const &spec) override
~TAPReporter() override
bool assertionEnded(AssertionStats const &_assertionStats) override
void assertionStarting(AssertionInfo const &) override