1 // 210-Evt-EventListeners.cpp
2
3 // Contents:
4 // 1. Printing of listener data
5 // 2. My listener and registration
6 // 3. Test cases
7
8 // main() provided in 000-CatchMain.cpp
9
10 // Let Catch provide the required interfaces:
11 #define CATCH_CONFIG_EXTERNAL_INTERFACES
12
13 #include <catch2/catch.hpp>
14 #include <iostream>
15
16 // -----------------------------------------------------------------------
17 // 1. Printing of listener data:
18 //
19
ws(int const level)20 std::string ws(int const level) {
21 return std::string( 2 * level, ' ' );
22 }
23
24 template< typename T >
operator <<(std::ostream & os,std::vector<T> const & v)25 std::ostream& operator<<( std::ostream& os, std::vector<T> const& v ) {
26 os << "{ ";
27 for ( auto x : v )
28 os << x << ", ";
29 return os << "}";
30 }
31
32 // struct SourceLineInfo {
33 // char const* file;
34 // std::size_t line;
35 // };
36
print(std::ostream & os,int const level,std::string const & title,Catch::SourceLineInfo const & info)37 void print( std::ostream& os, int const level, std::string const& title, Catch::SourceLineInfo const& info ) {
38 os << ws(level ) << title << ":\n"
39 << ws(level+1) << "- file: " << info.file << "\n"
40 << ws(level+1) << "- line: " << info.line << "\n";
41 }
42
43 //struct MessageInfo {
44 // std::string macroName;
45 // std::string message;
46 // SourceLineInfo lineInfo;
47 // ResultWas::OfType type;
48 // unsigned int sequence;
49 //};
50
print(std::ostream & os,int const level,Catch::MessageInfo const & info)51 void print( std::ostream& os, int const level, Catch::MessageInfo const& info ) {
52 os << ws(level+1) << "- macroName: '" << info.macroName << "'\n"
53 << ws(level+1) << "- message '" << info.message << "'\n";
54 print( os,level+1 , "- lineInfo", info.lineInfo );
55 os << ws(level+1) << "- sequence " << info.sequence << "\n";
56 }
57
print(std::ostream & os,int const level,std::string const & title,std::vector<Catch::MessageInfo> const & v)58 void print( std::ostream& os, int const level, std::string const& title, std::vector<Catch::MessageInfo> const& v ) {
59 os << ws(level ) << title << ":\n";
60 for ( auto x : v )
61 {
62 os << ws(level+1) << "{\n";
63 print( os, level+2, x );
64 os << ws(level+1) << "}\n";
65 }
66 // os << ws(level+1) << "\n";
67 }
68
69 // struct TestRunInfo {
70 // std::string name;
71 // };
72
print(std::ostream & os,int const level,std::string const & title,Catch::TestRunInfo const & info)73 void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunInfo const& info ) {
74 os << ws(level ) << title << ":\n"
75 << ws(level+1) << "- name: " << info.name << "\n";
76 }
77
78 // struct Counts {
79 // std::size_t total() const;
80 // bool allPassed() const;
81 // bool allOk() const;
82 //
83 // std::size_t passed = 0;
84 // std::size_t failed = 0;
85 // std::size_t failedButOk = 0;
86 // };
87
print(std::ostream & os,int const level,std::string const & title,Catch::Counts const & info)88 void print( std::ostream& os, int const level, std::string const& title, Catch::Counts const& info ) {
89 os << ws(level ) << title << ":\n"
90 << ws(level+1) << "- total(): " << info.total() << "\n"
91 << ws(level+1) << "- allPassed(): " << info.allPassed() << "\n"
92 << ws(level+1) << "- allOk(): " << info.allOk() << "\n"
93 << ws(level+1) << "- passed: " << info.passed << "\n"
94 << ws(level+1) << "- failed: " << info.failed << "\n"
95 << ws(level+1) << "- failedButOk: " << info.failedButOk << "\n";
96 }
97
98 // struct Totals {
99 // Counts assertions;
100 // Counts testCases;
101 // };
102
print(std::ostream & os,int const level,std::string const & title,Catch::Totals const & info)103 void print( std::ostream& os, int const level, std::string const& title, Catch::Totals const& info ) {
104 os << ws(level) << title << ":\n";
105 print( os, level+1, "- assertions", info.assertions );
106 print( os, level+1, "- testCases" , info.testCases );
107 }
108
109 // struct TestRunStats {
110 // TestRunInfo runInfo;
111 // Totals totals;
112 // bool aborting;
113 // };
114
print(std::ostream & os,int const level,std::string const & title,Catch::TestRunStats const & info)115 void print( std::ostream& os, int const level, std::string const& title, Catch::TestRunStats const& info ) {
116 os << ws(level) << title << ":\n";
117 print( os, level+1 , "- runInfo", info.runInfo );
118 print( os, level+1 , "- totals" , info.totals );
119 os << ws(level+1) << "- aborting: " << info.aborting << "\n";
120 }
121
122 // struct TestCaseInfo {
123 // enum SpecialProperties{
124 // None = 0,
125 // IsHidden = 1 << 1,
126 // ShouldFail = 1 << 2,
127 // MayFail = 1 << 3,
128 // Throws = 1 << 4,
129 // NonPortable = 1 << 5,
130 // Benchmark = 1 << 6
131 // };
132 //
133 // bool isHidden() const;
134 // bool throws() const;
135 // bool okToFail() const;
136 // bool expectedToFail() const;
137 //
138 // std::string tagsAsString() const;
139 //
140 // std::string name;
141 // std::string className;
142 // std::string description;
143 // std::vector<std::string> tags;
144 // std::vector<std::string> lcaseTags;
145 // SourceLineInfo lineInfo;
146 // SpecialProperties properties;
147 // };
148
print(std::ostream & os,int const level,std::string const & title,Catch::TestCaseInfo const & info)149 void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseInfo const& info ) {
150 os << ws(level ) << title << ":\n"
151 << ws(level+1) << "- isHidden(): " << info.isHidden() << "\n"
152 << ws(level+1) << "- throws(): " << info.throws() << "\n"
153 << ws(level+1) << "- okToFail(): " << info.okToFail() << "\n"
154 << ws(level+1) << "- expectedToFail(): " << info.expectedToFail() << "\n"
155 << ws(level+1) << "- tagsAsString(): '" << info.tagsAsString() << "'\n"
156 << ws(level+1) << "- name: '" << info.name << "'\n"
157 << ws(level+1) << "- className: '" << info.className << "'\n"
158 << ws(level+1) << "- description: '" << info.description << "'\n"
159 << ws(level+1) << "- tags: " << info.tags << "\n"
160 << ws(level+1) << "- lcaseTags: " << info.lcaseTags << "\n";
161 print( os, level+1 , "- lineInfo", info.lineInfo );
162 os << ws(level+1) << "- properties (flags): 0x" << std::hex << info.properties << std::dec << "\n";
163 }
164
165 // struct TestCaseStats {
166 // TestCaseInfo testInfo;
167 // Totals totals;
168 // std::string stdOut;
169 // std::string stdErr;
170 // bool aborting;
171 // };
172
print(std::ostream & os,int const level,std::string const & title,Catch::TestCaseStats const & info)173 void print( std::ostream& os, int const level, std::string const& title, Catch::TestCaseStats const& info ) {
174 os << ws(level ) << title << ":\n";
175 print( os, level+1 , "- testInfo", info.testInfo );
176 print( os, level+1 , "- totals" , info.totals );
177 os << ws(level+1) << "- stdOut: " << info.stdOut << "\n"
178 << ws(level+1) << "- stdErr: " << info.stdErr << "\n"
179 << ws(level+1) << "- aborting: " << info.aborting << "\n";
180 }
181
182 // struct SectionInfo {
183 // std::string name;
184 // std::string description;
185 // SourceLineInfo lineInfo;
186 // };
187
print(std::ostream & os,int const level,std::string const & title,Catch::SectionInfo const & info)188 void print( std::ostream& os, int const level, std::string const& title, Catch::SectionInfo const& info ) {
189 os << ws(level ) << title << ":\n"
190 << ws(level+1) << "- name: " << info.name << "\n";
191 print( os, level+1 , "- lineInfo", info.lineInfo );
192 }
193
194 // struct SectionStats {
195 // SectionInfo sectionInfo;
196 // Counts assertions;
197 // double durationInSeconds;
198 // bool missingAssertions;
199 // };
200
print(std::ostream & os,int const level,std::string const & title,Catch::SectionStats const & info)201 void print( std::ostream& os, int const level, std::string const& title, Catch::SectionStats const& info ) {
202 os << ws(level ) << title << ":\n";
203 print( os, level+1 , "- sectionInfo", info.sectionInfo );
204 print( os, level+1 , "- assertions" , info.assertions );
205 os << ws(level+1) << "- durationInSeconds: " << info.durationInSeconds << "\n"
206 << ws(level+1) << "- missingAssertions: " << info.missingAssertions << "\n";
207 }
208
209 // struct AssertionInfo
210 // {
211 // StringRef macroName;
212 // SourceLineInfo lineInfo;
213 // StringRef capturedExpression;
214 // ResultDisposition::Flags resultDisposition;
215 // };
216
print(std::ostream & os,int const level,std::string const & title,Catch::AssertionInfo const & info)217 void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionInfo const& info ) {
218 os << ws(level ) << title << ":\n"
219 << ws(level+1) << "- macroName: '" << info.macroName << "'\n";
220 print( os, level+1 , "- lineInfo" , info.lineInfo );
221 os << ws(level+1) << "- capturedExpression: '" << info.capturedExpression << "'\n"
222 << ws(level+1) << "- resultDisposition (flags): 0x" << std::hex << info.resultDisposition << std::dec << "\n";
223 }
224
225 //struct AssertionResultData
226 //{
227 // std::string reconstructExpression() const;
228 //
229 // std::string message;
230 // mutable std::string reconstructedExpression;
231 // LazyExpression lazyExpression;
232 // ResultWas::OfType resultType;
233 //};
234
print(std::ostream & os,int const level,std::string const & title,Catch::AssertionResultData const & info)235 void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResultData const& info ) {
236 os << ws(level ) << title << ":\n"
237 << ws(level+1) << "- reconstructExpression(): '" << info.reconstructExpression() << "'\n"
238 << ws(level+1) << "- message: '" << info.message << "'\n"
239 << ws(level+1) << "- lazyExpression: '" << "(info.lazyExpression)" << "'\n"
240 << ws(level+1) << "- resultType: '" << info.resultType << "'\n";
241 }
242
243 //class AssertionResult {
244 // bool isOk() const;
245 // bool succeeded() const;
246 // ResultWas::OfType getResultType() const;
247 // bool hasExpression() const;
248 // bool hasMessage() const;
249 // std::string getExpression() const;
250 // std::string getExpressionInMacro() const;
251 // bool hasExpandedExpression() const;
252 // std::string getExpandedExpression() const;
253 // std::string getMessage() const;
254 // SourceLineInfo getSourceInfo() const;
255 // std::string getTestMacroName() const;
256 //
257 // AssertionInfo m_info;
258 // AssertionResultData m_resultData;
259 //};
260
print(std::ostream & os,int const level,std::string const & title,Catch::AssertionResult const & info)261 void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionResult const& info ) {
262 os << ws(level ) << title << ":\n"
263 << ws(level+1) << "- isOk(): " << info.isOk() << "\n"
264 << ws(level+1) << "- succeeded(): " << info.succeeded() << "\n"
265 << ws(level+1) << "- getResultType(): " << info.getResultType() << "\n"
266 << ws(level+1) << "- hasExpression(): " << info.hasExpression() << "\n"
267 << ws(level+1) << "- hasMessage(): " << info.hasMessage() << "\n"
268 << ws(level+1) << "- getExpression(): '" << info.getExpression() << "'\n"
269 << ws(level+1) << "- getExpressionInMacro(): '" << info.getExpressionInMacro() << "'\n"
270 << ws(level+1) << "- hasExpandedExpression(): " << info.hasExpandedExpression() << "\n"
271 << ws(level+1) << "- getExpandedExpression(): " << info.getExpandedExpression() << "'\n"
272 << ws(level+1) << "- getMessage(): '" << info.getMessage() << "'\n";
273 print( os, level+1 , "- getSourceInfo(): ", info.getSourceInfo() );
274 os << ws(level+1) << "- getTestMacroName(): '" << info.getTestMacroName() << "'\n";
275
276 // print( os, level+1 , "- *** m_info (AssertionInfo)", info.m_info );
277 // print( os, level+1 , "- *** m_resultData (AssertionResultData)", info.m_resultData );
278 }
279
280 // struct AssertionStats {
281 // AssertionResult assertionResult;
282 // std::vector<MessageInfo> infoMessages;
283 // Totals totals;
284 // };
285
print(std::ostream & os,int const level,std::string const & title,Catch::AssertionStats const & info)286 void print( std::ostream& os, int const level, std::string const& title, Catch::AssertionStats const& info ) {
287 os << ws(level ) << title << ":\n";
288 print( os, level+1 , "- assertionResult", info.assertionResult );
289 print( os, level+1 , "- infoMessages", info.infoMessages );
290 print( os, level+1 , "- totals", info.totals );
291 }
292
293 // -----------------------------------------------------------------------
294 // 2. My listener and registration:
295 //
296
297 char const * dashed_line =
298 "--------------------------------------------------------------------------";
299
300 struct MyListener : Catch::TestEventListenerBase {
301
302 using TestEventListenerBase::TestEventListenerBase; // inherit constructor
303
304 // Get rid of Wweak-tables
305 ~MyListener();
306
307 // The whole test run starting
testRunStartingMyListener308 virtual void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {
309 std::cout
310 << std::boolalpha
311 << "\nEvent: testRunStarting:\n";
312 print( std::cout, 1, "- testRunInfo", testRunInfo );
313 }
314
315 // The whole test run ending
testRunEndedMyListener316 virtual void testRunEnded( Catch::TestRunStats const& testRunStats ) override {
317 std::cout
318 << dashed_line
319 << "\nEvent: testRunEnded:\n";
320 print( std::cout, 1, "- testRunStats", testRunStats );
321 }
322
323 // A test is being skipped (because it is "hidden")
skipTestMyListener324 virtual void skipTest( Catch::TestCaseInfo const& testInfo ) override {
325 std::cout
326 << dashed_line
327 << "\nEvent: skipTest:\n";
328 print( std::cout, 1, "- testInfo", testInfo );
329 }
330
331 // Test cases starting
testCaseStartingMyListener332 virtual void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
333 std::cout
334 << dashed_line
335 << "\nEvent: testCaseStarting:\n";
336 print( std::cout, 1, "- testInfo", testInfo );
337 }
338
339 // Test cases ending
testCaseEndedMyListener340 virtual void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
341 std::cout << "\nEvent: testCaseEnded:\n";
342 print( std::cout, 1, "testCaseStats", testCaseStats );
343 }
344
345 // Sections starting
sectionStartingMyListener346 virtual void sectionStarting( Catch::SectionInfo const& sectionInfo ) override {
347 std::cout << "\nEvent: sectionStarting:\n";
348 print( std::cout, 1, "- sectionInfo", sectionInfo );
349 }
350
351 // Sections ending
sectionEndedMyListener352 virtual void sectionEnded( Catch::SectionStats const& sectionStats ) override {
353 std::cout << "\nEvent: sectionEnded:\n";
354 print( std::cout, 1, "- sectionStats", sectionStats );
355 }
356
357 // Assertions before/ after
assertionStartingMyListener358 virtual void assertionStarting( Catch::AssertionInfo const& assertionInfo ) override {
359 std::cout << "\nEvent: assertionStarting:\n";
360 print( std::cout, 1, "- assertionInfo", assertionInfo );
361 }
362
assertionEndedMyListener363 virtual bool assertionEnded( Catch::AssertionStats const& assertionStats ) override {
364 std::cout << "\nEvent: assertionEnded:\n";
365 print( std::cout, 1, "- assertionStats", assertionStats );
366 return true;
367 }
368 };
369
CATCH_REGISTER_LISTENER(MyListener)370 CATCH_REGISTER_LISTENER( MyListener )
371
372 // Get rid of Wweak-tables
373 MyListener::~MyListener() {}
374
375
376 // -----------------------------------------------------------------------
377 // 3. Test cases:
378 //
379
380 TEST_CASE( "1: Hidden testcase", "[.hidden]" ) {
381 }
382
383 TEST_CASE( "2: Testcase with sections", "[tag-A][tag-B]" ) {
384
385 int i = 42;
386
387 REQUIRE( i == 42 );
388
389 SECTION("Section 1") {
390 INFO("Section 1");
391 i = 7;
392 SECTION("Section 1.1") {
393 INFO("Section 1.1");
394 REQUIRE( i == 42 );
395 }
396 }
397
398 SECTION("Section 2") {
399 INFO("Section 2");
400 REQUIRE( i == 42 );
401 }
402 WARN("At end of test case");
403 }
404
405 struct Fixture {
fortytwoFixture406 int fortytwo() const {
407 return 42;
408 }
409 };
410
411 TEST_CASE_METHOD( Fixture, "3: Testcase with class-based fixture", "[tag-C][tag-D]" ) {
412 REQUIRE( fortytwo() == 42 );
413 }
414
415 // Compile & run:
416 // - g++ -std=c++11 -Wall -I$(CATCH_SINGLE_INCLUDE) -o 210-Evt-EventListeners 210-Evt-EventListeners.cpp 000-CatchMain.o && 210-Evt-EventListeners --success
417 // - cl -EHsc -I%CATCH_SINGLE_INCLUDE% 210-Evt-EventListeners.cpp 000-CatchMain.obj && 210-Evt-EventListeners --success
418
419 // Expected compact output (all assertions):
420 //
421 // prompt> 210-Evt-EventListeners --reporter compact --success
422 // result omitted for brevity.
423