comparison include/catch.hpp @ 806:c6f497291fd8 opencv3

updated catch and C++ code to opencv2.4.13
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Fri, 10 Jun 2016 12:29:58 -0400
parents f0f800b95765
children
comparison
equal deleted inserted replaced
805:180b6b0231c0 806:c6f497291fd8
1 /* 1 /*
2 * Generated: 2012-06-06 08:05:56.928287 2 * Catch v1.5.6
3 * Generated: 2016-06-09 19:20:41.460328
3 * ---------------------------------------------------------- 4 * ----------------------------------------------------------
4 * This file has been merged from multiple headers. Please don't edit it directly 5 * This file has been merged from multiple headers. Please don't edit it directly
5 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. 6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
6 * 7 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying 8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 */ 10 */
10 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
11 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 13
13 // #included from: internal/catch_context.h 14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
14 15
15 // #included from: catch_interfaces_reporter.h 16 #ifdef __clang__
17 # pragma clang system_header
18 #elif defined __GNUC__
19 # pragma GCC system_header
20 #endif
21
22 // #included from: internal/catch_suppress_warnings.h
23
24 #ifdef __clang__
25 # ifdef __ICC // icpc defines the __clang__ macro
26 # pragma warning(push)
27 # pragma warning(disable: 161 1682)
28 # else // __ICC
29 # pragma clang diagnostic ignored "-Wglobal-constructors"
30 # pragma clang diagnostic ignored "-Wvariadic-macros"
31 # pragma clang diagnostic ignored "-Wc99-extensions"
32 # pragma clang diagnostic ignored "-Wunused-variable"
33 # pragma clang diagnostic push
34 # pragma clang diagnostic ignored "-Wpadded"
35 # pragma clang diagnostic ignored "-Wc++98-compat"
36 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
37 # pragma clang diagnostic ignored "-Wswitch-enum"
38 # pragma clang diagnostic ignored "-Wcovered-switch-default"
39 # endif
40 #elif defined __GNUC__
41 # pragma GCC diagnostic ignored "-Wvariadic-macros"
42 # pragma GCC diagnostic ignored "-Wunused-variable"
43 # pragma GCC diagnostic push
44 # pragma GCC diagnostic ignored "-Wpadded"
45 #endif
46 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
47 # define CATCH_IMPL
48 #endif
49
50 #ifdef CATCH_IMPL
51 # ifndef CLARA_CONFIG_MAIN
52 # define CLARA_CONFIG_MAIN_NOT_DEFINED
53 # define CLARA_CONFIG_MAIN
54 # endif
55 #endif
56
57 // #included from: internal/catch_notimplemented_exception.h
58 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
16 59
17 // #included from: catch_common.h 60 // #included from: catch_common.h
61 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
18 62
19 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 63 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
20 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 64 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
21 #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 65 #ifdef CATCH_CONFIG_COUNTER
66 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
67 #else
68 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
69 #endif
22 70
23 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr 71 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
24 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) 72 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
25
26 #ifdef __GNUC__
27 #define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
28 #else
29 #define ATTRIBUTE_NORETURN
30 #endif
31 73
32 #include <sstream> 74 #include <sstream>
33 #include <stdexcept> 75 #include <stdexcept>
34 #include <algorithm> 76 #include <algorithm>
35 77
78 // #included from: catch_compiler_capabilities.h
79 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
80
81 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
82 // The following features are defined:
83 //
84 // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
85 // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
86 // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
87 // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
88 // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
89 // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
90 // CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
91 // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
92
93 // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
94
95 // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
96 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
97 // ****************
98 // Note to maintainers: if new toggles are added please document them
99 // in configuration.md, too
100 // ****************
101
102 // In general each macro has a _NO_<feature name> form
103 // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
104 // Many features, at point of detection, define an _INTERNAL_ macro, so they
105 // can be combined, en-mass, with the _NO_ forms later.
106
107 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
108
109 #ifdef __cplusplus
110
111 # if __cplusplus >= 201103L
112 # define CATCH_CPP11_OR_GREATER
113 # endif
114
115 # if __cplusplus >= 201402L
116 # define CATCH_CPP14_OR_GREATER
117 # endif
118
119 #endif
120
121 #ifdef __clang__
122
123 # if __has_feature(cxx_nullptr)
124 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
125 # endif
126
127 # if __has_feature(cxx_noexcept)
128 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
129 # endif
130
131 # if defined(CATCH_CPP11_OR_GREATER)
132 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
133 # endif
134
135 #endif // __clang__
136
137 ////////////////////////////////////////////////////////////////////////////////
138 // Borland
139 #ifdef __BORLANDC__
140
141 #endif // __BORLANDC__
142
143 ////////////////////////////////////////////////////////////////////////////////
144 // EDG
145 #ifdef __EDG_VERSION__
146
147 #endif // __EDG_VERSION__
148
149 ////////////////////////////////////////////////////////////////////////////////
150 // Digital Mars
151 #ifdef __DMC__
152
153 #endif // __DMC__
154
155 ////////////////////////////////////////////////////////////////////////////////
156 // GCC
157 #ifdef __GNUC__
158
159 # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
160 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
161 # endif
162
163 # if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
164 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
165 # endif
166
167 // - otherwise more recent versions define __cplusplus >= 201103L
168 // and will get picked up below
169
170 #endif // __GNUC__
171
172 ////////////////////////////////////////////////////////////////////////////////
173 // Visual C++
174 #ifdef _MSC_VER
175
176 #if (_MSC_VER >= 1600)
177 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
178 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
179 #endif
180
181 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
182 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
183 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
184 #endif
185
186 #endif // _MSC_VER
187
188 ////////////////////////////////////////////////////////////////////////////////
189
190 // Use variadic macros if the compiler supports them
191 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
192 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
193 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
194 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
195
196 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
197
198 #endif
199
200 // Use __COUNTER__ if the compiler supports it
201 #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
202 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
203 ( defined __clang__ && __clang_major__ >= 3 )
204
205 #define CATCH_INTERNAL_CONFIG_COUNTER
206
207 #endif
208
209 ////////////////////////////////////////////////////////////////////////////////
210 // C++ language feature support
211
212 // catch all support for C++11
213 #if defined(CATCH_CPP11_OR_GREATER)
214
215 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
216 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
217 # endif
218
219 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
220 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
221 # endif
222
223 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
224 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
225 # endif
226
227 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
228 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
229 # endif
230
231 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
232 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
233 # endif
234
235 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
236 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
237 # endif
238
239 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
240 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
241 # endif
242
243 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
244 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
245 # endif
246 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
247 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
248 # endif
249
250 #endif // __cplusplus >= 201103L
251
252 // Now set the actual defines based on the above + anything the user has configured
253 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
254 # define CATCH_CONFIG_CPP11_NULLPTR
255 #endif
256 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
257 # define CATCH_CONFIG_CPP11_NOEXCEPT
258 #endif
259 #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
260 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
261 #endif
262 #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
263 # define CATCH_CONFIG_CPP11_IS_ENUM
264 #endif
265 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
266 # define CATCH_CONFIG_CPP11_TUPLE
267 #endif
268 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
269 # define CATCH_CONFIG_VARIADIC_MACROS
270 #endif
271 #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
272 # define CATCH_CONFIG_CPP11_LONG_LONG
273 #endif
274 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
275 # define CATCH_CONFIG_CPP11_OVERRIDE
276 #endif
277 #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
278 # define CATCH_CONFIG_CPP11_UNIQUE_PTR
279 #endif
280 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
281 # define CATCH_CONFIG_COUNTER
282 #endif
283
284 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
285 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
286 #endif
287
288 // noexcept support:
289 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
290 # define CATCH_NOEXCEPT noexcept
291 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
292 #else
293 # define CATCH_NOEXCEPT throw()
294 # define CATCH_NOEXCEPT_IS(x)
295 #endif
296
297 // nullptr support
298 #ifdef CATCH_CONFIG_CPP11_NULLPTR
299 # define CATCH_NULL nullptr
300 #else
301 # define CATCH_NULL NULL
302 #endif
303
304 // override support
305 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
306 # define CATCH_OVERRIDE override
307 #else
308 # define CATCH_OVERRIDE
309 #endif
310
311 // unique_ptr support
312 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
313 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
314 #else
315 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
316 #endif
317
36 namespace Catch { 318 namespace Catch {
37 319
38 class NonCopyable { 320 struct IConfig;
39 NonCopyable( const NonCopyable& ); 321
40 void operator = ( const NonCopyable& ); 322 struct CaseSensitive { enum Choice {
41 protected: 323 Yes,
42 NonCopyable() {} 324 No
43 virtual ~NonCopyable() {} 325 }; };
44 }; 326
327 class NonCopyable {
328 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
329 NonCopyable( NonCopyable const& ) = delete;
330 NonCopyable( NonCopyable && ) = delete;
331 NonCopyable& operator = ( NonCopyable const& ) = delete;
332 NonCopyable& operator = ( NonCopyable && ) = delete;
333 #else
334 NonCopyable( NonCopyable const& info );
335 NonCopyable& operator = ( NonCopyable const& );
336 #endif
337
338 protected:
339 NonCopyable() {}
340 virtual ~NonCopyable();
341 };
45 342
46 class SafeBool { 343 class SafeBool {
47 public: 344 public:
48 typedef void (SafeBool::*type)() const; 345 typedef void (SafeBool::*type)() const;
49 346
57 template<typename ContainerT> 354 template<typename ContainerT>
58 inline void deleteAll( ContainerT& container ) { 355 inline void deleteAll( ContainerT& container ) {
59 typename ContainerT::const_iterator it = container.begin(); 356 typename ContainerT::const_iterator it = container.begin();
60 typename ContainerT::const_iterator itEnd = container.end(); 357 typename ContainerT::const_iterator itEnd = container.end();
61 for(; it != itEnd; ++it ) 358 for(; it != itEnd; ++it )
62 {
63 delete *it; 359 delete *it;
64 }
65 } 360 }
66 template<typename AssociativeContainerT> 361 template<typename AssociativeContainerT>
67 inline void deleteAllValues( AssociativeContainerT& container ) { 362 inline void deleteAllValues( AssociativeContainerT& container ) {
68 typename AssociativeContainerT::const_iterator it = container.begin(); 363 typename AssociativeContainerT::const_iterator it = container.begin();
69 typename AssociativeContainerT::const_iterator itEnd = container.end(); 364 typename AssociativeContainerT::const_iterator itEnd = container.end();
70 for(; it != itEnd; ++it ) 365 for(; it != itEnd; ++it )
71 {
72 delete it->second; 366 delete it->second;
73 } 367 }
74 } 368
75 369 bool startsWith( std::string const& s, std::string const& prefix );
76 template<typename ContainerT, typename Function> 370 bool endsWith( std::string const& s, std::string const& suffix );
77 inline void forEach( ContainerT& container, Function function ) { 371 bool contains( std::string const& s, std::string const& infix );
78 std::for_each( container.begin(), container.end(), function ); 372 void toLowerInPlace( std::string& s );
79 } 373 std::string toLower( std::string const& s );
80 374 std::string trim( std::string const& str );
81 template<typename ContainerT, typename Function> 375 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
82 inline void forEach( const ContainerT& container, Function function ) { 376
83 std::for_each( container.begin(), container.end(), function ); 377 struct pluralise {
84 } 378 pluralise( std::size_t count, std::string const& label );
379
380 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
381
382 std::size_t m_count;
383 std::string m_label;
384 };
85 385
86 struct SourceLineInfo { 386 struct SourceLineInfo {
87 387
88 SourceLineInfo() : line( 0 ){} 388 SourceLineInfo();
89 SourceLineInfo( const std::string& _file, std::size_t _line ) 389 SourceLineInfo( char const* _file, std::size_t _line );
90 : file( _file ), 390 SourceLineInfo( SourceLineInfo const& other );
91 line( _line ) 391 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
92 {} 392 SourceLineInfo( SourceLineInfo && ) = default;
93 SourceLineInfo( const SourceLineInfo& other ) 393 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
94 : file( other.file ), 394 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
95 line( other.line ) 395 # endif
96 {} 396 bool empty() const;
97 void swap( SourceLineInfo& other ){ 397 bool operator == ( SourceLineInfo const& other ) const;
98 file.swap( other.file ); 398 bool operator < ( SourceLineInfo const& other ) const;
99 std::swap( line, other.line );
100 }
101 399
102 std::string file; 400 std::string file;
103 std::size_t line; 401 std::size_t line;
104 }; 402 };
105 403
106 inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) { 404 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
107 #ifndef __GNUG__ 405
108 os << info.file << "(" << info.line << "): "; 406 // This is just here to avoid compiler warnings with macro constants and boolean literals
109 #else 407 inline bool isTrue( bool value ){ return value; }
110 os << info.file << ":" << info.line << ": "; 408 inline bool alwaysTrue() { return true; }
111 #endif 409 inline bool alwaysFalse() { return false; }
112 return os; 410
113 } 411 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
114 412
115 ATTRIBUTE_NORETURN 413 void seedRng( IConfig const& config );
116 inline void throwLogicError( const std::string& message, const std::string& file, std::size_t line ) { 414 unsigned int rngSeed();
117 std::ostringstream oss; 415
118 oss << "Internal Catch error: '" << message << "' at: " << SourceLineInfo( file, line ); 416 // Use this in variadic streaming macros to allow
119 throw std::logic_error( oss.str() ); 417 // >> +StreamEndStop
418 // as well as
419 // >> stuff +StreamEndStop
420 struct StreamEndStop {
421 std::string operator+() {
422 return std::string();
423 }
424 };
425 template<typename T>
426 T const& operator + ( T const& value, StreamEndStop ) {
427 return value;
120 } 428 }
121 } 429 }
122 430
123 #define CATCH_INTERNAL_ERROR( msg ) throwLogicError( msg, __FILE__, __LINE__ ); 431 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
124 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, __LINE__ ) 432 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
125 433
126 // #included from: catch_totals.hpp 434 #include <ostream>
127 435
128 namespace Catch { 436 namespace Catch {
129 437
130 struct Counts { 438 class NotImplementedException : public std::exception
131 Counts() : passed( 0 ), failed( 0 ) {} 439 {
132 440 public:
133 Counts operator - ( const Counts& other ) const { 441 NotImplementedException( SourceLineInfo const& lineInfo );
134 Counts diff; 442 NotImplementedException( NotImplementedException const& ) {}
135 diff.passed = passed - other.passed; 443
136 diff.failed = failed - other.failed; 444 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
137 return diff; 445
138 } 446 virtual const char* what() const CATCH_NOEXCEPT;
139 Counts& operator += ( const Counts& other ) { 447
140 passed += other.passed; 448 private:
141 failed += other.failed; 449 std::string m_what;
142 return *this; 450 SourceLineInfo m_lineInfo;
143 } 451 };
144 452
145 std::size_t total() const { 453 } // end namespace Catch
146 return passed + failed; 454
147 } 455 ///////////////////////////////////////////////////////////////////////////////
148 456 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
149 std::size_t passed; 457
150 std::size_t failed; 458 // #included from: internal/catch_context.h
151 }; 459 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
152 460
153 struct Totals { 461 // #included from: catch_interfaces_generators.h
154 462 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
155 Totals operator - ( const Totals& other ) const { 463
156 Totals diff; 464 #include <string>
157 diff.assertions = assertions - other.assertions; 465
158 diff.testCases = testCases - other.testCases; 466 namespace Catch {
159 return diff; 467
160 } 468 struct IGeneratorInfo {
161 469 virtual ~IGeneratorInfo();
162 Totals delta( const Totals& prevTotals ) const { 470 virtual bool moveNext() = 0;
163 Totals diff = *this - prevTotals; 471 virtual std::size_t getCurrentIndex() const = 0;
164 if( diff.assertions.failed > 0 ) 472 };
165 ++diff.testCases.failed; 473
166 else 474 struct IGeneratorsForTest {
167 ++diff.testCases.passed; 475 virtual ~IGeneratorsForTest();
168 return diff; 476
169 } 477 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
170 478 virtual bool moveNext() = 0;
171 Counts assertions; 479 };
172 Counts testCases; 480
173 }; 481 IGeneratorsForTest* createGeneratorsForTest();
174 } 482
483 } // end namespace Catch
175 484
176 // #included from: catch_ptr.hpp 485 // #included from: catch_ptr.hpp
486 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
487
488 #ifdef __clang__
489 #pragma clang diagnostic push
490 #pragma clang diagnostic ignored "-Wpadded"
491 #endif
177 492
178 namespace Catch { 493 namespace Catch {
179 494
180 // An intrusive reference counting smart pointer. 495 // An intrusive reference counting smart pointer.
181 // T must implement addRef() and release() methods 496 // T must implement addRef() and release() methods
182 // typically implementing the IShared interface 497 // typically implementing the IShared interface
183 template<typename T> 498 template<typename T>
184 class Ptr { 499 class Ptr {
185 public: 500 public:
186 Ptr() : m_p( NULL ){} 501 Ptr() : m_p( CATCH_NULL ){}
187 Ptr( T* p ) : m_p( p ){ 502 Ptr( T* p ) : m_p( p ){
188 m_p->addRef(); 503 if( m_p )
189 } 504 m_p->addRef();
190 Ptr( const Ptr& other ) : m_p( other.m_p ){ 505 }
191 m_p->addRef(); 506 Ptr( Ptr const& other ) : m_p( other.m_p ){
507 if( m_p )
508 m_p->addRef();
192 } 509 }
193 ~Ptr(){ 510 ~Ptr(){
194 if( m_p ) 511 if( m_p )
195 m_p->release(); 512 m_p->release();
513 }
514 void reset() {
515 if( m_p )
516 m_p->release();
517 m_p = CATCH_NULL;
196 } 518 }
197 Ptr& operator = ( T* p ){ 519 Ptr& operator = ( T* p ){
198 Ptr temp( p ); 520 Ptr temp( p );
199 swap( temp ); 521 swap( temp );
200 return *this; 522 return *this;
201 } 523 }
202 Ptr& operator = ( Ptr& other ){ 524 Ptr& operator = ( Ptr const& other ){
203 Ptr temp( other ); 525 Ptr temp( other );
204 swap( temp ); 526 swap( temp );
205 return *this; 527 return *this;
206 } 528 }
207 void swap( Ptr& other ){ 529 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
208 std::swap( m_p, other.m_p ); 530 T* get() const{ return m_p; }
209 } 531 T& operator*() const { return *m_p; }
210 532 T* operator->() const { return m_p; }
211 T* get(){ 533 bool operator !() const { return m_p == CATCH_NULL; }
212 return m_p; 534 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
213 }
214 const T* get() const{
215 return m_p;
216 }
217
218 T& operator*(){
219 return *m_p;
220 }
221 const T& operator*() const{
222 return *m_p;
223 }
224
225 T* operator->(){
226 return m_p;
227 }
228 const T* operator->() const{
229 return m_p;
230 }
231 535
232 private: 536 private:
233 T* m_p; 537 T* m_p;
234 }; 538 };
235 539
236 struct IShared : NonCopyable { 540 struct IShared : NonCopyable {
237 virtual ~IShared(){} 541 virtual ~IShared();
238 virtual void addRef() = 0; 542 virtual void addRef() const = 0;
239 virtual void release() = 0; 543 virtual void release() const = 0;
240 }; 544 };
241 545
242 template<typename T> 546 template<typename T = IShared>
243 struct SharedImpl : T { 547 struct SharedImpl : T {
244 548
245 SharedImpl() : m_rc( 0 ){} 549 SharedImpl() : m_rc( 0 ){}
246 550
247 virtual void addRef(){ 551 virtual void addRef() const {
248 ++m_rc; 552 ++m_rc;
249 } 553 }
250 virtual void release(){ 554 virtual void release() const {
251 if( --m_rc == 0 ) 555 if( --m_rc == 0 )
252 delete this; 556 delete this;
253 } 557 }
254 558
255 int m_rc; 559 mutable unsigned int m_rc;
256 }; 560 };
257 561
258 } // end namespace Catch 562 } // end namespace Catch
259 563
260 #include <string> 564 #ifdef __clang__
261 #include <ostream> 565 #pragma clang diagnostic pop
262 #include <map> 566 #endif
263
264 namespace Catch
265 {
266 struct IReporterConfig {
267 virtual ~IReporterConfig() {}
268 virtual std::ostream& stream () const = 0;
269 virtual bool includeSuccessfulResults () const = 0;
270 virtual std::string getName () const = 0;
271 };
272
273 class TestCaseInfo;
274 class ResultInfo;
275
276 struct IReporter : IShared {
277 virtual ~IReporter() {}
278 virtual bool shouldRedirectStdout() const = 0;
279 virtual void StartTesting() = 0;
280 virtual void EndTesting( const Totals& totals ) = 0;
281 virtual void StartGroup( const std::string& groupName ) = 0;
282 virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0;
283 virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0;
284 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;
285 virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
286 virtual void Aborted() = 0;
287 virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0;
288 virtual void Result( const ResultInfo& result ) = 0;
289 };
290
291 struct IReporterFactory {
292 virtual ~IReporterFactory() {}
293 virtual IReporter* create( const IReporterConfig& config ) const = 0;
294 virtual std::string getDescription() const = 0;
295 };
296
297 struct IReporterRegistry {
298 typedef std::map<std::string, IReporterFactory*> FactoryMap;
299
300 virtual ~IReporterRegistry() {}
301 virtual IReporter* create( const std::string& name, const IReporterConfig& config ) const = 0;
302 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0;
303 virtual const FactoryMap& getFactories() const = 0;
304 };
305
306 inline std::string trim( const std::string& str ) {
307 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
308 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
309
310 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
311 }
312 }
313
314 // #included from: catch_interfaces_config.h
315
316 namespace Catch {
317
318 struct IConfig {
319
320 virtual ~IConfig(){}
321
322 virtual bool allowThrows() const = 0;
323 };
324 }
325 567
326 #include <memory> 568 #include <memory>
327 #include <vector> 569 #include <vector>
328 #include <stdlib.h> 570 #include <stdlib.h>
329 571
330 namespace Catch { 572 namespace Catch {
331 573
332 class TestCaseInfo; 574 class TestCase;
575 class Stream;
333 struct IResultCapture; 576 struct IResultCapture;
334 struct ITestCaseRegistry;
335 struct IRunner; 577 struct IRunner;
336 struct IExceptionTranslatorRegistry; 578 struct IGeneratorsForTest;
337 class GeneratorsForTest; 579 struct IConfig;
338
339 class StreamBufBase : public std::streambuf{};
340 580
341 struct IContext 581 struct IContext
342 { 582 {
343 virtual ~IContext(){} 583 virtual ~IContext();
344 584
345 virtual IResultCapture& getResultCapture() = 0; 585 virtual IResultCapture* getResultCapture() = 0;
346 virtual IRunner& getRunner() = 0; 586 virtual IRunner* getRunner() = 0;
347 virtual IReporterRegistry& getReporterRegistry() = 0; 587 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
348 virtual ITestCaseRegistry& getTestCaseRegistry() = 0;
349 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
350 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0;
351 virtual bool advanceGeneratorsForCurrentTest() = 0; 588 virtual bool advanceGeneratorsForCurrentTest() = 0;
352 virtual const IConfig* getConfig() const = 0; 589 virtual Ptr<IConfig const> getConfig() const = 0;
353 }; 590 };
354 591
355 struct IMutableContext : IContext 592 struct IMutableContext : IContext
356 { 593 {
594 virtual ~IMutableContext();
357 virtual void setResultCapture( IResultCapture* resultCapture ) = 0; 595 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
358 virtual void setRunner( IRunner* runner ) = 0; 596 virtual void setRunner( IRunner* runner ) = 0;
359 virtual void setConfig( const IConfig* config ) = 0; 597 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
360 }; 598 };
361 599
362 IContext& getCurrentContext(); 600 IContext& getCurrentContext();
363 IMutableContext& getCurrentMutableContext(); 601 IMutableContext& getCurrentMutableContext();
364 602 void cleanUpContext();
365 class Context : public IMutableContext { 603 Stream createStream( std::string const& streamName );
366 604
367 Context();
368 Context( const Context& );
369 void operator=( const Context& );
370
371 public: // IContext
372 virtual IResultCapture& getResultCapture();
373 virtual IRunner& getRunner();
374 virtual IReporterRegistry& getReporterRegistry();
375 virtual ITestCaseRegistry& getTestCaseRegistry();
376 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry();
377 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize );
378 virtual bool advanceGeneratorsForCurrentTest();
379 virtual const IConfig* getConfig() const;
380
381 public: // IMutableContext
382 virtual void setResultCapture( IResultCapture* resultCapture );
383 virtual void setRunner( IRunner* runner );
384 virtual void setConfig( const IConfig* config );
385
386 public: // Statics
387 static std::streambuf* createStreamBuf( const std::string& streamName );
388 static void cleanUp();
389
390 friend IMutableContext& getCurrentMutableContext();
391
392 private:
393 GeneratorsForTest* findGeneratorsForCurrentTest();
394 GeneratorsForTest& getGeneratorsForCurrentTest();
395
396 private:
397 std::auto_ptr<IReporterRegistry> m_reporterRegistry;
398 std::auto_ptr<ITestCaseRegistry> m_testCaseRegistry;
399 std::auto_ptr<IExceptionTranslatorRegistry> m_exceptionTranslatorRegistry;
400 IRunner* m_runner;
401 IResultCapture* m_resultCapture;
402 const IConfig* m_config;
403 std::map<std::string, GeneratorsForTest*> m_generatorsByTestName;
404 };
405 } 605 }
406 606
407 // #included from: internal/catch_test_registry.hpp 607 // #included from: internal/catch_test_registry.hpp
608 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
408 609
409 // #included from: catch_interfaces_testcase.h 610 // #included from: catch_interfaces_testcase.h
611 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
410 612
411 #include <vector> 613 #include <vector>
412 614
413 namespace Catch { 615 namespace Catch {
414 struct ITestCase { 616
415 virtual ~ITestCase(){} 617 class TestSpec;
618
619 struct ITestCase : IShared {
416 virtual void invoke () const = 0; 620 virtual void invoke () const = 0;
417 virtual ITestCase* clone() const = 0; 621 protected:
418 virtual bool operator == ( const ITestCase& other ) const = 0; 622 virtual ~ITestCase();
419 virtual bool operator < ( const ITestCase& other ) const = 0; 623 };
420 }; 624
421 625 class TestCase;
422 class TestCaseInfo; 626 struct IConfig;
423 627
424 struct ITestCaseRegistry { 628 struct ITestCaseRegistry {
425 virtual ~ITestCaseRegistry(){} 629 virtual ~ITestCaseRegistry();
426 virtual void registerTest( const TestCaseInfo& testInfo ) = 0; 630 virtual std::vector<TestCase> const& getAllTests() const = 0;
427 virtual const std::vector<TestCaseInfo>& getAllTests() const = 0; 631 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
428 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) = 0; 632 };
429 }; 633
634 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
635 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
636 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
637
430 } 638 }
431 639
432 namespace Catch { 640 namespace Catch {
433 641
434 template<typename C> 642 template<typename C>
435 class MethodTestCase : public ITestCase { 643 class MethodTestCase : public SharedImpl<ITestCase> {
436 644
437 public: 645 public:
438 MethodTestCase( void (C::*method)() ) : m_method( method ) {} 646 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
439 647
440 virtual void invoke() const { 648 virtual void invoke() const {
441 C obj; 649 C obj;
442 (obj.*m_method)(); 650 (obj.*m_method)();
443 } 651 }
444 652
445 virtual ITestCase* clone() const {
446 return new MethodTestCase<C>( m_method );
447 }
448
449 virtual bool operator == ( const ITestCase& other ) const {
450 const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other );
451 return mtOther && m_method == mtOther->m_method;
452 }
453
454 virtual bool operator < ( const ITestCase& other ) const {
455 const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other );
456 return mtOther && &m_method < &mtOther->m_method;
457 }
458
459 private: 653 private:
654 virtual ~MethodTestCase() {}
655
460 void (C::*m_method)(); 656 void (C::*m_method)();
461 }; 657 };
462 658
463 typedef void(*TestFunction)(); 659 typedef void(*TestFunction)();
464 660
661 struct NameAndDesc {
662 NameAndDesc( const char* _name = "", const char* _description= "" )
663 : name( _name ), description( _description )
664 {}
665
666 const char* name;
667 const char* description;
668 };
669
670 void registerTestCase
671 ( ITestCase* testCase,
672 char const* className,
673 NameAndDesc const& nameAndDesc,
674 SourceLineInfo const& lineInfo );
675
465 struct AutoReg { 676 struct AutoReg {
466 677
467 AutoReg( TestFunction function, 678 AutoReg
468 const char* name, 679 ( TestFunction function,
469 const char* description, 680 SourceLineInfo const& lineInfo,
470 const SourceLineInfo& lineInfo ); 681 NameAndDesc const& nameAndDesc );
471 682
472 template<typename C> 683 template<typename C>
473 AutoReg( void (C::*method)(), 684 AutoReg
474 const char* name, 685 ( void (C::*method)(),
475 const char* description, 686 char const* className,
476 const SourceLineInfo& lineInfo ) { 687 NameAndDesc const& nameAndDesc,
477 registerTestCase( new MethodTestCase<C>( method ), name, description, lineInfo ); 688 SourceLineInfo const& lineInfo ) {
478 } 689
479 690 registerTestCase
480 void registerTestCase( ITestCase* testCase, 691 ( new MethodTestCase<C>( method ),
481 const char* name, 692 className,
482 const char* description, 693 nameAndDesc,
483 const SourceLineInfo& lineInfo ); 694 lineInfo );
695 }
484 696
485 ~AutoReg(); 697 ~AutoReg();
486 698
487 private: 699 private:
488 AutoReg( const AutoReg& ); 700 AutoReg( AutoReg const& );
489 void operator= ( const AutoReg& ); 701 void operator= ( AutoReg const& );
490 }; 702 };
491 703
704 void registerTestCaseFunction
705 ( TestFunction function,
706 SourceLineInfo const& lineInfo,
707 NameAndDesc const& nameAndDesc );
708
492 } // end namespace Catch 709 } // end namespace Catch
493 710
494 /////////////////////////////////////////////////////////////////////////////// 711 #ifdef CATCH_CONFIG_VARIADIC_MACROS
495 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ 712 ///////////////////////////////////////////////////////////////////////////////
496 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \ 713 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
497 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\ 714 static void TestName(); \
498 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() 715 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
499 716 static void TestName()
500 /////////////////////////////////////////////////////////////////////////////// 717 #define INTERNAL_CATCH_TESTCASE( ... ) \
501 #define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \ 718 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
502 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() ATTRIBUTE_NORETURN; \ 719
503 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\ 720 ///////////////////////////////////////////////////////////////////////////////
504 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() 721 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
505 722 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
506 /////////////////////////////////////////////////////////////////////////////// 723
507 #define CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ 724 ///////////////////////////////////////////////////////////////////////////////
508 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); } 725 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
509 726 namespace{ \
510 /////////////////////////////////////////////////////////////////////////////// 727 struct TestName : ClassName{ \
511 #define TEST_CASE_METHOD( ClassName, TestName, Desc )\ 728 void test(); \
512 namespace{ \ 729 }; \
513 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \ 730 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
514 void test(); \ 731 } \
515 }; \ 732 void TestName::test()
516 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, TestName, Desc, CATCH_INTERNAL_LINEINFO ); \ 733 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
517 } \ 734 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
518 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test() 735
736 ///////////////////////////////////////////////////////////////////////////////
737 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
738 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
739
740 #else
741 ///////////////////////////////////////////////////////////////////////////////
742 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
743 static void TestName(); \
744 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
745 static void TestName()
746 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
747 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
748
749 ///////////////////////////////////////////////////////////////////////////////
750 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
751 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
752
753 ///////////////////////////////////////////////////////////////////////////////
754 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
755 namespace{ \
756 struct TestCaseName : ClassName{ \
757 void test(); \
758 }; \
759 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
760 } \
761 void TestCaseName::test()
762 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
763 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
764
765 ///////////////////////////////////////////////////////////////////////////////
766 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
767 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
768 #endif
519 769
520 // #included from: internal/catch_capture.hpp 770 // #included from: internal/catch_capture.hpp
521 771 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
522 // #included from: catch_expression_builder.hpp 772
523 773 // #included from: catch_result_builder.h
524 // #included from: catch_expression.hpp 774 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
525 775
526 // #included from: catch_resultinfo_builder.hpp 776 // #included from: catch_result_type.h
527 777 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
528 // #included from: catch_tostring.hpp 778
779 namespace Catch {
780
781 // ResultWas::OfType enum
782 struct ResultWas { enum OfType {
783 Unknown = -1,
784 Ok = 0,
785 Info = 1,
786 Warning = 2,
787
788 FailureBit = 0x10,
789
790 ExpressionFailed = FailureBit | 1,
791 ExplicitFailure = FailureBit | 2,
792
793 Exception = 0x100 | FailureBit,
794
795 ThrewException = Exception | 1,
796 DidntThrowException = Exception | 2,
797
798 FatalErrorCondition = 0x200 | FailureBit
799
800 }; };
801
802 inline bool isOk( ResultWas::OfType resultType ) {
803 return ( resultType & ResultWas::FailureBit ) == 0;
804 }
805 inline bool isJustInfo( int flags ) {
806 return flags == ResultWas::Info;
807 }
808
809 // ResultDisposition::Flags enum
810 struct ResultDisposition { enum Flags {
811 Normal = 0x01,
812
813 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
814 FalseTest = 0x04, // Prefix expression with !
815 SuppressFail = 0x08 // Failures are reported but do not fail the test
816 }; };
817
818 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
819 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
820 }
821
822 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
823 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
824 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
825
826 } // end namespace Catch
827
828 // #included from: catch_assertionresult.h
829 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
830
831 #include <string>
832
833 namespace Catch {
834
835 struct AssertionInfo
836 {
837 AssertionInfo() {}
838 AssertionInfo( std::string const& _macroName,
839 SourceLineInfo const& _lineInfo,
840 std::string const& _capturedExpression,
841 ResultDisposition::Flags _resultDisposition );
842
843 std::string macroName;
844 SourceLineInfo lineInfo;
845 std::string capturedExpression;
846 ResultDisposition::Flags resultDisposition;
847 };
848
849 struct AssertionResultData
850 {
851 AssertionResultData() : resultType( ResultWas::Unknown ) {}
852
853 std::string reconstructedExpression;
854 std::string message;
855 ResultWas::OfType resultType;
856 };
857
858 class AssertionResult {
859 public:
860 AssertionResult();
861 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
862 ~AssertionResult();
863 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
864 AssertionResult( AssertionResult const& ) = default;
865 AssertionResult( AssertionResult && ) = default;
866 AssertionResult& operator = ( AssertionResult const& ) = default;
867 AssertionResult& operator = ( AssertionResult && ) = default;
868 # endif
869
870 bool isOk() const;
871 bool succeeded() const;
872 ResultWas::OfType getResultType() const;
873 bool hasExpression() const;
874 bool hasMessage() const;
875 std::string getExpression() const;
876 std::string getExpressionInMacro() const;
877 bool hasExpandedExpression() const;
878 std::string getExpandedExpression() const;
879 std::string getMessage() const;
880 SourceLineInfo getSourceInfo() const;
881 std::string getTestMacroName() const;
882
883 protected:
884 AssertionInfo m_info;
885 AssertionResultData m_resultData;
886 };
887
888 } // end namespace Catch
889
890 // #included from: catch_matchers.hpp
891 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
892
893 namespace Catch {
894 namespace Matchers {
895 namespace Impl {
896
897 namespace Generic {
898 template<typename ExpressionT> class AllOf;
899 template<typename ExpressionT> class AnyOf;
900 template<typename ExpressionT> class Not;
901 }
902
903 template<typename ExpressionT>
904 struct Matcher : SharedImpl<IShared>
905 {
906 typedef ExpressionT ExpressionType;
907
908 virtual ~Matcher() {}
909 virtual Ptr<Matcher> clone() const = 0;
910 virtual bool match( ExpressionT const& expr ) const = 0;
911 virtual std::string toString() const = 0;
912
913 Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
914 Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
915 Generic::Not<ExpressionT> operator ! () const;
916 };
917
918 template<typename DerivedT, typename ExpressionT>
919 struct MatcherImpl : Matcher<ExpressionT> {
920
921 virtual Ptr<Matcher<ExpressionT> > clone() const {
922 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
923 }
924 };
925
926 namespace Generic {
927 template<typename ExpressionT>
928 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
929 public:
930 explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
931 Not( Not const& other ) : m_matcher( other.m_matcher ) {}
932
933 virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
934 return !m_matcher->match( expr );
935 }
936
937 virtual std::string toString() const CATCH_OVERRIDE {
938 return "not " + m_matcher->toString();
939 }
940 private:
941 Ptr< Matcher<ExpressionT> > m_matcher;
942 };
943
944 template<typename ExpressionT>
945 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
946 public:
947
948 AllOf() {}
949 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
950
951 AllOf& add( Matcher<ExpressionT> const& matcher ) {
952 m_matchers.push_back( matcher.clone() );
953 return *this;
954 }
955 virtual bool match( ExpressionT const& expr ) const
956 {
957 for( std::size_t i = 0; i < m_matchers.size(); ++i )
958 if( !m_matchers[i]->match( expr ) )
959 return false;
960 return true;
961 }
962 virtual std::string toString() const {
963 std::ostringstream oss;
964 oss << "( ";
965 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
966 if( i != 0 )
967 oss << " and ";
968 oss << m_matchers[i]->toString();
969 }
970 oss << " )";
971 return oss.str();
972 }
973
974 AllOf operator && ( Matcher<ExpressionT> const& other ) const {
975 AllOf allOfExpr( *this );
976 allOfExpr.add( other );
977 return allOfExpr;
978 }
979
980 private:
981 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
982 };
983
984 template<typename ExpressionT>
985 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
986 public:
987
988 AnyOf() {}
989 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
990
991 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
992 m_matchers.push_back( matcher.clone() );
993 return *this;
994 }
995 virtual bool match( ExpressionT const& expr ) const
996 {
997 for( std::size_t i = 0; i < m_matchers.size(); ++i )
998 if( m_matchers[i]->match( expr ) )
999 return true;
1000 return false;
1001 }
1002 virtual std::string toString() const {
1003 std::ostringstream oss;
1004 oss << "( ";
1005 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1006 if( i != 0 )
1007 oss << " or ";
1008 oss << m_matchers[i]->toString();
1009 }
1010 oss << " )";
1011 return oss.str();
1012 }
1013
1014 AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
1015 AnyOf anyOfExpr( *this );
1016 anyOfExpr.add( other );
1017 return anyOfExpr;
1018 }
1019
1020 private:
1021 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
1022 };
1023
1024 } // namespace Generic
1025
1026 template<typename ExpressionT>
1027 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
1028 Generic::AllOf<ExpressionT> allOfExpr;
1029 allOfExpr.add( *this );
1030 allOfExpr.add( other );
1031 return allOfExpr;
1032 }
1033
1034 template<typename ExpressionT>
1035 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
1036 Generic::AnyOf<ExpressionT> anyOfExpr;
1037 anyOfExpr.add( *this );
1038 anyOfExpr.add( other );
1039 return anyOfExpr;
1040 }
1041
1042 template<typename ExpressionT>
1043 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
1044 return Generic::Not<ExpressionT>( *this );
1045 }
1046
1047 namespace StdString {
1048
1049 inline std::string makeString( std::string const& str ) { return str; }
1050 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
1051
1052 struct CasedString
1053 {
1054 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
1055 : m_caseSensitivity( caseSensitivity ),
1056 m_str( adjustString( str ) )
1057 {}
1058 std::string adjustString( std::string const& str ) const {
1059 return m_caseSensitivity == CaseSensitive::No
1060 ? toLower( str )
1061 : str;
1062
1063 }
1064 std::string toStringSuffix() const
1065 {
1066 return m_caseSensitivity == CaseSensitive::No
1067 ? " (case insensitive)"
1068 : "";
1069 }
1070 CaseSensitive::Choice m_caseSensitivity;
1071 std::string m_str;
1072 };
1073
1074 struct Equals : MatcherImpl<Equals, std::string> {
1075 Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1076 : m_data( str, caseSensitivity )
1077 {}
1078 Equals( Equals const& other ) : m_data( other.m_data ){}
1079
1080 virtual ~Equals();
1081
1082 virtual bool match( std::string const& expr ) const {
1083 return m_data.m_str == m_data.adjustString( expr );;
1084 }
1085 virtual std::string toString() const {
1086 return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1087 }
1088
1089 CasedString m_data;
1090 };
1091
1092 struct Contains : MatcherImpl<Contains, std::string> {
1093 Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1094 : m_data( substr, caseSensitivity ){}
1095 Contains( Contains const& other ) : m_data( other.m_data ){}
1096
1097 virtual ~Contains();
1098
1099 virtual bool match( std::string const& expr ) const {
1100 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
1101 }
1102 virtual std::string toString() const {
1103 return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1104 }
1105
1106 CasedString m_data;
1107 };
1108
1109 struct StartsWith : MatcherImpl<StartsWith, std::string> {
1110 StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1111 : m_data( substr, caseSensitivity ){}
1112
1113 StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
1114
1115 virtual ~StartsWith();
1116
1117 virtual bool match( std::string const& expr ) const {
1118 return startsWith( m_data.adjustString( expr ), m_data.m_str );
1119 }
1120 virtual std::string toString() const {
1121 return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1122 }
1123
1124 CasedString m_data;
1125 };
1126
1127 struct EndsWith : MatcherImpl<EndsWith, std::string> {
1128 EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1129 : m_data( substr, caseSensitivity ){}
1130 EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
1131
1132 virtual ~EndsWith();
1133
1134 virtual bool match( std::string const& expr ) const {
1135 return endsWith( m_data.adjustString( expr ), m_data.m_str );
1136 }
1137 virtual std::string toString() const {
1138 return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1139 }
1140
1141 CasedString m_data;
1142 };
1143 } // namespace StdString
1144 } // namespace Impl
1145
1146 // The following functions create the actual matcher objects.
1147 // This allows the types to be inferred
1148 template<typename ExpressionT>
1149 inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
1150 return Impl::Generic::Not<ExpressionT>( m );
1151 }
1152
1153 template<typename ExpressionT>
1154 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1155 Impl::Matcher<ExpressionT> const& m2 ) {
1156 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
1157 }
1158 template<typename ExpressionT>
1159 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1160 Impl::Matcher<ExpressionT> const& m2,
1161 Impl::Matcher<ExpressionT> const& m3 ) {
1162 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1163 }
1164 template<typename ExpressionT>
1165 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1166 Impl::Matcher<ExpressionT> const& m2 ) {
1167 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
1168 }
1169 template<typename ExpressionT>
1170 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1171 Impl::Matcher<ExpressionT> const& m2,
1172 Impl::Matcher<ExpressionT> const& m3 ) {
1173 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1174 }
1175
1176 inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1177 return Impl::StdString::Equals( str, caseSensitivity );
1178 }
1179 inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1180 return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
1181 }
1182 inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1183 return Impl::StdString::Contains( substr, caseSensitivity );
1184 }
1185 inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1186 return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
1187 }
1188 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
1189 return Impl::StdString::StartsWith( substr );
1190 }
1191 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
1192 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
1193 }
1194 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
1195 return Impl::StdString::EndsWith( substr );
1196 }
1197 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
1198 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
1199 }
1200
1201 } // namespace Matchers
1202
1203 using namespace Matchers;
1204
1205 } // namespace Catch
1206
1207 namespace Catch {
1208
1209 struct TestFailureException{};
1210
1211 template<typename T> class ExpressionLhs;
1212
1213 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1214
1215 struct CopyableStream {
1216 CopyableStream() {}
1217 CopyableStream( CopyableStream const& other ) {
1218 oss << other.oss.str();
1219 }
1220 CopyableStream& operator=( CopyableStream const& other ) {
1221 oss.str("");
1222 oss << other.oss.str();
1223 return *this;
1224 }
1225 std::ostringstream oss;
1226 };
1227
1228 class ResultBuilder {
1229 public:
1230 ResultBuilder( char const* macroName,
1231 SourceLineInfo const& lineInfo,
1232 char const* capturedExpression,
1233 ResultDisposition::Flags resultDisposition,
1234 char const* secondArg = "" );
1235
1236 template<typename T>
1237 ExpressionLhs<T const&> operator <= ( T const& operand );
1238 ExpressionLhs<bool> operator <= ( bool value );
1239
1240 template<typename T>
1241 ResultBuilder& operator << ( T const& value ) {
1242 m_stream.oss << value;
1243 return *this;
1244 }
1245
1246 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1247 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1248
1249 ResultBuilder& setResultType( ResultWas::OfType result );
1250 ResultBuilder& setResultType( bool result );
1251 ResultBuilder& setLhs( std::string const& lhs );
1252 ResultBuilder& setRhs( std::string const& rhs );
1253 ResultBuilder& setOp( std::string const& op );
1254
1255 void endExpression();
1256
1257 std::string reconstructExpression() const;
1258 AssertionResult build() const;
1259
1260 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1261 void captureResult( ResultWas::OfType resultType );
1262 void captureExpression();
1263 void captureExpectedException( std::string const& expectedMessage );
1264 void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
1265 void handleResult( AssertionResult const& result );
1266 void react();
1267 bool shouldDebugBreak() const;
1268 bool allowThrows() const;
1269
1270 private:
1271 AssertionInfo m_assertionInfo;
1272 AssertionResultData m_data;
1273 struct ExprComponents {
1274 ExprComponents() : testFalse( false ) {}
1275 bool testFalse;
1276 std::string lhs, rhs, op;
1277 } m_exprComponents;
1278 CopyableStream m_stream;
1279
1280 bool m_shouldDebugBreak;
1281 bool m_shouldThrow;
1282 };
1283
1284 } // namespace Catch
1285
1286 // Include after due to circular dependency:
1287 // #included from: catch_expression_lhs.hpp
1288 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1289
1290 // #included from: catch_evaluate.hpp
1291 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1292
1293 #ifdef _MSC_VER
1294 #pragma warning(push)
1295 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1296 #endif
1297
1298 #include <cstddef>
1299
1300 namespace Catch {
1301 namespace Internal {
1302
1303 enum Operator {
1304 IsEqualTo,
1305 IsNotEqualTo,
1306 IsLessThan,
1307 IsGreaterThan,
1308 IsLessThanOrEqualTo,
1309 IsGreaterThanOrEqualTo
1310 };
1311
1312 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1313 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1314 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1315 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1316 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1317 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1318 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1319
1320 template<typename T>
1321 inline T& opCast(T const& t) { return const_cast<T&>(t); }
1322
1323 // nullptr_t support based on pull request #154 from Konstantin Baumann
1324 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1325 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1326 #endif // CATCH_CONFIG_CPP11_NULLPTR
1327
1328 // So the compare overloads can be operator agnostic we convey the operator as a template
1329 // enum, which is used to specialise an Evaluator for doing the comparison.
1330 template<typename T1, typename T2, Operator Op>
1331 class Evaluator{};
1332
1333 template<typename T1, typename T2>
1334 struct Evaluator<T1, T2, IsEqualTo> {
1335 static bool evaluate( T1 const& lhs, T2 const& rhs) {
1336 return bool( opCast( lhs ) == opCast( rhs ) );
1337 }
1338 };
1339 template<typename T1, typename T2>
1340 struct Evaluator<T1, T2, IsNotEqualTo> {
1341 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1342 return bool( opCast( lhs ) != opCast( rhs ) );
1343 }
1344 };
1345 template<typename T1, typename T2>
1346 struct Evaluator<T1, T2, IsLessThan> {
1347 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1348 return bool( opCast( lhs ) < opCast( rhs ) );
1349 }
1350 };
1351 template<typename T1, typename T2>
1352 struct Evaluator<T1, T2, IsGreaterThan> {
1353 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1354 return bool( opCast( lhs ) > opCast( rhs ) );
1355 }
1356 };
1357 template<typename T1, typename T2>
1358 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
1359 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1360 return bool( opCast( lhs ) >= opCast( rhs ) );
1361 }
1362 };
1363 template<typename T1, typename T2>
1364 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
1365 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1366 return bool( opCast( lhs ) <= opCast( rhs ) );
1367 }
1368 };
1369
1370 template<Operator Op, typename T1, typename T2>
1371 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
1372 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1373 }
1374
1375 // This level of indirection allows us to specialise for integer types
1376 // to avoid signed/ unsigned warnings
1377
1378 // "base" overload
1379 template<Operator Op, typename T1, typename T2>
1380 bool compare( T1 const& lhs, T2 const& rhs ) {
1381 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1382 }
1383
1384 // unsigned X to int
1385 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
1386 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1387 }
1388 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
1389 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1390 }
1391 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
1392 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1393 }
1394
1395 // unsigned X to long
1396 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
1397 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1398 }
1399 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
1400 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1401 }
1402 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
1403 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1404 }
1405
1406 // int to unsigned X
1407 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
1408 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1409 }
1410 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
1411 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1412 }
1413 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
1414 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1415 }
1416
1417 // long to unsigned X
1418 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
1419 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1420 }
1421 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
1422 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1423 }
1424 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
1425 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1426 }
1427
1428 // pointer to long (when comparing against NULL)
1429 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
1430 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1431 }
1432 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
1433 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1434 }
1435
1436 // pointer to int (when comparing against NULL)
1437 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
1438 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1439 }
1440 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
1441 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1442 }
1443
1444 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1445 // long long to unsigned X
1446 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1447 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1448 }
1449 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1450 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1451 }
1452 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1453 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1454 }
1455 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1456 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1457 }
1458
1459 // unsigned long long to X
1460 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1461 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1462 }
1463 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1464 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1465 }
1466 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1467 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1468 }
1469 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1470 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1471 }
1472
1473 // pointer to long long (when comparing against NULL)
1474 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1475 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1476 }
1477 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1478 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1479 }
1480 #endif // CATCH_CONFIG_CPP11_LONG_LONG
1481
1482 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1483 // pointer to nullptr_t (when comparing against nullptr)
1484 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1485 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
1486 }
1487 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1488 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
1489 }
1490 #endif // CATCH_CONFIG_CPP11_NULLPTR
1491
1492 } // end of namespace Internal
1493 } // end of namespace Catch
1494
1495 #ifdef _MSC_VER
1496 #pragma warning(pop)
1497 #endif
1498
1499 // #included from: catch_tostring.h
1500 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
529 1501
530 #include <sstream> 1502 #include <sstream>
1503 #include <iomanip>
1504 #include <limits>
1505 #include <vector>
1506 #include <cstddef>
1507
1508 #ifdef __OBJC__
1509 // #included from: catch_objc_arc.hpp
1510 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1511
1512 #import <Foundation/Foundation.h>
1513
1514 #ifdef __has_feature
1515 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1516 #else
1517 #define CATCH_ARC_ENABLED 0
1518 #endif
1519
1520 void arcSafeRelease( NSObject* obj );
1521 id performOptionalSelector( id obj, SEL sel );
1522
1523 #if !CATCH_ARC_ENABLED
1524 inline void arcSafeRelease( NSObject* obj ) {
1525 [obj release];
1526 }
1527 inline id performOptionalSelector( id obj, SEL sel ) {
1528 if( [obj respondsToSelector: sel] )
1529 return [obj performSelector: sel];
1530 return nil;
1531 }
1532 #define CATCH_UNSAFE_UNRETAINED
1533 #define CATCH_ARC_STRONG
1534 #else
1535 inline void arcSafeRelease( NSObject* ){}
1536 inline id performOptionalSelector( id obj, SEL sel ) {
1537 #ifdef __clang__
1538 #pragma clang diagnostic push
1539 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1540 #endif
1541 if( [obj respondsToSelector: sel] )
1542 return [obj performSelector: sel];
1543 #ifdef __clang__
1544 #pragma clang diagnostic pop
1545 #endif
1546 return nil;
1547 }
1548 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1549 #define CATCH_ARC_STRONG __strong
1550 #endif
1551
1552 #endif
1553
1554 #ifdef CATCH_CONFIG_CPP11_TUPLE
1555 #include <tuple>
1556 #endif
1557
1558 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1559 #include <type_traits>
1560 #endif
531 1561
532 namespace Catch { 1562 namespace Catch {
1563
1564 // Why we're here.
1565 template<typename T>
1566 std::string toString( T const& value );
1567
1568 // Built in overloads
1569
1570 std::string toString( std::string const& value );
1571 std::string toString( std::wstring const& value );
1572 std::string toString( const char* const value );
1573 std::string toString( char* const value );
1574 std::string toString( const wchar_t* const value );
1575 std::string toString( wchar_t* const value );
1576 std::string toString( int value );
1577 std::string toString( unsigned long value );
1578 std::string toString( unsigned int value );
1579 std::string toString( const double value );
1580 std::string toString( const float value );
1581 std::string toString( bool value );
1582 std::string toString( char value );
1583 std::string toString( signed char value );
1584 std::string toString( unsigned char value );
1585
1586 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1587 std::string toString( long long value );
1588 std::string toString( unsigned long long value );
1589 #endif
1590
1591 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1592 std::string toString( std::nullptr_t );
1593 #endif
1594
1595 #ifdef __OBJC__
1596 std::string toString( NSString const * const& nsstring );
1597 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1598 std::string toString( NSObject* const& nsObject );
1599 #endif
1600
533 namespace Detail { 1601 namespace Detail {
534 1602
535 struct NonStreamable { 1603 extern const std::string unprintableString;
536 template<typename T> NonStreamable( const T& ){} 1604
537 }; 1605 struct BorgType {
538 1606 template<typename T> BorgType( T const& );
539 // If the type does not have its own << overload for ostream then 1607 };
540 // this one will be used instead 1608
541 inline std::ostream& operator << ( std::ostream& ss, NonStreamable ){ 1609 struct TrueType { char sizer[1]; };
542 return ss << "{?}"; 1610 struct FalseType { char sizer[2]; };
543 } 1611
1612 TrueType& testStreamable( std::ostream& );
1613 FalseType testStreamable( FalseType );
1614
1615 FalseType operator<<( std::ostream const&, BorgType const& );
544 1616
545 template<typename T> 1617 template<typename T>
546 inline std::string makeString( const T& value ) { 1618 struct IsStreamInsertable {
547 std::ostringstream oss; 1619 static std::ostream &s;
548 oss << value; 1620 static T const&t;
549 return oss.str(); 1621 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
550 } 1622 };
1623
1624 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1625 template<typename T,
1626 bool IsEnum = std::is_enum<T>::value
1627 >
1628 struct EnumStringMaker
1629 {
1630 static std::string convert( T const& ) { return unprintableString; }
1631 };
551 1632
552 template<typename T> 1633 template<typename T>
553 inline std::string makeString( T* p ) { 1634 struct EnumStringMaker<T,true>
1635 {
1636 static std::string convert( T const& v )
1637 {
1638 return ::Catch::toString(
1639 static_cast<typename std::underlying_type<T>::type>(v)
1640 );
1641 }
1642 };
1643 #endif
1644 template<bool C>
1645 struct StringMakerBase {
1646 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1647 template<typename T>
1648 static std::string convert( T const& v )
1649 {
1650 return EnumStringMaker<T>::convert( v );
1651 }
1652 #else
1653 template<typename T>
1654 static std::string convert( T const& ) { return unprintableString; }
1655 #endif
1656 };
1657
1658 template<>
1659 struct StringMakerBase<true> {
1660 template<typename T>
1661 static std::string convert( T const& _value ) {
1662 std::ostringstream oss;
1663 oss << _value;
1664 return oss.str();
1665 }
1666 };
1667
1668 std::string rawMemoryToString( const void *object, std::size_t size );
1669
1670 template<typename T>
1671 inline std::string rawMemoryToString( const T& object ) {
1672 return rawMemoryToString( &object, sizeof(object) );
1673 }
1674
1675 } // end namespace Detail
1676
1677 template<typename T>
1678 struct StringMaker :
1679 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1680
1681 template<typename T>
1682 struct StringMaker<T*> {
1683 template<typename U>
1684 static std::string convert( U* p ) {
554 if( !p ) 1685 if( !p )
555 return INTERNAL_CATCH_STRINGIFY( NULL ); 1686 return "NULL";
556 std::ostringstream oss; 1687 else
557 oss << p; 1688 return Detail::rawMemoryToString( p );
558 return oss.str(); 1689 }
559 } 1690 };
560 1691
1692 template<typename R, typename C>
1693 struct StringMaker<R C::*> {
1694 static std::string convert( R C::* p ) {
1695 if( !p )
1696 return "NULL";
1697 else
1698 return Detail::rawMemoryToString( p );
1699 }
1700 };
1701
1702 namespace Detail {
1703 template<typename InputIterator>
1704 std::string rangeToString( InputIterator first, InputIterator last );
1705 }
1706
1707 //template<typename T, typename Allocator>
1708 //struct StringMaker<std::vector<T, Allocator> > {
1709 // static std::string convert( std::vector<T,Allocator> const& v ) {
1710 // return Detail::rangeToString( v.begin(), v.end() );
1711 // }
1712 //};
1713
1714 template<typename T, typename Allocator>
1715 std::string toString( std::vector<T,Allocator> const& v ) {
1716 return Detail::rangeToString( v.begin(), v.end() );
1717 }
1718
1719 #ifdef CATCH_CONFIG_CPP11_TUPLE
1720
1721 // toString for tuples
1722 namespace TupleDetail {
1723 template<
1724 typename Tuple,
1725 std::size_t N = 0,
1726 bool = (N < std::tuple_size<Tuple>::value)
1727 >
1728 struct ElementPrinter {
1729 static void print( const Tuple& tuple, std::ostream& os )
1730 {
1731 os << ( N ? ", " : " " )
1732 << Catch::toString(std::get<N>(tuple));
1733 ElementPrinter<Tuple,N+1>::print(tuple,os);
1734 }
1735 };
1736
1737 template<
1738 typename Tuple,
1739 std::size_t N
1740 >
1741 struct ElementPrinter<Tuple,N,false> {
1742 static void print( const Tuple&, std::ostream& ) {}
1743 };
1744
1745 }
1746
1747 template<typename ...Types>
1748 struct StringMaker<std::tuple<Types...>> {
1749
1750 static std::string convert( const std::tuple<Types...>& tuple )
1751 {
1752 std::ostringstream os;
1753 os << '{';
1754 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1755 os << " }";
1756 return os.str();
1757 }
1758 };
1759 #endif // CATCH_CONFIG_CPP11_TUPLE
1760
1761 namespace Detail {
561 template<typename T> 1762 template<typename T>
562 inline std::string makeString( const T* p ) { 1763 std::string makeString( T const& value ) {
563 if( !p ) 1764 return StringMaker<T>::convert( value );
564 return INTERNAL_CATCH_STRINGIFY( NULL ); 1765 }
565 std::ostringstream oss;
566 oss << p;
567 return oss.str();
568 }
569
570 } // end namespace Detail 1766 } // end namespace Detail
571 1767
572 /// \brief converts any type to a string 1768 /// \brief converts any type to a string
573 /// 1769 ///
574 /// The default template forwards on to ostringstream - except when an 1770 /// The default template forwards on to ostringstream - except when an
575 /// ostringstream overload does not exist - in which case it attempts to detect 1771 /// ostringstream overload does not exist - in which case it attempts to detect
576 /// that and writes {?}. 1772 /// that and writes {?}.
577 /// Overload (not specialise) this template for custom typs that you don't want 1773 /// Overload (not specialise) this template for custom typs that you don't want
578 /// to provide an ostream overload for. 1774 /// to provide an ostream overload for.
579 template<typename T> 1775 template<typename T>
580 std::string toString( const T& value ) { 1776 std::string toString( T const& value ) {
581 return Detail::makeString( value ); 1777 return StringMaker<T>::convert( value );
582 } 1778 }
583 1779
584 // Built in overloads 1780 namespace Detail {
585 1781 template<typename InputIterator>
586 inline std::string toString( const std::string& value ) { 1782 std::string rangeToString( InputIterator first, InputIterator last ) {
587 return "\"" + value + "\""; 1783 std::ostringstream oss;
1784 oss << "{ ";
1785 if( first != last ) {
1786 oss << Catch::toString( *first );
1787 for( ++first ; first != last ; ++first )
1788 oss << ", " << Catch::toString( *first );
1789 }
1790 oss << " }";
1791 return oss.str();
1792 }
588 } 1793 }
589 1794
590 inline std::string toString( const std::wstring& value ) {
591 std::ostringstream oss;
592 oss << "\"";
593 for(size_t i = 0; i < value.size(); ++i )
594 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
595 oss << "\"";
596 return oss.str();
597 }
598
599 inline std::string toString( const char* const value ) {
600 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
601 }
602
603 inline std::string toString( char* const value ) {
604 return Catch::toString( static_cast<const char*>( value ) );
605 }
606
607 inline std::string toString( int value ) {
608 std::ostringstream oss;
609 oss << value;
610 return oss.str();
611 }
612
613 inline std::string toString( unsigned long value ) {
614 std::ostringstream oss;
615 if( value > 8192 )
616 oss << "0x" << std::hex << value;
617 else
618 oss << value;
619 return oss.str();
620 }
621
622 inline std::string toString( unsigned int value ) {
623 return toString( static_cast<unsigned long>( value ) );
624 }
625
626 inline std::string toString( const double value ) {
627 std::ostringstream oss;
628 oss << value;
629 return oss.str();
630 }
631
632 inline std::string toString( bool value ) {
633 return value ? "true" : "false";
634 }
635
636 inline std::string toString( char value ) {
637 return value < ' '
638 ? toString( (unsigned int)value )
639 : Detail::makeString( value );
640 }
641
642 inline std::string toString( signed char value ) {
643 return toString( static_cast<char>( value ) );
644 }
645
646 #ifdef CATCH_CONFIG_CPP11_NULLPTR
647 inline std::string toString( std::nullptr_t ) {
648 return "nullptr";
649 }
650 #endif
651
652 } // end namespace Catch 1795 } // end namespace Catch
653 1796
654 // #included from: catch_resultinfo.hpp
655
656 #include <string>
657 // #included from: catch_result_type.h
658
659 namespace Catch { 1797 namespace Catch {
660 1798
661 struct ResultWas { enum OfType { 1799 // Wraps the LHS of an expression and captures the operator and RHS (if any) -
662 Unknown = -1, 1800 // wrapping them all in a ResultBuilder object
663 Ok = 0, 1801 template<typename T>
664 Info = 1, 1802 class ExpressionLhs {
665 Warning = 2, 1803 ExpressionLhs& operator = ( ExpressionLhs const& );
666 1804 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
667 FailureBit = 0x10, 1805 ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
668 1806 # endif
669 ExpressionFailed = FailureBit | 1,
670 ExplicitFailure = FailureBit | 2,
671
672 Exception = 0x100 | FailureBit,
673
674 ThrewException = Exception | 1,
675 DidntThrowException = Exception | 2
676
677 }; };
678
679 struct ResultAction { enum Value {
680 None,
681 Failed = 1, // Failure - but no debug break if Debug bit not set
682 Debug = 2, // If this bit is set, invoke the debugger
683 Abort = 4 // Test run should abort
684 }; };
685
686 }
687
688
689 namespace Catch {
690
691 class ResultInfo {
692 public:
693 ResultInfo()
694 : m_macroName(),
695 m_expr(),
696 m_lhs(),
697 m_rhs(),
698 m_op(),
699 m_message(),
700 m_result( ResultWas::Unknown ),
701 m_isNot( false )
702 {}
703
704 ResultInfo( const char* expr,
705 ResultWas::OfType result,
706 bool isNot,
707 const SourceLineInfo& lineInfo,
708 const char* macroName,
709 const char* message )
710 : m_macroName( macroName ),
711 m_lineInfo( lineInfo ),
712 m_expr( expr ),
713 m_lhs(),
714 m_rhs(),
715 m_op( isNotExpression( expr ) ? "!" : "" ),
716 m_message( message ),
717 m_result( result ),
718 m_isNot( isNot )
719 {
720 if( isNot )
721 m_expr = "!" + m_expr;
722 }
723
724 virtual ~ResultInfo() {}
725
726 bool ok() const {
727 return ( m_result & ResultWas::FailureBit ) != ResultWas::FailureBit;
728 }
729
730 ResultWas::OfType getResultType() const {
731 return m_result;
732 }
733
734 bool hasExpression() const {
735 return !m_expr.empty();
736 }
737
738 bool hasMessage() const {
739 return !m_message.empty();
740 }
741
742 std::string getExpression() const {
743 return m_expr;
744 }
745
746 bool hasExpandedExpression() const {
747 return hasExpression() && getExpandedExpressionInternal() != m_expr;
748 }
749
750 std::string getExpandedExpression() const {
751 return hasExpression() ? getExpandedExpressionInternal() : "";
752 }
753
754 std::string getMessage() const {
755 return m_message;
756 }
757
758 std::string getFilename() const {
759 return m_lineInfo.file;
760 }
761
762 std::size_t getLine() const {
763 return m_lineInfo.line;
764 }
765
766 std::string getTestMacroName() const {
767 return m_macroName;
768 }
769
770 protected:
771
772 std::string getExpandedExpressionInternal() const {
773 if( m_op == "" || m_isNot )
774 return m_lhs.empty() ? m_expr : m_op + m_lhs;
775 else if( m_op == "matches" )
776 return m_lhs + " " + m_rhs;
777 else if( m_op != "!" )
778 {
779 if( m_lhs.size() + m_rhs.size() < 30 )
780 return m_lhs + " " + m_op + " " + m_rhs;
781 else if( m_lhs.size() < 70 && m_rhs.size() < 70 )
782 return "\n\t" + m_lhs + "\n\t" + m_op + "\n\t" + m_rhs;
783 else
784 return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n";
785 }
786 else
787 return "{can't expand - use " + m_macroName + "_FALSE( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}";
788 }
789
790 bool isNotExpression( const char* expr ) {
791 return expr && expr[0] == '!';
792 }
793
794 protected:
795 std::string m_macroName;
796 SourceLineInfo m_lineInfo;
797 std::string m_expr, m_lhs, m_rhs, m_op;
798 std::string m_message;
799 ResultWas::OfType m_result;
800 bool m_isNot;
801 };
802
803 } // end namespace Catch
804
805 // #included from: catch_evaluate.hpp
806
807 namespace Catch {
808 namespace Internal {
809
810 enum Operator {
811 IsEqualTo,
812 IsNotEqualTo,
813 IsLessThan,
814 IsGreaterThan,
815 IsLessThanOrEqualTo,
816 IsGreaterThanOrEqualTo
817 };
818
819 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
820 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
821 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
822 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
823 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
824 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
825 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
826
827 // So the compare overloads can be operator agnostic we convey the operator as a template
828 // enum, which is used to specialise an Evaluator for doing the comparison.
829 template<typename T1, typename T2, Operator Op>
830 class Evaluator{};
831
832 template<typename T1, typename T2>
833 struct Evaluator<T1, T2, IsEqualTo> {
834 static bool evaluate( const T1& lhs, const T2& rhs) {
835 return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
836 }
837 };
838 template<typename T1, typename T2>
839 struct Evaluator<T1, T2, IsNotEqualTo> {
840 static bool evaluate( const T1& lhs, const T2& rhs ) {
841 return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
842 }
843 };
844 template<typename T1, typename T2>
845 struct Evaluator<T1, T2, IsLessThan> {
846 static bool evaluate( const T1& lhs, const T2& rhs ) {
847 return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
848 }
849 };
850 template<typename T1, typename T2>
851 struct Evaluator<T1, T2, IsGreaterThan> {
852 static bool evaluate( const T1& lhs, const T2& rhs ) {
853 return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
854 }
855 };
856 template<typename T1, typename T2>
857 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
858 static bool evaluate( const T1& lhs, const T2& rhs ) {
859 return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
860 }
861 };
862 template<typename T1, typename T2>
863 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
864 static bool evaluate( const T1& lhs, const T2& rhs ) {
865 return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
866 }
867 };
868
869 template<Operator Op, typename T1, typename T2>
870 bool applyEvaluator( const T1& lhs, const T2& rhs ) {
871 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
872 }
873
874 // "base" overload
875 template<Operator Op, typename T1, typename T2>
876 bool compare( const T1& lhs, const T2& rhs ) {
877 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
878 }
879
880 // unsigned X to int
881 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
882 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
883 }
884 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
885 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
886 }
887 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
888 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
889 }
890
891 // unsigned X to long
892 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
893 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
894 }
895 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
896 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
897 }
898 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
899 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
900 }
901
902 // int to unsigned X
903 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
904 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
905 }
906 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
907 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
908 }
909 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
910 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
911 }
912
913 // long to unsigned X
914 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
915 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
916 }
917 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
918 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
919 }
920 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
921 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
922 }
923
924 // pointer to long (when comparing against NULL)
925 template<Operator Op, typename T>
926 bool compare( long lhs, const T* rhs ) {
927 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
928 }
929
930 template<Operator Op, typename T>
931 bool compare( long lhs, T* rhs ) {
932 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
933 }
934
935 template<Operator Op, typename T>
936 bool compare( const T* lhs, long rhs ) {
937 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
938 }
939
940 template<Operator Op, typename T>
941 bool compare( T* lhs, long rhs ) {
942 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
943 }
944
945 // pointer to int (when comparing against NULL)
946 template<Operator Op, typename T>
947 bool compare( int lhs, const T* rhs ) {
948 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
949 }
950
951 template<Operator Op, typename T>
952 bool compare( int lhs, T* rhs ) {
953 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
954 }
955
956 template<Operator Op, typename T>
957 bool compare( const T* lhs, int rhs ) {
958 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
959 }
960
961 template<Operator Op, typename T>
962 bool compare( T* lhs, int rhs ) {
963 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
964 }
965
966 } // end of namespace Internal
967 } // end of namespace Catch
968
969 namespace Catch {
970
971 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
972
973 class ResultInfoBuilder : public ResultInfo {
974 1807
975 public: 1808 public:
976 1809 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
977 ResultInfoBuilder() {} 1810 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
978 1811 ExpressionLhs( ExpressionLhs const& ) = default;
979 ResultInfoBuilder( const char* expr, 1812 ExpressionLhs( ExpressionLhs && ) = default;
980 bool isNot, 1813 # endif
981 const SourceLineInfo& lineInfo,
982 const char* macroName,
983 const char* message = "" )
984 : ResultInfo( expr, ResultWas::Unknown, isNot, lineInfo, macroName, message )
985 {}
986
987 void setResultType( ResultWas::OfType result ) {
988 // Flip bool results if isNot is set
989 if( m_isNot && result == ResultWas::Ok )
990 m_result = ResultWas::ExpressionFailed;
991 else if( m_isNot && result == ResultWas::ExpressionFailed )
992 m_result = ResultWas::Ok;
993 else
994 m_result = result;
995 }
996
997 void setMessage( const std::string& message ) {
998 m_message = message;
999 }
1000
1001 void setLineInfo( const SourceLineInfo& lineInfo ) {
1002 m_lineInfo = lineInfo;
1003 }
1004
1005 void setLhs( const std::string& lhs ) {
1006 m_lhs = lhs;
1007 }
1008
1009 void setRhs( const std::string& rhs ) {
1010 m_rhs = rhs;
1011 }
1012
1013 void setOp( const std::string& op ) {
1014 m_op = op;
1015 }
1016 1814
1017 template<typename RhsT> 1815 template<typename RhsT>
1018 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || 1816 ResultBuilder& operator == ( RhsT const& rhs ) {
1019 ( 1817 return captureExpression<Internal::IsEqualTo>( rhs );
1020 const RhsT& 1818 }
1021 );
1022 1819
1023 template<typename RhsT> 1820 template<typename RhsT>
1024 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && 1821 ResultBuilder& operator != ( RhsT const& rhs ) {
1025 ( 1822 return captureExpression<Internal::IsNotEqualTo>( rhs );
1026 const RhsT& 1823 }
1027 ); 1824
1825 template<typename RhsT>
1826 ResultBuilder& operator < ( RhsT const& rhs ) {
1827 return captureExpression<Internal::IsLessThan>( rhs );
1828 }
1829
1830 template<typename RhsT>
1831 ResultBuilder& operator > ( RhsT const& rhs ) {
1832 return captureExpression<Internal::IsGreaterThan>( rhs );
1833 }
1834
1835 template<typename RhsT>
1836 ResultBuilder& operator <= ( RhsT const& rhs ) {
1837 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1838 }
1839
1840 template<typename RhsT>
1841 ResultBuilder& operator >= ( RhsT const& rhs ) {
1842 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1843 }
1844
1845 ResultBuilder& operator == ( bool rhs ) {
1846 return captureExpression<Internal::IsEqualTo>( rhs );
1847 }
1848
1849 ResultBuilder& operator != ( bool rhs ) {
1850 return captureExpression<Internal::IsNotEqualTo>( rhs );
1851 }
1852
1853 void endExpression() {
1854 bool value = m_lhs ? true : false;
1855 m_rb
1856 .setLhs( Catch::toString( value ) )
1857 .setResultType( value )
1858 .endExpression();
1859 }
1860
1861 // Only simple binary expressions are allowed on the LHS.
1862 // If more complex compositions are required then place the sub expression in parentheses
1863 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1864 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1865 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1866 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
1867 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1868 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1028 1869
1029 private: 1870 private:
1030 friend class ExpressionBuilder; 1871 template<Internal::Operator Op, typename RhsT>
1031 template<typename T> friend class Expression; 1872 ResultBuilder& captureExpression( RhsT const& rhs ) {
1032 1873 return m_rb
1033 template<typename T> friend class PtrExpression; 1874 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1034 1875 .setLhs( Catch::toString( m_lhs ) )
1035 ResultInfoBuilder& captureBoolExpression( bool result ) { 1876 .setRhs( Catch::toString( rhs ) )
1036 m_lhs = Catch::toString( result ); 1877 .setOp( Internal::OperatorTraits<Op>::getName() );
1037 m_op = m_isNot ? "!" : ""; 1878 }
1038 setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
1039 return *this;
1040 }
1041
1042 template<Internal::Operator Op, typename T1, typename T2>
1043 ResultInfoBuilder& captureExpression( const T1& lhs, const T2& rhs ) {
1044 setResultType( Internal::compare<Op>( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1045 m_lhs = Catch::toString( lhs );
1046 m_rhs = Catch::toString( rhs );
1047 m_op = Internal::OperatorTraits<Op>::getName();
1048 return *this;
1049 }
1050
1051 template<Internal::Operator Op, typename T>
1052 ResultInfoBuilder& captureExpression( const T* lhs, int rhs ) {
1053 return captureExpression<Op>( lhs, reinterpret_cast<const T*>( rhs ) );
1054 }
1055 };
1056
1057 } // end namespace Catch
1058
1059 namespace Catch {
1060
1061 template<typename T>
1062 class Expression {
1063 void operator = ( const Expression& );
1064
1065 public:
1066 Expression( ResultInfoBuilder& result, T lhs )
1067 : m_result( result ),
1068 m_lhs( lhs )
1069 {}
1070
1071 template<typename RhsT>
1072 ResultInfoBuilder& operator == ( const RhsT& rhs ) {
1073 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1074 }
1075
1076 template<typename RhsT>
1077 ResultInfoBuilder& operator != ( const RhsT& rhs ) {
1078 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1079 }
1080
1081 template<typename RhsT>
1082 ResultInfoBuilder& operator < ( const RhsT& rhs ) {
1083 return m_result.captureExpression<Internal::IsLessThan>( m_lhs, rhs );
1084 }
1085
1086 template<typename RhsT>
1087 ResultInfoBuilder& operator > ( const RhsT& rhs ) {
1088 return m_result.captureExpression<Internal::IsGreaterThan>( m_lhs, rhs );
1089 }
1090
1091 template<typename RhsT>
1092 ResultInfoBuilder& operator <= ( const RhsT& rhs ) {
1093 return m_result.captureExpression<Internal::IsLessThanOrEqualTo>( m_lhs, rhs );
1094 }
1095
1096 template<typename RhsT>
1097 ResultInfoBuilder& operator >= ( const RhsT& rhs ) {
1098 return m_result.captureExpression<Internal::IsGreaterThanOrEqualTo>( m_lhs, rhs );
1099 }
1100
1101 ResultInfoBuilder& operator == ( bool rhs ) {
1102 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1103 }
1104
1105 ResultInfoBuilder& operator != ( bool rhs ) {
1106 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1107 }
1108
1109 operator ResultInfoBuilder& () {
1110 return m_result.captureBoolExpression( m_lhs );
1111 }
1112
1113 template<typename RhsT>
1114 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& );
1115
1116 template<typename RhsT>
1117 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& );
1118 1879
1119 private: 1880 private:
1120 ResultInfoBuilder& m_result; 1881 ResultBuilder& m_rb;
1121 T m_lhs; 1882 T m_lhs;
1122 }; 1883 };
1123 1884
1124 } // end namespace Catch 1885 } // end namespace Catch
1125 1886
1126 #include <sstream>
1127 1887
1128 namespace Catch { 1888 namespace Catch {
1129 1889
1130 class ExpressionBuilder {
1131 public:
1132
1133 ExpressionBuilder( const SourceLineInfo& lineInfo,
1134 const char* macroName,
1135 const char* expr = "",
1136 bool isNot = false )
1137 : m_result( expr, isNot, lineInfo, macroName ),
1138 m_messageStream()
1139 {}
1140
1141 template<typename T> 1890 template<typename T>
1142 Expression<const T&> operator->* ( const T & operand ) { 1891 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
1143 Expression<const T&> expr( m_result, operand ); 1892 return ExpressionLhs<T const&>( *this, operand );
1144 return expr; 1893 }
1145 } 1894
1146 1895 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
1147 Expression<bool> operator->* ( bool value ) { 1896 return ExpressionLhs<bool>( *this, value );
1148 Expression<bool> expr( m_result, value ); 1897 }
1149 return expr; 1898
1150 } 1899 } // namespace Catch
1151 1900
1152 template<typename T> 1901 // #included from: catch_message.h
1153 ExpressionBuilder& operator << ( const T & value ) { 1902 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1154 m_messageStream << Catch::toString( value ); 1903
1155 return *this; 1904 #include <string>
1156 } 1905
1157 1906 namespace Catch {
1158 template<typename MatcherT, typename ArgT> 1907
1159 ExpressionBuilder& acceptMatcher( const MatcherT& matcher, 1908 struct MessageInfo {
1160 const ArgT& arg, 1909 MessageInfo( std::string const& _macroName,
1161 const std::string& matcherCallAsString ) { 1910 SourceLineInfo const& _lineInfo,
1162 std::string matcherAsString = Catch::toString( matcher ); 1911 ResultWas::OfType _type );
1163 if( matcherAsString == "{?}" ) 1912
1164 matcherAsString = matcherCallAsString; 1913 std::string macroName;
1165 m_result.setLhs( Catch::toString( arg ) ); 1914 SourceLineInfo lineInfo;
1166 m_result.setRhs( matcherAsString ); 1915 ResultWas::OfType type;
1167 m_result.setOp( "matches" ); 1916 std::string message;
1168 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); 1917 unsigned int sequence;
1169 return *this; 1918
1170 } 1919 bool operator == ( MessageInfo const& other ) const {
1171 1920 return sequence == other.sequence;
1172 template<typename MatcherT, typename ArgT> 1921 }
1173 ExpressionBuilder& acceptMatcher( const MatcherT& matcher, 1922 bool operator < ( MessageInfo const& other ) const {
1174 ArgT* arg, 1923 return sequence < other.sequence;
1175 const std::string& matcherCallAsString ) { 1924 }
1176 std::string matcherAsString = Catch::toString( matcher ); 1925 private:
1177 if( matcherAsString == "{?}" ) 1926 static unsigned int globalCount;
1178 matcherAsString = matcherCallAsString; 1927 };
1179 m_result.setLhs( Catch::toString( arg ) ); 1928
1180 m_result.setRhs( matcherAsString ); 1929 struct MessageBuilder {
1181 m_result.setOp( "matches" ); 1930 MessageBuilder( std::string const& macroName,
1182 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); 1931 SourceLineInfo const& lineInfo,
1183 return *this; 1932 ResultWas::OfType type )
1184 } 1933 : m_info( macroName, lineInfo, type )
1185 1934 {}
1186 ExpressionBuilder& setResultType( ResultWas::OfType resultType ) { 1935
1187 m_result.setResultType( resultType ); 1936 template<typename T>
1188 return *this; 1937 MessageBuilder& operator << ( T const& value ) {
1189 } 1938 m_stream << value;
1190 1939 return *this;
1191 operator ResultInfoBuilder&() { 1940 }
1192 m_result.setMessage( m_messageStream.str() ); 1941
1193 return m_result; 1942 MessageInfo m_info;
1194 } 1943 std::ostringstream m_stream;
1195 1944 };
1196 private: 1945
1197 ResultInfoBuilder m_result; 1946 class ScopedMessage {
1198 std::ostringstream m_messageStream; 1947 public:
1199 }; 1948 ScopedMessage( MessageBuilder const& builder );
1949 ScopedMessage( ScopedMessage const& other );
1950 ~ScopedMessage();
1951
1952 MessageInfo m_info;
1953 };
1200 1954
1201 } // end namespace Catch 1955 } // end namespace Catch
1202 1956
1203 // #included from: catch_interfaces_capture.h 1957 // #included from: catch_interfaces_capture.h
1958 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1204 1959
1205 #include <string> 1960 #include <string>
1206 1961
1207 namespace Catch { 1962 namespace Catch {
1208 1963
1209 class TestCaseInfo; 1964 class TestCase;
1210 class ScopedInfo; 1965 class AssertionResult;
1211 class ResultInfoBuilder; 1966 struct AssertionInfo;
1212 class ResultInfo; 1967 struct SectionInfo;
1968 struct SectionEndInfo;
1969 struct MessageInfo;
1970 class ScopedMessageBuilder;
1971 struct Counts;
1213 1972
1214 struct IResultCapture { 1973 struct IResultCapture {
1215 1974
1216 virtual ~IResultCapture(){} 1975 virtual ~IResultCapture();
1217 1976
1218 virtual void testEnded( const ResultInfo& result ) = 0; 1977 virtual void assertionEnded( AssertionResult const& result ) = 0;
1219 virtual bool sectionStarted( const std::string& name, 1978 virtual bool sectionStarted( SectionInfo const& sectionInfo,
1220 const std::string& description,
1221 const SourceLineInfo& lineInfo,
1222 Counts& assertions ) = 0; 1979 Counts& assertions ) = 0;
1223 virtual void sectionEnded( const std::string& name, const Counts& assertions ) = 0; 1980 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
1224 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0; 1981 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
1225 virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0; 1982 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1226 virtual bool shouldDebugBreak() const = 0; 1983 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1227
1228 virtual ResultAction::Value acceptResult( bool result ) = 0;
1229 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) = 0;
1230 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) = 0;
1231 virtual void acceptMessage( const std::string& msg ) = 0;
1232 1984
1233 virtual std::string getCurrentTestName() const = 0; 1985 virtual std::string getCurrentTestName() const = 0;
1234 virtual const ResultInfo* getLastResult() const = 0; 1986 virtual const AssertionResult* getLastResult() const = 0;
1235 }; 1987
1988 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
1989 };
1990
1991 IResultCapture& getResultCapture();
1236 } 1992 }
1237 1993
1238 // #included from: catch_debugger.hpp 1994 // #included from: catch_debugger.h
1239 1995 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1240 #include <iostream> 1996
1997 // #included from: catch_platform.h
1998 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1241 1999
1242 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 2000 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1243 #define CATCH_PLATFORM_MAC 2001 #define CATCH_PLATFORM_MAC
1244 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 2002 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1245 #define CATCH_PLATFORM_IPHONE 2003 #define CATCH_PLATFORM_IPHONE
1246 #elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) 2004 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1247 #define CATCH_PLATFORM_WINDOWS 2005 #define CATCH_PLATFORM_WINDOWS
1248 #endif 2006 #endif
1249 2007
2008 #include <string>
2009
2010 namespace Catch{
2011
2012 bool isDebuggerActive();
2013 void writeToDebugConsole( std::string const& text );
2014 }
2015
1250 #ifdef CATCH_PLATFORM_MAC 2016 #ifdef CATCH_PLATFORM_MAC
1251 2017
1252 #include <assert.h> 2018 // The following code snippet based on:
1253 #include <stdbool.h>
1254 #include <sys/types.h>
1255 #include <unistd.h>
1256 #include <sys/sysctl.h>
1257
1258 namespace Catch{
1259
1260 // The following function is taken directly from the following technical note:
1261 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1262
1263 // Returns true if the current process is being debugged (either
1264 // running under the debugger or has a debugger attached post facto).
1265 inline bool isDebuggerActive(){
1266
1267 int junk;
1268 int mib[4];
1269 struct kinfo_proc info;
1270 size_t size;
1271
1272 // Initialize the flags so that, if sysctl fails for some bizarre
1273 // reason, we get a predictable result.
1274
1275 info.kp_proc.p_flag = 0;
1276
1277 // Initialize mib, which tells sysctl the info we want, in this case
1278 // we're looking for information about a specific process ID.
1279
1280 mib[0] = CTL_KERN;
1281 mib[1] = KERN_PROC;
1282 mib[2] = KERN_PROC_PID;
1283 mib[3] = getpid();
1284
1285 // Call sysctl.
1286
1287 size = sizeof(info);
1288 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1289 assert(junk == 0);
1290
1291 // We're being debugged if the P_TRACED flag is set.
1292
1293 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1294 }
1295 }
1296
1297 // The following code snippet taken from:
1298 // http://cocoawithlove.com/2008/03/break-into-debugger.html 2019 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1299 #ifdef DEBUG 2020 #ifdef DEBUG
1300 #if defined(__ppc64__) || defined(__ppc__) 2021 #if defined(__ppc64__) || defined(__ppc__)
1301 #define BreakIntoDebugger() \ 2022 #define CATCH_BREAK_INTO_DEBUGGER() \
1302 if( Catch::isDebuggerActive() ) { \ 2023 if( Catch::isDebuggerActive() ) { \
1303 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ 2024 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1304 : : : "memory","r0","r3","r4" ); \ 2025 : : : "memory","r0","r3","r4" ); \
1305 } 2026 }
1306 #else 2027 #else
1307 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} 2028 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1308 #endif 2029 #endif
1309 #else
1310 inline void BreakIntoDebugger(){}
1311 #endif 2030 #endif
1312 2031
1313 #elif defined(_MSC_VER) 2032 #elif defined(_MSC_VER)
1314 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 2033 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
1315 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
1316 inline bool isDebuggerActive() {
1317 return IsDebuggerPresent() != 0;
1318 }
1319 #elif defined(__MINGW32__) 2034 #elif defined(__MINGW32__)
1320 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1321 extern "C" __declspec(dllimport) void __stdcall DebugBreak(); 2035 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1322 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); } 2036 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
1323 inline bool isDebuggerActive() { 2037 #endif
1324 return IsDebuggerPresent() != 0; 2038
1325 } 2039 #ifndef CATCH_BREAK_INTO_DEBUGGER
2040 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2041 #endif
2042
2043 // #included from: catch_interfaces_runner.h
2044 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2045
2046 namespace Catch {
2047 class TestCase;
2048
2049 struct IRunner {
2050 virtual ~IRunner();
2051 virtual bool aborting() const = 0;
2052 };
2053 }
2054
2055 ///////////////////////////////////////////////////////////////////////////////
2056 // In the event of a failure works out if the debugger needs to be invoked
2057 // and/or an exception thrown and takes appropriate action.
2058 // This needs to be done as a macro so the debugger will stop in the user
2059 // source code rather than in Catch library code
2060 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2061 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2062 resultBuilder.react();
2063
2064 ///////////////////////////////////////////////////////////////////////////////
2065 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2066 do { \
2067 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2068 try { \
2069 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2070 ( __catchResult <= expr ).endExpression(); \
2071 } \
2072 catch( ... ) { \
2073 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
2074 } \
2075 INTERNAL_CATCH_REACT( __catchResult ) \
2076 } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2077
2078 ///////////////////////////////////////////////////////////////////////////////
2079 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2080 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2081 if( Catch::getResultCapture().getLastResult()->succeeded() )
2082
2083 ///////////////////////////////////////////////////////////////////////////////
2084 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2085 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2086 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2087
2088 ///////////////////////////////////////////////////////////////////////////////
2089 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2090 do { \
2091 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2092 try { \
2093 expr; \
2094 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2095 } \
2096 catch( ... ) { \
2097 __catchResult.useActiveException( resultDisposition ); \
2098 } \
2099 INTERNAL_CATCH_REACT( __catchResult ) \
2100 } while( Catch::alwaysFalse() )
2101
2102 ///////////////////////////////////////////////////////////////////////////////
2103 #define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2104 do { \
2105 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2106 if( __catchResult.allowThrows() ) \
2107 try { \
2108 expr; \
2109 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2110 } \
2111 catch( ... ) { \
2112 __catchResult.captureExpectedException( matcher ); \
2113 } \
2114 else \
2115 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2116 INTERNAL_CATCH_REACT( __catchResult ) \
2117 } while( Catch::alwaysFalse() )
2118
2119 ///////////////////////////////////////////////////////////////////////////////
2120 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2121 do { \
2122 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2123 if( __catchResult.allowThrows() ) \
2124 try { \
2125 expr; \
2126 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2127 } \
2128 catch( exceptionType ) { \
2129 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2130 } \
2131 catch( ... ) { \
2132 __catchResult.useActiveException( resultDisposition ); \
2133 } \
2134 else \
2135 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2136 INTERNAL_CATCH_REACT( __catchResult ) \
2137 } while( Catch::alwaysFalse() )
2138
2139 ///////////////////////////////////////////////////////////////////////////////
2140 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2141 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2142 do { \
2143 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2144 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2145 __catchResult.captureResult( messageType ); \
2146 INTERNAL_CATCH_REACT( __catchResult ) \
2147 } while( Catch::alwaysFalse() )
1326 #else 2148 #else
1327 inline void BreakIntoDebugger(){} 2149 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
1328 inline bool isDebuggerActive() { return false; } 2150 do { \
1329 #endif 2151 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2152 __catchResult << log + ::Catch::StreamEndStop(); \
2153 __catchResult.captureResult( messageType ); \
2154 INTERNAL_CATCH_REACT( __catchResult ) \
2155 } while( Catch::alwaysFalse() )
2156 #endif
2157
2158 ///////////////////////////////////////////////////////////////////////////////
2159 #define INTERNAL_CATCH_INFO( log, macroName ) \
2160 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2161
2162 ///////////////////////////////////////////////////////////////////////////////
2163 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2164 do { \
2165 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2166 try { \
2167 std::string matcherAsString = (matcher).toString(); \
2168 __catchResult \
2169 .setLhs( Catch::toString( arg ) ) \
2170 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
2171 .setOp( "matches" ) \
2172 .setResultType( (matcher).match( arg ) ); \
2173 __catchResult.captureExpression(); \
2174 } catch( ... ) { \
2175 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2176 } \
2177 INTERNAL_CATCH_REACT( __catchResult ) \
2178 } while( Catch::alwaysFalse() )
2179
2180 // #included from: internal/catch_section.h
2181 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2182
2183 // #included from: catch_section_info.h
2184 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2185
2186 // #included from: catch_totals.hpp
2187 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2188
2189 #include <cstddef>
2190
2191 namespace Catch {
2192
2193 struct Counts {
2194 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2195
2196 Counts operator - ( Counts const& other ) const {
2197 Counts diff;
2198 diff.passed = passed - other.passed;
2199 diff.failed = failed - other.failed;
2200 diff.failedButOk = failedButOk - other.failedButOk;
2201 return diff;
2202 }
2203 Counts& operator += ( Counts const& other ) {
2204 passed += other.passed;
2205 failed += other.failed;
2206 failedButOk += other.failedButOk;
2207 return *this;
2208 }
2209
2210 std::size_t total() const {
2211 return passed + failed + failedButOk;
2212 }
2213 bool allPassed() const {
2214 return failed == 0 && failedButOk == 0;
2215 }
2216 bool allOk() const {
2217 return failed == 0;
2218 }
2219
2220 std::size_t passed;
2221 std::size_t failed;
2222 std::size_t failedButOk;
2223 };
2224
2225 struct Totals {
2226
2227 Totals operator - ( Totals const& other ) const {
2228 Totals diff;
2229 diff.assertions = assertions - other.assertions;
2230 diff.testCases = testCases - other.testCases;
2231 return diff;
2232 }
2233
2234 Totals delta( Totals const& prevTotals ) const {
2235 Totals diff = *this - prevTotals;
2236 if( diff.assertions.failed > 0 )
2237 ++diff.testCases.failed;
2238 else if( diff.assertions.failedButOk > 0 )
2239 ++diff.testCases.failedButOk;
2240 else
2241 ++diff.testCases.passed;
2242 return diff;
2243 }
2244
2245 Totals& operator += ( Totals const& other ) {
2246 assertions += other.assertions;
2247 testCases += other.testCases;
2248 return *this;
2249 }
2250
2251 Counts assertions;
2252 Counts testCases;
2253 };
2254 }
2255
2256 namespace Catch {
2257
2258 struct SectionInfo {
2259 SectionInfo
2260 ( SourceLineInfo const& _lineInfo,
2261 std::string const& _name,
2262 std::string const& _description = std::string() );
2263
2264 std::string name;
2265 std::string description;
2266 SourceLineInfo lineInfo;
2267 };
2268
2269 struct SectionEndInfo {
2270 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2271 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2272 {}
2273
2274 SectionInfo sectionInfo;
2275 Counts prevAssertions;
2276 double durationInSeconds;
2277 };
2278
2279 } // end namespace Catch
2280
2281 // #included from: catch_timer.h
2282 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
1330 2283
1331 #ifdef CATCH_PLATFORM_WINDOWS 2284 #ifdef CATCH_PLATFORM_WINDOWS
1332 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); 2285 typedef unsigned long long uint64_t;
1333 inline void writeToDebugConsole( const std::string& text ) {
1334 ::OutputDebugStringA( text.c_str() );
1335 }
1336 #else 2286 #else
1337 inline void writeToDebugConsole( const std::string& text ) { 2287 #include <stdint.h>
1338 // !TBD: Need a version for Mac/ XCode and other IDEs 2288 #endif
1339 std::cout << text;
1340 }
1341 #endif // CATCH_PLATFORM_WINDOWS
1342
1343 #include <ostream>
1344 2289
1345 namespace Catch { 2290 namespace Catch {
1346 2291
1347 struct TestFailureException{}; 2292 class Timer {
1348 2293 public:
1349 class ScopedInfo { 2294 Timer() : m_ticks( 0 ) {}
1350 public: 2295 void start();
1351 ScopedInfo() : m_oss() { 2296 unsigned int getElapsedMicroseconds() const;
1352 getCurrentContext().getResultCapture().pushScopedInfo( this ); 2297 unsigned int getElapsedMilliseconds() const;
1353 } 2298 double getElapsedSeconds() const;
1354 2299
1355 ~ScopedInfo() { 2300 private:
1356 getCurrentContext().getResultCapture().popScopedInfo( this ); 2301 uint64_t m_ticks;
1357 } 2302 };
1358 2303
1359 template<typename T> 2304 } // namespace Catch
1360 ScopedInfo& operator << ( const T& value ) {
1361 m_oss << value;
1362 return *this;
1363 }
1364
1365 std::string getInfo () const {
1366 return m_oss.str();
1367 }
1368
1369 private:
1370 std::ostringstream m_oss;
1371 };
1372
1373 // This is just here to avoid compiler warnings with macro constants
1374 inline bool isTrue( bool value ){ return value; }
1375
1376 } // end namespace Catch
1377
1378 ///////////////////////////////////////////////////////////////////////////////
1379 #define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \
1380 if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) { \
1381 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
1382 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
1383 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
1384 if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \
1385 }
1386
1387 ///////////////////////////////////////////////////////////////////////////////
1388 #define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
1389 do { try { \
1390 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr, isNot )->*expr ), stopOnFailure, expr ); \
1391 } catch( Catch::TestFailureException& ) { \
1392 throw; \
1393 } catch( ... ) { \
1394 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \
1395 throw; \
1396 } } while( Catch::isTrue( false ) )
1397
1398 ///////////////////////////////////////////////////////////////////////////////
1399 #define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \
1400 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
1401 if( Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
1402
1403 ///////////////////////////////////////////////////////////////////////////////
1404 #define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \
1405 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
1406 if( !Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
1407
1408 ///////////////////////////////////////////////////////////////////////////////
1409 #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
1410 try { \
1411 expr; \
1412 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
1413 } \
1414 catch( ... ) { \
1415 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
1416 }
1417
1418 ///////////////////////////////////////////////////////////////////////////////
1419 #define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1420 try { \
1421 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1422 expr; \
1423 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \
1424 } \
1425 } \
1426 catch( Catch::TestFailureException& ) { \
1427 throw; \
1428 } \
1429 catch( exceptionType ) { \
1430 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
1431 }
1432
1433 ///////////////////////////////////////////////////////////////////////////////
1434 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1435 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1436 catch( ... ) { \
1437 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
1438 }
1439
1440 ///////////////////////////////////////////////////////////////////////////////
1441 #define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
1442 Catch::getCurrentContext().getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) );
1443
1444 ///////////////////////////////////////////////////////////////////////////////
1445 #define INTERNAL_CATCH_SCOPED_INFO( log ) \
1446 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1447 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1448
1449 ///////////////////////////////////////////////////////////////////////////////
1450 #define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \
1451 do { try { \
1452 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher, false ).acceptMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), stopOnFailure, false ); \
1453 } catch( Catch::TestFailureException& ) { \
1454 throw; \
1455 } catch( ... ) { \
1456 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \
1457 throw; \
1458 }}while( Catch::isTrue( false ) )
1459
1460 // #included from: internal/catch_section.hpp
1461 2305
1462 #include <string> 2306 #include <string>
1463 2307
1464 namespace Catch { 2308 namespace Catch {
1465 2309
1466 class Section { 2310 class Section : NonCopyable {
1467 public: 2311 public:
1468 Section( const std::string& name, 2312 Section( SectionInfo const& info );
1469 const std::string& description, 2313 ~Section();
1470 const SourceLineInfo& lineInfo )
1471 : m_name( name ),
1472 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) )
1473 {}
1474
1475 ~Section() {
1476 if( m_sectionIncluded )
1477 getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions );
1478 }
1479 2314
1480 // This indicates whether the section should be executed or not 2315 // This indicates whether the section should be executed or not
1481 operator bool() { 2316 operator bool() const;
1482 return m_sectionIncluded;
1483 }
1484 2317
1485 private: 2318 private:
2319 SectionInfo m_info;
1486 2320
1487 std::string m_name; 2321 std::string m_name;
1488 Counts m_assertions; 2322 Counts m_assertions;
1489 bool m_sectionIncluded; 2323 bool m_sectionIncluded;
2324 Timer m_timer;
1490 }; 2325 };
1491 2326
1492 } // end namespace Catch 2327 } // end namespace Catch
1493 2328
1494 #define INTERNAL_CATCH_SECTION( name, desc ) \ 2329 #ifdef CATCH_CONFIG_VARIADIC_MACROS
1495 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) ) 2330 #define INTERNAL_CATCH_SECTION( ... ) \
2331 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2332 #else
2333 #define INTERNAL_CATCH_SECTION( name, desc ) \
2334 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2335 #endif
1496 2336
1497 // #included from: internal/catch_generators.hpp 2337 // #included from: internal/catch_generators.hpp
2338 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1498 2339
1499 #include <iterator> 2340 #include <iterator>
1500 #include <vector> 2341 #include <vector>
1501 #include <string> 2342 #include <string>
1502 #include <stdlib.h> 2343 #include <stdlib.h>
1514 class BetweenGenerator : public IGenerator<T> { 2355 class BetweenGenerator : public IGenerator<T> {
1515 public: 2356 public:
1516 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} 2357 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
1517 2358
1518 virtual T getValue( std::size_t index ) const { 2359 virtual T getValue( std::size_t index ) const {
1519 return m_from+static_cast<T>( index ); 2360 return m_from+static_cast<int>( index );
1520 } 2361 }
1521 2362
1522 virtual std::size_t size() const { 2363 virtual std::size_t size() const {
1523 return static_cast<std::size_t>( 1+m_to-m_from ); 2364 return static_cast<std::size_t>( 1+m_to-m_from );
1524 } 2365 }
1553 template<typename T> 2394 template<typename T>
1554 class CompositeGenerator { 2395 class CompositeGenerator {
1555 public: 2396 public:
1556 CompositeGenerator() : m_totalSize( 0 ) {} 2397 CompositeGenerator() : m_totalSize( 0 ) {}
1557 2398
1558 // *** Move semantics, similar to auto_ptr *** 2399 // *** Move semantics, similar to auto_ptr ***
1559 CompositeGenerator( CompositeGenerator& other ) 2400 CompositeGenerator( CompositeGenerator& other )
1560 : m_fileInfo( other.m_fileInfo ), 2401 : m_fileInfo( other.m_fileInfo ),
1561 m_totalSize( 0 ) 2402 m_totalSize( 0 )
1562 { 2403 {
1563 move( other ); 2404 move( other );
1564 } 2405 }
1565 2406
1566 CompositeGenerator& setFileInfo( const char* fileInfo ) { 2407 CompositeGenerator& setFileInfo( const char* fileInfo ) {
1567 m_fileInfo = fileInfo; 2408 m_fileInfo = fileInfo;
1568 return *this; 2409 return *this;
1585 return generator->getValue( overallIndex-index ); 2426 return generator->getValue( overallIndex-index );
1586 } 2427 }
1587 index += generator->size(); 2428 index += generator->size();
1588 } 2429 }
1589 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); 2430 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
1590 return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so 2431 return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
1591 } 2432 }
1592 2433
1593 void add( const IGenerator<T>* generator ) { 2434 void add( const IGenerator<T>* generator ) {
1594 m_totalSize += generator->size(); 2435 m_totalSize += generator->size();
1595 m_composed.push_back( generator ); 2436 m_composed.push_back( generator );
1672 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) 2513 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
1673 2514
1674 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) 2515 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
1675 2516
1676 // #included from: internal/catch_interfaces_exception.h 2517 // #included from: internal/catch_interfaces_exception.h
2518 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
1677 2519
1678 #include <string> 2520 #include <string>
2521 #include <vector>
2522
2523 // #included from: catch_interfaces_registry_hub.h
2524 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2525
2526 #include <string>
1679 2527
1680 namespace Catch { 2528 namespace Catch {
1681 2529
2530 class TestCase;
2531 struct ITestCaseRegistry;
2532 struct IExceptionTranslatorRegistry;
2533 struct IExceptionTranslator;
2534 struct IReporterRegistry;
2535 struct IReporterFactory;
2536
2537 struct IRegistryHub {
2538 virtual ~IRegistryHub();
2539
2540 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2541 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2542 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2543 };
2544
2545 struct IMutableRegistryHub {
2546 virtual ~IMutableRegistryHub();
2547 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2548 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
2549 virtual void registerTest( TestCase const& testInfo ) = 0;
2550 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2551 };
2552
2553 IRegistryHub& getRegistryHub();
2554 IMutableRegistryHub& getMutableRegistryHub();
2555 void cleanUp();
2556 std::string translateActiveException();
2557
2558 }
2559
2560 namespace Catch {
2561
1682 typedef std::string(*exceptionTranslateFunction)(); 2562 typedef std::string(*exceptionTranslateFunction)();
1683 2563
2564 struct IExceptionTranslator;
2565 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2566
1684 struct IExceptionTranslator { 2567 struct IExceptionTranslator {
1685 virtual ~IExceptionTranslator(){} 2568 virtual ~IExceptionTranslator();
1686 virtual std::string translate() const = 0; 2569 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
1687 }; 2570 };
1688 2571
1689 struct IExceptionTranslatorRegistry { 2572 struct IExceptionTranslatorRegistry {
1690 virtual ~IExceptionTranslatorRegistry(){} 2573 virtual ~IExceptionTranslatorRegistry();
1691 2574
1692 virtual void registerTranslator( IExceptionTranslator* translator ) = 0;
1693 virtual std::string translateActiveException() const = 0; 2575 virtual std::string translateActiveException() const = 0;
1694 }; 2576 };
1695 2577
1696 class ExceptionTranslatorRegistrar { 2578 class ExceptionTranslatorRegistrar {
1697 template<typename T> 2579 template<typename T>
1700 2582
1701 ExceptionTranslator( std::string(*translateFunction)( T& ) ) 2583 ExceptionTranslator( std::string(*translateFunction)( T& ) )
1702 : m_translateFunction( translateFunction ) 2584 : m_translateFunction( translateFunction )
1703 {} 2585 {}
1704 2586
1705 virtual std::string translate() const { 2587 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
1706 try { 2588 try {
1707 throw; 2589 if( it == itEnd )
2590 throw;
2591 else
2592 return (*it)->translate( it+1, itEnd );
1708 } 2593 }
1709 catch( T& ex ) { 2594 catch( T& ex ) {
1710 return m_translateFunction( ex ); 2595 return m_translateFunction( ex );
1711 } 2596 }
1712 } 2597 }
1716 }; 2601 };
1717 2602
1718 public: 2603 public:
1719 template<typename T> 2604 template<typename T>
1720 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { 2605 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
1721 getCurrentContext().getExceptionTranslatorRegistry().registerTranslator 2606 getMutableRegistryHub().registerTranslator
1722 ( new ExceptionTranslator<T>( translateFunction ) ); 2607 ( new ExceptionTranslator<T>( translateFunction ) );
1723 } 2608 }
1724 }; 2609 };
1725 } 2610 }
1726 2611
1727 /////////////////////////////////////////////////////////////////////////////// 2612 ///////////////////////////////////////////////////////////////////////////////
1728 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ 2613 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
1729 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ 2614 static std::string translatorName( signature ); \
1730 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ 2615 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
1731 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) 2616 static std::string translatorName( signature )
2617
2618 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
1732 2619
1733 // #included from: internal/catch_approx.hpp 2620 // #included from: internal/catch_approx.hpp
2621 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
1734 2622
1735 #include <cmath> 2623 #include <cmath>
1736 #include <limits> 2624 #include <limits>
1737 2625
1738 namespace Catch { 2626 namespace Catch {
1744 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), 2632 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
1745 m_scale( 1.0 ), 2633 m_scale( 1.0 ),
1746 m_value( value ) 2634 m_value( value )
1747 {} 2635 {}
1748 2636
1749 Approx( const Approx& other ) 2637 Approx( Approx const& other )
1750 : m_epsilon( other.m_epsilon ), 2638 : m_epsilon( other.m_epsilon ),
1751 m_scale( other.m_scale ), 2639 m_scale( other.m_scale ),
1752 m_value( other.m_value ) 2640 m_value( other.m_value )
1753 {} 2641 {}
1754 2642
1761 approx.epsilon( m_epsilon ); 2649 approx.epsilon( m_epsilon );
1762 approx.scale( m_scale ); 2650 approx.scale( m_scale );
1763 return approx; 2651 return approx;
1764 } 2652 }
1765 2653
1766 friend bool operator == ( double lhs, const Approx& rhs ) { 2654 friend bool operator == ( double lhs, Approx const& rhs ) {
1767 // Thanks to Richard Harris for his help refining this formula 2655 // Thanks to Richard Harris for his help refining this formula
1768 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); 2656 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
1769 } 2657 }
1770 2658
1771 friend bool operator == ( const Approx& lhs, double rhs ) { 2659 friend bool operator == ( Approx const& lhs, double rhs ) {
1772 return operator==( rhs, lhs ); 2660 return operator==( rhs, lhs );
1773 } 2661 }
1774 2662
1775 friend bool operator != ( double lhs, const Approx& rhs ) { 2663 friend bool operator != ( double lhs, Approx const& rhs ) {
1776 return !operator==( lhs, rhs ); 2664 return !operator==( lhs, rhs );
1777 } 2665 }
1778 2666
1779 friend bool operator != ( const Approx& lhs, double rhs ) { 2667 friend bool operator != ( Approx const& lhs, double rhs ) {
1780 return !operator==( rhs, lhs ); 2668 return !operator==( rhs, lhs );
1781 } 2669 }
1782 2670
1783 Approx& epsilon( double newEpsilon ) { 2671 Approx& epsilon( double newEpsilon ) {
1784 m_epsilon = newEpsilon; 2672 m_epsilon = newEpsilon;
1790 return *this; 2678 return *this;
1791 } 2679 }
1792 2680
1793 std::string toString() const { 2681 std::string toString() const {
1794 std::ostringstream oss; 2682 std::ostringstream oss;
1795 oss << "Approx( " << m_value << ")"; 2683 oss << "Approx( " << Catch::toString( m_value ) << " )";
1796 return oss.str(); 2684 return oss.str();
1797 } 2685 }
1798 2686
1799 private: 2687 private:
1800 double m_epsilon; 2688 double m_epsilon;
1802 double m_value; 2690 double m_value;
1803 }; 2691 };
1804 } 2692 }
1805 2693
1806 template<> 2694 template<>
1807 inline std::string toString<Detail::Approx>( const Detail::Approx& value ) { 2695 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
1808 return value.toString(); 2696 return value.toString();
1809 } 2697 }
1810 2698
1811 } // end namespace Catch 2699 } // end namespace Catch
1812 2700
1813 // #included from: internal/catch_matchers.hpp 2701 // #included from: internal/catch_interfaces_tag_alias_registry.h
2702 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2703
2704 // #included from: catch_tag_alias.h
2705 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2706
2707 #include <string>
1814 2708
1815 namespace Catch { 2709 namespace Catch {
1816 namespace Matchers { 2710
1817 namespace Impl { 2711 struct TagAlias {
1818 namespace StdString { 2712 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
1819 2713
1820 struct Equals { 2714 std::string tag;
1821 Equals( const std::string& str ) : m_str( str ){} 2715 SourceLineInfo lineInfo;
1822 2716 };
1823 bool operator()( const std::string& str ) const 2717
1824 { 2718 struct RegistrarForTagAliases {
1825 return str == m_str; 2719 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
1826 } 2720 };
1827 2721
1828 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher ) 2722 } // end namespace Catch
1829 { 2723
1830 os << "equals: \"" << matcher.m_str << "\""; 2724 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
1831 return os; 2725 // #included from: catch_option.hpp
1832 } 2726 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
1833 std::string m_str; 2727
1834 }; 2728 namespace Catch {
1835 2729
1836 struct Contains { 2730 // An optional type
1837 Contains( const std::string& substr ) : m_substr( substr ){} 2731 template<typename T>
1838 2732 class Option {
1839 bool operator()( const std::string& str ) const 2733 public:
1840 { 2734 Option() : nullableValue( CATCH_NULL ) {}
1841 return str.find( m_substr ) != std::string::npos; 2735 Option( T const& _value )
1842 } 2736 : nullableValue( new( storage ) T( _value ) )
1843 2737 {}
1844 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) 2738 Option( Option const& _other )
1845 { 2739 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
1846 os << "contains: \"" << matcher.m_substr << "\""; 2740 {}
1847 return os; 2741
1848 } 2742 ~Option() {
1849 std::string m_substr; 2743 reset();
1850 }; 2744 }
1851 2745
1852 struct StartsWith { 2746 Option& operator= ( Option const& _other ) {
1853 StartsWith( const std::string& substr ) : m_substr( substr ){} 2747 if( &_other != this ) {
1854 2748 reset();
1855 bool operator()( const std::string& str ) const 2749 if( _other )
1856 { 2750 nullableValue = new( storage ) T( *_other );
1857 return str.find( m_substr ) == 0; 2751 }
1858 } 2752 return *this;
1859 2753 }
1860 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) 2754 Option& operator = ( T const& _value ) {
1861 { 2755 reset();
1862 os << "starts with: \"" << matcher.m_substr << "\""; 2756 nullableValue = new( storage ) T( _value );
1863 return os; 2757 return *this;
1864 } 2758 }
1865 std::string m_substr; 2759
1866 }; 2760 void reset() {
1867 2761 if( nullableValue )
1868 struct EndsWith { 2762 nullableValue->~T();
1869 EndsWith( const std::string& substr ) : m_substr( substr ){} 2763 nullableValue = CATCH_NULL;
1870 2764 }
1871 bool operator()( const std::string& str ) const 2765
1872 { 2766 T& operator*() { return *nullableValue; }
1873 return str.find( m_substr ) == str.size() - m_substr.size(); 2767 T const& operator*() const { return *nullableValue; }
1874 } 2768 T* operator->() { return nullableValue; }
1875 2769 const T* operator->() const { return nullableValue; }
1876 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) 2770
1877 { 2771 T valueOr( T const& defaultValue ) const {
1878 os << "ends with: \"" << matcher.m_substr << "\""; 2772 return nullableValue ? *nullableValue : defaultValue;
1879 return os; 2773 }
1880 } 2774
1881 std::string m_substr; 2775 bool some() const { return nullableValue != CATCH_NULL; }
1882 }; 2776 bool none() const { return nullableValue == CATCH_NULL; }
1883 } // namespace StdString 2777
1884 } // namespace Impl 2778 bool operator !() const { return nullableValue == CATCH_NULL; }
1885 2779 operator SafeBool::type() const {
1886 inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); } 2780 return SafeBool::makeSafe( some() );
1887 inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); } 2781 }
1888 inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); } 2782
1889 inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); } 2783 private:
1890 2784 T* nullableValue;
1891 } // namespace Matchers 2785 char storage[sizeof(T)];
1892 2786 };
1893 using namespace Matchers; 2787
1894 2788 } // end namespace Catch
1895 } // namespace Catch 2789
2790 namespace Catch {
2791
2792 struct ITagAliasRegistry {
2793 virtual ~ITagAliasRegistry();
2794 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
2795 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
2796
2797 static ITagAliasRegistry const& get();
2798 };
2799
2800 } // end namespace Catch
1896 2801
1897 // These files are included here so the single_include script doesn't put them 2802 // These files are included here so the single_include script doesn't put them
1898 // in the conditionally compiled sections 2803 // in the conditionally compiled sections
1899 // #included from: internal/catch_test_case_info.hpp 2804 // #included from: internal/catch_test_case_info.h
1900 2805 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
1901 #include <map> 2806
1902 #include <string> 2807 #include <string>
2808 #include <set>
2809
2810 #ifdef __clang__
2811 #pragma clang diagnostic push
2812 #pragma clang diagnostic ignored "-Wpadded"
2813 #endif
1903 2814
1904 namespace Catch { 2815 namespace Catch {
1905 2816
1906 class TestCaseInfo { 2817 struct ITestCase;
2818
2819 struct TestCaseInfo {
2820 enum SpecialProperties{
2821 None = 0,
2822 IsHidden = 1 << 1,
2823 ShouldFail = 1 << 2,
2824 MayFail = 1 << 3,
2825 Throws = 1 << 4
2826 };
2827
2828 TestCaseInfo( std::string const& _name,
2829 std::string const& _className,
2830 std::string const& _description,
2831 std::set<std::string> const& _tags,
2832 SourceLineInfo const& _lineInfo );
2833
2834 TestCaseInfo( TestCaseInfo const& other );
2835
2836 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
2837
2838 bool isHidden() const;
2839 bool throws() const;
2840 bool okToFail() const;
2841 bool expectedToFail() const;
2842
2843 std::string name;
2844 std::string className;
2845 std::string description;
2846 std::set<std::string> tags;
2847 std::set<std::string> lcaseTags;
2848 std::string tagsAsString;
2849 SourceLineInfo lineInfo;
2850 SpecialProperties properties;
2851 };
2852
2853 class TestCase : public TestCaseInfo {
1907 public: 2854 public:
1908 TestCaseInfo( ITestCase* testCase, 2855
1909 const char* name, 2856 TestCase( ITestCase* testCase, TestCaseInfo const& info );
1910 const char* description, 2857 TestCase( TestCase const& other );
1911 const SourceLineInfo& lineInfo ) 2858
1912 : m_test( testCase ), 2859 TestCase withName( std::string const& _newName ) const;
1913 m_name( name ), 2860
1914 m_description( description ), 2861 void invoke() const;
1915 m_lineInfo( lineInfo ) 2862
1916 {} 2863 TestCaseInfo const& getTestCaseInfo() const;
1917 2864
1918 TestCaseInfo() 2865 void swap( TestCase& other );
1919 : m_test( NULL ), 2866 bool operator == ( TestCase const& other ) const;
1920 m_name(), 2867 bool operator < ( TestCase const& other ) const;
1921 m_description() 2868 TestCase& operator = ( TestCase const& other );
1922 {}
1923
1924 TestCaseInfo( const TestCaseInfo& other )
1925 : m_test( other.m_test->clone() ),
1926 m_name( other.m_name ),
1927 m_description( other.m_description ),
1928 m_lineInfo( other.m_lineInfo )
1929 {}
1930
1931 TestCaseInfo( const TestCaseInfo& other, const std::string& name )
1932 : m_test( other.m_test->clone() ),
1933 m_name( name ),
1934 m_description( other.m_description ),
1935 m_lineInfo( other.m_lineInfo )
1936 {}
1937
1938 TestCaseInfo& operator = ( const TestCaseInfo& other ) {
1939 TestCaseInfo temp( other );
1940 swap( temp );
1941 return *this;
1942 }
1943
1944 ~TestCaseInfo() {
1945 delete m_test;
1946 }
1947
1948 void invoke() const {
1949 m_test->invoke();
1950 }
1951
1952 const std::string& getName() const {
1953 return m_name;
1954 }
1955
1956 const std::string& getDescription() const {
1957 return m_description;
1958 }
1959
1960 const SourceLineInfo& getLineInfo() const {
1961 return m_lineInfo;
1962 }
1963
1964 bool isHidden() const {
1965 return m_name.size() >= 2 && m_name[0] == '.' && m_name[1] == '/';
1966 }
1967
1968 void swap( TestCaseInfo& other ) {
1969 std::swap( m_test, other.m_test );
1970 m_name.swap( other.m_name );
1971 m_description.swap( other.m_description );
1972 m_lineInfo.swap( other.m_lineInfo );
1973 }
1974
1975 bool operator == ( const TestCaseInfo& other ) const {
1976 return *m_test == *other.m_test && m_name == other.m_name;
1977 }
1978
1979 bool operator < ( const TestCaseInfo& other ) const {
1980 return m_name < other.m_name;
1981 }
1982 2869
1983 private: 2870 private:
1984 ITestCase* m_test; 2871 Ptr<ITestCase> test;
1985 std::string m_name; 2872 };
1986 std::string m_description; 2873
1987 SourceLineInfo m_lineInfo; 2874 TestCase makeTestCase( ITestCase* testCase,
1988 }; 2875 std::string const& className,
1989 2876 std::string const& name,
1990 /////////////////////////////////////////////////////////////////////////// 2877 std::string const& description,
1991 2878 SourceLineInfo const& lineInfo );
1992 class TestSpec {
1993 public:
1994 TestSpec( const std::string& rawSpec )
1995 : m_rawSpec( rawSpec ),
1996 m_isWildcarded( false ) {
1997
1998 if( m_rawSpec[m_rawSpec.size()-1] == '*' ) {
1999 m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 );
2000 m_isWildcarded = true;
2001 }
2002 }
2003
2004 bool matches ( const std::string& testName ) const {
2005 if( !m_isWildcarded )
2006 return m_rawSpec == testName;
2007 else
2008 return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;
2009 }
2010
2011 private:
2012 std::string m_rawSpec;
2013 bool m_isWildcarded;
2014 };
2015 } 2879 }
2016 2880
2017 // #included from: internal/catch_interfaces_runner.h 2881 #ifdef __clang__
2018 2882 #pragma clang diagnostic pop
2019 #include <string> 2883 #endif
2020
2021 namespace Catch {
2022 class TestCaseInfo;
2023
2024 struct IRunner {
2025 virtual ~IRunner() {}
2026 virtual void runAll( bool runHiddenTests = false ) = 0;
2027 virtual std::size_t runMatching( const std::string& rawTestSpec ) = 0;
2028 virtual Totals getTotals() const = 0;
2029 };
2030 }
2031 2884
2032 2885
2033 #ifdef __OBJC__ 2886 #ifdef __OBJC__
2034 // #included from: internal/catch_objc.hpp 2887 // #included from: internal/catch_objc.hpp
2035 2888 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2036 #import <Foundation/Foundation.h> 2889
2037 #import <objc/runtime.h> 2890 #import <objc/runtime.h>
2038 2891
2039 #include <string> 2892 #include <string>
2040 2893
2041 // NB. Any general catch headers included here must be included 2894 // NB. Any general catch headers included here must be included
2042 // in catch.hpp first to make sure they are included by the single 2895 // in catch.hpp first to make sure they are included by the single
2043 // header for non obj-usage 2896 // header for non obj-usage
2044
2045 #ifdef __has_feature
2046 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
2047 #else
2048 #define CATCH_ARC_ENABLED 0
2049 #endif
2050
2051 void arcSafeRelease( NSObject* obj );
2052 id performOptionalSelector( id obj, SEL sel );
2053
2054 #if !CATCH_ARC_ENABLED
2055 inline void arcSafeRelease( NSObject* obj ) {
2056 [obj release];
2057 }
2058 inline id performOptionalSelector( id obj, SEL sel ) {
2059 if( [obj respondsToSelector: sel] )
2060 return [obj performSelector: sel];
2061 return nil;
2062 }
2063 #define CATCH_UNSAFE_UNRETAINED
2064 #else
2065 inline void arcSafeRelease( NSObject* ){}
2066 inline id performOptionalSelector( id obj, SEL sel ) {
2067 #pragma clang diagnostic push
2068 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
2069 if( [obj respondsToSelector: sel] )
2070 return [obj performSelector: sel];
2071 #pragma clang diagnostic pop
2072 return nil;
2073 }
2074 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
2075 #endif
2076 2897
2077 /////////////////////////////////////////////////////////////////////////////// 2898 ///////////////////////////////////////////////////////////////////////////////
2078 // This protocol is really only here for (self) documenting purposes, since 2899 // This protocol is really only here for (self) documenting purposes, since
2079 // all its methods are optional. 2900 // all its methods are optional.
2080 @protocol OcFixture 2901 @protocol OcFixture
2086 2907
2087 @end 2908 @end
2088 2909
2089 namespace Catch { 2910 namespace Catch {
2090 2911
2091 class OcMethod : public ITestCase { 2912 class OcMethod : public SharedImpl<ITestCase> {
2092 2913
2093 public: 2914 public:
2094 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} 2915 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2095 2916
2096 virtual void invoke() const { 2917 virtual void invoke() const {
2100 performOptionalSelector( obj, m_sel ); 2921 performOptionalSelector( obj, m_sel );
2101 performOptionalSelector( obj, @selector(tearDown) ); 2922 performOptionalSelector( obj, @selector(tearDown) );
2102 2923
2103 arcSafeRelease( obj ); 2924 arcSafeRelease( obj );
2104 } 2925 }
2105
2106 virtual ITestCase* clone() const {
2107 return new OcMethod( m_cls, m_sel );
2108 }
2109
2110 virtual bool operator == ( const ITestCase& other ) const {
2111 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2112 return ocmOther && ocmOther->m_sel == m_sel;
2113 }
2114
2115 virtual bool operator < ( const ITestCase& other ) const {
2116 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2117 return ocmOther && ocmOther->m_sel < m_sel;
2118 }
2119
2120 private: 2926 private:
2927 virtual ~OcMethod() {}
2928
2121 Class m_cls; 2929 Class m_cls;
2122 SEL m_sel; 2930 SEL m_sel;
2123 }; 2931 };
2124 2932
2125 namespace Detail{ 2933 namespace Detail{
2126 2934
2127 inline bool startsWith( const std::string& str, const std::string& sub ) {
2128 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2129 }
2130
2131 inline std::string getAnnotation( Class cls, 2935 inline std::string getAnnotation( Class cls,
2132 const std::string& annotationName, 2936 std::string const& annotationName,
2133 const std::string& testCaseName ) { 2937 std::string const& testCaseName ) {
2134 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; 2938 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2135 SEL sel = NSSelectorFromString( selStr ); 2939 SEL sel = NSSelectorFromString( selStr );
2136 arcSafeRelease( selStr ); 2940 arcSafeRelease( selStr );
2137 id value = performOptionalSelector( cls, sel ); 2941 id value = performOptionalSelector( cls, sel );
2138 if( value ) 2942 if( value )
2141 } 2945 }
2142 } 2946 }
2143 2947
2144 inline size_t registerTestMethods() { 2948 inline size_t registerTestMethods() {
2145 size_t noTestMethods = 0; 2949 size_t noTestMethods = 0;
2146 int noClasses = objc_getClassList( NULL, 0 ); 2950 int noClasses = objc_getClassList( CATCH_NULL, 0 );
2147 2951
2148 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); 2952 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
2149 objc_getClassList( classes, noClasses ); 2953 objc_getClassList( classes, noClasses );
2150 2954
2151 for( int c = 0; c < noClasses; c++ ) { 2955 for( int c = 0; c < noClasses; c++ ) {
2154 u_int count; 2958 u_int count;
2155 Method* methods = class_copyMethodList( cls, &count ); 2959 Method* methods = class_copyMethodList( cls, &count );
2156 for( u_int m = 0; m < count ; m++ ) { 2960 for( u_int m = 0; m < count ; m++ ) {
2157 SEL selector = method_getName(methods[m]); 2961 SEL selector = method_getName(methods[m]);
2158 std::string methodName = sel_getName(selector); 2962 std::string methodName = sel_getName(selector);
2159 if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) { 2963 if( startsWith( methodName, "Catch_TestCase_" ) ) {
2160 std::string testCaseName = methodName.substr( 15 ); 2964 std::string testCaseName = methodName.substr( 15 );
2161 std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); 2965 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2162 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); 2966 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
2163 2967 const char* className = class_getName( cls );
2164 getCurrentContext().getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) ); 2968
2969 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
2165 noTestMethods++; 2970 noTestMethods++;
2166 } 2971 }
2167 } 2972 }
2168 free(methods); 2973 free(methods);
2169 } 2974 }
2170 } 2975 }
2171 return noTestMethods; 2976 return noTestMethods;
2172 } 2977 }
2173 2978
2174 inline std::string toString( NSString* const& nsstring ) {
2175 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
2176 }
2177
2178 namespace Matchers { 2979 namespace Matchers {
2179 namespace Impl { 2980 namespace Impl {
2180 namespace NSStringMatchers { 2981 namespace NSStringMatchers {
2181 2982
2182 struct StringHolder { 2983 template<typename MatcherT>
2984 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
2183 StringHolder( NSString* substr ) : m_substr( [substr copy] ){} 2985 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2986 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
2184 StringHolder() { 2987 StringHolder() {
2185 arcSafeRelease( m_substr ); 2988 arcSafeRelease( m_substr );
2186 } 2989 }
2187 2990
2188 NSString* m_substr; 2991 NSString* m_substr;
2189 }; 2992 };
2190 2993
2191 struct Equals : StringHolder { 2994 struct Equals : StringHolder<Equals> {
2192 Equals( NSString* substr ) : StringHolder( substr ){} 2995 Equals( NSString* substr ) : StringHolder( substr ){}
2193 2996
2194 bool operator()( NSString* str ) const { 2997 virtual bool match( ExpressionType const& str ) const {
2195 return [str isEqualToString:m_substr]; 2998 return (str != nil || m_substr == nil ) &&
2999 [str isEqualToString:m_substr];
2196 } 3000 }
2197 3001
2198 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher ) { 3002 virtual std::string toString() const {
2199 os << "equals string: " << Catch::toString( matcher.m_substr ); 3003 return "equals string: " + Catch::toString( m_substr );
2200 return os;
2201 } 3004 }
2202 }; 3005 };
2203 3006
2204 struct Contains : StringHolder { 3007 struct Contains : StringHolder<Contains> {
2205 Contains( NSString* substr ) : StringHolder( substr ){} 3008 Contains( NSString* substr ) : StringHolder( substr ){}
2206 3009
2207 bool operator()( NSString* str ) const { 3010 virtual bool match( ExpressionType const& str ) const {
2208 return [str rangeOfString:m_substr].location != NSNotFound; 3011 return (str != nil || m_substr == nil ) &&
3012 [str rangeOfString:m_substr].location != NSNotFound;
2209 } 3013 }
2210 3014
2211 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) { 3015 virtual std::string toString() const {
2212 os << "contains: " << Catch::toString( matcher.m_substr ); 3016 return "contains string: " + Catch::toString( m_substr );
2213 return os;
2214 } 3017 }
2215 }; 3018 };
2216 3019
2217 struct StartsWith : StringHolder { 3020 struct StartsWith : StringHolder<StartsWith> {
2218 StartsWith( NSString* substr ) : StringHolder( substr ){} 3021 StartsWith( NSString* substr ) : StringHolder( substr ){}
2219 3022
2220 bool operator()( NSString* str ) const { 3023 virtual bool match( ExpressionType const& str ) const {
2221 return [str rangeOfString:m_substr].location == 0; 3024 return (str != nil || m_substr == nil ) &&
3025 [str rangeOfString:m_substr].location == 0;
2222 } 3026 }
2223 3027
2224 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) { 3028 virtual std::string toString() const {
2225 os << "starts with: " << Catch::toString( matcher.m_substr ); 3029 return "starts with: " + Catch::toString( m_substr );
2226 return os;
2227 } 3030 }
2228 }; 3031 };
2229 struct EndsWith : StringHolder { 3032 struct EndsWith : StringHolder<EndsWith> {
2230 EndsWith( NSString* substr ) : StringHolder( substr ){} 3033 EndsWith( NSString* substr ) : StringHolder( substr ){}
2231 3034
2232 bool operator()( NSString* str ) const { 3035 virtual bool match( ExpressionType const& str ) const {
2233 return [str rangeOfString:m_substr].location == [str length] - [m_substr length]; 3036 return (str != nil || m_substr == nil ) &&
3037 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2234 } 3038 }
2235 3039
2236 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) { 3040 virtual std::string toString() const {
2237 os << "ends with: " << Catch::toString( matcher.m_substr ); 3041 return "ends with: " + Catch::toString( m_substr );
2238 return os;
2239 } 3042 }
2240 }; 3043 };
2241 3044
2242 } // namespace NSStringMatchers 3045 } // namespace NSStringMatchers
2243 } // namespace Impl 3046 } // namespace Impl
2272 } \ 3075 } \
2273 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) 3076 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2274 3077
2275 #endif 3078 #endif
2276 3079
2277 #if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER ) 3080 #ifdef CATCH_IMPL
2278 // #included from: catch_runner.hpp 3081 // #included from: internal/catch_impl.hpp
2279 3082 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2280 // #included from: internal/catch_context_impl.hpp 3083
2281 // #included from: catch_test_case_registry_impl.hpp 3084 // Collect all the implementation files together here
2282 3085 // These are the equivalent of what would usually be cpp files
3086
3087 #ifdef __clang__
3088 #pragma clang diagnostic push
3089 #pragma clang diagnostic ignored "-Wweak-vtables"
3090 #endif
3091
3092 // #included from: ../catch_session.hpp
3093 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3094
3095 // #included from: internal/catch_commandline.hpp
3096 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3097
3098 // #included from: catch_config.hpp
3099 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3100
3101 // #included from: catch_test_spec_parser.hpp
3102 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3103
3104 #ifdef __clang__
3105 #pragma clang diagnostic push
3106 #pragma clang diagnostic ignored "-Wpadded"
3107 #endif
3108
3109 // #included from: catch_test_spec.hpp
3110 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3111
3112 #ifdef __clang__
3113 #pragma clang diagnostic push
3114 #pragma clang diagnostic ignored "-Wpadded"
3115 #endif
3116
3117 // #included from: catch_wildcard_pattern.hpp
3118 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3119
3120 namespace Catch
3121 {
3122 class WildcardPattern {
3123 enum WildcardPosition {
3124 NoWildcard = 0,
3125 WildcardAtStart = 1,
3126 WildcardAtEnd = 2,
3127 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3128 };
3129
3130 public:
3131
3132 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
3133 : m_caseSensitivity( caseSensitivity ),
3134 m_wildcard( NoWildcard ),
3135 m_pattern( adjustCase( pattern ) )
3136 {
3137 if( startsWith( m_pattern, "*" ) ) {
3138 m_pattern = m_pattern.substr( 1 );
3139 m_wildcard = WildcardAtStart;
3140 }
3141 if( endsWith( m_pattern, "*" ) ) {
3142 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3143 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3144 }
3145 }
3146 virtual ~WildcardPattern();
3147 virtual bool matches( std::string const& str ) const {
3148 switch( m_wildcard ) {
3149 case NoWildcard:
3150 return m_pattern == adjustCase( str );
3151 case WildcardAtStart:
3152 return endsWith( adjustCase( str ), m_pattern );
3153 case WildcardAtEnd:
3154 return startsWith( adjustCase( str ), m_pattern );
3155 case WildcardAtBothEnds:
3156 return contains( adjustCase( str ), m_pattern );
3157 }
3158
3159 #ifdef __clang__
3160 #pragma clang diagnostic push
3161 #pragma clang diagnostic ignored "-Wunreachable-code"
3162 #endif
3163 throw std::logic_error( "Unknown enum" );
3164 #ifdef __clang__
3165 #pragma clang diagnostic pop
3166 #endif
3167 }
3168 private:
3169 std::string adjustCase( std::string const& str ) const {
3170 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
3171 }
3172 CaseSensitive::Choice m_caseSensitivity;
3173 WildcardPosition m_wildcard;
3174 std::string m_pattern;
3175 };
3176 }
3177
3178 #include <string>
2283 #include <vector> 3179 #include <vector>
2284 #include <set> 3180
2285 #include <sstream> 3181 namespace Catch {
3182
3183 class TestSpec {
3184 struct Pattern : SharedImpl<> {
3185 virtual ~Pattern();
3186 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3187 };
3188 class NamePattern : public Pattern {
3189 public:
3190 NamePattern( std::string const& name )
3191 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
3192 {}
3193 virtual ~NamePattern();
3194 virtual bool matches( TestCaseInfo const& testCase ) const {
3195 return m_wildcardPattern.matches( toLower( testCase.name ) );
3196 }
3197 private:
3198 WildcardPattern m_wildcardPattern;
3199 };
3200
3201 class TagPattern : public Pattern {
3202 public:
3203 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3204 virtual ~TagPattern();
3205 virtual bool matches( TestCaseInfo const& testCase ) const {
3206 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
3207 }
3208 private:
3209 std::string m_tag;
3210 };
3211
3212 class ExcludedPattern : public Pattern {
3213 public:
3214 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3215 virtual ~ExcludedPattern();
3216 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3217 private:
3218 Ptr<Pattern> m_underlyingPattern;
3219 };
3220
3221 struct Filter {
3222 std::vector<Ptr<Pattern> > m_patterns;
3223
3224 bool matches( TestCaseInfo const& testCase ) const {
3225 // All patterns in a filter must match for the filter to be a match
3226 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
3227 if( !(*it)->matches( testCase ) )
3228 return false;
3229 return true;
3230 }
3231 };
3232
3233 public:
3234 bool hasFilters() const {
3235 return !m_filters.empty();
3236 }
3237 bool matches( TestCaseInfo const& testCase ) const {
3238 // A TestSpec matches if any filter matches
3239 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3240 if( it->matches( testCase ) )
3241 return true;
3242 return false;
3243 }
3244
3245 private:
3246 std::vector<Filter> m_filters;
3247
3248 friend class TestSpecParser;
3249 };
3250 }
3251
3252 #ifdef __clang__
3253 #pragma clang diagnostic pop
3254 #endif
3255
3256 namespace Catch {
3257
3258 class TestSpecParser {
3259 enum Mode{ None, Name, QuotedName, Tag };
3260 Mode m_mode;
3261 bool m_exclusion;
3262 std::size_t m_start, m_pos;
3263 std::string m_arg;
3264 TestSpec::Filter m_currentFilter;
3265 TestSpec m_testSpec;
3266 ITagAliasRegistry const* m_tagAliases;
3267
3268 public:
3269 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
3270
3271 TestSpecParser& parse( std::string const& arg ) {
3272 m_mode = None;
3273 m_exclusion = false;
3274 m_start = std::string::npos;
3275 m_arg = m_tagAliases->expandAliases( arg );
3276 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3277 visitChar( m_arg[m_pos] );
3278 if( m_mode == Name )
3279 addPattern<TestSpec::NamePattern>();
3280 return *this;
3281 }
3282 TestSpec testSpec() {
3283 addFilter();
3284 return m_testSpec;
3285 }
3286 private:
3287 void visitChar( char c ) {
3288 if( m_mode == None ) {
3289 switch( c ) {
3290 case ' ': return;
3291 case '~': m_exclusion = true; return;
3292 case '[': return startNewMode( Tag, ++m_pos );
3293 case '"': return startNewMode( QuotedName, ++m_pos );
3294 default: startNewMode( Name, m_pos ); break;
3295 }
3296 }
3297 if( m_mode == Name ) {
3298 if( c == ',' ) {
3299 addPattern<TestSpec::NamePattern>();
3300 addFilter();
3301 }
3302 else if( c == '[' ) {
3303 if( subString() == "exclude:" )
3304 m_exclusion = true;
3305 else
3306 addPattern<TestSpec::NamePattern>();
3307 startNewMode( Tag, ++m_pos );
3308 }
3309 }
3310 else if( m_mode == QuotedName && c == '"' )
3311 addPattern<TestSpec::NamePattern>();
3312 else if( m_mode == Tag && c == ']' )
3313 addPattern<TestSpec::TagPattern>();
3314 }
3315 void startNewMode( Mode mode, std::size_t start ) {
3316 m_mode = mode;
3317 m_start = start;
3318 }
3319 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3320 template<typename T>
3321 void addPattern() {
3322 std::string token = subString();
3323 if( startsWith( token, "exclude:" ) ) {
3324 m_exclusion = true;
3325 token = token.substr( 8 );
3326 }
3327 if( !token.empty() ) {
3328 Ptr<TestSpec::Pattern> pattern = new T( token );
3329 if( m_exclusion )
3330 pattern = new TestSpec::ExcludedPattern( pattern );
3331 m_currentFilter.m_patterns.push_back( pattern );
3332 }
3333 m_exclusion = false;
3334 m_mode = None;
3335 }
3336 void addFilter() {
3337 if( !m_currentFilter.m_patterns.empty() ) {
3338 m_testSpec.m_filters.push_back( m_currentFilter );
3339 m_currentFilter = TestSpec::Filter();
3340 }
3341 }
3342 };
3343 inline TestSpec parseTestSpec( std::string const& arg ) {
3344 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
3345 }
3346
3347 } // namespace Catch
3348
3349 #ifdef __clang__
3350 #pragma clang diagnostic pop
3351 #endif
3352
3353 // #included from: catch_interfaces_config.h
3354 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3355
2286 #include <iostream> 3356 #include <iostream>
3357 #include <string>
3358 #include <vector>
2287 3359
2288 namespace Catch { 3360 namespace Catch {
2289 3361
2290 class TestRegistry : public ITestCaseRegistry { 3362 struct Verbosity { enum Level {
3363 NoOutput = 0,
3364 Quiet,
3365 Normal
3366 }; };
3367
3368 struct WarnAbout { enum What {
3369 Nothing = 0x00,
3370 NoAssertions = 0x01
3371 }; };
3372
3373 struct ShowDurations { enum OrNot {
3374 DefaultForReporter,
3375 Always,
3376 Never
3377 }; };
3378 struct RunTests { enum InWhatOrder {
3379 InDeclarationOrder,
3380 InLexicographicalOrder,
3381 InRandomOrder
3382 }; };
3383 struct UseColour { enum YesOrNo {
3384 Auto,
3385 Yes,
3386 No
3387 }; };
3388
3389 class TestSpec;
3390
3391 struct IConfig : IShared {
3392
3393 virtual ~IConfig();
3394
3395 virtual bool allowThrows() const = 0;
3396 virtual std::ostream& stream() const = 0;
3397 virtual std::string name() const = 0;
3398 virtual bool includeSuccessfulResults() const = 0;
3399 virtual bool shouldDebugBreak() const = 0;
3400 virtual bool warnAboutMissingAssertions() const = 0;
3401 virtual int abortAfter() const = 0;
3402 virtual bool showInvisibles() const = 0;
3403 virtual ShowDurations::OrNot showDurations() const = 0;
3404 virtual TestSpec const& testSpec() const = 0;
3405 virtual RunTests::InWhatOrder runOrder() const = 0;
3406 virtual unsigned int rngSeed() const = 0;
3407 virtual UseColour::YesOrNo useColour() const = 0;
3408 };
3409 }
3410
3411 // #included from: catch_stream.h
3412 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3413
3414 // #included from: catch_streambuf.h
3415 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3416
3417 #include <streambuf>
3418
3419 namespace Catch {
3420
3421 class StreamBufBase : public std::streambuf {
2291 public: 3422 public:
2292 TestRegistry() : m_unnamedCount( 0 ) {} 3423 virtual ~StreamBufBase() CATCH_NOEXCEPT;
2293 3424 };
2294 virtual void registerTest( const TestCaseInfo& testInfo ) { 3425 }
2295 if( testInfo.getName() == "" ) { 3426
2296 std::ostringstream oss; 3427 #include <streambuf>
2297 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount; 3428 #include <ostream>
2298 return registerTest( TestCaseInfo( testInfo, oss.str() ) ); 3429 #include <fstream>
2299 } 3430
2300 3431 namespace Catch {
2301 if( m_functions.find( testInfo ) == m_functions.end() ) { 3432
2302 m_functions.insert( testInfo ); 3433 std::ostream& cout();
2303 m_functionsInOrder.push_back( testInfo ); 3434 std::ostream& cerr();
2304 } 3435
2305 else { 3436 struct IStream {
2306 const TestCaseInfo& prev = *m_functions.find( testInfo ); 3437 virtual ~IStream() CATCH_NOEXCEPT;
2307 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n" 3438 virtual std::ostream& stream() const = 0;
2308 << "\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) << "\n" 3439 };
2309 << "\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl; 3440
2310 exit(1); 3441 class FileStream : public IStream {
2311 } 3442 mutable std::ofstream m_ofs;
2312 }
2313
2314 virtual const std::vector<TestCaseInfo>& getAllTests() const {
2315 return m_functionsInOrder;
2316 }
2317
2318 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) {
2319 TestSpec testSpec( rawTestSpec );
2320
2321 std::vector<TestCaseInfo> testList;
2322 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
2323 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
2324 for(; it != itEnd; ++it ) {
2325 if( testSpec.matches( it->getName() ) ) {
2326 testList.push_back( *it );
2327 }
2328 }
2329 return testList;
2330 }
2331
2332 private:
2333
2334 std::set<TestCaseInfo> m_functions;
2335 std::vector<TestCaseInfo> m_functionsInOrder;
2336 size_t m_unnamedCount;
2337 };
2338
2339 ///////////////////////////////////////////////////////////////////////////
2340
2341 class FreeFunctionTestCase : public ITestCase {
2342 public: 3443 public:
2343 3444 FileStream( std::string const& filename );
2344 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} 3445 virtual ~FileStream() CATCH_NOEXCEPT;
2345 3446 public: // IStream
2346 virtual void invoke() const { 3447 virtual std::ostream& stream() const CATCH_OVERRIDE;
2347 m_fun(); 3448 };
2348 } 3449
2349 3450 class CoutStream : public IStream {
2350 virtual ITestCase* clone() const { 3451 mutable std::ostream m_os;
2351 return new FreeFunctionTestCase( m_fun ); 3452 public:
2352 } 3453 CoutStream();
2353 3454 virtual ~CoutStream() CATCH_NOEXCEPT;
2354 virtual bool operator == ( const ITestCase& other ) const { 3455
2355 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other ); 3456 public: // IStream
2356 return ffOther && m_fun == ffOther->m_fun; 3457 virtual std::ostream& stream() const CATCH_OVERRIDE;
2357 } 3458 };
2358 3459
2359 virtual bool operator < ( const ITestCase& other ) const { 3460 class DebugOutStream : public IStream {
2360 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other ); 3461 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
2361 return ffOther && m_fun < ffOther->m_fun; 3462 mutable std::ostream m_os;
2362 } 3463 public:
2363 3464 DebugOutStream();
2364 private: 3465 virtual ~DebugOutStream() CATCH_NOEXCEPT;
2365 TestFunction m_fun; 3466
2366 }; 3467 public: // IStream
2367 3468 virtual std::ostream& stream() const CATCH_OVERRIDE;
2368 /////////////////////////////////////////////////////////////////////////// 3469 };
2369 3470 }
2370 AutoReg::AutoReg( TestFunction function,
2371 const char* name,
2372 const char* description,
2373 const SourceLineInfo& lineInfo ) {
2374 registerTestCase( new FreeFunctionTestCase( function ), name, description, lineInfo );
2375 }
2376
2377 AutoReg::~AutoReg() {}
2378
2379 void AutoReg::registerTestCase( ITestCase* testCase,
2380 const char* name,
2381 const char* description,
2382 const SourceLineInfo& lineInfo ) {
2383 getCurrentContext().getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) );
2384 }
2385
2386 } // end namespace Catch
2387
2388 // #included from: catch_runner_impl.hpp
2389
2390 // #included from: catch_config.hpp
2391 3471
2392 #include <memory> 3472 #include <memory>
2393 #include <vector> 3473 #include <vector>
2394 #include <string> 3474 #include <string>
2395 #include <iostream> 3475 #include <iostream>
3476 #include <ctime>
3477
3478 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3479 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3480 #endif
2396 3481
2397 namespace Catch { 3482 namespace Catch {
2398 3483
2399 struct Include { enum WhichResults { 3484 struct ConfigData {
2400 FailedOnly, 3485
2401 SuccessfulResults 3486 ConfigData()
2402 }; }; 3487 : listTests( false ),
2403 3488 listTags( false ),
2404 struct List{ enum What { 3489 listReporters( false ),
2405 None = 0, 3490 listTestNamesOnly( false ),
2406 3491 showSuccessfulTests( false ),
2407 Reports = 1, 3492 shouldDebugBreak( false ),
2408 Tests = 2, 3493 noThrow( false ),
2409 All = 3, 3494 showHelp( false ),
2410 3495 showInvisibles( false ),
2411 WhatMask = 0xf, 3496 filenamesAsTags( false ),
2412 3497 abortAfter( -1 ),
2413 AsText = 0x10, 3498 rngSeed( 0 ),
2414 AsXml = 0x11, 3499 verbosity( Verbosity::Normal ),
2415 3500 warnings( WarnAbout::Nothing ),
2416 AsMask = 0xf0 3501 showDurations( ShowDurations::DefaultForReporter ),
2417 }; }; 3502 runOrder( RunTests::InDeclarationOrder ),
2418 3503 useColour( UseColour::Auto )
2419 class Config : public IReporterConfig, public IConfig { 3504 {}
3505
3506 bool listTests;
3507 bool listTags;
3508 bool listReporters;
3509 bool listTestNamesOnly;
3510
3511 bool showSuccessfulTests;
3512 bool shouldDebugBreak;
3513 bool noThrow;
3514 bool showHelp;
3515 bool showInvisibles;
3516 bool filenamesAsTags;
3517
3518 int abortAfter;
3519 unsigned int rngSeed;
3520
3521 Verbosity::Level verbosity;
3522 WarnAbout::What warnings;
3523 ShowDurations::OrNot showDurations;
3524 RunTests::InWhatOrder runOrder;
3525 UseColour::YesOrNo useColour;
3526
3527 std::string outputFilename;
3528 std::string name;
3529 std::string processName;
3530
3531 std::vector<std::string> reporterNames;
3532 std::vector<std::string> testsOrTags;
3533 };
3534
3535 class Config : public SharedImpl<IConfig> {
2420 private: 3536 private:
2421 Config( const Config& other ); 3537 Config( Config const& other );
2422 Config& operator = ( const Config& other ); 3538 Config& operator = ( Config const& other );
3539 virtual void dummy();
2423 public: 3540 public:
2424 3541
2425 Config() 3542 Config()
2426 : m_listSpec( List::None ),
2427 m_shouldDebugBreak( false ),
2428 m_showHelp( false ),
2429 m_streambuf( NULL ),
2430 m_os( std::cout.rdbuf() ),
2431 m_includeWhichResults( Include::FailedOnly ),
2432 m_cutoff( -1 ),
2433 m_allowThrows( true )
2434 {} 3543 {}
2435 3544
2436 ~Config() { 3545 Config( ConfigData const& data )
2437 m_os.rdbuf( std::cout.rdbuf() ); 3546 : m_data( data ),
2438 delete m_streambuf; 3547 m_stream( openStream() )
2439 } 3548 {
2440 3549 if( !data.testsOrTags.empty() ) {
2441 void setReporter( const std::string& reporterName ) { 3550 TestSpecParser parser( ITagAliasRegistry::get() );
2442 if( m_reporter.get() ) 3551 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
2443 return setError( "Only one reporter may be specified" ); 3552 parser.parse( data.testsOrTags[i] );
2444 setReporter( getCurrentContext().getReporterRegistry().create( reporterName, *this ) ); 3553 m_testSpec = parser.testSpec();
2445 } 3554 }
2446 3555 }
2447 void addTestSpec( const std::string& testSpec ) { 3556
2448 m_testSpecs.push_back( testSpec ); 3557 virtual ~Config() {
2449 } 3558 }
2450 3559
2451 bool testsSpecified() const { 3560 std::string const& getFilename() const {
2452 return !m_testSpecs.empty(); 3561 return m_data.outputFilename ;
2453 } 3562 }
2454 3563
2455 const std::vector<std::string>& getTestSpecs() const { 3564 bool listTests() const { return m_data.listTests; }
2456 return m_testSpecs; 3565 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
2457 } 3566 bool listTags() const { return m_data.listTags; }
2458 3567 bool listReporters() const { return m_data.listReporters; }
2459 List::What getListSpec( void ) const { 3568
2460 return m_listSpec; 3569 std::string getProcessName() const { return m_data.processName; }
2461 } 3570
2462 3571 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
2463 void setListSpec( List::What listSpec ) { 3572
2464 m_listSpec = listSpec; 3573 std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
2465 } 3574
2466 3575 int abortAfter() const { return m_data.abortAfter; }
2467 void setFilename( const std::string& filename ) { 3576
2468 m_filename = filename; 3577 TestSpec const& testSpec() const { return m_testSpec; }
2469 } 3578
2470 3579 bool showHelp() const { return m_data.showHelp; }
2471 const std::string& getFilename() const { 3580 bool showInvisibles() const { return m_data.showInvisibles; }
2472 return m_filename; 3581
2473 } 3582 // IConfig interface
2474 3583 virtual bool allowThrows() const { return !m_data.noThrow; }
2475 const std::string& getMessage() const { 3584 virtual std::ostream& stream() const { return m_stream->stream(); }
2476 return m_message; 3585 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
2477 } 3586 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
2478 3587 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
2479 void setError( const std::string& errorMessage ) { 3588 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
2480 m_message = errorMessage; 3589 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
2481 } 3590 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
2482 3591 virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
2483 void setReporter( IReporter* reporter ) {
2484 m_reporter = reporter;
2485 }
2486
2487 Ptr<IReporter> getReporter() {
2488 if( !m_reporter.get() )
2489 const_cast<Config*>( this )->setReporter( getCurrentContext().getReporterRegistry().create( "basic", *this ) );
2490 return m_reporter;
2491 }
2492
2493 List::What listWhat() const {
2494 return static_cast<List::What>( m_listSpec & List::WhatMask );
2495 }
2496
2497 List::What listAs() const {
2498 return static_cast<List::What>( m_listSpec & List::AsMask );
2499 }
2500
2501 void setIncludeWhichResults( Include::WhichResults includeWhichResults ) {
2502 m_includeWhichResults = includeWhichResults;
2503 }
2504
2505 void setShouldDebugBreak( bool shouldDebugBreakFlag ) {
2506 m_shouldDebugBreak = shouldDebugBreakFlag;
2507 }
2508
2509 void setName( const std::string& name ) {
2510 m_name = name;
2511 }
2512
2513 std::string getName() const {
2514 return m_name;
2515 }
2516
2517 bool shouldDebugBreak() const {
2518 return m_shouldDebugBreak;
2519 }
2520
2521 void setShowHelp( bool showHelpFlag ) {
2522 m_showHelp = showHelpFlag;
2523 }
2524
2525 bool showHelp() const {
2526 return m_showHelp;
2527 }
2528
2529 virtual std::ostream& stream() const {
2530 return m_os;
2531 }
2532
2533 void setStreamBuf( std::streambuf* buf ) {
2534 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2535 }
2536
2537 void useStream( const std::string& streamName ) {
2538 std::streambuf* newBuf = Context::createStreamBuf( streamName );
2539 setStreamBuf( newBuf );
2540 delete m_streambuf;
2541 m_streambuf = newBuf;
2542 }
2543
2544 virtual bool includeSuccessfulResults() const {
2545 return m_includeWhichResults == Include::SuccessfulResults;
2546 }
2547
2548 int getCutoff() const {
2549 return m_cutoff;
2550 }
2551
2552 void setCutoff( int cutoff ) {
2553 m_cutoff = cutoff;
2554 }
2555
2556 void setAllowThrows( bool allowThrows ) {
2557 m_allowThrows = allowThrows;
2558 }
2559
2560 virtual bool allowThrows() const {
2561 return m_allowThrows;
2562 }
2563 3592
2564 private: 3593 private:
2565 Ptr<IReporter> m_reporter; 3594
2566 std::string m_filename; 3595 IStream const* openStream() {
2567 std::string m_message; 3596 if( m_data.outputFilename.empty() )
2568 List::What m_listSpec; 3597 return new CoutStream();
2569 std::vector<std::string> m_testSpecs; 3598 else if( m_data.outputFilename[0] == '%' ) {
2570 bool m_shouldDebugBreak; 3599 if( m_data.outputFilename == "%debug" )
2571 bool m_showHelp; 3600 return new DebugOutStream();
2572 std::streambuf* m_streambuf; 3601 else
2573 mutable std::ostream m_os; 3602 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
2574 Include::WhichResults m_includeWhichResults; 3603 }
2575 std::string m_name; 3604 else
2576 int m_cutoff; 3605 return new FileStream( m_data.outputFilename );
2577 bool m_allowThrows; 3606 }
2578 }; 3607 ConfigData m_data;
2579 3608
2580 struct NewConfig { 3609 CATCH_AUTO_PTR( IStream const ) m_stream;
2581 std::string reporter; 3610 TestSpec m_testSpec;
2582 std::string outputFilename; 3611 };
2583 List::What listSpec; 3612
2584 std::vector<std::string> testSpecs; 3613 } // end namespace Catch
2585 bool shouldDebugBreak; 3614
2586 bool showHelp; 3615 // #included from: catch_clara.h
2587 Include::WhichResults includeWhichResults; 3616 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3617
3618 // Use Catch's value for console width (store Clara's off to the side, if present)
3619 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
3620 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3621 #undef CLARA_CONFIG_CONSOLE_WIDTH
3622 #endif
3623 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3624
3625 // Declare Clara inside the Catch namespace
3626 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3627 // #included from: ../external/clara.h
3628
3629 // Version 0.0.2.4
3630
3631 // Only use header guard if we are not using an outer namespace
3632 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3633
3634 #ifndef STITCH_CLARA_OPEN_NAMESPACE
3635 #define TWOBLUECUBES_CLARA_H_INCLUDED
3636 #define STITCH_CLARA_OPEN_NAMESPACE
3637 #define STITCH_CLARA_CLOSE_NAMESPACE
3638 #else
3639 #define STITCH_CLARA_CLOSE_NAMESPACE }
3640 #endif
3641
3642 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3643
3644 // ----------- #included from tbc_text_format.h -----------
3645
3646 // Only use header guard if we are not using an outer namespace
3647 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3648 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3649 #define TBC_TEXT_FORMAT_H_INCLUDED
3650 #endif
3651
3652 #include <string>
3653 #include <vector>
3654 #include <sstream>
3655 #include <algorithm>
3656
3657 // Use optional outer namespace
3658 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3659 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3660 #endif
3661
3662 namespace Tbc {
3663
3664 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3665 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3666 #else
3667 const unsigned int consoleWidth = 80;
3668 #endif
3669
3670 struct TextAttributes {
3671 TextAttributes()
3672 : initialIndent( std::string::npos ),
3673 indent( 0 ),
3674 width( consoleWidth-1 ),
3675 tabChar( '\t' )
3676 {}
3677
3678 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
3679 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
3680 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
3681 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
3682
3683 std::size_t initialIndent; // indent of first line, or npos
3684 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3685 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3686 char tabChar; // If this char is seen the indent is changed to current pos
3687 };
3688
3689 class Text {
3690 public:
3691 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
3692 : attr( _attr )
3693 {
3694 std::string wrappableChars = " [({.,/|\\-";
3695 std::size_t indent = _attr.initialIndent != std::string::npos
3696 ? _attr.initialIndent
3697 : _attr.indent;
3698 std::string remainder = _str;
3699
3700 while( !remainder.empty() ) {
3701 if( lines.size() >= 1000 ) {
3702 lines.push_back( "... message truncated due to excessive size" );
3703 return;
3704 }
3705 std::size_t tabPos = std::string::npos;
3706 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3707 std::size_t pos = remainder.find_first_of( '\n' );
3708 if( pos <= width ) {
3709 width = pos;
3710 }
3711 pos = remainder.find_last_of( _attr.tabChar, width );
3712 if( pos != std::string::npos ) {
3713 tabPos = pos;
3714 if( remainder[width] == '\n' )
3715 width--;
3716 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3717 }
3718
3719 if( width == remainder.size() ) {
3720 spliceLine( indent, remainder, width );
3721 }
3722 else if( remainder[width] == '\n' ) {
3723 spliceLine( indent, remainder, width );
3724 if( width <= 1 || remainder.size() != 1 )
3725 remainder = remainder.substr( 1 );
3726 indent = _attr.indent;
3727 }
3728 else {
3729 pos = remainder.find_last_of( wrappableChars, width );
3730 if( pos != std::string::npos && pos > 0 ) {
3731 spliceLine( indent, remainder, pos );
3732 if( remainder[0] == ' ' )
3733 remainder = remainder.substr( 1 );
3734 }
3735 else {
3736 spliceLine( indent, remainder, width-1 );
3737 lines.back() += "-";
3738 }
3739 if( lines.size() == 1 )
3740 indent = _attr.indent;
3741 if( tabPos != std::string::npos )
3742 indent += tabPos;
3743 }
3744 }
3745 }
3746
3747 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3748 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
3749 _remainder = _remainder.substr( _pos );
3750 }
3751
3752 typedef std::vector<std::string>::const_iterator const_iterator;
3753
3754 const_iterator begin() const { return lines.begin(); }
3755 const_iterator end() const { return lines.end(); }
3756 std::string const& last() const { return lines.back(); }
3757 std::size_t size() const { return lines.size(); }
3758 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
3759 std::string toString() const {
3760 std::ostringstream oss;
3761 oss << *this;
3762 return oss.str();
3763 }
3764
3765 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
3766 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3767 it != itEnd; ++it ) {
3768 if( it != _text.begin() )
3769 _stream << "\n";
3770 _stream << *it;
3771 }
3772 return _stream;
3773 }
3774
3775 private:
3776 std::string str;
3777 TextAttributes attr;
3778 std::vector<std::string> lines;
3779 };
3780
3781 } // end namespace Tbc
3782
3783 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3784 } // end outer namespace
3785 #endif
3786
3787 #endif // TBC_TEXT_FORMAT_H_INCLUDED
3788
3789 // ----------- end of #include from tbc_text_format.h -----------
3790 // ........... back in clara.h
3791
3792 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3793
3794 // ----------- #included from clara_compilers.h -----------
3795
3796 #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3797 #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3798
3799 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
3800 // The following features are defined:
3801 //
3802 // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
3803 // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
3804 // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
3805 // CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
3806 // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
3807
3808 // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
3809
3810 // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
3811
3812 // In general each macro has a _NO_<feature name> form
3813 // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
3814 // Many features, at point of detection, define an _INTERNAL_ macro, so they
3815 // can be combined, en-mass, with the _NO_ forms later.
3816
3817 // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
3818
3819 #ifdef __clang__
3820
3821 #if __has_feature(cxx_nullptr)
3822 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3823 #endif
3824
3825 #if __has_feature(cxx_noexcept)
3826 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3827 #endif
3828
3829 #endif // __clang__
3830
3831 ////////////////////////////////////////////////////////////////////////////////
3832 // GCC
3833 #ifdef __GNUC__
3834
3835 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
3836 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3837 #endif
3838
3839 // - otherwise more recent versions define __cplusplus >= 201103L
3840 // and will get picked up below
3841
3842 #endif // __GNUC__
3843
3844 ////////////////////////////////////////////////////////////////////////////////
3845 // Visual C++
3846 #ifdef _MSC_VER
3847
3848 #if (_MSC_VER >= 1600)
3849 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3850 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3851 #endif
3852
3853 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
3854 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3855 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3856 #endif
3857
3858 #endif // _MSC_VER
3859
3860 ////////////////////////////////////////////////////////////////////////////////
3861 // C++ language feature support
3862
3863 // catch all support for C++11
3864 #if defined(__cplusplus) && __cplusplus >= 201103L
3865
3866 #define CLARA_CPP11_OR_GREATER
3867
3868 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
3869 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3870 #endif
3871
3872 #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3873 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3874 #endif
3875
3876 #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3877 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3878 #endif
3879
3880 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
3881 #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
3882 #endif
3883 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
3884 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3885 #endif
3886
3887 #endif // __cplusplus >= 201103L
3888
3889 // Now set the actual defines based on the above + anything the user has configured
3890 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
3891 #define CLARA_CONFIG_CPP11_NULLPTR
3892 #endif
3893 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
3894 #define CLARA_CONFIG_CPP11_NOEXCEPT
3895 #endif
3896 #if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
3897 #define CLARA_CONFIG_CPP11_GENERATED_METHODS
3898 #endif
3899 #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
3900 #define CLARA_CONFIG_CPP11_OVERRIDE
3901 #endif
3902 #if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
3903 #define CLARA_CONFIG_CPP11_UNIQUE_PTR
3904 #endif
3905
3906 // noexcept support:
3907 #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
3908 #define CLARA_NOEXCEPT noexcept
3909 # define CLARA_NOEXCEPT_IS(x) noexcept(x)
3910 #else
3911 #define CLARA_NOEXCEPT throw()
3912 # define CLARA_NOEXCEPT_IS(x)
3913 #endif
3914
3915 // nullptr support
3916 #ifdef CLARA_CONFIG_CPP11_NULLPTR
3917 #define CLARA_NULL nullptr
3918 #else
3919 #define CLARA_NULL NULL
3920 #endif
3921
3922 // override support
3923 #ifdef CLARA_CONFIG_CPP11_OVERRIDE
3924 #define CLARA_OVERRIDE override
3925 #else
3926 #define CLARA_OVERRIDE
3927 #endif
3928
3929 // unique_ptr support
3930 #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
3931 # define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
3932 #else
3933 # define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
3934 #endif
3935
3936 #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3937
3938 // ----------- end of #include from clara_compilers.h -----------
3939 // ........... back in clara.h
3940
3941 #include <map>
3942 #include <stdexcept>
3943 #include <memory>
3944
3945 #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
3946 #define CLARA_PLATFORM_WINDOWS
3947 #endif
3948
3949 // Use optional outer namespace
3950 #ifdef STITCH_CLARA_OPEN_NAMESPACE
3951 STITCH_CLARA_OPEN_NAMESPACE
3952 #endif
3953
3954 namespace Clara {
3955
3956 struct UnpositionalTag {};
3957
3958 extern UnpositionalTag _;
3959
3960 #ifdef CLARA_CONFIG_MAIN
3961 UnpositionalTag _;
3962 #endif
3963
3964 namespace Detail {
3965
3966 #ifdef CLARA_CONSOLE_WIDTH
3967 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3968 #else
3969 const unsigned int consoleWidth = 80;
3970 #endif
3971
3972 using namespace Tbc;
3973
3974 inline bool startsWith( std::string const& str, std::string const& prefix ) {
3975 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3976 }
3977
3978 template<typename T> struct RemoveConstRef{ typedef T type; };
3979 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3980 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3981 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3982
3983 template<typename T> struct IsBool { static const bool value = false; };
3984 template<> struct IsBool<bool> { static const bool value = true; };
3985
3986 template<typename T>
3987 void convertInto( std::string const& _source, T& _dest ) {
3988 std::stringstream ss;
3989 ss << _source;
3990 ss >> _dest;
3991 if( ss.fail() )
3992 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
3993 }
3994 inline void convertInto( std::string const& _source, std::string& _dest ) {
3995 _dest = _source;
3996 }
3997 inline void convertInto( std::string const& _source, bool& _dest ) {
3998 std::string sourceLC = _source;
3999 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
4000 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
4001 _dest = true;
4002 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
4003 _dest = false;
4004 else
4005 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
4006 }
4007
4008 template<typename ConfigT>
4009 struct IArgFunction {
4010 virtual ~IArgFunction() {}
4011 #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
4012 IArgFunction() = default;
4013 IArgFunction( IArgFunction const& ) = default;
4014 #endif
4015 virtual void set( ConfigT& config, std::string const& value ) const = 0;
4016 virtual bool takesArg() const = 0;
4017 virtual IArgFunction* clone() const = 0;
4018 };
4019
4020 template<typename ConfigT>
4021 class BoundArgFunction {
4022 public:
4023 BoundArgFunction() : functionObj( CLARA_NULL ) {}
4024 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
4025 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
4026 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
4027 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
4028 delete functionObj;
4029 functionObj = newFunctionObj;
4030 return *this;
4031 }
4032 ~BoundArgFunction() { delete functionObj; }
4033
4034 void set( ConfigT& config, std::string const& value ) const {
4035 functionObj->set( config, value );
4036 }
4037 bool takesArg() const { return functionObj->takesArg(); }
4038
4039 bool isSet() const {
4040 return functionObj != CLARA_NULL;
4041 }
4042 private:
4043 IArgFunction<ConfigT>* functionObj;
4044 };
4045
4046 template<typename C>
4047 struct NullBinder : IArgFunction<C>{
4048 virtual void set( C&, std::string const& ) const {}
4049 virtual bool takesArg() const { return true; }
4050 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4051 };
4052
4053 template<typename C, typename M>
4054 struct BoundDataMember : IArgFunction<C>{
4055 BoundDataMember( M C::* _member ) : member( _member ) {}
4056 virtual void set( C& p, std::string const& stringValue ) const {
4057 convertInto( stringValue, p.*member );
4058 }
4059 virtual bool takesArg() const { return !IsBool<M>::value; }
4060 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4061 M C::* member;
4062 };
4063 template<typename C, typename M>
4064 struct BoundUnaryMethod : IArgFunction<C>{
4065 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
4066 virtual void set( C& p, std::string const& stringValue ) const {
4067 typename RemoveConstRef<M>::type value;
4068 convertInto( stringValue, value );
4069 (p.*member)( value );
4070 }
4071 virtual bool takesArg() const { return !IsBool<M>::value; }
4072 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4073 void (C::*member)( M );
4074 };
4075 template<typename C>
4076 struct BoundNullaryMethod : IArgFunction<C>{
4077 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
4078 virtual void set( C& p, std::string const& stringValue ) const {
4079 bool value;
4080 convertInto( stringValue, value );
4081 if( value )
4082 (p.*member)();
4083 }
4084 virtual bool takesArg() const { return false; }
4085 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4086 void (C::*member)();
4087 };
4088
4089 template<typename C>
4090 struct BoundUnaryFunction : IArgFunction<C>{
4091 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
4092 virtual void set( C& obj, std::string const& stringValue ) const {
4093 bool value;
4094 convertInto( stringValue, value );
4095 if( value )
4096 function( obj );
4097 }
4098 virtual bool takesArg() const { return false; }
4099 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4100 void (*function)( C& );
4101 };
4102
4103 template<typename C, typename T>
4104 struct BoundBinaryFunction : IArgFunction<C>{
4105 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
4106 virtual void set( C& obj, std::string const& stringValue ) const {
4107 typename RemoveConstRef<T>::type value;
4108 convertInto( stringValue, value );
4109 function( obj, value );
4110 }
4111 virtual bool takesArg() const { return !IsBool<T>::value; }
4112 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4113 void (*function)( C&, T );
4114 };
4115
4116 } // namespace Detail
4117
4118 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
4119 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
4120 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4121 args[i] = argv[i];
4122
4123 return args;
4124 }
4125
4126 class Parser {
4127 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4128 Mode mode;
4129 std::size_t from;
4130 bool inQuotes;
4131 public:
4132
4133 struct Token {
4134 enum Type { Positional, ShortOpt, LongOpt };
4135 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4136 Type type;
4137 std::string data;
4138 };
4139
4140 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
4141
4142 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
4143 const std::string doubleDash = "--";
4144 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4145 parseIntoTokens( args[i], tokens);
4146 }
4147
4148 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
4149 for( std::size_t i = 0; i <= arg.size(); ++i ) {
4150 char c = arg[i];
4151 if( c == '"' )
4152 inQuotes = !inQuotes;
4153 mode = handleMode( i, c, arg, tokens );
4154 }
4155 }
4156 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4157 switch( mode ) {
4158 case None: return handleNone( i, c );
4159 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
4160 case ShortOpt:
4161 case LongOpt:
4162 case SlashOpt: return handleOpt( i, c, arg, tokens );
4163 case Positional: return handlePositional( i, c, arg, tokens );
4164 default: throw std::logic_error( "Unknown mode" );
4165 }
4166 }
4167
4168 Mode handleNone( std::size_t i, char c ) {
4169 if( inQuotes ) {
4170 from = i;
4171 return Positional;
4172 }
4173 switch( c ) {
4174 case '-': return MaybeShortOpt;
4175 #ifdef CLARA_PLATFORM_WINDOWS
4176 case '/': from = i+1; return SlashOpt;
4177 #endif
4178 default: from = i; return Positional;
4179 }
4180 }
4181 Mode handleMaybeShortOpt( std::size_t i, char c ) {
4182 switch( c ) {
4183 case '-': from = i+1; return LongOpt;
4184 default: from = i; return ShortOpt;
4185 }
4186 }
4187 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4188 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
4189 return mode;
4190
4191 std::string optName = arg.substr( from, i-from );
4192 if( mode == ShortOpt )
4193 for( std::size_t j = 0; j < optName.size(); ++j )
4194 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
4195 else if( mode == SlashOpt && optName.size() == 1 )
4196 tokens.push_back( Token( Token::ShortOpt, optName ) );
4197 else
4198 tokens.push_back( Token( Token::LongOpt, optName ) );
4199 return None;
4200 }
4201 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4202 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
4203 return mode;
4204
4205 std::string data = arg.substr( from, i-from );
4206 tokens.push_back( Token( Token::Positional, data ) );
4207 return None;
4208 }
4209 };
4210
4211 template<typename ConfigT>
4212 struct CommonArgProperties {
4213 CommonArgProperties() {}
4214 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4215
4216 Detail::BoundArgFunction<ConfigT> boundField;
4217 std::string description;
4218 std::string detail;
4219 std::string placeholder; // Only value if boundField takes an arg
4220
4221 bool takesArg() const {
4222 return !placeholder.empty();
4223 }
4224 void validate() const {
4225 if( !boundField.isSet() )
4226 throw std::logic_error( "option not bound" );
4227 }
4228 };
4229 struct OptionArgProperties {
4230 std::vector<std::string> shortNames;
4231 std::string longName;
4232
4233 bool hasShortName( std::string const& shortName ) const {
4234 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4235 }
4236 bool hasLongName( std::string const& _longName ) const {
4237 return _longName == longName;
4238 }
4239 };
4240 struct PositionalArgProperties {
4241 PositionalArgProperties() : position( -1 ) {}
4242 int position; // -1 means non-positional (floating)
4243
4244 bool isFixedPositional() const {
4245 return position != -1;
4246 }
4247 };
4248
4249 template<typename ConfigT>
4250 class CommandLine {
4251
4252 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4253 Arg() {}
4254 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
4255
4256 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4257
4258 std::string dbgName() const {
4259 if( !longName.empty() )
4260 return "--" + longName;
4261 if( !shortNames.empty() )
4262 return "-" + shortNames[0];
4263 return "positional args";
4264 }
4265 std::string commands() const {
4266 std::ostringstream oss;
4267 bool first = true;
4268 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4269 for(; it != itEnd; ++it ) {
4270 if( first )
4271 first = false;
4272 else
4273 oss << ", ";
4274 oss << "-" << *it;
4275 }
4276 if( !longName.empty() ) {
4277 if( !first )
4278 oss << ", ";
4279 oss << "--" << longName;
4280 }
4281 if( !placeholder.empty() )
4282 oss << " <" << placeholder << ">";
4283 return oss.str();
4284 }
4285 };
4286
4287 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
4288
4289 friend void addOptName( Arg& arg, std::string const& optName )
4290 {
4291 if( optName.empty() )
4292 return;
4293 if( Detail::startsWith( optName, "--" ) ) {
4294 if( !arg.longName.empty() )
4295 throw std::logic_error( "Only one long opt may be specified. '"
4296 + arg.longName
4297 + "' already specified, now attempting to add '"
4298 + optName + "'" );
4299 arg.longName = optName.substr( 2 );
4300 }
4301 else if( Detail::startsWith( optName, "-" ) )
4302 arg.shortNames.push_back( optName.substr( 1 ) );
4303 else
4304 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4305 }
4306 friend void setPositionalArg( Arg& arg, int position )
4307 {
4308 arg.position = position;
4309 }
4310
4311 class ArgBuilder {
4312 public:
4313 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
4314
4315 // Bind a non-boolean data member (requires placeholder string)
4316 template<typename C, typename M>
4317 void bind( M C::* field, std::string const& placeholder ) {
4318 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4319 m_arg->placeholder = placeholder;
4320 }
4321 // Bind a boolean data member (no placeholder required)
4322 template<typename C>
4323 void bind( bool C::* field ) {
4324 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
4325 }
4326
4327 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4328 template<typename C, typename M>
4329 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4330 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4331 m_arg->placeholder = placeholder;
4332 }
4333
4334 // Bind a method taking a single, boolean argument (no placeholder string required)
4335 template<typename C>
4336 void bind( void (C::* unaryMethod)( bool ) ) {
4337 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
4338 }
4339
4340 // Bind a method that takes no arguments (will be called if opt is present)
4341 template<typename C>
4342 void bind( void (C::* nullaryMethod)() ) {
4343 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
4344 }
4345
4346 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4347 template<typename C>
4348 void bind( void (* unaryFunction)( C& ) ) {
4349 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
4350 }
4351
4352 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4353 template<typename C, typename T>
4354 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4355 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4356 m_arg->placeholder = placeholder;
4357 }
4358
4359 ArgBuilder& describe( std::string const& description ) {
4360 m_arg->description = description;
4361 return *this;
4362 }
4363 ArgBuilder& detail( std::string const& detail ) {
4364 m_arg->detail = detail;
4365 return *this;
4366 }
4367
4368 protected:
4369 Arg* m_arg;
4370 };
4371
4372 class OptBuilder : public ArgBuilder {
4373 public:
4374 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
4375 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4376
4377 OptBuilder& operator[]( std::string const& optName ) {
4378 addOptName( *ArgBuilder::m_arg, optName );
4379 return *this;
4380 }
4381 };
4382
4383 public:
4384
4385 CommandLine()
4386 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
4387 m_highestSpecifiedArgPosition( 0 ),
4388 m_throwOnUnrecognisedTokens( false )
4389 {}
4390 CommandLine( CommandLine const& other )
4391 : m_boundProcessName( other.m_boundProcessName ),
4392 m_options ( other.m_options ),
4393 m_positionalArgs( other.m_positionalArgs ),
4394 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4395 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
4396 {
4397 if( other.m_floatingArg.get() )
4398 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
4399 }
4400
4401 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4402 m_throwOnUnrecognisedTokens = shouldThrow;
4403 return *this;
4404 }
4405
4406 OptBuilder operator[]( std::string const& optName ) {
4407 m_options.push_back( Arg() );
4408 addOptName( m_options.back(), optName );
4409 OptBuilder builder( &m_options.back() );
4410 return builder;
4411 }
4412
4413 ArgBuilder operator[]( int position ) {
4414 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4415 if( position > m_highestSpecifiedArgPosition )
4416 m_highestSpecifiedArgPosition = position;
4417 setPositionalArg( m_positionalArgs[position], position );
4418 ArgBuilder builder( &m_positionalArgs[position] );
4419 return builder;
4420 }
4421
4422 // Invoke this with the _ instance
4423 ArgBuilder operator[]( UnpositionalTag ) {
4424 if( m_floatingArg.get() )
4425 throw std::logic_error( "Only one unpositional argument can be added" );
4426 m_floatingArg.reset( new Arg() );
4427 ArgBuilder builder( m_floatingArg.get() );
4428 return builder;
4429 }
4430
4431 template<typename C, typename M>
4432 void bindProcessName( M C::* field ) {
4433 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4434 }
4435 template<typename C, typename M>
4436 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4437 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
4438 }
4439
4440 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
4441 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4442 std::size_t maxWidth = 0;
4443 for( it = itBegin; it != itEnd; ++it )
4444 maxWidth = (std::max)( maxWidth, it->commands().size() );
4445
4446 for( it = itBegin; it != itEnd; ++it ) {
4447 Detail::Text usage( it->commands(), Detail::TextAttributes()
4448 .setWidth( maxWidth+indent )
4449 .setIndent( indent ) );
4450 Detail::Text desc( it->description, Detail::TextAttributes()
4451 .setWidth( width - maxWidth - 3 ) );
4452
4453 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4454 std::string usageCol = i < usage.size() ? usage[i] : "";
4455 os << usageCol;
4456
4457 if( i < desc.size() && !desc[i].empty() )
4458 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4459 << desc[i];
4460 os << "\n";
4461 }
4462 }
4463 }
4464 std::string optUsage() const {
4465 std::ostringstream oss;
4466 optUsage( oss );
4467 return oss.str();
4468 }
4469
4470 void argSynopsis( std::ostream& os ) const {
4471 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4472 if( i > 1 )
4473 os << " ";
4474 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4475 if( it != m_positionalArgs.end() )
4476 os << "<" << it->second.placeholder << ">";
4477 else if( m_floatingArg.get() )
4478 os << "<" << m_floatingArg->placeholder << ">";
4479 else
4480 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4481 }
4482 // !TBD No indication of mandatory args
4483 if( m_floatingArg.get() ) {
4484 if( m_highestSpecifiedArgPosition > 1 )
4485 os << " ";
4486 os << "[<" << m_floatingArg->placeholder << "> ...]";
4487 }
4488 }
4489 std::string argSynopsis() const {
4490 std::ostringstream oss;
4491 argSynopsis( oss );
4492 return oss.str();
4493 }
4494
4495 void usage( std::ostream& os, std::string const& procName ) const {
4496 validate();
4497 os << "usage:\n " << procName << " ";
4498 argSynopsis( os );
4499 if( !m_options.empty() ) {
4500 os << " [options]\n\nwhere options are: \n";
4501 optUsage( os, 2 );
4502 }
4503 os << "\n";
4504 }
4505 std::string usage( std::string const& procName ) const {
4506 std::ostringstream oss;
4507 usage( oss, procName );
4508 return oss.str();
4509 }
4510
4511 ConfigT parse( std::vector<std::string> const& args ) const {
4512 ConfigT config;
4513 parseInto( args, config );
4514 return config;
4515 }
4516
4517 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
4518 std::string processName = args[0];
4519 std::size_t lastSlash = processName.find_last_of( "/\\" );
4520 if( lastSlash != std::string::npos )
4521 processName = processName.substr( lastSlash+1 );
4522 m_boundProcessName.set( config, processName );
4523 std::vector<Parser::Token> tokens;
4524 Parser parser;
4525 parser.parseIntoTokens( args, tokens );
4526 return populate( tokens, config );
4527 }
4528
4529 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4530 validate();
4531 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4532 unusedTokens = populateFixedArgs( unusedTokens, config );
4533 unusedTokens = populateFloatingArgs( unusedTokens, config );
4534 return unusedTokens;
4535 }
4536
4537 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4538 std::vector<Parser::Token> unusedTokens;
4539 std::vector<std::string> errors;
4540 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4541 Parser::Token const& token = tokens[i];
4542 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4543 for(; it != itEnd; ++it ) {
4544 Arg const& arg = *it;
4545
4546 try {
4547 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4548 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4549 if( arg.takesArg() ) {
4550 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4551 errors.push_back( "Expected argument to option: " + token.data );
4552 else
4553 arg.boundField.set( config, tokens[++i].data );
4554 }
4555 else {
4556 arg.boundField.set( config, "true" );
4557 }
4558 break;
4559 }
4560 }
4561 catch( std::exception& ex ) {
4562 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
4563 }
4564 }
4565 if( it == itEnd ) {
4566 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4567 unusedTokens.push_back( token );
4568 else if( errors.empty() && m_throwOnUnrecognisedTokens )
4569 errors.push_back( "unrecognised option: " + token.data );
4570 }
4571 }
4572 if( !errors.empty() ) {
4573 std::ostringstream oss;
4574 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4575 it != itEnd;
4576 ++it ) {
4577 if( it != errors.begin() )
4578 oss << "\n";
4579 oss << *it;
4580 }
4581 throw std::runtime_error( oss.str() );
4582 }
4583 return unusedTokens;
4584 }
4585 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4586 std::vector<Parser::Token> unusedTokens;
4587 int position = 1;
4588 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4589 Parser::Token const& token = tokens[i];
4590 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4591 if( it != m_positionalArgs.end() )
4592 it->second.boundField.set( config, token.data );
4593 else
4594 unusedTokens.push_back( token );
4595 if( token.type == Parser::Token::Positional )
4596 position++;
4597 }
4598 return unusedTokens;
4599 }
4600 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4601 if( !m_floatingArg.get() )
4602 return tokens;
4603 std::vector<Parser::Token> unusedTokens;
4604 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4605 Parser::Token const& token = tokens[i];
4606 if( token.type == Parser::Token::Positional )
4607 m_floatingArg->boundField.set( config, token.data );
4608 else
4609 unusedTokens.push_back( token );
4610 }
4611 return unusedTokens;
4612 }
4613
4614 void validate() const
4615 {
4616 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4617 throw std::logic_error( "No options or arguments specified" );
4618
4619 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
4620 itEnd = m_options.end();
4621 it != itEnd; ++it )
4622 it->validate();
4623 }
4624
4625 private:
4626 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4627 std::vector<Arg> m_options;
4628 std::map<int, Arg> m_positionalArgs;
4629 ArgAutoPtr m_floatingArg;
4630 int m_highestSpecifiedArgPosition;
4631 bool m_throwOnUnrecognisedTokens;
4632 };
4633
4634 } // end namespace Clara
4635
4636 STITCH_CLARA_CLOSE_NAMESPACE
4637 #undef STITCH_CLARA_OPEN_NAMESPACE
4638 #undef STITCH_CLARA_CLOSE_NAMESPACE
4639
4640 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
4641 #undef STITCH_CLARA_OPEN_NAMESPACE
4642
4643 // Restore Clara's value for console width, if present
4644 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4645 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4646 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4647 #endif
4648
4649 #include <fstream>
4650
4651 namespace Catch {
4652
4653 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
4654 inline void abortAfterX( ConfigData& config, int x ) {
4655 if( x < 1 )
4656 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
4657 config.abortAfter = x;
4658 }
4659 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
4660 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
4661
4662 inline void addWarning( ConfigData& config, std::string const& _warning ) {
4663 if( _warning == "NoAssertions" )
4664 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
4665 else
4666 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
4667 }
4668 inline void setOrder( ConfigData& config, std::string const& order ) {
4669 if( startsWith( "declared", order ) )
4670 config.runOrder = RunTests::InDeclarationOrder;
4671 else if( startsWith( "lexical", order ) )
4672 config.runOrder = RunTests::InLexicographicalOrder;
4673 else if( startsWith( "random", order ) )
4674 config.runOrder = RunTests::InRandomOrder;
4675 else
4676 throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
4677 }
4678 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
4679 if( seed == "time" ) {
4680 config.rngSeed = static_cast<unsigned int>( std::time(0) );
4681 }
4682 else {
4683 std::stringstream ss;
4684 ss << seed;
4685 ss >> config.rngSeed;
4686 if( ss.fail() )
4687 throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
4688 }
4689 }
4690 inline void setVerbosity( ConfigData& config, int level ) {
4691 // !TBD: accept strings?
4692 config.verbosity = static_cast<Verbosity::Level>( level );
4693 }
4694 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
4695 config.showDurations = _showDurations
4696 ? ShowDurations::Always
4697 : ShowDurations::Never;
4698 }
4699 inline void setUseColour( ConfigData& config, std::string const& value ) {
4700 std::string mode = toLower( value );
4701
4702 if( mode == "yes" )
4703 config.useColour = UseColour::Yes;
4704 else if( mode == "no" )
4705 config.useColour = UseColour::No;
4706 else if( mode == "auto" )
4707 config.useColour = UseColour::Auto;
4708 else
4709 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
4710 }
4711 inline void forceColour( ConfigData& config ) {
4712 config.useColour = UseColour::Yes;
4713 }
4714 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
4715 std::ifstream f( _filename.c_str() );
4716 if( !f.is_open() )
4717 throw std::domain_error( "Unable to load input file: " + _filename );
4718
4719 std::string line;
4720 while( std::getline( f, line ) ) {
4721 line = trim(line);
4722 if( !line.empty() && !startsWith( line, "#" ) )
4723 addTestOrTags( config, "\"" + line + "\"," );
4724 }
4725 }
4726
4727 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4728
4729 using namespace Clara;
4730 CommandLine<ConfigData> cli;
4731
4732 cli.bindProcessName( &ConfigData::processName );
4733
4734 cli["-?"]["-h"]["--help"]
4735 .describe( "display usage information" )
4736 .bind( &ConfigData::showHelp );
4737
4738 cli["-l"]["--list-tests"]
4739 .describe( "list all/matching test cases" )
4740 .bind( &ConfigData::listTests );
4741
4742 cli["-t"]["--list-tags"]
4743 .describe( "list all/matching tags" )
4744 .bind( &ConfigData::listTags );
4745
4746 cli["-s"]["--success"]
4747 .describe( "include successful tests in output" )
4748 .bind( &ConfigData::showSuccessfulTests );
4749
4750 cli["-b"]["--break"]
4751 .describe( "break into debugger on failure" )
4752 .bind( &ConfigData::shouldDebugBreak );
4753
4754 cli["-e"]["--nothrow"]
4755 .describe( "skip exception tests" )
4756 .bind( &ConfigData::noThrow );
4757
4758 cli["-i"]["--invisibles"]
4759 .describe( "show invisibles (tabs, newlines)" )
4760 .bind( &ConfigData::showInvisibles );
4761
4762 cli["-o"]["--out"]
4763 .describe( "output filename" )
4764 .bind( &ConfigData::outputFilename, "filename" );
4765
4766 cli["-r"]["--reporter"]
4767 // .placeholder( "name[:filename]" )
4768 .describe( "reporter to use (defaults to console)" )
4769 .bind( &addReporterName, "name" );
4770
4771 cli["-n"]["--name"]
4772 .describe( "suite name" )
4773 .bind( &ConfigData::name, "name" );
4774
4775 cli["-a"]["--abort"]
4776 .describe( "abort at first failure" )
4777 .bind( &abortAfterFirst );
4778
4779 cli["-x"]["--abortx"]
4780 .describe( "abort after x failures" )
4781 .bind( &abortAfterX, "no. failures" );
4782
4783 cli["-w"]["--warn"]
4784 .describe( "enable warnings" )
4785 .bind( &addWarning, "warning name" );
4786
4787 // - needs updating if reinstated
4788 // cli.into( &setVerbosity )
4789 // .describe( "level of verbosity (0=no output)" )
4790 // .shortOpt( "v")
4791 // .longOpt( "verbosity" )
4792 // .placeholder( "level" );
4793
4794 cli[_]
4795 .describe( "which test or tests to use" )
4796 .bind( &addTestOrTags, "test name, pattern or tags" );
4797
4798 cli["-d"]["--durations"]
4799 .describe( "show test durations" )
4800 .bind( &setShowDurations, "yes|no" );
4801
4802 cli["-f"]["--input-file"]
4803 .describe( "load test names to run from a file" )
4804 .bind( &loadTestNamesFromFile, "filename" );
4805
4806 cli["-#"]["--filenames-as-tags"]
4807 .describe( "adds a tag for the filename" )
4808 .bind( &ConfigData::filenamesAsTags );
4809
4810 // Less common commands which don't have a short form
4811 cli["--list-test-names-only"]
4812 .describe( "list all/matching test cases names only" )
4813 .bind( &ConfigData::listTestNamesOnly );
4814
4815 cli["--list-reporters"]
4816 .describe( "list all reporters" )
4817 .bind( &ConfigData::listReporters );
4818
4819 cli["--order"]
4820 .describe( "test case order (defaults to decl)" )
4821 .bind( &setOrder, "decl|lex|rand" );
4822
4823 cli["--rng-seed"]
4824 .describe( "set a specific seed for random numbers" )
4825 .bind( &setRngSeed, "'time'|number" );
4826
4827 cli["--force-colour"]
4828 .describe( "force colourised output (deprecated)" )
4829 .bind( &forceColour );
4830
4831 cli["--use-colour"]
4832 .describe( "should output be colourised" )
4833 .bind( &setUseColour, "yes|no" );
4834
4835 return cli;
4836 }
4837
4838 } // end namespace Catch
4839
4840 // #included from: internal/catch_list.hpp
4841 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4842
4843 // #included from: catch_text.h
4844 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4845
4846 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4847
4848 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4849 // #included from: ../external/tbc_text_format.h
4850 // Only use header guard if we are not using an outer namespace
4851 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4852 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4853 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4854 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4855 # endif
4856 # else
4857 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4858 # endif
4859 #endif
4860 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4861 #include <string>
4862 #include <vector>
4863 #include <sstream>
4864
4865 // Use optional outer namespace
4866 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4867 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4868 #endif
4869
4870 namespace Tbc {
4871
4872 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4873 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4874 #else
4875 const unsigned int consoleWidth = 80;
4876 #endif
4877
4878 struct TextAttributes {
4879 TextAttributes()
4880 : initialIndent( std::string::npos ),
4881 indent( 0 ),
4882 width( consoleWidth-1 ),
4883 tabChar( '\t' )
4884 {}
4885
4886 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
4887 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
4888 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
4889 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4890
4891 std::size_t initialIndent; // indent of first line, or npos
4892 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4893 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4894 char tabChar; // If this char is seen the indent is changed to current pos
4895 };
4896
4897 class Text {
4898 public:
4899 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4900 : attr( _attr )
4901 {
4902 std::string wrappableChars = " [({.,/|\\-";
4903 std::size_t indent = _attr.initialIndent != std::string::npos
4904 ? _attr.initialIndent
4905 : _attr.indent;
4906 std::string remainder = _str;
4907
4908 while( !remainder.empty() ) {
4909 if( lines.size() >= 1000 ) {
4910 lines.push_back( "... message truncated due to excessive size" );
4911 return;
4912 }
4913 std::size_t tabPos = std::string::npos;
4914 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4915 std::size_t pos = remainder.find_first_of( '\n' );
4916 if( pos <= width ) {
4917 width = pos;
4918 }
4919 pos = remainder.find_last_of( _attr.tabChar, width );
4920 if( pos != std::string::npos ) {
4921 tabPos = pos;
4922 if( remainder[width] == '\n' )
4923 width--;
4924 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4925 }
4926
4927 if( width == remainder.size() ) {
4928 spliceLine( indent, remainder, width );
4929 }
4930 else if( remainder[width] == '\n' ) {
4931 spliceLine( indent, remainder, width );
4932 if( width <= 1 || remainder.size() != 1 )
4933 remainder = remainder.substr( 1 );
4934 indent = _attr.indent;
4935 }
4936 else {
4937 pos = remainder.find_last_of( wrappableChars, width );
4938 if( pos != std::string::npos && pos > 0 ) {
4939 spliceLine( indent, remainder, pos );
4940 if( remainder[0] == ' ' )
4941 remainder = remainder.substr( 1 );
4942 }
4943 else {
4944 spliceLine( indent, remainder, width-1 );
4945 lines.back() += "-";
4946 }
4947 if( lines.size() == 1 )
4948 indent = _attr.indent;
4949 if( tabPos != std::string::npos )
4950 indent += tabPos;
4951 }
4952 }
4953 }
4954
4955 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4956 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4957 _remainder = _remainder.substr( _pos );
4958 }
4959
4960 typedef std::vector<std::string>::const_iterator const_iterator;
4961
4962 const_iterator begin() const { return lines.begin(); }
4963 const_iterator end() const { return lines.end(); }
4964 std::string const& last() const { return lines.back(); }
4965 std::size_t size() const { return lines.size(); }
4966 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
4967 std::string toString() const {
4968 std::ostringstream oss;
4969 oss << *this;
4970 return oss.str();
4971 }
4972
4973 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4974 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4975 it != itEnd; ++it ) {
4976 if( it != _text.begin() )
4977 _stream << "\n";
4978 _stream << *it;
4979 }
4980 return _stream;
4981 }
4982
4983 private:
4984 std::string str;
4985 TextAttributes attr;
4986 std::vector<std::string> lines;
4987 };
4988
4989 } // end namespace Tbc
4990
4991 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4992 } // end outer namespace
4993 #endif
4994
4995 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4996 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4997
4998 namespace Catch {
4999 using Tbc::Text;
5000 using Tbc::TextAttributes;
5001 }
5002
5003 // #included from: catch_console_colour.hpp
5004 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
5005
5006 namespace Catch {
5007
5008 struct Colour {
5009 enum Code {
5010 None = 0,
5011
5012 White,
5013 Red,
5014 Green,
5015 Blue,
5016 Cyan,
5017 Yellow,
5018 Grey,
5019
5020 Bright = 0x10,
5021
5022 BrightRed = Bright | Red,
5023 BrightGreen = Bright | Green,
5024 LightGrey = Bright | Grey,
5025 BrightWhite = Bright | White,
5026
5027 // By intention
5028 FileName = LightGrey,
5029 Warning = Yellow,
5030 ResultError = BrightRed,
5031 ResultSuccess = BrightGreen,
5032 ResultExpectedFailure = Warning,
5033
5034 Error = BrightRed,
5035 Success = Green,
5036
5037 OriginalExpression = Cyan,
5038 ReconstructedExpression = Yellow,
5039
5040 SecondaryText = LightGrey,
5041 Headers = White
5042 };
5043
5044 // Use constructed object for RAII guard
5045 Colour( Code _colourCode );
5046 Colour( Colour const& other );
5047 ~Colour();
5048
5049 // Use static method for one-shot changes
5050 static void use( Code _colourCode );
5051
5052 private:
5053 bool m_moved;
5054 };
5055
5056 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5057
5058 } // end namespace Catch
5059
5060 // #included from: catch_interfaces_reporter.h
5061 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5062
5063 #include <string>
5064 #include <ostream>
5065 #include <map>
5066 #include <assert.h>
5067
5068 namespace Catch
5069 {
5070 struct ReporterConfig {
5071 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
5072 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5073
5074 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
5075 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5076
5077 std::ostream& stream() const { return *m_stream; }
5078 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
5079
5080 private:
5081 std::ostream* m_stream;
5082 Ptr<IConfig const> m_fullConfig;
5083 };
5084
5085 struct ReporterPreferences {
5086 ReporterPreferences()
5087 : shouldRedirectStdOut( false )
5088 {}
5089
5090 bool shouldRedirectStdOut;
5091 };
5092
5093 template<typename T>
5094 struct LazyStat : Option<T> {
5095 LazyStat() : used( false ) {}
5096 LazyStat& operator=( T const& _value ) {
5097 Option<T>::operator=( _value );
5098 used = false;
5099 return *this;
5100 }
5101 void reset() {
5102 Option<T>::reset();
5103 used = false;
5104 }
5105 bool used;
5106 };
5107
5108 struct TestRunInfo {
5109 TestRunInfo( std::string const& _name ) : name( _name ) {}
2588 std::string name; 5110 std::string name;
2589 }; 5111 };
5112 struct GroupInfo {
5113 GroupInfo( std::string const& _name,
5114 std::size_t _groupIndex,
5115 std::size_t _groupsCount )
5116 : name( _name ),
5117 groupIndex( _groupIndex ),
5118 groupsCounts( _groupsCount )
5119 {}
5120
5121 std::string name;
5122 std::size_t groupIndex;
5123 std::size_t groupsCounts;
5124 };
5125
5126 struct AssertionStats {
5127 AssertionStats( AssertionResult const& _assertionResult,
5128 std::vector<MessageInfo> const& _infoMessages,
5129 Totals const& _totals )
5130 : assertionResult( _assertionResult ),
5131 infoMessages( _infoMessages ),
5132 totals( _totals )
5133 {
5134 if( assertionResult.hasMessage() ) {
5135 // Copy message into messages list.
5136 // !TBD This should have been done earlier, somewhere
5137 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5138 builder << assertionResult.getMessage();
5139 builder.m_info.message = builder.m_stream.str();
5140
5141 infoMessages.push_back( builder.m_info );
5142 }
5143 }
5144 virtual ~AssertionStats();
5145
5146 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5147 AssertionStats( AssertionStats const& ) = default;
5148 AssertionStats( AssertionStats && ) = default;
5149 AssertionStats& operator = ( AssertionStats const& ) = default;
5150 AssertionStats& operator = ( AssertionStats && ) = default;
5151 # endif
5152
5153 AssertionResult assertionResult;
5154 std::vector<MessageInfo> infoMessages;
5155 Totals totals;
5156 };
5157
5158 struct SectionStats {
5159 SectionStats( SectionInfo const& _sectionInfo,
5160 Counts const& _assertions,
5161 double _durationInSeconds,
5162 bool _missingAssertions )
5163 : sectionInfo( _sectionInfo ),
5164 assertions( _assertions ),
5165 durationInSeconds( _durationInSeconds ),
5166 missingAssertions( _missingAssertions )
5167 {}
5168 virtual ~SectionStats();
5169 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5170 SectionStats( SectionStats const& ) = default;
5171 SectionStats( SectionStats && ) = default;
5172 SectionStats& operator = ( SectionStats const& ) = default;
5173 SectionStats& operator = ( SectionStats && ) = default;
5174 # endif
5175
5176 SectionInfo sectionInfo;
5177 Counts assertions;
5178 double durationInSeconds;
5179 bool missingAssertions;
5180 };
5181
5182 struct TestCaseStats {
5183 TestCaseStats( TestCaseInfo const& _testInfo,
5184 Totals const& _totals,
5185 std::string const& _stdOut,
5186 std::string const& _stdErr,
5187 bool _aborting )
5188 : testInfo( _testInfo ),
5189 totals( _totals ),
5190 stdOut( _stdOut ),
5191 stdErr( _stdErr ),
5192 aborting( _aborting )
5193 {}
5194 virtual ~TestCaseStats();
5195
5196 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5197 TestCaseStats( TestCaseStats const& ) = default;
5198 TestCaseStats( TestCaseStats && ) = default;
5199 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5200 TestCaseStats& operator = ( TestCaseStats && ) = default;
5201 # endif
5202
5203 TestCaseInfo testInfo;
5204 Totals totals;
5205 std::string stdOut;
5206 std::string stdErr;
5207 bool aborting;
5208 };
5209
5210 struct TestGroupStats {
5211 TestGroupStats( GroupInfo const& _groupInfo,
5212 Totals const& _totals,
5213 bool _aborting )
5214 : groupInfo( _groupInfo ),
5215 totals( _totals ),
5216 aborting( _aborting )
5217 {}
5218 TestGroupStats( GroupInfo const& _groupInfo )
5219 : groupInfo( _groupInfo ),
5220 aborting( false )
5221 {}
5222 virtual ~TestGroupStats();
5223
5224 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5225 TestGroupStats( TestGroupStats const& ) = default;
5226 TestGroupStats( TestGroupStats && ) = default;
5227 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5228 TestGroupStats& operator = ( TestGroupStats && ) = default;
5229 # endif
5230
5231 GroupInfo groupInfo;
5232 Totals totals;
5233 bool aborting;
5234 };
5235
5236 struct TestRunStats {
5237 TestRunStats( TestRunInfo const& _runInfo,
5238 Totals const& _totals,
5239 bool _aborting )
5240 : runInfo( _runInfo ),
5241 totals( _totals ),
5242 aborting( _aborting )
5243 {}
5244 virtual ~TestRunStats();
5245
5246 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
5247 TestRunStats( TestRunStats const& _other )
5248 : runInfo( _other.runInfo ),
5249 totals( _other.totals ),
5250 aborting( _other.aborting )
5251 {}
5252 # else
5253 TestRunStats( TestRunStats const& ) = default;
5254 TestRunStats( TestRunStats && ) = default;
5255 TestRunStats& operator = ( TestRunStats const& ) = default;
5256 TestRunStats& operator = ( TestRunStats && ) = default;
5257 # endif
5258
5259 TestRunInfo runInfo;
5260 Totals totals;
5261 bool aborting;
5262 };
5263
5264 class MultipleReporters;
5265
5266 struct IStreamingReporter : IShared {
5267 virtual ~IStreamingReporter();
5268
5269 // Implementing class must also provide the following static method:
5270 // static std::string getDescription();
5271
5272 virtual ReporterPreferences getPreferences() const = 0;
5273
5274 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5275
5276 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5277 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5278
5279 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5280 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5281
5282 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5283
5284 // The return value indicates if the messages buffer should be cleared:
5285 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
5286
5287 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5288 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5289 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5290 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
5291
5292 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
5293
5294 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
5295 };
5296
5297 struct IReporterFactory : IShared {
5298 virtual ~IReporterFactory();
5299 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5300 virtual std::string getDescription() const = 0;
5301 };
5302
5303 struct IReporterRegistry {
5304 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5305 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5306
5307 virtual ~IReporterRegistry();
5308 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
5309 virtual FactoryMap const& getFactories() const = 0;
5310 virtual Listeners const& getListeners() const = 0;
5311 };
5312
5313 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5314
5315 }
5316
5317 #include <limits>
5318 #include <algorithm>
5319
5320 namespace Catch {
5321
5322 inline std::size_t listTests( Config const& config ) {
5323
5324 TestSpec testSpec = config.testSpec();
5325 if( config.testSpec().hasFilters() )
5326 Catch::cout() << "Matching test cases:\n";
5327 else {
5328 Catch::cout() << "All available test cases:\n";
5329 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5330 }
5331
5332 std::size_t matchedTests = 0;
5333 TextAttributes nameAttr, tagsAttr;
5334 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5335 tagsAttr.setIndent( 6 );
5336
5337 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5338 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5339 it != itEnd;
5340 ++it ) {
5341 matchedTests++;
5342 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5343 Colour::Code colour = testCaseInfo.isHidden()
5344 ? Colour::SecondaryText
5345 : Colour::None;
5346 Colour colourGuard( colour );
5347
5348 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
5349 if( !testCaseInfo.tags.empty() )
5350 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
5351 }
5352
5353 if( !config.testSpec().hasFilters() )
5354 Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
5355 else
5356 Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
5357 return matchedTests;
5358 }
5359
5360 inline std::size_t listTestsNamesOnly( Config const& config ) {
5361 TestSpec testSpec = config.testSpec();
5362 if( !config.testSpec().hasFilters() )
5363 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5364 std::size_t matchedTests = 0;
5365 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5366 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5367 it != itEnd;
5368 ++it ) {
5369 matchedTests++;
5370 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5371 Catch::cout() << testCaseInfo.name << std::endl;
5372 }
5373 return matchedTests;
5374 }
5375
5376 struct TagInfo {
5377 TagInfo() : count ( 0 ) {}
5378 void add( std::string const& spelling ) {
5379 ++count;
5380 spellings.insert( spelling );
5381 }
5382 std::string all() const {
5383 std::string out;
5384 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5385 it != itEnd;
5386 ++it )
5387 out += "[" + *it + "]";
5388 return out;
5389 }
5390 std::set<std::string> spellings;
5391 std::size_t count;
5392 };
5393
5394 inline std::size_t listTags( Config const& config ) {
5395 TestSpec testSpec = config.testSpec();
5396 if( config.testSpec().hasFilters() )
5397 Catch::cout() << "Tags for matching test cases:\n";
5398 else {
5399 Catch::cout() << "All available tags:\n";
5400 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5401 }
5402
5403 std::map<std::string, TagInfo> tagCounts;
5404
5405 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5406 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5407 it != itEnd;
5408 ++it ) {
5409 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5410 tagItEnd = it->getTestCaseInfo().tags.end();
5411 tagIt != tagItEnd;
5412 ++tagIt ) {
5413 std::string tagName = *tagIt;
5414 std::string lcaseTagName = toLower( tagName );
5415 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
5416 if( countIt == tagCounts.end() )
5417 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5418 countIt->second.add( tagName );
5419 }
5420 }
5421
5422 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5423 countItEnd = tagCounts.end();
5424 countIt != countItEnd;
5425 ++countIt ) {
5426 std::ostringstream oss;
5427 oss << " " << std::setw(2) << countIt->second.count << " ";
5428 Text wrapper( countIt->second.all(), TextAttributes()
5429 .setInitialIndent( 0 )
5430 .setIndent( oss.str().size() )
5431 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
5432 Catch::cout() << oss.str() << wrapper << "\n";
5433 }
5434 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
5435 return tagCounts.size();
5436 }
5437
5438 inline std::size_t listReporters( Config const& /*config*/ ) {
5439 Catch::cout() << "Available reporters:\n";
5440 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
5441 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5442 std::size_t maxNameLen = 0;
5443 for(it = itBegin; it != itEnd; ++it )
5444 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5445
5446 for(it = itBegin; it != itEnd; ++it ) {
5447 Text wrapper( it->second->getDescription(), TextAttributes()
5448 .setInitialIndent( 0 )
5449 .setIndent( 7+maxNameLen )
5450 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
5451 Catch::cout() << " "
5452 << it->first
5453 << ":"
5454 << std::string( maxNameLen - it->first.size() + 2, ' ' )
5455 << wrapper << "\n";
5456 }
5457 Catch::cout() << std::endl;
5458 return factories.size();
5459 }
5460
5461 inline Option<std::size_t> list( Config const& config ) {
5462 Option<std::size_t> listedCount;
5463 if( config.listTests() )
5464 listedCount = listedCount.valueOr(0) + listTests( config );
5465 if( config.listTestNamesOnly() )
5466 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
5467 if( config.listTags() )
5468 listedCount = listedCount.valueOr(0) + listTags( config );
5469 if( config.listReporters() )
5470 listedCount = listedCount.valueOr(0) + listReporters( config );
5471 return listedCount;
5472 }
2590 5473
2591 } // end namespace Catch 5474 } // end namespace Catch
2592 5475
2593 // #included from: catch_running_test.hpp 5476 // #included from: internal/catch_run_context.hpp
2594 5477 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
2595 // #included from: catch_section_info.hpp 5478
5479 // #included from: catch_test_case_tracker.hpp
5480 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
2596 5481
2597 #include <map> 5482 #include <map>
2598 #include <string> 5483 #include <string>
5484 #include <assert.h>
5485 #include <vector>
2599 5486
2600 namespace Catch { 5487 namespace Catch {
2601 5488 namespace TestCaseTracking {
2602 class SectionInfo { 5489
5490 struct ITracker : SharedImpl<> {
5491 virtual ~ITracker();
5492
5493 // static queries
5494 virtual std::string name() const = 0;
5495
5496 // dynamic queries
5497 virtual bool isComplete() const = 0; // Successfully completed or failed
5498 virtual bool isSuccessfullyCompleted() const = 0;
5499 virtual bool isOpen() const = 0; // Started but not complete
5500 virtual bool hasChildren() const = 0;
5501
5502 virtual ITracker& parent() = 0;
5503
5504 // actions
5505 virtual void close() = 0; // Successfully complete
5506 virtual void fail() = 0;
5507 virtual void markAsNeedingAnotherRun() = 0;
5508
5509 virtual void addChild( Ptr<ITracker> const& child ) = 0;
5510 virtual ITracker* findChild( std::string const& name ) = 0;
5511 virtual void openChild() = 0;
5512
5513 // Debug/ checking
5514 virtual bool isSectionTracker() const = 0;
5515 virtual bool isIndexTracker() const = 0;
5516 };
5517
5518 class TrackerContext {
5519
5520 enum RunState {
5521 NotStarted,
5522 Executing,
5523 CompletedCycle
5524 };
5525
5526 Ptr<ITracker> m_rootTracker;
5527 ITracker* m_currentTracker;
5528 RunState m_runState;
5529
2603 public: 5530 public:
2604 5531
2605 enum Status { 5532 static TrackerContext& instance() {
2606 Root, 5533 static TrackerContext s_instance;
2607 Unknown, 5534 return s_instance;
2608 Branch, 5535 }
2609 TestedBranch, 5536
2610 TestedLeaf 5537 TrackerContext()
5538 : m_currentTracker( CATCH_NULL ),
5539 m_runState( NotStarted )
5540 {}
5541
5542 ITracker& startRun();
5543
5544 void endRun() {
5545 m_rootTracker.reset();
5546 m_currentTracker = CATCH_NULL;
5547 m_runState = NotStarted;
5548 }
5549
5550 void startCycle() {
5551 m_currentTracker = m_rootTracker.get();
5552 m_runState = Executing;
5553 }
5554 void completeCycle() {
5555 m_runState = CompletedCycle;
5556 }
5557
5558 bool completedCycle() const {
5559 return m_runState == CompletedCycle;
5560 }
5561 ITracker& currentTracker() {
5562 return *m_currentTracker;
5563 }
5564 void setCurrentTracker( ITracker* tracker ) {
5565 m_currentTracker = tracker;
5566 }
5567 };
5568
5569 class TrackerBase : public ITracker {
5570 protected:
5571 enum CycleState {
5572 NotStarted,
5573 Executing,
5574 ExecutingChildren,
5575 NeedsAnotherRun,
5576 CompletedSuccessfully,
5577 Failed
2611 }; 5578 };
2612 5579 class TrackerHasName {
2613 SectionInfo( SectionInfo* parent ) 5580 std::string m_name;
2614 : m_status( Unknown ), 5581 public:
2615 m_parent( parent ) 5582 TrackerHasName( std::string const& name ) : m_name( name ) {}
5583 bool operator ()( Ptr<ITracker> const& tracker ) {
5584 return tracker->name() == m_name;
5585 }
5586 };
5587 typedef std::vector<Ptr<ITracker> > Children;
5588 std::string m_name;
5589 TrackerContext& m_ctx;
5590 ITracker* m_parent;
5591 Children m_children;
5592 CycleState m_runState;
5593 public:
5594 TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent )
5595 : m_name( name ),
5596 m_ctx( ctx ),
5597 m_parent( parent ),
5598 m_runState( NotStarted )
2616 {} 5599 {}
2617 5600 virtual ~TrackerBase();
2618 SectionInfo() 5601
2619 : m_status( Root ), 5602 virtual std::string name() const CATCH_OVERRIDE {
2620 m_parent( NULL ) 5603 return m_name;
5604 }
5605 virtual bool isComplete() const CATCH_OVERRIDE {
5606 return m_runState == CompletedSuccessfully || m_runState == Failed;
5607 }
5608 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
5609 return m_runState == CompletedSuccessfully;
5610 }
5611 virtual bool isOpen() const CATCH_OVERRIDE {
5612 return m_runState != NotStarted && !isComplete();
5613 }
5614 virtual bool hasChildren() const CATCH_OVERRIDE {
5615 return !m_children.empty();
5616 }
5617
5618 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
5619 m_children.push_back( child );
5620 }
5621
5622 virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE {
5623 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) );
5624 return( it != m_children.end() )
5625 ? it->get()
5626 : CATCH_NULL;
5627 }
5628 virtual ITracker& parent() CATCH_OVERRIDE {
5629 assert( m_parent ); // Should always be non-null except for root
5630 return *m_parent;
5631 }
5632
5633 virtual void openChild() CATCH_OVERRIDE {
5634 if( m_runState != ExecutingChildren ) {
5635 m_runState = ExecutingChildren;
5636 if( m_parent )
5637 m_parent->openChild();
5638 }
5639 }
5640
5641 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
5642 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
5643
5644 void open() {
5645 m_runState = Executing;
5646 moveToThis();
5647 if( m_parent )
5648 m_parent->openChild();
5649 }
5650
5651 virtual void close() CATCH_OVERRIDE {
5652
5653 // Close any still open children (e.g. generators)
5654 while( &m_ctx.currentTracker() != this )
5655 m_ctx.currentTracker().close();
5656
5657 switch( m_runState ) {
5658 case NotStarted:
5659 case CompletedSuccessfully:
5660 case Failed:
5661 throw std::logic_error( "Illogical state" );
5662
5663 case NeedsAnotherRun:
5664 break;;
5665
5666 case Executing:
5667 m_runState = CompletedSuccessfully;
5668 break;
5669 case ExecutingChildren:
5670 if( m_children.empty() || m_children.back()->isComplete() )
5671 m_runState = CompletedSuccessfully;
5672 break;
5673
5674 default:
5675 throw std::logic_error( "Unexpected state" );
5676 }
5677 moveToParent();
5678 m_ctx.completeCycle();
5679 }
5680 virtual void fail() CATCH_OVERRIDE {
5681 m_runState = Failed;
5682 if( m_parent )
5683 m_parent->markAsNeedingAnotherRun();
5684 moveToParent();
5685 m_ctx.completeCycle();
5686 }
5687 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
5688 m_runState = NeedsAnotherRun;
5689 }
5690 private:
5691 void moveToParent() {
5692 assert( m_parent );
5693 m_ctx.setCurrentTracker( m_parent );
5694 }
5695 void moveToThis() {
5696 m_ctx.setCurrentTracker( this );
5697 }
5698 };
5699
5700 class SectionTracker : public TrackerBase {
5701 public:
5702 SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent )
5703 : TrackerBase( name, ctx, parent )
2621 {} 5704 {}
2622 5705 virtual ~SectionTracker();
2623 ~SectionInfo() { 5706
2624 deleteAllValues( m_subSections ); 5707 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
2625 } 5708
2626 5709 static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
2627 bool shouldRun() const { 5710 SectionTracker* section = CATCH_NULL;
2628 return m_status < TestedBranch; 5711
2629 } 5712 ITracker& currentTracker = ctx.currentTracker();
2630 5713 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
2631 bool ran() { 5714 assert( childTracker );
2632 if( m_status < Branch ) { 5715 assert( childTracker->isSectionTracker() );
2633 m_status = TestedLeaf; 5716 section = static_cast<SectionTracker*>( childTracker );
2634 return true; 5717 }
2635 } 5718 else {
2636 return false; 5719 section = new SectionTracker( name, ctx, &currentTracker );
2637 } 5720 currentTracker.addChild( section );
2638 5721 }
2639 void ranToCompletion() { 5722 if( !ctx.completedCycle() && !section->isComplete() ) {
2640 if( m_status == Branch && !hasUntestedSections() ) 5723
2641 m_status = TestedBranch; 5724 section->open();
2642 } 5725 }
2643 5726 return *section;
2644 SectionInfo* findSubSection( const std::string& name ) { 5727 }
2645 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name ); 5728 };
2646 return it != m_subSections.end() 5729
2647 ? it->second 5730 class IndexTracker : public TrackerBase {
2648 : NULL; 5731 int m_size;
2649 } 5732 int m_index;
2650 5733 public:
2651 SectionInfo* addSubSection( const std::string& name ) { 5734 IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size )
2652 SectionInfo* subSection = new SectionInfo( this ); 5735 : TrackerBase( name, ctx, parent ),
2653 m_subSections.insert( std::make_pair( name, subSection ) ); 5736 m_size( size ),
2654 m_status = Branch; 5737 m_index( -1 )
2655 return subSection; 5738 {}
2656 } 5739 virtual ~IndexTracker();
2657 5740
2658 SectionInfo* getParent() { 5741 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
2659 return m_parent; 5742
2660 } 5743 static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
2661 5744 IndexTracker* tracker = CATCH_NULL;
2662 bool hasUntestedSections() const { 5745
2663 if( m_status == Unknown ) 5746 ITracker& currentTracker = ctx.currentTracker();
2664 return true; 5747 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
2665 5748 assert( childTracker );
2666 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin(); 5749 assert( childTracker->isIndexTracker() );
2667 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end(); 5750 tracker = static_cast<IndexTracker*>( childTracker );
2668 for(; it != itEnd; ++it ) { 5751 }
2669 if( it->second->hasUntestedSections() ) 5752 else {
2670 return true; 5753 tracker = new IndexTracker( name, ctx, &currentTracker, size );
2671 } 5754 currentTracker.addChild( tracker );
2672 return false; 5755 }
2673 } 5756
2674 5757 if( !ctx.completedCycle() && !tracker->isComplete() ) {
2675 private: 5758 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
2676 Status m_status; 5759 tracker->moveNext();
2677 std::map<std::string, SectionInfo*> m_subSections; 5760 tracker->open();
2678 SectionInfo* m_parent; 5761 }
2679 }; 5762
2680 } 5763 return *tracker;
5764 }
5765
5766 int index() const { return m_index; }
5767
5768 void moveNext() {
5769 m_index++;
5770 m_children.clear();
5771 }
5772
5773 virtual void close() CATCH_OVERRIDE {
5774 TrackerBase::close();
5775 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
5776 m_runState = Executing;
5777 }
5778 };
5779
5780 inline ITracker& TrackerContext::startRun() {
5781 m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL );
5782 m_currentTracker = CATCH_NULL;
5783 m_runState = Executing;
5784 return *m_rootTracker;
5785 }
5786
5787 } // namespace TestCaseTracking
5788
5789 using TestCaseTracking::ITracker;
5790 using TestCaseTracking::TrackerContext;
5791 using TestCaseTracking::SectionTracker;
5792 using TestCaseTracking::IndexTracker;
5793
5794 } // namespace Catch
5795
5796 // #included from: catch_fatal_condition.hpp
5797 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
2681 5798
2682 namespace Catch { 5799 namespace Catch {
2683 5800
2684 class RunningTest { 5801 // Report the error condition then exit the process
2685 5802 inline void fatal( std::string const& message, int exitCode ) {
2686 enum RunStatus { 5803 IContext& context = Catch::getCurrentContext();
2687 NothingRun, 5804 IResultCapture* resultCapture = context.getResultCapture();
2688 EncounteredASection, 5805 resultCapture->handleFatalErrorCondition( message );
2689 RanAtLeastOneSection, 5806
2690 RanToCompletionWithSections, 5807 if( Catch::alwaysTrue() ) // avoids "no return" warnings
2691 RanToCompletionWithNoSections 5808 exit( exitCode );
5809 }
5810
5811 } // namespace Catch
5812
5813 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
5814
5815 namespace Catch {
5816
5817 struct FatalConditionHandler {
5818 void reset() {}
5819 };
5820
5821 } // namespace Catch
5822
5823 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
5824
5825 #include <signal.h>
5826
5827 namespace Catch {
5828
5829 struct SignalDefs { int id; const char* name; };
5830 extern SignalDefs signalDefs[];
5831 SignalDefs signalDefs[] = {
5832 { SIGINT, "SIGINT - Terminal interrupt signal" },
5833 { SIGILL, "SIGILL - Illegal instruction signal" },
5834 { SIGFPE, "SIGFPE - Floating point error signal" },
5835 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
5836 { SIGTERM, "SIGTERM - Termination request signal" },
5837 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
2692 }; 5838 };
2693 5839
2694 public: 5840 struct FatalConditionHandler {
2695 explicit RunningTest( const TestCaseInfo* info = NULL ) 5841
2696 : m_info( info ), 5842 static void handleSignal( int sig ) {
2697 m_runStatus( RanAtLeastOneSection ), 5843 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
2698 m_currentSection( &m_rootSection ), 5844 if( sig == signalDefs[i].id )
2699 m_changed( false ) 5845 fatal( signalDefs[i].name, -sig );
2700 {} 5846 fatal( "<unknown signal>", -sig );
2701 5847 }
2702 bool wasSectionSeen() const { 5848
2703 return m_runStatus == RanAtLeastOneSection || 5849 FatalConditionHandler() : m_isSet( true ) {
2704 m_runStatus == RanToCompletionWithSections; 5850 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
2705 } 5851 signal( signalDefs[i].id, handleSignal );
2706 5852 }
5853 ~FatalConditionHandler() {
5854 reset();
5855 }
2707 void reset() { 5856 void reset() {
2708 m_runStatus = NothingRun; 5857 if( m_isSet ) {
2709 m_changed = false; 5858 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
2710 m_lastSectionToRun = NULL; 5859 signal( signalDefs[i].id, SIG_DFL );
2711 } 5860 m_isSet = false;
2712 5861 }
2713 void ranToCompletion() { 5862 }
2714 if( m_runStatus == RanAtLeastOneSection || 5863
2715 m_runStatus == EncounteredASection ) { 5864 bool m_isSet;
2716 m_runStatus = RanToCompletionWithSections; 5865 };
2717 if( m_lastSectionToRun ) { 5866
2718 m_lastSectionToRun->ranToCompletion(); 5867 } // namespace Catch
2719 m_changed = true; 5868
2720 } 5869 #endif // not Windows
2721 }
2722 else {
2723 m_runStatus = RanToCompletionWithNoSections;
2724 }
2725 }
2726
2727 bool addSection( const std::string& name ) {
2728 if( m_runStatus == NothingRun )
2729 m_runStatus = EncounteredASection;
2730
2731 SectionInfo* thisSection = m_currentSection->findSubSection( name );
2732 if( !thisSection ) {
2733 thisSection = m_currentSection->addSubSection( name );
2734 m_changed = true;
2735 }
2736
2737 if( !wasSectionSeen() && thisSection->shouldRun() ) {
2738 m_currentSection = thisSection;
2739 m_lastSectionToRun = NULL;
2740 return true;
2741 }
2742 return false;
2743 }
2744
2745 void endSection( const std::string& ) {
2746 if( m_currentSection->ran() ) {
2747 m_runStatus = RanAtLeastOneSection;
2748 m_changed = true;
2749 }
2750 else if( m_runStatus == EncounteredASection ) {
2751 m_runStatus = RanAtLeastOneSection;
2752 m_lastSectionToRun = m_currentSection;
2753 }
2754 m_currentSection = m_currentSection->getParent();
2755 }
2756
2757 const TestCaseInfo& getTestCaseInfo() const {
2758 return *m_info;
2759 }
2760
2761 bool hasUntestedSections() const {
2762 return m_runStatus == RanAtLeastOneSection ||
2763 ( m_rootSection.hasUntestedSections() && m_changed );
2764 }
2765
2766 private:
2767 const TestCaseInfo* m_info;
2768 RunStatus m_runStatus;
2769 SectionInfo m_rootSection;
2770 SectionInfo* m_currentSection;
2771 SectionInfo* m_lastSectionToRun;
2772 bool m_changed;
2773 };
2774 }
2775 5870
2776 #include <set> 5871 #include <set>
2777 #include <string> 5872 #include <string>
2778 5873
2779 namespace Catch { 5874 namespace Catch {
2801 std::string& m_targetString; 5896 std::string& m_targetString;
2802 }; 5897 };
2803 5898
2804 /////////////////////////////////////////////////////////////////////////// 5899 ///////////////////////////////////////////////////////////////////////////
2805 5900
2806 class Runner : public IResultCapture, public IRunner { 5901 class RunContext : public IResultCapture, public IRunner {
2807 5902
2808 Runner( const Runner& ); 5903 RunContext( RunContext const& );
2809 void operator =( const Runner& ); 5904 void operator =( RunContext const& );
2810 5905
2811 public: 5906 public:
2812 5907
2813 explicit Runner( Config& config ) 5908 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
2814 : m_context( getCurrentMutableContext() ), 5909 : m_runInfo( _config->name() ),
2815 m_runningTest( NULL ), 5910 m_context( getCurrentMutableContext() ),
2816 m_config( config ), 5911 m_activeTestCase( CATCH_NULL ),
2817 m_reporter( config.getReporter() ), 5912 m_config( _config ),
2818 m_prevRunner( &m_context.getRunner() ), 5913 m_reporter( reporter )
2819 m_prevResultCapture( &m_context.getResultCapture() )
2820 { 5914 {
2821 m_context.setRunner( this ); 5915 m_context.setRunner( this );
2822 m_context.setConfig( &m_config ); 5916 m_context.setConfig( m_config );
2823 m_context.setResultCapture( this ); 5917 m_context.setResultCapture( this );
2824 m_reporter->StartTesting(); 5918 m_reporter->testRunStarting( m_runInfo );
2825 } 5919 }
2826 5920
2827 ~Runner() { 5921 virtual ~RunContext() {
2828 m_reporter->EndTesting( m_totals ); 5922 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
2829 m_context.setRunner( m_prevRunner ); 5923 }
2830 m_context.setConfig( NULL ); 5924
2831 m_context.setResultCapture( m_prevResultCapture ); 5925 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
2832 } 5926 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
2833 5927 }
2834 virtual void runAll( bool runHiddenTests = false ) { 5928 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
2835 const std::vector<TestCaseInfo>& allTests = getCurrentContext().getTestCaseRegistry().getAllTests(); 5929 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
2836 for( std::size_t i=0; i < allTests.size(); ++i ) { 5930 }
2837 if( runHiddenTests || !allTests[i].isHidden() ) 5931
2838 { 5932 Totals runTest( TestCase const& testCase ) {
2839 if( aborting() ) {
2840 m_reporter->Aborted();
2841 break;
2842 }
2843 runTest( allTests[i] );
2844 }
2845 }
2846 }
2847
2848 virtual std::size_t runMatching( const std::string& rawTestSpec ) {
2849 TestSpec testSpec( rawTestSpec );
2850
2851 const std::vector<TestCaseInfo>& allTests = getCurrentContext().getTestCaseRegistry().getAllTests();
2852 std::size_t testsRun = 0;
2853 for( std::size_t i=0; i < allTests.size(); ++i ) {
2854 if( testSpec.matches( allTests[i].getName() ) ) {
2855 if( aborting() ) {
2856 m_reporter->Aborted();
2857 break;
2858 }
2859 runTest( allTests[i] );
2860 testsRun++;
2861 }
2862 }
2863 return testsRun;
2864 }
2865
2866 void runTest( const TestCaseInfo& testInfo ) {
2867 Totals prevTotals = m_totals; 5933 Totals prevTotals = m_totals;
2868 5934
2869 std::string redirectedCout; 5935 std::string redirectedCout;
2870 std::string redirectedCerr; 5936 std::string redirectedCerr;
2871 5937
2872 m_reporter->StartTestCase( testInfo ); 5938 TestCaseInfo testInfo = testCase.getTestCaseInfo();
2873 5939
2874 m_runningTest = new RunningTest( &testInfo ); 5940 m_reporter->testCaseStarting( testInfo );
5941
5942 m_activeTestCase = &testCase;
2875 5943
2876 do { 5944 do {
5945 m_trackerContext.startRun();
2877 do { 5946 do {
2878 // m_reporter->StartGroup( "test case run" ); 5947 m_trackerContext.startCycle();
2879 m_currentResult.setLineInfo( m_runningTest->getTestCaseInfo().getLineInfo() ); 5948 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name );
2880 runCurrentTest( redirectedCout, redirectedCerr ); 5949 runCurrentTest( redirectedCout, redirectedCerr );
2881 // m_reporter->EndGroup( "test case run", m_totals.delta( prevTotals ) );
2882 } 5950 }
2883 while( m_runningTest->hasUntestedSections() && !aborting() ); 5951 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
2884 } 5952 }
5953 // !TBD: deprecated - this will be replaced by indexed trackers
2885 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); 5954 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
2886 5955
2887 delete m_runningTest;
2888 m_runningTest = NULL;
2889
2890 Totals deltaTotals = m_totals.delta( prevTotals ); 5956 Totals deltaTotals = m_totals.delta( prevTotals );
5957 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
5958 deltaTotals.assertions.failed++;
5959 deltaTotals.testCases.passed--;
5960 deltaTotals.testCases.failed++;
5961 }
2891 m_totals.testCases += deltaTotals.testCases; 5962 m_totals.testCases += deltaTotals.testCases;
2892 m_reporter->EndTestCase( testInfo, deltaTotals, redirectedCout, redirectedCerr ); 5963 m_reporter->testCaseEnded( TestCaseStats( testInfo,
2893 } 5964 deltaTotals,
2894 5965 redirectedCout,
2895 virtual Totals getTotals() const { 5966 redirectedCerr,
2896 return m_totals; 5967 aborting() ) );
2897 } 5968
2898 5969 m_activeTestCase = CATCH_NULL;
2899 const Config& config() const { 5970 m_testCaseTracker = CATCH_NULL;
5971
5972 return deltaTotals;
5973 }
5974
5975 Ptr<IConfig const> config() const {
2900 return m_config; 5976 return m_config;
2901 } 5977 }
2902 5978
2903 private: // IResultCapture 5979 private: // IResultCapture
2904 5980
2905 virtual ResultAction::Value acceptResult( bool result ) { 5981 virtual void assertionEnded( AssertionResult const& result ) {
2906 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
2907 }
2908
2909 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) {
2910 m_currentResult.setResultType( result );
2911 return actOnCurrentResult();
2912 }
2913
2914 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) {
2915 m_currentResult = resultInfo;
2916 return actOnCurrentResult();
2917 }
2918
2919 virtual void acceptMessage( const std::string& msg ) {
2920 m_currentResult.setMessage( msg );
2921 }
2922
2923 virtual void testEnded( const ResultInfo& result ) {
2924 if( result.getResultType() == ResultWas::Ok ) { 5982 if( result.getResultType() == ResultWas::Ok ) {
2925 m_totals.assertions.passed++; 5983 m_totals.assertions.passed++;
2926 } 5984 }
2927 else if( !result.ok() ) { 5985 else if( !result.isOk() ) {
2928 m_totals.assertions.failed++; 5986 m_totals.assertions.failed++;
2929 5987 }
2930 std::vector<ResultInfo>::const_iterator it = m_info.begin(); 5988
2931 std::vector<ResultInfo>::const_iterator itEnd = m_info.end(); 5989 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
2932 for(; it != itEnd; ++it ) 5990 m_messages.clear();
2933 m_reporter->Result( *it ); 5991
2934 m_info.clear(); 5992 // Reset working state
2935 } 5993 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
2936 5994 m_lastResult = result;
2937 if( result.getResultType() == ResultWas::Info )
2938 m_info.push_back( result );
2939 else
2940 m_reporter->Result( result );
2941 } 5995 }
2942 5996
2943 virtual bool sectionStarted ( 5997 virtual bool sectionStarted (
2944 const std::string& name, 5998 SectionInfo const& sectionInfo,
2945 const std::string& description,
2946 const SourceLineInfo& lineInfo,
2947 Counts& assertions 5999 Counts& assertions
2948 ) 6000 )
2949 { 6001 {
2950 std::ostringstream oss; 6002 std::ostringstream oss;
2951 oss << name << "@" << lineInfo; 6003 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
2952 6004
2953 if( !m_runningTest->addSection( oss.str() ) ) 6005 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() );
6006 if( !sectionTracker.isOpen() )
2954 return false; 6007 return false;
2955 6008 m_activeSections.push_back( &sectionTracker );
2956 m_currentResult.setLineInfo( lineInfo ); 6009
2957 m_reporter->StartSection( name, description ); 6010 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
6011
6012 m_reporter->sectionStarting( sectionInfo );
6013
2958 assertions = m_totals.assertions; 6014 assertions = m_totals.assertions;
2959 6015
2960 return true; 6016 return true;
2961 } 6017 }
2962 6018 bool testForMissingAssertions( Counts& assertions ) {
2963 virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) { 6019 if( assertions.total() != 0 )
2964 m_runningTest->endSection( name ); 6020 return false;
2965 m_reporter->EndSection( name, m_totals.assertions - prevAssertions ); 6021 if( !m_config->warnAboutMissingAssertions() )
2966 } 6022 return false;
2967 6023 if( m_trackerContext.currentTracker().hasChildren() )
2968 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) { 6024 return false;
2969 m_scopedInfos.push_back( scopedInfo ); 6025 m_totals.assertions.failed++;
2970 } 6026 assertions.failed++;
2971 6027 return true;
2972 virtual void popScopedInfo( ScopedInfo* scopedInfo ) { 6028 }
2973 if( m_scopedInfos.back() == scopedInfo ) 6029
2974 m_scopedInfos.pop_back(); 6030 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
2975 } 6031 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
2976 6032 bool missingAssertions = testForMissingAssertions( assertions );
2977 virtual bool shouldDebugBreak() const { 6033
2978 return m_config.shouldDebugBreak(); 6034 if( !m_activeSections.empty() ) {
6035 m_activeSections.back()->close();
6036 m_activeSections.pop_back();
6037 }
6038
6039 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
6040 m_messages.clear();
6041 }
6042
6043 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
6044 if( m_unfinishedSections.empty() )
6045 m_activeSections.back()->fail();
6046 else
6047 m_activeSections.back()->close();
6048 m_activeSections.pop_back();
6049
6050 m_unfinishedSections.push_back( endInfo );
6051 }
6052
6053 virtual void pushScopedMessage( MessageInfo const& message ) {
6054 m_messages.push_back( message );
6055 }
6056
6057 virtual void popScopedMessage( MessageInfo const& message ) {
6058 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
2979 } 6059 }
2980 6060
2981 virtual std::string getCurrentTestName() const { 6061 virtual std::string getCurrentTestName() const {
2982 return m_runningTest 6062 return m_activeTestCase
2983 ? m_runningTest->getTestCaseInfo().getName() 6063 ? m_activeTestCase->getTestCaseInfo().name
2984 : ""; 6064 : "";
2985 } 6065 }
2986 6066
2987 virtual const ResultInfo* getLastResult() const { 6067 virtual const AssertionResult* getLastResult() const {
2988 return &m_lastResult; 6068 return &m_lastResult;
2989 } 6069 }
2990 6070
6071 virtual void handleFatalErrorCondition( std::string const& message ) {
6072 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
6073 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
6074 resultBuilder << message;
6075 resultBuilder.captureExpression();
6076
6077 handleUnfinishedSections();
6078
6079 // Recreate section for test case (as we will lose the one that was in scope)
6080 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6081 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6082
6083 Counts assertions;
6084 assertions.failed = 1;
6085 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6086 m_reporter->sectionEnded( testCaseSectionStats );
6087
6088 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6089
6090 Totals deltaTotals;
6091 deltaTotals.testCases.failed = 1;
6092 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6093 deltaTotals,
6094 "",
6095 "",
6096 false ) );
6097 m_totals.testCases.failed++;
6098 testGroupEnded( "", m_totals, 1, 1 );
6099 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6100 }
6101
6102 public:
6103 // !TBD We need to do this another way!
6104 bool aborting() const {
6105 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
6106 }
6107
2991 private: 6108 private:
2992 6109
2993 bool aborting() const {
2994 return m_totals.assertions.failed == static_cast<std::size_t>( m_config.getCutoff() );
2995 }
2996
2997 ResultAction::Value actOnCurrentResult() {
2998 testEnded( m_currentResult );
2999 m_lastResult = m_currentResult;
3000
3001 m_currentResult = ResultInfoBuilder();
3002
3003 ResultAction::Value action = ResultAction::None;
3004
3005 if( !m_lastResult.ok() ) {
3006 action = ResultAction::Failed;
3007 if( shouldDebugBreak() )
3008 action = (ResultAction::Value)( action | ResultAction::Debug );
3009 if( aborting() )
3010 action = (ResultAction::Value)( action | ResultAction::Abort );
3011 }
3012 return action;
3013 }
3014
3015 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { 6110 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
6111 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6112 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6113 m_reporter->sectionStarting( testCaseSection );
6114 Counts prevAssertions = m_totals.assertions;
6115 double duration = 0;
3016 try { 6116 try {
3017 m_runningTest->reset(); 6117 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
3018 if( m_reporter->shouldRedirectStdout() ) { 6118
3019 StreamRedirect coutRedir( std::cout, redirectedCout ); 6119 seedRng( *m_config );
3020 StreamRedirect cerrRedir( std::cerr, redirectedCerr ); 6120
3021 m_runningTest->getTestCaseInfo().invoke(); 6121 Timer timer;
6122 timer.start();
6123 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
6124 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6125 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
6126 invokeActiveTestCase();
3022 } 6127 }
3023 else { 6128 else {
3024 m_runningTest->getTestCaseInfo().invoke(); 6129 invokeActiveTestCase();
3025 } 6130 }
3026 m_runningTest->ranToCompletion(); 6131 duration = timer.getElapsedSeconds();
3027 } 6132 }
3028 catch( TestFailureException& ) { 6133 catch( TestFailureException& ) {
3029 // This just means the test was aborted due to failure 6134 // This just means the test was aborted due to failure
3030 } 6135 }
3031 catch(...) { 6136 catch(...) {
3032 acceptMessage( getCurrentContext().getExceptionTranslatorRegistry().translateActiveException() ); 6137 makeUnexpectedResultBuilder().useActiveException();
3033 acceptResult( ResultWas::ThrewException ); 6138 }
3034 } 6139 m_testCaseTracker->close();
3035 m_info.clear(); 6140 handleUnfinishedSections();
6141 m_messages.clear();
6142
6143 Counts assertions = m_totals.assertions - prevAssertions;
6144 bool missingAssertions = testForMissingAssertions( assertions );
6145
6146 if( testCaseInfo.okToFail() ) {
6147 std::swap( assertions.failedButOk, assertions.failed );
6148 m_totals.assertions.failed -= assertions.failedButOk;
6149 m_totals.assertions.failedButOk += assertions.failedButOk;
6150 }
6151
6152 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
6153 m_reporter->sectionEnded( testCaseSectionStats );
6154 }
6155
6156 void invokeActiveTestCase() {
6157 FatalConditionHandler fatalConditionHandler; // Handle signals
6158 m_activeTestCase->invoke();
6159 fatalConditionHandler.reset();
3036 } 6160 }
3037 6161
3038 private: 6162 private:
6163
6164 ResultBuilder makeUnexpectedResultBuilder() const {
6165 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6166 m_lastAssertionInfo.lineInfo,
6167 m_lastAssertionInfo.capturedExpression.c_str(),
6168 m_lastAssertionInfo.resultDisposition );
6169 }
6170
6171 void handleUnfinishedSections() {
6172 // If sections ended prematurely due to an exception we stored their
6173 // infos here so we can tear them down outside the unwind process.
6174 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
6175 itEnd = m_unfinishedSections.rend();
6176 it != itEnd;
6177 ++it )
6178 sectionEnded( *it );
6179 m_unfinishedSections.clear();
6180 }
6181
6182 TestRunInfo m_runInfo;
3039 IMutableContext& m_context; 6183 IMutableContext& m_context;
3040 RunningTest* m_runningTest; 6184 TestCase const* m_activeTestCase;
3041 ResultInfoBuilder m_currentResult; 6185 ITracker* m_testCaseTracker;
3042 ResultInfo m_lastResult; 6186 ITracker* m_currentSectionTracker;
3043 6187 AssertionResult m_lastResult;
3044 const Config& m_config; 6188
6189 Ptr<IConfig const> m_config;
3045 Totals m_totals; 6190 Totals m_totals;
3046 Ptr<IReporter> m_reporter; 6191 Ptr<IStreamingReporter> m_reporter;
3047 std::vector<ScopedInfo*> m_scopedInfos; 6192 std::vector<MessageInfo> m_messages;
3048 std::vector<ResultInfo> m_info; 6193 AssertionInfo m_lastAssertionInfo;
3049 IRunner* m_prevRunner; 6194 std::vector<SectionEndInfo> m_unfinishedSections;
3050 IResultCapture* m_prevResultCapture; 6195 std::vector<ITracker*> m_activeSections;
3051 }; 6196 TrackerContext m_trackerContext;
6197 };
6198
6199 IResultCapture& getResultCapture() {
6200 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6201 return *capture;
6202 else
6203 throw std::logic_error( "No result capture instance" );
6204 }
3052 6205
3053 } // end namespace Catch 6206 } // end namespace Catch
3054 6207
3055 // #included from: catch_generators_impl.hpp 6208 // #included from: internal/catch_version.h
6209 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6210
6211 namespace Catch {
6212
6213 // Versioning information
6214 struct Version {
6215 Version( unsigned int _majorVersion,
6216 unsigned int _minorVersion,
6217 unsigned int _patchNumber,
6218 std::string const& _branchName,
6219 unsigned int _buildNumber );
6220
6221 unsigned int const majorVersion;
6222 unsigned int const minorVersion;
6223 unsigned int const patchNumber;
6224
6225 // buildNumber is only used if branchName is not null
6226 std::string const branchName;
6227 unsigned int const buildNumber;
6228
6229 friend std::ostream& operator << ( std::ostream& os, Version const& version );
6230
6231 private:
6232 void operator=( Version const& );
6233 };
6234
6235 extern Version libraryVersion;
6236 }
6237
6238 #include <fstream>
6239 #include <stdlib.h>
6240 #include <limits>
6241
6242 namespace Catch {
6243
6244 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
6245 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
6246 if( !reporter ) {
6247 std::ostringstream oss;
6248 oss << "No reporter registered with name: '" << reporterName << "'";
6249 throw std::domain_error( oss.str() );
6250 }
6251 return reporter;
6252 }
6253
6254 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
6255 std::vector<std::string> reporters = config->getReporterNames();
6256 if( reporters.empty() )
6257 reporters.push_back( "console" );
6258
6259 Ptr<IStreamingReporter> reporter;
6260 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6261 it != itEnd;
6262 ++it )
6263 reporter = addReporter( reporter, createReporter( *it, config ) );
6264 return reporter;
6265 }
6266 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
6267 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6268 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6269 it != itEnd;
6270 ++it )
6271 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6272 return reporters;
6273 }
6274
6275 Totals runTests( Ptr<Config> const& config ) {
6276
6277 Ptr<IConfig const> iconfig = config.get();
6278
6279 Ptr<IStreamingReporter> reporter = makeReporter( config );
6280 reporter = addListeners( iconfig, reporter );
6281
6282 RunContext context( iconfig, reporter );
6283
6284 Totals totals;
6285
6286 context.testGroupStarting( config->name(), 1, 1 );
6287
6288 TestSpec testSpec = config->testSpec();
6289 if( !testSpec.hasFilters() )
6290 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6291
6292 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
6293 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6294 it != itEnd;
6295 ++it ) {
6296 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
6297 totals += context.runTest( *it );
6298 else
6299 reporter->skipTest( *it );
6300 }
6301
6302 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
6303 return totals;
6304 }
6305
6306 void applyFilenamesAsTags( IConfig const& config ) {
6307 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
6308 for(std::size_t i = 0; i < tests.size(); ++i ) {
6309 TestCase& test = const_cast<TestCase&>( tests[i] );
6310 std::set<std::string> tags = test.tags;
6311
6312 std::string filename = test.lineInfo.file;
6313 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
6314 if( lastSlash != std::string::npos )
6315 filename = filename.substr( lastSlash+1 );
6316
6317 std::string::size_type lastDot = filename.find_last_of( "." );
6318 if( lastDot != std::string::npos )
6319 filename = filename.substr( 0, lastDot );
6320
6321 tags.insert( "#" + filename );
6322 setTags( test, tags );
6323 }
6324 }
6325
6326 class Session : NonCopyable {
6327 static bool alreadyInstantiated;
6328
6329 public:
6330
6331 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
6332
6333 Session()
6334 : m_cli( makeCommandLineParser() ) {
6335 if( alreadyInstantiated ) {
6336 std::string msg = "Only one instance of Catch::Session can ever be used";
6337 Catch::cerr() << msg << std::endl;
6338 throw std::logic_error( msg );
6339 }
6340 alreadyInstantiated = true;
6341 }
6342 ~Session() {
6343 Catch::cleanUp();
6344 }
6345
6346 void showHelp( std::string const& processName ) {
6347 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
6348
6349 m_cli.usage( Catch::cout(), processName );
6350 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
6351 }
6352
6353 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
6354 try {
6355 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
6356 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
6357 if( m_configData.showHelp )
6358 showHelp( m_configData.processName );
6359 m_config.reset();
6360 }
6361 catch( std::exception& ex ) {
6362 {
6363 Colour colourGuard( Colour::Red );
6364 Catch::cerr()
6365 << "\nError(s) in input:\n"
6366 << Text( ex.what(), TextAttributes().setIndent(2) )
6367 << "\n\n";
6368 }
6369 m_cli.usage( Catch::cout(), m_configData.processName );
6370 return (std::numeric_limits<int>::max)();
6371 }
6372 return 0;
6373 }
6374
6375 void useConfigData( ConfigData const& _configData ) {
6376 m_configData = _configData;
6377 m_config.reset();
6378 }
6379
6380 int run( int argc, char const* const* const argv ) {
6381
6382 int returnCode = applyCommandLine( argc, argv );
6383 if( returnCode == 0 )
6384 returnCode = run();
6385 return returnCode;
6386 }
6387
6388 int run() {
6389 if( m_configData.showHelp )
6390 return 0;
6391
6392 try
6393 {
6394 config(); // Force config to be constructed
6395
6396 seedRng( *m_config );
6397
6398 if( m_configData.filenamesAsTags )
6399 applyFilenamesAsTags( *m_config );
6400
6401 // Handle list request
6402 if( Option<std::size_t> listed = list( config() ) )
6403 return static_cast<int>( *listed );
6404
6405 return static_cast<int>( runTests( m_config ).assertions.failed );
6406 }
6407 catch( std::exception& ex ) {
6408 Catch::cerr() << ex.what() << std::endl;
6409 return (std::numeric_limits<int>::max)();
6410 }
6411 }
6412
6413 Clara::CommandLine<ConfigData> const& cli() const {
6414 return m_cli;
6415 }
6416 std::vector<Clara::Parser::Token> const& unusedTokens() const {
6417 return m_unusedTokens;
6418 }
6419 ConfigData& configData() {
6420 return m_configData;
6421 }
6422 Config& config() {
6423 if( !m_config )
6424 m_config = new Config( m_configData );
6425 return *m_config;
6426 }
6427 private:
6428 Clara::CommandLine<ConfigData> m_cli;
6429 std::vector<Clara::Parser::Token> m_unusedTokens;
6430 ConfigData m_configData;
6431 Ptr<Config> m_config;
6432 };
6433
6434 bool Session::alreadyInstantiated = false;
6435
6436 } // end namespace Catch
6437
6438 // #included from: catch_registry_hub.hpp
6439 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
6440
6441 // #included from: catch_test_case_registry_impl.hpp
6442 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
3056 6443
3057 #include <vector> 6444 #include <vector>
3058 #include <string> 6445 #include <set>
6446 #include <sstream>
6447 #include <iostream>
6448 #include <algorithm>
6449
6450 #ifdef CATCH_CPP14_OR_GREATER
6451 #include <random>
6452 #endif
6453
6454 namespace Catch {
6455
6456 struct RandomNumberGenerator {
6457 typedef int result_type;
6458
6459 result_type operator()( result_type n ) const { return std::rand() % n; }
6460
6461 #ifdef CATCH_CPP14_OR_GREATER
6462 static constexpr result_type min() { return 0; }
6463 static constexpr result_type max() { return 1000000; }
6464 result_type operator()() const { return std::rand() % max(); }
6465 #endif
6466 template<typename V>
6467 static void shuffle( V& vector ) {
6468 RandomNumberGenerator rng;
6469 #ifdef CATCH_CPP14_OR_GREATER
6470 std::shuffle( vector.begin(), vector.end(), rng );
6471 #else
6472 std::random_shuffle( vector.begin(), vector.end(), rng );
6473 #endif
6474 }
6475 };
6476
6477 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
6478
6479 std::vector<TestCase> sorted = unsortedTestCases;
6480
6481 switch( config.runOrder() ) {
6482 case RunTests::InLexicographicalOrder:
6483 std::sort( sorted.begin(), sorted.end() );
6484 break;
6485 case RunTests::InRandomOrder:
6486 {
6487 seedRng( config );
6488 RandomNumberGenerator::shuffle( sorted );
6489 }
6490 break;
6491 case RunTests::InDeclarationOrder:
6492 // already in declaration order
6493 break;
6494 }
6495 return sorted;
6496 }
6497 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
6498 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
6499 }
6500
6501 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
6502 std::set<TestCase> seenFunctions;
6503 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
6504 it != itEnd;
6505 ++it ) {
6506 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
6507 if( !prev.second ) {
6508 std::ostringstream ss;
6509
6510 ss << Colour( Colour::Red )
6511 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
6512 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
6513 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
6514
6515 throw std::runtime_error(ss.str());
6516 }
6517 }
6518 }
6519
6520 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
6521 std::vector<TestCase> filtered;
6522 filtered.reserve( testCases.size() );
6523 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
6524 it != itEnd;
6525 ++it )
6526 if( matchTest( *it, testSpec, config ) )
6527 filtered.push_back( *it );
6528 return filtered;
6529 }
6530 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
6531 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
6532 }
6533
6534 class TestRegistry : public ITestCaseRegistry {
6535 public:
6536 TestRegistry()
6537 : m_currentSortOrder( RunTests::InDeclarationOrder ),
6538 m_unnamedCount( 0 )
6539 {}
6540 virtual ~TestRegistry();
6541
6542 virtual void registerTest( TestCase const& testCase ) {
6543 std::string name = testCase.getTestCaseInfo().name;
6544 if( name == "" ) {
6545 std::ostringstream oss;
6546 oss << "Anonymous test case " << ++m_unnamedCount;
6547 return registerTest( testCase.withName( oss.str() ) );
6548 }
6549 m_functions.push_back( testCase );
6550 }
6551
6552 virtual std::vector<TestCase> const& getAllTests() const {
6553 return m_functions;
6554 }
6555 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
6556 if( m_sortedFunctions.empty() )
6557 enforceNoDuplicateTestCases( m_functions );
6558
6559 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
6560 m_sortedFunctions = sortTests( config, m_functions );
6561 m_currentSortOrder = config.runOrder();
6562 }
6563 return m_sortedFunctions;
6564 }
6565
6566 private:
6567 std::vector<TestCase> m_functions;
6568 mutable RunTests::InWhatOrder m_currentSortOrder;
6569 mutable std::vector<TestCase> m_sortedFunctions;
6570 size_t m_unnamedCount;
6571 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
6572 };
6573
6574 ///////////////////////////////////////////////////////////////////////////
6575
6576 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
6577 public:
6578
6579 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
6580
6581 virtual void invoke() const {
6582 m_fun();
6583 }
6584
6585 private:
6586 virtual ~FreeFunctionTestCase();
6587
6588 TestFunction m_fun;
6589 };
6590
6591 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
6592 std::string className = classOrQualifiedMethodName;
6593 if( startsWith( className, "&" ) )
6594 {
6595 std::size_t lastColons = className.rfind( "::" );
6596 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
6597 if( penultimateColons == std::string::npos )
6598 penultimateColons = 1;
6599 className = className.substr( penultimateColons, lastColons-penultimateColons );
6600 }
6601 return className;
6602 }
6603
6604 void registerTestCase
6605 ( ITestCase* testCase,
6606 char const* classOrQualifiedMethodName,
6607 NameAndDesc const& nameAndDesc,
6608 SourceLineInfo const& lineInfo ) {
6609
6610 getMutableRegistryHub().registerTest
6611 ( makeTestCase
6612 ( testCase,
6613 extractClassName( classOrQualifiedMethodName ),
6614 nameAndDesc.name,
6615 nameAndDesc.description,
6616 lineInfo ) );
6617 }
6618 void registerTestCaseFunction
6619 ( TestFunction function,
6620 SourceLineInfo const& lineInfo,
6621 NameAndDesc const& nameAndDesc ) {
6622 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
6623 }
6624
6625 ///////////////////////////////////////////////////////////////////////////
6626
6627 AutoReg::AutoReg
6628 ( TestFunction function,
6629 SourceLineInfo const& lineInfo,
6630 NameAndDesc const& nameAndDesc ) {
6631 registerTestCaseFunction( function, lineInfo, nameAndDesc );
6632 }
6633
6634 AutoReg::~AutoReg() {}
6635
6636 } // end namespace Catch
6637
6638 // #included from: catch_reporter_registry.hpp
6639 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
6640
3059 #include <map> 6641 #include <map>
3060 6642
3061 namespace Catch { 6643 namespace Catch {
3062 6644
3063 struct GeneratorInfo { 6645 class ReporterRegistry : public IReporterRegistry {
3064
3065 GeneratorInfo( std::size_t size )
3066 : m_size( size ),
3067 m_currentIndex( 0 )
3068 {}
3069
3070 bool moveNext() {
3071 if( ++m_currentIndex == m_size ) {
3072 m_currentIndex = 0;
3073 return false;
3074 }
3075 return true;
3076 }
3077
3078 std::size_t getCurrentIndex() const {
3079 return m_currentIndex;
3080 }
3081
3082 std::size_t m_size;
3083 std::size_t m_currentIndex;
3084 };
3085
3086 ///////////////////////////////////////////////////////////////////////////
3087
3088 class GeneratorsForTest {
3089 6646
3090 public: 6647 public:
3091 ~GeneratorsForTest() { 6648
3092 deleteAll( m_generatorsInOrder ); 6649 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
3093 } 6650
3094 6651 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
3095 GeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) { 6652 FactoryMap::const_iterator it = m_factories.find( name );
3096 std::map<std::string, GeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo ); 6653 if( it == m_factories.end() )
3097 if( it == m_generatorsByName.end() ) { 6654 return CATCH_NULL;
3098 GeneratorInfo* info = new GeneratorInfo( size ); 6655 return it->second->create( ReporterConfig( config ) );
3099 m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); 6656 }
3100 m_generatorsInOrder.push_back( info ); 6657
3101 return *info; 6658 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
3102 } 6659 m_factories.insert( std::make_pair( name, factory ) );
3103 return *it->second; 6660 }
3104 } 6661 void registerListener( Ptr<IReporterFactory> const& factory ) {
3105 6662 m_listeners.push_back( factory );
3106 bool moveNext() { 6663 }
3107 std::vector<GeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin(); 6664
3108 std::vector<GeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end(); 6665 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
3109 for(; it != itEnd; ++it ) { 6666 return m_factories;
3110 if( (*it)->moveNext() ) 6667 }
3111 return true; 6668 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
3112 } 6669 return m_listeners;
3113 return false;
3114 } 6670 }
3115 6671
3116 private: 6672 private:
3117 std::map<std::string, GeneratorInfo*> m_generatorsByName; 6673 FactoryMap m_factories;
3118 std::vector<GeneratorInfo*> m_generatorsInOrder; 6674 Listeners m_listeners;
3119 }; 6675 };
3120 6676 }
3121 } // end namespace Catch
3122
3123 #define INTERNAL_CATCH_LINESTR2( line ) #line
3124 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
3125
3126 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
3127
3128 // #included from: catch_console_colour_impl.hpp
3129
3130 // #included from: catch_console_colour.hpp
3131
3132 namespace Catch {
3133
3134 struct ConsoleColourImpl;
3135
3136 class TextColour : NonCopyable {
3137 public:
3138
3139 enum Colours {
3140 None,
3141
3142 FileName,
3143 ResultError,
3144 ResultSuccess,
3145
3146 Error,
3147 Success,
3148
3149 OriginalExpression,
3150 ReconstructedExpression
3151 };
3152
3153 TextColour( Colours colour = None );
3154 void set( Colours colour );
3155 ~TextColour();
3156
3157 private:
3158 ConsoleColourImpl* m_impl;
3159 };
3160
3161 } // end namespace Catch
3162
3163 #ifdef CATCH_PLATFORM_WINDOWS
3164
3165 #include <windows.h>
3166
3167 namespace Catch {
3168
3169 namespace {
3170
3171 WORD mapConsoleColour( TextColour::Colours colour ) {
3172 switch( colour ) {
3173 case TextColour::FileName:
3174 return FOREGROUND_INTENSITY; // greyed out
3175 case TextColour::ResultError:
3176 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
3177 case TextColour::ResultSuccess:
3178 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
3179 case TextColour::Error:
3180 return FOREGROUND_RED; // dark red
3181 case TextColour::Success:
3182 return FOREGROUND_GREEN; // dark green
3183 case TextColour::OriginalExpression:
3184 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
3185 case TextColour::ReconstructedExpression:
3186 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
3187 default: return 0;
3188 }
3189 }
3190 }
3191
3192 struct ConsoleColourImpl {
3193
3194 ConsoleColourImpl()
3195 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
3196 wOldColorAttrs( 0 )
3197 {
3198 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
3199 wOldColorAttrs = csbiInfo.wAttributes;
3200 }
3201
3202 ~ConsoleColourImpl() {
3203 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
3204 }
3205
3206 void set( TextColour::Colours colour ) {
3207 WORD consoleColour = mapConsoleColour( colour );
3208 if( consoleColour > 0 )
3209 SetConsoleTextAttribute( hStdout, consoleColour );
3210 }
3211
3212 HANDLE hStdout;
3213 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
3214 WORD wOldColorAttrs;
3215 };
3216
3217 TextColour::TextColour( Colours colour )
3218 : m_impl( new ConsoleColourImpl() )
3219 {
3220 if( colour )
3221 m_impl->set( colour );
3222 }
3223
3224 TextColour::~TextColour() {
3225 delete m_impl;
3226 }
3227
3228 void TextColour::set( Colours colour ) {
3229 m_impl->set( colour );
3230 }
3231
3232 } // end namespace Catch
3233
3234 #else
3235
3236 namespace Catch {
3237 TextColour::TextColour( Colours ){}
3238 TextColour::~TextColour(){}
3239 void TextColour::set( Colours ){}
3240
3241 } // end namespace Catch
3242
3243 #endif
3244
3245 6677
3246 // #included from: catch_exception_translator_registry.hpp 6678 // #included from: catch_exception_translator_registry.hpp
6679 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
3247 6680
3248 #ifdef __OBJC__ 6681 #ifdef __OBJC__
3249 #import "Foundation/Foundation.h" 6682 #import "Foundation/Foundation.h"
3250 #endif 6683 #endif
3251 6684
3252 namespace Catch { 6685 namespace Catch {
3253 6686
3254 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 6687 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
3255 6688 public:
3256 ~ExceptionTranslatorRegistry() { 6689 ~ExceptionTranslatorRegistry() {
3257 deleteAll( m_translators ); 6690 deleteAll( m_translators );
3258 } 6691 }
3259 6692
3260 virtual void registerTranslator( IExceptionTranslator* translator ) { 6693 virtual void registerTranslator( const IExceptionTranslator* translator ) {
3261 m_translators.push_back( translator ); 6694 m_translators.push_back( translator );
3262 } 6695 }
3263 6696
3264 virtual std::string translateActiveException() const { 6697 virtual std::string translateActiveException() const {
3265 try { 6698 try {
3266 #ifdef __OBJC__ 6699 #ifdef __OBJC__
3267 // In Objective-C try objective-c exceptions first 6700 // In Objective-C try objective-c exceptions first
3268 @try { 6701 @try {
3269 throw; 6702 return tryTranslators();
3270 } 6703 }
3271 @catch (NSException *exception) { 6704 @catch (NSException *exception) {
3272 return toString( [exception description] ); 6705 return Catch::toString( [exception description] );
3273 } 6706 }
3274 #else 6707 #else
6708 return tryTranslators();
6709 #endif
6710 }
6711 catch( TestFailureException& ) {
3275 throw; 6712 throw;
3276 #endif
3277 } 6713 }
3278 catch( std::exception& ex ) { 6714 catch( std::exception& ex ) {
3279 return ex.what(); 6715 return ex.what();
3280 } 6716 }
3281 catch( std::string& msg ) { 6717 catch( std::string& msg ) {
3283 } 6719 }
3284 catch( const char* msg ) { 6720 catch( const char* msg ) {
3285 return msg; 6721 return msg;
3286 } 6722 }
3287 catch(...) { 6723 catch(...) {
3288 return tryTranslators( m_translators.begin() );
3289 }
3290 }
3291
3292 std::string tryTranslators( std::vector<IExceptionTranslator*>::const_iterator it ) const {
3293 if( it == m_translators.end() )
3294 return "Unknown exception"; 6724 return "Unknown exception";
3295 6725 }
3296 try { 6726 }
3297 return (*it)->translate(); 6727
3298 } 6728 std::string tryTranslators() const {
3299 catch(...) { 6729 if( m_translators.empty() )
3300 return tryTranslators( it+1 ); 6730 throw;
3301 } 6731 else
6732 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
3302 } 6733 }
3303 6734
3304 private: 6735 private:
3305 std::vector<IExceptionTranslator*> m_translators; 6736 std::vector<const IExceptionTranslator*> m_translators;
3306 }; 6737 };
3307 } 6738 }
3308 6739
3309 // #included from: catch_reporter_registry.hpp
3310
3311 #include <map>
3312
3313 namespace Catch { 6740 namespace Catch {
3314 6741
3315 class ReporterRegistry : public IReporterRegistry { 6742 namespace {
3316 6743
3317 public: 6744 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
3318 6745
3319 ~ReporterRegistry() { 6746 RegistryHub( RegistryHub const& );
3320 deleteAllValues( m_factories ); 6747 void operator=( RegistryHub const& );
3321 } 6748
3322 6749 public: // IRegistryHub
3323 virtual IReporter* create( const std::string& name, const IReporterConfig& config ) const { 6750 RegistryHub() {
3324 FactoryMap::const_iterator it = m_factories.find( name ); 6751 }
3325 if( it == m_factories.end() ) 6752 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
3326 return NULL; 6753 return m_reporterRegistry;
3327 return it->second->create( config ); 6754 }
3328 } 6755 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
3329 6756 return m_testCaseRegistry;
3330 void registerReporter( const std::string& name, IReporterFactory* factory ) { 6757 }
3331 m_factories.insert( std::make_pair( name, factory ) ); 6758 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
3332 } 6759 return m_exceptionTranslatorRegistry;
3333 6760 }
3334 const FactoryMap& getFactories() const { 6761
3335 return m_factories; 6762 public: // IMutableRegistryHub
3336 } 6763 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
3337 6764 m_reporterRegistry.registerReporter( name, factory );
3338 private: 6765 }
3339 FactoryMap m_factories; 6766 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
3340 }; 6767 m_reporterRegistry.registerListener( factory );
3341 } 6768 }
6769 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
6770 m_testCaseRegistry.registerTest( testInfo );
6771 }
6772 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
6773 m_exceptionTranslatorRegistry.registerTranslator( translator );
6774 }
6775
6776 private:
6777 TestRegistry m_testCaseRegistry;
6778 ReporterRegistry m_reporterRegistry;
6779 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
6780 };
6781
6782 // Single, global, instance
6783 inline RegistryHub*& getTheRegistryHub() {
6784 static RegistryHub* theRegistryHub = CATCH_NULL;
6785 if( !theRegistryHub )
6786 theRegistryHub = new RegistryHub();
6787 return theRegistryHub;
6788 }
6789 }
6790
6791 IRegistryHub& getRegistryHub() {
6792 return *getTheRegistryHub();
6793 }
6794 IMutableRegistryHub& getMutableRegistryHub() {
6795 return *getTheRegistryHub();
6796 }
6797 void cleanUp() {
6798 delete getTheRegistryHub();
6799 getTheRegistryHub() = CATCH_NULL;
6800 cleanUpContext();
6801 }
6802 std::string translateActiveException() {
6803 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
6804 }
6805
6806 } // end namespace Catch
6807
6808 // #included from: catch_notimplemented_exception.hpp
6809 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6810
6811 #include <ostream>
6812
6813 namespace Catch {
6814
6815 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
6816 : m_lineInfo( lineInfo ) {
6817 std::ostringstream oss;
6818 oss << lineInfo << ": function ";
6819 oss << "not implemented";
6820 m_what = oss.str();
6821 }
6822
6823 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
6824 return m_what.c_str();
6825 }
6826
6827 } // end namespace Catch
6828
6829 // #included from: catch_context_impl.hpp
6830 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
3342 6831
3343 // #included from: catch_stream.hpp 6832 // #included from: catch_stream.hpp
6833 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
3344 6834
3345 #include <stdexcept> 6835 #include <stdexcept>
3346 #include <cstdio> 6836 #include <cstdio>
6837 #include <iostream>
3347 6838
3348 namespace Catch { 6839 namespace Catch {
3349 6840
3350 template<typename WriterF, size_t bufferSize=256> 6841 template<typename WriterF, size_t bufferSize=256>
3351 class StreamBufImpl : public StreamBufBase { 6842 class StreamBufImpl : public StreamBufBase {
3355 public: 6846 public:
3356 StreamBufImpl() { 6847 StreamBufImpl() {
3357 setp( data, data + sizeof(data) ); 6848 setp( data, data + sizeof(data) );
3358 } 6849 }
3359 6850
3360 ~StreamBufImpl() { 6851 ~StreamBufImpl() CATCH_NOEXCEPT {
3361 sync(); 6852 sync();
3362 } 6853 }
3363 6854
3364 private: 6855 private:
3365 int overflow( int c ) { 6856 int overflow( int c ) {
3366 sync(); 6857 sync();
3367 6858
3368 if( c != EOF ) { 6859 if( c != EOF ) {
3369 if( pbase() == epptr() ) 6860 if( pbase() == epptr() )
3370 m_writer( std::string( 1, static_cast<char>( c ) ) ); 6861 m_writer( std::string( 1, static_cast<char>( c ) ) );
3372 sputc( static_cast<char>( c ) ); 6863 sputc( static_cast<char>( c ) );
3373 } 6864 }
3374 return 0; 6865 return 0;
3375 } 6866 }
3376 6867
3377 int sync() { 6868 int sync() {
3378 if( pbase() != pptr() ) { 6869 if( pbase() != pptr() ) {
3379 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); 6870 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
3380 setp( pbase(), epptr() ); 6871 setp( pbase(), epptr() );
3381 } 6872 }
3382 return 0; 6873 return 0;
3383 } 6874 }
3384 }; 6875 };
3385 6876
3386 /////////////////////////////////////////////////////////////////////////// 6877 ///////////////////////////////////////////////////////////////////////////
3387 6878
6879 FileStream::FileStream( std::string const& filename ) {
6880 m_ofs.open( filename.c_str() );
6881 if( m_ofs.fail() ) {
6882 std::ostringstream oss;
6883 oss << "Unable to open file: '" << filename << "'";
6884 throw std::domain_error( oss.str() );
6885 }
6886 }
6887
6888 std::ostream& FileStream::stream() const {
6889 return m_ofs;
6890 }
6891
3388 struct OutputDebugWriter { 6892 struct OutputDebugWriter {
3389 6893
3390 void operator()( const std::string &str ) { 6894 void operator()( std::string const&str ) {
3391 writeToDebugConsole( str ); 6895 writeToDebugConsole( str );
3392 } 6896 }
3393 }; 6897 };
6898
6899 DebugOutStream::DebugOutStream()
6900 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
6901 m_os( m_streamBuf.get() )
6902 {}
6903
6904 std::ostream& DebugOutStream::stream() const {
6905 return m_os;
6906 }
6907
6908 // Store the streambuf from cout up-front because
6909 // cout may get redirected when running tests
6910 CoutStream::CoutStream()
6911 : m_os( Catch::cout().rdbuf() )
6912 {}
6913
6914 std::ostream& CoutStream::stream() const {
6915 return m_os;
6916 }
6917
6918 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
6919 std::ostream& cout() {
6920 return std::cout;
6921 }
6922 std::ostream& cerr() {
6923 return std::cerr;
6924 }
6925 #endif
3394 } 6926 }
3395 6927
3396 namespace Catch { 6928 namespace Catch {
3397 6929
6930 class Context : public IMutableContext {
6931
6932 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
6933 Context( Context const& );
6934 void operator=( Context const& );
6935
6936 public: // IContext
6937 virtual IResultCapture* getResultCapture() {
6938 return m_resultCapture;
6939 }
6940 virtual IRunner* getRunner() {
6941 return m_runner;
6942 }
6943 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
6944 return getGeneratorsForCurrentTest()
6945 .getGeneratorInfo( fileInfo, totalSize )
6946 .getCurrentIndex();
6947 }
6948 virtual bool advanceGeneratorsForCurrentTest() {
6949 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6950 return generators && generators->moveNext();
6951 }
6952
6953 virtual Ptr<IConfig const> getConfig() const {
6954 return m_config;
6955 }
6956
6957 public: // IMutableContext
6958 virtual void setResultCapture( IResultCapture* resultCapture ) {
6959 m_resultCapture = resultCapture;
6960 }
6961 virtual void setRunner( IRunner* runner ) {
6962 m_runner = runner;
6963 }
6964 virtual void setConfig( Ptr<IConfig const> const& config ) {
6965 m_config = config;
6966 }
6967
6968 friend IMutableContext& getCurrentMutableContext();
6969
6970 private:
6971 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6972 std::string testName = getResultCapture()->getCurrentTestName();
6973
6974 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6975 m_generatorsByTestName.find( testName );
6976 return it != m_generatorsByTestName.end()
6977 ? it->second
6978 : CATCH_NULL;
6979 }
6980
6981 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6982 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6983 if( !generators ) {
6984 std::string testName = getResultCapture()->getCurrentTestName();
6985 generators = createGeneratorsForTest();
6986 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6987 }
6988 return *generators;
6989 }
6990
6991 private:
6992 Ptr<IConfig const> m_config;
6993 IRunner* m_runner;
6994 IResultCapture* m_resultCapture;
6995 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6996 };
6997
3398 namespace { 6998 namespace {
3399 Context* currentContext = NULL; 6999 Context* currentContext = CATCH_NULL;
3400 } 7000 }
3401 IMutableContext& getCurrentMutableContext() { 7001 IMutableContext& getCurrentMutableContext() {
3402 if( !currentContext ) 7002 if( !currentContext )
3403 currentContext = new Context(); 7003 currentContext = new Context();
3404 return *currentContext; 7004 return *currentContext;
3405 } 7005 }
3406 IContext& getCurrentContext() { 7006 IContext& getCurrentContext() {
3407 return getCurrentMutableContext(); 7007 return getCurrentMutableContext();
3408 } 7008 }
3409 7009
3410 Context::Context() 7010 void cleanUpContext() {
3411 : m_reporterRegistry( new ReporterRegistry ), 7011 delete currentContext;
3412 m_testCaseRegistry( new TestRegistry ), 7012 currentContext = CATCH_NULL;
3413 m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry ), 7013 }
3414 m_config( NULL ) 7014 }
7015
7016 // #included from: catch_console_colour_impl.hpp
7017 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7018
7019 namespace Catch {
7020 namespace {
7021
7022 struct IColourImpl {
7023 virtual ~IColourImpl() {}
7024 virtual void use( Colour::Code _colourCode ) = 0;
7025 };
7026
7027 struct NoColourImpl : IColourImpl {
7028 void use( Colour::Code ) {}
7029
7030 static IColourImpl* instance() {
7031 static NoColourImpl s_instance;
7032 return &s_instance;
7033 }
7034 };
7035
7036 } // anon namespace
7037 } // namespace Catch
7038
7039 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7040 # ifdef CATCH_PLATFORM_WINDOWS
7041 # define CATCH_CONFIG_COLOUR_WINDOWS
7042 # else
7043 # define CATCH_CONFIG_COLOUR_ANSI
7044 # endif
7045 #endif
7046
7047 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
7048
7049 #ifndef NOMINMAX
7050 #define NOMINMAX
7051 #endif
7052
7053 #ifdef __AFXDLL
7054 #include <AfxWin.h>
7055 #else
7056 #include <windows.h>
7057 #endif
7058
7059 namespace Catch {
7060 namespace {
7061
7062 class Win32ColourImpl : public IColourImpl {
7063 public:
7064 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
7065 {
7066 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7067 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
7068 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7069 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
7070 }
7071
7072 virtual void use( Colour::Code _colourCode ) {
7073 switch( _colourCode ) {
7074 case Colour::None: return setTextAttribute( originalForegroundAttributes );
7075 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7076 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
7077 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
7078 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
7079 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7080 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7081 case Colour::Grey: return setTextAttribute( 0 );
7082
7083 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
7084 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7085 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
7086 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7087
7088 case Colour::Bright: throw std::logic_error( "not a colour" );
7089 }
7090 }
7091
7092 private:
7093 void setTextAttribute( WORD _textAttribute ) {
7094 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
7095 }
7096 HANDLE stdoutHandle;
7097 WORD originalForegroundAttributes;
7098 WORD originalBackgroundAttributes;
7099 };
7100
7101 IColourImpl* platformColourInstance() {
7102 static Win32ColourImpl s_instance;
7103
7104 Ptr<IConfig const> config = getCurrentContext().getConfig();
7105 UseColour::YesOrNo colourMode = config
7106 ? config->useColour()
7107 : UseColour::Auto;
7108 if( colourMode == UseColour::Auto )
7109 colourMode = !isDebuggerActive()
7110 ? UseColour::Yes
7111 : UseColour::No;
7112 return colourMode == UseColour::Yes
7113 ? &s_instance
7114 : NoColourImpl::instance();
7115 }
7116
7117 } // end anon namespace
7118 } // end namespace Catch
7119
7120 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
7121
7122 #include <unistd.h>
7123
7124 namespace Catch {
7125 namespace {
7126
7127 // use POSIX/ ANSI console terminal codes
7128 // Thanks to Adam Strzelecki for original contribution
7129 // (http://github.com/nanoant)
7130 // https://github.com/philsquared/Catch/pull/131
7131 class PosixColourImpl : public IColourImpl {
7132 public:
7133 virtual void use( Colour::Code _colourCode ) {
7134 switch( _colourCode ) {
7135 case Colour::None:
7136 case Colour::White: return setColour( "[0m" );
7137 case Colour::Red: return setColour( "[0;31m" );
7138 case Colour::Green: return setColour( "[0;32m" );
7139 case Colour::Blue: return setColour( "[0:34m" );
7140 case Colour::Cyan: return setColour( "[0;36m" );
7141 case Colour::Yellow: return setColour( "[0;33m" );
7142 case Colour::Grey: return setColour( "[1;30m" );
7143
7144 case Colour::LightGrey: return setColour( "[0;37m" );
7145 case Colour::BrightRed: return setColour( "[1;31m" );
7146 case Colour::BrightGreen: return setColour( "[1;32m" );
7147 case Colour::BrightWhite: return setColour( "[1;37m" );
7148
7149 case Colour::Bright: throw std::logic_error( "not a colour" );
7150 }
7151 }
7152 static IColourImpl* instance() {
7153 static PosixColourImpl s_instance;
7154 return &s_instance;
7155 }
7156
7157 private:
7158 void setColour( const char* _escapeCode ) {
7159 Catch::cout() << '\033' << _escapeCode;
7160 }
7161 };
7162
7163 IColourImpl* platformColourInstance() {
7164 Ptr<IConfig const> config = getCurrentContext().getConfig();
7165 UseColour::YesOrNo colourMode = config
7166 ? config->useColour()
7167 : UseColour::Auto;
7168 if( colourMode == UseColour::Auto )
7169 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
7170 ? UseColour::Yes
7171 : UseColour::No;
7172 return colourMode == UseColour::Yes
7173 ? PosixColourImpl::instance()
7174 : NoColourImpl::instance();
7175 }
7176
7177 } // end anon namespace
7178 } // end namespace Catch
7179
7180 #else // not Windows or ANSI ///////////////////////////////////////////////
7181
7182 namespace Catch {
7183
7184 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
7185
7186 } // end namespace Catch
7187
7188 #endif // Windows/ ANSI/ None
7189
7190 namespace Catch {
7191
7192 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7193 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
7194 Colour::~Colour(){ if( !m_moved ) use( None ); }
7195
7196 void Colour::use( Code _colourCode ) {
7197 static IColourImpl* impl = platformColourInstance();
7198 impl->use( _colourCode );
7199 }
7200
7201 } // end namespace Catch
7202
7203 // #included from: catch_generators_impl.hpp
7204 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7205
7206 #include <vector>
7207 #include <string>
7208 #include <map>
7209
7210 namespace Catch {
7211
7212 struct GeneratorInfo : IGeneratorInfo {
7213
7214 GeneratorInfo( std::size_t size )
7215 : m_size( size ),
7216 m_currentIndex( 0 )
7217 {}
7218
7219 bool moveNext() {
7220 if( ++m_currentIndex == m_size ) {
7221 m_currentIndex = 0;
7222 return false;
7223 }
7224 return true;
7225 }
7226
7227 std::size_t getCurrentIndex() const {
7228 return m_currentIndex;
7229 }
7230
7231 std::size_t m_size;
7232 std::size_t m_currentIndex;
7233 };
7234
7235 ///////////////////////////////////////////////////////////////////////////
7236
7237 class GeneratorsForTest : public IGeneratorsForTest {
7238
7239 public:
7240 ~GeneratorsForTest() {
7241 deleteAll( m_generatorsInOrder );
7242 }
7243
7244 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
7245 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7246 if( it == m_generatorsByName.end() ) {
7247 IGeneratorInfo* info = new GeneratorInfo( size );
7248 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
7249 m_generatorsInOrder.push_back( info );
7250 return *info;
7251 }
7252 return *it->second;
7253 }
7254
7255 bool moveNext() {
7256 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7257 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7258 for(; it != itEnd; ++it ) {
7259 if( (*it)->moveNext() )
7260 return true;
7261 }
7262 return false;
7263 }
7264
7265 private:
7266 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7267 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7268 };
7269
7270 IGeneratorsForTest* createGeneratorsForTest()
7271 {
7272 return new GeneratorsForTest();
7273 }
7274
7275 } // end namespace Catch
7276
7277 // #included from: catch_assertionresult.hpp
7278 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
7279
7280 namespace Catch {
7281
7282 AssertionInfo::AssertionInfo( std::string const& _macroName,
7283 SourceLineInfo const& _lineInfo,
7284 std::string const& _capturedExpression,
7285 ResultDisposition::Flags _resultDisposition )
7286 : macroName( _macroName ),
7287 lineInfo( _lineInfo ),
7288 capturedExpression( _capturedExpression ),
7289 resultDisposition( _resultDisposition )
3415 {} 7290 {}
3416 7291
3417 void Context::cleanUp() { 7292 AssertionResult::AssertionResult() {}
3418 delete currentContext; 7293
3419 currentContext = NULL; 7294 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
3420 } 7295 : m_info( info ),
3421 7296 m_resultData( data )
3422 void Context::setRunner( IRunner* runner ) { 7297 {}
3423 m_runner = runner; 7298
3424 } 7299 AssertionResult::~AssertionResult() {}
3425 7300
3426 void Context::setResultCapture( IResultCapture* resultCapture ) { 7301 // Result was a success
3427 m_resultCapture = resultCapture; 7302 bool AssertionResult::succeeded() const {
3428 } 7303 return Catch::isOk( m_resultData.resultType );
3429 7304 }
3430 const IConfig* Context::getConfig() const { 7305
3431 return m_config; 7306 // Result was a success, or failure is suppressed
3432 } 7307 bool AssertionResult::isOk() const {
3433 void Context::setConfig( const IConfig* config ) { 7308 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
3434 m_config = config; 7309 }
3435 } 7310
3436 7311 ResultWas::OfType AssertionResult::getResultType() const {
3437 IResultCapture& Context::getResultCapture() { 7312 return m_resultData.resultType;
3438 return *m_resultCapture; 7313 }
3439 } 7314
3440 7315 bool AssertionResult::hasExpression() const {
3441 IRunner& Context::getRunner() { 7316 return !m_info.capturedExpression.empty();
3442 return *m_runner; 7317 }
3443 } 7318
3444 7319 bool AssertionResult::hasMessage() const {
3445 IReporterRegistry& Context::getReporterRegistry() { 7320 return !m_resultData.message.empty();
3446 return *m_reporterRegistry.get(); 7321 }
3447 } 7322
3448 7323 std::string AssertionResult::getExpression() const {
3449 ITestCaseRegistry& Context::getTestCaseRegistry() { 7324 if( isFalseTest( m_info.resultDisposition ) )
3450 return *m_testCaseRegistry.get(); 7325 return "!" + m_info.capturedExpression;
3451 } 7326 else
3452 7327 return m_info.capturedExpression;
3453 IExceptionTranslatorRegistry& Context::getExceptionTranslatorRegistry() { 7328 }
3454 return *m_exceptionTranslatorRegistry.get(); 7329 std::string AssertionResult::getExpressionInMacro() const {
3455 } 7330 if( m_info.macroName.empty() )
3456 7331 return m_info.capturedExpression;
3457 std::streambuf* Context::createStreamBuf( const std::string& streamName ) { 7332 else
3458 if( streamName == "stdout" ) return std::cout.rdbuf(); 7333 return m_info.macroName + "( " + m_info.capturedExpression + " )";
3459 if( streamName == "stderr" ) return std::cerr.rdbuf(); 7334 }
3460 if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>; 7335
3461 7336 bool AssertionResult::hasExpandedExpression() const {
3462 throw std::domain_error( "Unknown stream: " + streamName ); 7337 return hasExpression() && getExpandedExpression() != getExpression();
3463 } 7338 }
3464 7339
3465 GeneratorsForTest* Context::findGeneratorsForCurrentTest() { 7340 std::string AssertionResult::getExpandedExpression() const {
3466 std::string testName = getResultCapture().getCurrentTestName(); 7341 return m_resultData.reconstructedExpression;
3467 7342 }
3468 std::map<std::string, GeneratorsForTest*>::const_iterator it = 7343
3469 m_generatorsByTestName.find( testName ); 7344 std::string AssertionResult::getMessage() const {
3470 return it != m_generatorsByTestName.end() 7345 return m_resultData.message;
3471 ? it->second 7346 }
3472 : NULL; 7347 SourceLineInfo AssertionResult::getSourceInfo() const {
3473 } 7348 return m_info.lineInfo;
3474 7349 }
3475 GeneratorsForTest& Context::getGeneratorsForCurrentTest() { 7350
3476 GeneratorsForTest* generators = findGeneratorsForCurrentTest(); 7351 std::string AssertionResult::getTestMacroName() const {
3477 if( !generators ) { 7352 return m_info.macroName;
3478 std::string testName = getResultCapture().getCurrentTestName(); 7353 }
3479 generators = new GeneratorsForTest(); 7354
3480 m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); 7355 } // end namespace Catch
3481 } 7356
3482 return *generators; 7357 // #included from: catch_test_case_info.hpp
3483 } 7358 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
3484 7359
3485 size_t Context::getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) { 7360 namespace Catch {
3486 return getGeneratorsForCurrentTest() 7361
3487 .getGeneratorInfo( fileInfo, totalSize ) 7362 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
3488 .getCurrentIndex(); 7363 if( startsWith( tag, "." ) ||
3489 } 7364 tag == "hide" ||
3490 7365 tag == "!hide" )
3491 bool Context::advanceGeneratorsForCurrentTest() { 7366 return TestCaseInfo::IsHidden;
3492 GeneratorsForTest* generators = findGeneratorsForCurrentTest(); 7367 else if( tag == "!throws" )
3493 return generators && generators->moveNext(); 7368 return TestCaseInfo::Throws;
3494 } 7369 else if( tag == "!shouldfail" )
7370 return TestCaseInfo::ShouldFail;
7371 else if( tag == "!mayfail" )
7372 return TestCaseInfo::MayFail;
7373 else
7374 return TestCaseInfo::None;
7375 }
7376 inline bool isReservedTag( std::string const& tag ) {
7377 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
7378 }
7379 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
7380 if( isReservedTag( tag ) ) {
7381 {
7382 Colour colourGuard( Colour::Red );
7383 Catch::cerr()
7384 << "Tag name [" << tag << "] not allowed.\n"
7385 << "Tag names starting with non alpha-numeric characters are reserved\n";
7386 }
7387 {
7388 Colour colourGuard( Colour::FileName );
7389 Catch::cerr() << _lineInfo << std::endl;
7390 }
7391 exit(1);
7392 }
7393 }
7394
7395 TestCase makeTestCase( ITestCase* _testCase,
7396 std::string const& _className,
7397 std::string const& _name,
7398 std::string const& _descOrTags,
7399 SourceLineInfo const& _lineInfo )
7400 {
7401 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
7402
7403 // Parse out tags
7404 std::set<std::string> tags;
7405 std::string desc, tag;
7406 bool inTag = false;
7407 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7408 char c = _descOrTags[i];
7409 if( !inTag ) {
7410 if( c == '[' )
7411 inTag = true;
7412 else
7413 desc += c;
7414 }
7415 else {
7416 if( c == ']' ) {
7417 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
7418 if( prop == TestCaseInfo::IsHidden )
7419 isHidden = true;
7420 else if( prop == TestCaseInfo::None )
7421 enforceNotReservedTag( tag, _lineInfo );
7422
7423 tags.insert( tag );
7424 tag.clear();
7425 inTag = false;
7426 }
7427 else
7428 tag += c;
7429 }
7430 }
7431 if( isHidden ) {
7432 tags.insert( "hide" );
7433 tags.insert( "." );
7434 }
7435
7436 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
7437 return TestCase( _testCase, info );
7438 }
7439
7440 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
7441 {
7442 testCaseInfo.tags = tags;
7443 testCaseInfo.lcaseTags.clear();
7444
7445 std::ostringstream oss;
7446 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
7447 oss << "[" << *it << "]";
7448 std::string lcaseTag = toLower( *it );
7449 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
7450 testCaseInfo.lcaseTags.insert( lcaseTag );
7451 }
7452 testCaseInfo.tagsAsString = oss.str();
7453 }
7454
7455 TestCaseInfo::TestCaseInfo( std::string const& _name,
7456 std::string const& _className,
7457 std::string const& _description,
7458 std::set<std::string> const& _tags,
7459 SourceLineInfo const& _lineInfo )
7460 : name( _name ),
7461 className( _className ),
7462 description( _description ),
7463 lineInfo( _lineInfo ),
7464 properties( None )
7465 {
7466 setTags( *this, _tags );
7467 }
7468
7469 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
7470 : name( other.name ),
7471 className( other.className ),
7472 description( other.description ),
7473 tags( other.tags ),
7474 lcaseTags( other.lcaseTags ),
7475 tagsAsString( other.tagsAsString ),
7476 lineInfo( other.lineInfo ),
7477 properties( other.properties )
7478 {}
7479
7480 bool TestCaseInfo::isHidden() const {
7481 return ( properties & IsHidden ) != 0;
7482 }
7483 bool TestCaseInfo::throws() const {
7484 return ( properties & Throws ) != 0;
7485 }
7486 bool TestCaseInfo::okToFail() const {
7487 return ( properties & (ShouldFail | MayFail ) ) != 0;
7488 }
7489 bool TestCaseInfo::expectedToFail() const {
7490 return ( properties & (ShouldFail ) ) != 0;
7491 }
7492
7493 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
7494
7495 TestCase::TestCase( TestCase const& other )
7496 : TestCaseInfo( other ),
7497 test( other.test )
7498 {}
7499
7500 TestCase TestCase::withName( std::string const& _newName ) const {
7501 TestCase other( *this );
7502 other.name = _newName;
7503 return other;
7504 }
7505
7506 void TestCase::swap( TestCase& other ) {
7507 test.swap( other.test );
7508 name.swap( other.name );
7509 className.swap( other.className );
7510 description.swap( other.description );
7511 tags.swap( other.tags );
7512 lcaseTags.swap( other.lcaseTags );
7513 tagsAsString.swap( other.tagsAsString );
7514 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
7515 std::swap( lineInfo, other.lineInfo );
7516 }
7517
7518 void TestCase::invoke() const {
7519 test->invoke();
7520 }
7521
7522 bool TestCase::operator == ( TestCase const& other ) const {
7523 return test.get() == other.test.get() &&
7524 name == other.name &&
7525 className == other.className;
7526 }
7527
7528 bool TestCase::operator < ( TestCase const& other ) const {
7529 return name < other.name;
7530 }
7531 TestCase& TestCase::operator = ( TestCase const& other ) {
7532 TestCase temp( other );
7533 swap( temp );
7534 return *this;
7535 }
7536
7537 TestCaseInfo const& TestCase::getTestCaseInfo() const
7538 {
7539 return *this;
7540 }
7541
7542 } // end namespace Catch
7543
7544 // #included from: catch_version.hpp
7545 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7546
7547 namespace Catch {
7548
7549 Version::Version
7550 ( unsigned int _majorVersion,
7551 unsigned int _minorVersion,
7552 unsigned int _patchNumber,
7553 std::string const& _branchName,
7554 unsigned int _buildNumber )
7555 : majorVersion( _majorVersion ),
7556 minorVersion( _minorVersion ),
7557 patchNumber( _patchNumber ),
7558 branchName( _branchName ),
7559 buildNumber( _buildNumber )
7560 {}
7561
7562 std::ostream& operator << ( std::ostream& os, Version const& version ) {
7563 os << version.majorVersion << "."
7564 << version.minorVersion << "."
7565 << version.patchNumber;
7566
7567 if( !version.branchName.empty() ) {
7568 os << "-" << version.branchName
7569 << "." << version.buildNumber;
7570 }
7571 return os;
7572 }
7573
7574 Version libraryVersion( 1, 5, 6, "", 0 );
7575
3495 } 7576 }
3496 // #included from: internal/catch_commandline.hpp 7577
7578 // #included from: catch_message.hpp
7579 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
3497 7580
3498 namespace Catch { 7581 namespace Catch {
3499 7582
3500 class Command { 7583 MessageInfo::MessageInfo( std::string const& _macroName,
7584 SourceLineInfo const& _lineInfo,
7585 ResultWas::OfType _type )
7586 : macroName( _macroName ),
7587 lineInfo( _lineInfo ),
7588 type( _type ),
7589 sequence( ++globalCount )
7590 {}
7591
7592 // This may need protecting if threading support is added
7593 unsigned int MessageInfo::globalCount = 0;
7594
7595 ////////////////////////////////////////////////////////////////////////////
7596
7597 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
7598 : m_info( builder.m_info )
7599 {
7600 m_info.message = builder.m_stream.str();
7601 getResultCapture().pushScopedMessage( m_info );
7602 }
7603 ScopedMessage::ScopedMessage( ScopedMessage const& other )
7604 : m_info( other.m_info )
7605 {}
7606
7607 ScopedMessage::~ScopedMessage() {
7608 getResultCapture().popScopedMessage( m_info );
7609 }
7610
7611 } // end namespace Catch
7612
7613 // #included from: catch_legacy_reporter_adapter.hpp
7614 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
7615
7616 // #included from: catch_legacy_reporter_adapter.h
7617 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
7618
7619 namespace Catch
7620 {
7621 // Deprecated
7622 struct IReporter : IShared {
7623 virtual ~IReporter();
7624
7625 virtual bool shouldRedirectStdout() const = 0;
7626
7627 virtual void StartTesting() = 0;
7628 virtual void EndTesting( Totals const& totals ) = 0;
7629 virtual void StartGroup( std::string const& groupName ) = 0;
7630 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
7631 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
7632 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
7633 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
7634 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
7635 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
7636 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
7637 virtual void Aborted() = 0;
7638 virtual void Result( AssertionResult const& result ) = 0;
7639 };
7640
7641 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
7642 {
3501 public: 7643 public:
3502 Command(){} 7644 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
3503 7645 virtual ~LegacyReporterAdapter();
3504 explicit Command( const std::string& name ) : m_name( name ) {} 7646
3505 7647 virtual ReporterPreferences getPreferences() const;
3506 Command& operator += ( const std::string& arg ) { 7648 virtual void noMatchingTestCases( std::string const& );
3507 m_args.push_back( arg ); 7649 virtual void testRunStarting( TestRunInfo const& );
3508 return *this; 7650 virtual void testGroupStarting( GroupInfo const& groupInfo );
3509 } 7651 virtual void testCaseStarting( TestCaseInfo const& testInfo );
3510 Command& operator += ( const Command& other ) { 7652 virtual void sectionStarting( SectionInfo const& sectionInfo );
3511 std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) ); 7653 virtual void assertionStarting( AssertionInfo const& );
3512 if( m_name.empty() ) 7654 virtual bool assertionEnded( AssertionStats const& assertionStats );
3513 m_name = other.m_name; 7655 virtual void sectionEnded( SectionStats const& sectionStats );
3514 return *this; 7656 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
3515 } 7657 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
3516 Command operator + ( const Command& other ) { 7658 virtual void testRunEnded( TestRunStats const& testRunStats );
3517 Command newCommand( *this ); 7659 virtual void skipTest( TestCaseInfo const& );
3518 newCommand += other; 7660
3519 return newCommand; 7661 private:
3520 } 7662 Ptr<IReporter> m_legacyReporter;
3521 7663 };
3522 operator SafeBool::type() const { 7664 }
3523 return SafeBool::makeSafe( !m_name.empty() ); 7665
3524 } 7666 namespace Catch
3525 7667 {
3526 std::string name() const { return m_name; } 7668 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
3527 std::string operator[]( std::size_t i ) const { return m_args[i]; } 7669 : m_legacyReporter( legacyReporter )
3528 std::size_t argsCount() const { return m_args.size(); } 7670 {}
3529 7671 LegacyReporterAdapter::~LegacyReporterAdapter() {}
3530 void raiseError( const std::string& message ) const { 7672
7673 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
7674 ReporterPreferences prefs;
7675 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
7676 return prefs;
7677 }
7678
7679 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
7680 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
7681 m_legacyReporter->StartTesting();
7682 }
7683 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
7684 m_legacyReporter->StartGroup( groupInfo.name );
7685 }
7686 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
7687 m_legacyReporter->StartTestCase( testInfo );
7688 }
7689 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
7690 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
7691 }
7692 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
7693 // Not on legacy interface
7694 }
7695
7696 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
7697 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
7698 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
7699 it != itEnd;
7700 ++it ) {
7701 if( it->type == ResultWas::Info ) {
7702 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
7703 rb << it->message;
7704 rb.setResultType( ResultWas::Info );
7705 AssertionResult result = rb.build();
7706 m_legacyReporter->Result( result );
7707 }
7708 }
7709 }
7710 m_legacyReporter->Result( assertionStats.assertionResult );
7711 return true;
7712 }
7713 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
7714 if( sectionStats.missingAssertions )
7715 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
7716 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
7717 }
7718 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
7719 m_legacyReporter->EndTestCase
7720 ( testCaseStats.testInfo,
7721 testCaseStats.totals,
7722 testCaseStats.stdOut,
7723 testCaseStats.stdErr );
7724 }
7725 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
7726 if( testGroupStats.aborting )
7727 m_legacyReporter->Aborted();
7728 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
7729 }
7730 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
7731 m_legacyReporter->EndTesting( testRunStats.totals );
7732 }
7733 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
7734 }
7735 }
7736
7737 // #included from: catch_timer.hpp
7738
7739 #ifdef __clang__
7740 #pragma clang diagnostic push
7741 #pragma clang diagnostic ignored "-Wc++11-long-long"
7742 #endif
7743
7744 #ifdef CATCH_PLATFORM_WINDOWS
7745 #include <windows.h>
7746 #else
7747 #include <sys/time.h>
7748 #endif
7749
7750 namespace Catch {
7751
7752 namespace {
7753 #ifdef CATCH_PLATFORM_WINDOWS
7754 uint64_t getCurrentTicks() {
7755 static uint64_t hz=0, hzo=0;
7756 if (!hz) {
7757 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
7758 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
7759 }
7760 uint64_t t;
7761 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
7762 return ((t-hzo)*1000000)/hz;
7763 }
7764 #else
7765 uint64_t getCurrentTicks() {
7766 timeval t;
7767 gettimeofday(&t,CATCH_NULL);
7768 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
7769 }
7770 #endif
7771 }
7772
7773 void Timer::start() {
7774 m_ticks = getCurrentTicks();
7775 }
7776 unsigned int Timer::getElapsedMicroseconds() const {
7777 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
7778 }
7779 unsigned int Timer::getElapsedMilliseconds() const {
7780 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
7781 }
7782 double Timer::getElapsedSeconds() const {
7783 return getElapsedMicroseconds()/1000000.0;
7784 }
7785
7786 } // namespace Catch
7787
7788 #ifdef __clang__
7789 #pragma clang diagnostic pop
7790 #endif
7791 // #included from: catch_common.hpp
7792 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
7793
7794 namespace Catch {
7795
7796 bool startsWith( std::string const& s, std::string const& prefix ) {
7797 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
7798 }
7799 bool endsWith( std::string const& s, std::string const& suffix ) {
7800 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
7801 }
7802 bool contains( std::string const& s, std::string const& infix ) {
7803 return s.find( infix ) != std::string::npos;
7804 }
7805 void toLowerInPlace( std::string& s ) {
7806 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
7807 }
7808 std::string toLower( std::string const& s ) {
7809 std::string lc = s;
7810 toLowerInPlace( lc );
7811 return lc;
7812 }
7813 std::string trim( std::string const& str ) {
7814 static char const* whitespaceChars = "\n\r\t ";
7815 std::string::size_type start = str.find_first_not_of( whitespaceChars );
7816 std::string::size_type end = str.find_last_not_of( whitespaceChars );
7817
7818 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
7819 }
7820
7821 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
7822 bool replaced = false;
7823 std::size_t i = str.find( replaceThis );
7824 while( i != std::string::npos ) {
7825 replaced = true;
7826 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
7827 if( i < str.size()-withThis.size() )
7828 i = str.find( replaceThis, i+withThis.size() );
7829 else
7830 i = std::string::npos;
7831 }
7832 return replaced;
7833 }
7834
7835 pluralise::pluralise( std::size_t count, std::string const& label )
7836 : m_count( count ),
7837 m_label( label )
7838 {}
7839
7840 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
7841 os << pluraliser.m_count << " " << pluraliser.m_label;
7842 if( pluraliser.m_count != 1 )
7843 os << "s";
7844 return os;
7845 }
7846
7847 SourceLineInfo::SourceLineInfo() : line( 0 ){}
7848 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
7849 : file( _file ),
7850 line( _line )
7851 {}
7852 SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
7853 : file( other.file ),
7854 line( other.line )
7855 {}
7856 bool SourceLineInfo::empty() const {
7857 return file.empty();
7858 }
7859 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
7860 return line == other.line && file == other.file;
7861 }
7862 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
7863 return line < other.line || ( line == other.line && file < other.file );
7864 }
7865
7866 void seedRng( IConfig const& config ) {
7867 if( config.rngSeed() != 0 )
7868 std::srand( config.rngSeed() );
7869 }
7870 unsigned int rngSeed() {
7871 return getCurrentContext().getConfig()->rngSeed();
7872 }
7873
7874 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
7875 #ifndef __GNUG__
7876 os << info.file << "(" << info.line << ")";
7877 #else
7878 os << info.file << ":" << info.line;
7879 #endif
7880 return os;
7881 }
7882
7883 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
7884 std::ostringstream oss;
7885 oss << locationInfo << ": Internal Catch error: '" << message << "'";
7886 if( alwaysTrue() )
7887 throw std::logic_error( oss.str() );
7888 }
7889 }
7890
7891 // #included from: catch_section.hpp
7892 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
7893
7894 namespace Catch {
7895
7896 SectionInfo::SectionInfo
7897 ( SourceLineInfo const& _lineInfo,
7898 std::string const& _name,
7899 std::string const& _description )
7900 : name( _name ),
7901 description( _description ),
7902 lineInfo( _lineInfo )
7903 {}
7904
7905 Section::Section( SectionInfo const& info )
7906 : m_info( info ),
7907 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
7908 {
7909 m_timer.start();
7910 }
7911
7912 Section::~Section() {
7913 if( m_sectionIncluded ) {
7914 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
7915 if( std::uncaught_exception() )
7916 getResultCapture().sectionEndedEarly( endInfo );
7917 else
7918 getResultCapture().sectionEnded( endInfo );
7919 }
7920 }
7921
7922 // This indicates whether the section should be executed or not
7923 Section::operator bool() const {
7924 return m_sectionIncluded;
7925 }
7926
7927 } // end namespace Catch
7928
7929 // #included from: catch_debugger.hpp
7930 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
7931
7932 #include <iostream>
7933
7934 #ifdef CATCH_PLATFORM_MAC
7935
7936 #include <assert.h>
7937 #include <stdbool.h>
7938 #include <sys/types.h>
7939 #include <unistd.h>
7940 #include <sys/sysctl.h>
7941
7942 namespace Catch{
7943
7944 // The following function is taken directly from the following technical note:
7945 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
7946
7947 // Returns true if the current process is being debugged (either
7948 // running under the debugger or has a debugger attached post facto).
7949 bool isDebuggerActive(){
7950
7951 int mib[4];
7952 struct kinfo_proc info;
7953 size_t size;
7954
7955 // Initialize the flags so that, if sysctl fails for some bizarre
7956 // reason, we get a predictable result.
7957
7958 info.kp_proc.p_flag = 0;
7959
7960 // Initialize mib, which tells sysctl the info we want, in this case
7961 // we're looking for information about a specific process ID.
7962
7963 mib[0] = CTL_KERN;
7964 mib[1] = KERN_PROC;
7965 mib[2] = KERN_PROC_PID;
7966 mib[3] = getpid();
7967
7968 // Call sysctl.
7969
7970 size = sizeof(info);
7971 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
7972 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7973 return false;
7974 }
7975
7976 // We're being debugged if the P_TRACED flag is set.
7977
7978 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7979 }
7980 } // namespace Catch
7981
7982 #elif defined(_MSC_VER)
7983 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7984 namespace Catch {
7985 bool isDebuggerActive() {
7986 return IsDebuggerPresent() != 0;
7987 }
7988 }
7989 #elif defined(__MINGW32__)
7990 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7991 namespace Catch {
7992 bool isDebuggerActive() {
7993 return IsDebuggerPresent() != 0;
7994 }
7995 }
7996 #else
7997 namespace Catch {
7998 inline bool isDebuggerActive() { return false; }
7999 }
8000 #endif // Platform
8001
8002 #ifdef CATCH_PLATFORM_WINDOWS
8003 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
8004 namespace Catch {
8005 void writeToDebugConsole( std::string const& text ) {
8006 ::OutputDebugStringA( text.c_str() );
8007 }
8008 }
8009 #else
8010 namespace Catch {
8011 void writeToDebugConsole( std::string const& text ) {
8012 // !TBD: Need a version for Mac/ XCode and other IDEs
8013 Catch::cout() << text;
8014 }
8015 }
8016 #endif // Platform
8017
8018 // #included from: catch_tostring.hpp
8019 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8020
8021 namespace Catch {
8022
8023 namespace Detail {
8024
8025 const std::string unprintableString = "{?}";
8026
8027 namespace {
8028 const int hexThreshold = 255;
8029
8030 struct Endianness {
8031 enum Arch { Big, Little };
8032
8033 static Arch which() {
8034 union _{
8035 int asInt;
8036 char asChar[sizeof (int)];
8037 } u;
8038
8039 u.asInt = 1;
8040 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
8041 }
8042 };
8043 }
8044
8045 std::string rawMemoryToString( const void *object, std::size_t size )
8046 {
8047 // Reverse order for little endian architectures
8048 int i = 0, end = static_cast<int>( size ), inc = 1;
8049 if( Endianness::which() == Endianness::Little ) {
8050 i = end-1;
8051 end = inc = -1;
8052 }
8053
8054 unsigned char const *bytes = static_cast<unsigned char const *>(object);
8055 std::ostringstream os;
8056 os << "0x" << std::setfill('0') << std::hex;
8057 for( ; i != end; i += inc )
8058 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
8059 return os.str();
8060 }
8061 }
8062
8063 std::string toString( std::string const& value ) {
8064 std::string s = value;
8065 if( getCurrentContext().getConfig()->showInvisibles() ) {
8066 for(size_t i = 0; i < s.size(); ++i ) {
8067 std::string subs;
8068 switch( s[i] ) {
8069 case '\n': subs = "\\n"; break;
8070 case '\t': subs = "\\t"; break;
8071 default: break;
8072 }
8073 if( !subs.empty() ) {
8074 s = s.substr( 0, i ) + subs + s.substr( i+1 );
8075 ++i;
8076 }
8077 }
8078 }
8079 return "\"" + s + "\"";
8080 }
8081 std::string toString( std::wstring const& value ) {
8082
8083 std::string s;
8084 s.reserve( value.size() );
8085 for(size_t i = 0; i < value.size(); ++i )
8086 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
8087 return Catch::toString( s );
8088 }
8089
8090 std::string toString( const char* const value ) {
8091 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
8092 }
8093
8094 std::string toString( char* const value ) {
8095 return Catch::toString( static_cast<const char*>( value ) );
8096 }
8097
8098 std::string toString( const wchar_t* const value )
8099 {
8100 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
8101 }
8102
8103 std::string toString( wchar_t* const value )
8104 {
8105 return Catch::toString( static_cast<const wchar_t*>( value ) );
8106 }
8107
8108 std::string toString( int value ) {
8109 std::ostringstream oss;
8110 oss << value;
8111 if( value > Detail::hexThreshold )
8112 oss << " (0x" << std::hex << value << ")";
8113 return oss.str();
8114 }
8115
8116 std::string toString( unsigned long value ) {
8117 std::ostringstream oss;
8118 oss << value;
8119 if( value > Detail::hexThreshold )
8120 oss << " (0x" << std::hex << value << ")";
8121 return oss.str();
8122 }
8123
8124 std::string toString( unsigned int value ) {
8125 return Catch::toString( static_cast<unsigned long>( value ) );
8126 }
8127
8128 template<typename T>
8129 std::string fpToString( T value, int precision ) {
8130 std::ostringstream oss;
8131 oss << std::setprecision( precision )
8132 << std::fixed
8133 << value;
8134 std::string d = oss.str();
8135 std::size_t i = d.find_last_not_of( '0' );
8136 if( i != std::string::npos && i != d.size()-1 ) {
8137 if( d[i] == '.' )
8138 i++;
8139 d = d.substr( 0, i+1 );
8140 }
8141 return d;
8142 }
8143
8144 std::string toString( const double value ) {
8145 return fpToString( value, 10 );
8146 }
8147 std::string toString( const float value ) {
8148 return fpToString( value, 5 ) + "f";
8149 }
8150
8151 std::string toString( bool value ) {
8152 return value ? "true" : "false";
8153 }
8154
8155 std::string toString( char value ) {
8156 return value < ' '
8157 ? toString( static_cast<unsigned int>( value ) )
8158 : Detail::makeString( value );
8159 }
8160
8161 std::string toString( signed char value ) {
8162 return toString( static_cast<char>( value ) );
8163 }
8164
8165 std::string toString( unsigned char value ) {
8166 return toString( static_cast<char>( value ) );
8167 }
8168
8169 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
8170 std::string toString( long long value ) {
8171 std::ostringstream oss;
8172 oss << value;
8173 if( value > Detail::hexThreshold )
8174 oss << " (0x" << std::hex << value << ")";
8175 return oss.str();
8176 }
8177 std::string toString( unsigned long long value ) {
8178 std::ostringstream oss;
8179 oss << value;
8180 if( value > Detail::hexThreshold )
8181 oss << " (0x" << std::hex << value << ")";
8182 return oss.str();
8183 }
8184 #endif
8185
8186 #ifdef CATCH_CONFIG_CPP11_NULLPTR
8187 std::string toString( std::nullptr_t ) {
8188 return "nullptr";
8189 }
8190 #endif
8191
8192 #ifdef __OBJC__
8193 std::string toString( NSString const * const& nsstring ) {
8194 if( !nsstring )
8195 return "nil";
8196 return "@" + toString([nsstring UTF8String]);
8197 }
8198 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
8199 if( !nsstring )
8200 return "nil";
8201 return "@" + toString([nsstring UTF8String]);
8202 }
8203 std::string toString( NSObject* const& nsObject ) {
8204 return toString( [nsObject description] );
8205 }
8206 #endif
8207
8208 } // end namespace Catch
8209
8210 // #included from: catch_result_builder.hpp
8211 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
8212
8213 namespace Catch {
8214
8215 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
8216 return secondArg.empty() || secondArg == "\"\""
8217 ? capturedExpression
8218 : capturedExpression + ", " + secondArg;
8219 }
8220 ResultBuilder::ResultBuilder( char const* macroName,
8221 SourceLineInfo const& lineInfo,
8222 char const* capturedExpression,
8223 ResultDisposition::Flags resultDisposition,
8224 char const* secondArg )
8225 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
8226 m_shouldDebugBreak( false ),
8227 m_shouldThrow( false )
8228 {}
8229
8230 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
8231 m_data.resultType = result;
8232 return *this;
8233 }
8234 ResultBuilder& ResultBuilder::setResultType( bool result ) {
8235 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
8236 return *this;
8237 }
8238 ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) {
8239 m_exprComponents.lhs = lhs;
8240 return *this;
8241 }
8242 ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) {
8243 m_exprComponents.rhs = rhs;
8244 return *this;
8245 }
8246 ResultBuilder& ResultBuilder::setOp( std::string const& op ) {
8247 m_exprComponents.op = op;
8248 return *this;
8249 }
8250
8251 void ResultBuilder::endExpression() {
8252 m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition );
8253 captureExpression();
8254 }
8255
8256 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
8257 m_assertionInfo.resultDisposition = resultDisposition;
8258 m_stream.oss << Catch::translateActiveException();
8259 captureResult( ResultWas::ThrewException );
8260 }
8261
8262 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
8263 setResultType( resultType );
8264 captureExpression();
8265 }
8266 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
8267 if( expectedMessage.empty() )
8268 captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
8269 else
8270 captureExpectedException( Matchers::Equals( expectedMessage ) );
8271 }
8272
8273 void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
8274
8275 assert( m_exprComponents.testFalse == false );
8276 AssertionResultData data = m_data;
8277 data.resultType = ResultWas::Ok;
8278 data.reconstructedExpression = m_assertionInfo.capturedExpression;
8279
8280 std::string actualMessage = Catch::translateActiveException();
8281 if( !matcher.match( actualMessage ) ) {
8282 data.resultType = ResultWas::ExpressionFailed;
8283 data.reconstructedExpression = actualMessage;
8284 }
8285 AssertionResult result( m_assertionInfo, data );
8286 handleResult( result );
8287 }
8288
8289 void ResultBuilder::captureExpression() {
8290 AssertionResult result = build();
8291 handleResult( result );
8292 }
8293 void ResultBuilder::handleResult( AssertionResult const& result )
8294 {
8295 getResultCapture().assertionEnded( result );
8296
8297 if( !result.isOk() ) {
8298 if( getCurrentContext().getConfig()->shouldDebugBreak() )
8299 m_shouldDebugBreak = true;
8300 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
8301 m_shouldThrow = true;
8302 }
8303 }
8304 void ResultBuilder::react() {
8305 if( m_shouldThrow )
8306 throw Catch::TestFailureException();
8307 }
8308
8309 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
8310 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
8311
8312 AssertionResult ResultBuilder::build() const
8313 {
8314 assert( m_data.resultType != ResultWas::Unknown );
8315
8316 AssertionResultData data = m_data;
8317
8318 // Flip bool results if testFalse is set
8319 if( m_exprComponents.testFalse ) {
8320 if( data.resultType == ResultWas::Ok )
8321 data.resultType = ResultWas::ExpressionFailed;
8322 else if( data.resultType == ResultWas::ExpressionFailed )
8323 data.resultType = ResultWas::Ok;
8324 }
8325
8326 data.message = m_stream.oss.str();
8327 data.reconstructedExpression = reconstructExpression();
8328 if( m_exprComponents.testFalse ) {
8329 if( m_exprComponents.op == "" )
8330 data.reconstructedExpression = "!" + data.reconstructedExpression;
8331 else
8332 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
8333 }
8334 return AssertionResult( m_assertionInfo, data );
8335 }
8336 std::string ResultBuilder::reconstructExpression() const {
8337 if( m_exprComponents.op == "" )
8338 return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
8339 else if( m_exprComponents.op == "matches" )
8340 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
8341 else if( m_exprComponents.op != "!" ) {
8342 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
8343 m_exprComponents.lhs.find("\n") == std::string::npos &&
8344 m_exprComponents.rhs.find("\n") == std::string::npos )
8345 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
8346 else
8347 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
8348 }
8349 else
8350 return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
8351 }
8352
8353 } // end namespace Catch
8354
8355 // #included from: catch_tag_alias_registry.hpp
8356 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8357
8358 // #included from: catch_tag_alias_registry.h
8359 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
8360
8361 #include <map>
8362
8363 namespace Catch {
8364
8365 class TagAliasRegistry : public ITagAliasRegistry {
8366 public:
8367 virtual ~TagAliasRegistry();
8368 virtual Option<TagAlias> find( std::string const& alias ) const;
8369 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
8370 void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
8371 static TagAliasRegistry& get();
8372
8373 private:
8374 std::map<std::string, TagAlias> m_registry;
8375 };
8376
8377 } // end namespace Catch
8378
8379 #include <map>
8380 #include <iostream>
8381
8382 namespace Catch {
8383
8384 TagAliasRegistry::~TagAliasRegistry() {}
8385
8386 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
8387 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
8388 if( it != m_registry.end() )
8389 return it->second;
8390 else
8391 return Option<TagAlias>();
8392 }
8393
8394 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
8395 std::string expandedTestSpec = unexpandedTestSpec;
8396 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
8397 it != itEnd;
8398 ++it ) {
8399 std::size_t pos = expandedTestSpec.find( it->first );
8400 if( pos != std::string::npos ) {
8401 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
8402 it->second.tag +
8403 expandedTestSpec.substr( pos + it->first.size() );
8404 }
8405 }
8406 return expandedTestSpec;
8407 }
8408
8409 void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
8410
8411 if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) {
3531 std::ostringstream oss; 8412 std::ostringstream oss;
3532 oss << "Error while parsing " << m_name << ". " << message << "."; 8413 oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
3533 if( m_args.size() > 0 ) 8414 throw std::domain_error( oss.str().c_str() );
3534 oss << " Arguments where:"; 8415 }
3535 for( std::size_t i = 0; i < m_args.size(); ++i ) 8416 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
3536 oss << " " << m_args[i]; 8417 std::ostringstream oss;
3537 throw std::domain_error( oss.str() ); 8418 oss << "error: tag alias, \"" << alias << "\" already registered.\n"
3538 } 8419 << "\tFirst seen at " << find(alias)->lineInfo << "\n"
3539 8420 << "\tRedefined at " << lineInfo;
3540 private: 8421 throw std::domain_error( oss.str().c_str() );
3541 8422 }
3542 std::string m_name; 8423 }
3543 std::vector<std::string> m_args; 8424
3544 }; 8425 TagAliasRegistry& TagAliasRegistry::get() {
3545 8426 static TagAliasRegistry instance;
3546 class CommandParser { 8427 return instance;
8428
8429 }
8430
8431 ITagAliasRegistry::~ITagAliasRegistry() {}
8432 ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
8433
8434 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
8435 try {
8436 TagAliasRegistry::get().add( alias, tag, lineInfo );
8437 }
8438 catch( std::exception& ex ) {
8439 Colour colourGuard( Colour::Red );
8440 Catch::cerr() << ex.what() << std::endl;
8441 exit(1);
8442 }
8443 }
8444
8445 } // end namespace Catch
8446
8447 // #included from: ../reporters/catch_reporter_multi.hpp
8448 #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
8449
8450 namespace Catch {
8451
8452 class MultipleReporters : public SharedImpl<IStreamingReporter> {
8453 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
8454 Reporters m_reporters;
8455
8456 public:
8457 void add( Ptr<IStreamingReporter> const& reporter ) {
8458 m_reporters.push_back( reporter );
8459 }
8460
8461 public: // IStreamingReporter
8462
8463 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8464 return m_reporters[0]->getPreferences();
8465 }
8466
8467 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
8468 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8469 it != itEnd;
8470 ++it )
8471 (*it)->noMatchingTestCases( spec );
8472 }
8473
8474 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
8475 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8476 it != itEnd;
8477 ++it )
8478 (*it)->testRunStarting( testRunInfo );
8479 }
8480
8481 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
8482 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8483 it != itEnd;
8484 ++it )
8485 (*it)->testGroupStarting( groupInfo );
8486 }
8487
8488 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
8489 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8490 it != itEnd;
8491 ++it )
8492 (*it)->testCaseStarting( testInfo );
8493 }
8494
8495 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
8496 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8497 it != itEnd;
8498 ++it )
8499 (*it)->sectionStarting( sectionInfo );
8500 }
8501
8502 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
8503 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8504 it != itEnd;
8505 ++it )
8506 (*it)->assertionStarting( assertionInfo );
8507 }
8508
8509 // The return value indicates if the messages buffer should be cleared:
8510 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
8511 bool clearBuffer = false;
8512 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8513 it != itEnd;
8514 ++it )
8515 clearBuffer |= (*it)->assertionEnded( assertionStats );
8516 return clearBuffer;
8517 }
8518
8519 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
8520 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8521 it != itEnd;
8522 ++it )
8523 (*it)->sectionEnded( sectionStats );
8524 }
8525
8526 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
8527 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8528 it != itEnd;
8529 ++it )
8530 (*it)->testCaseEnded( testCaseStats );
8531 }
8532
8533 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
8534 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8535 it != itEnd;
8536 ++it )
8537 (*it)->testGroupEnded( testGroupStats );
8538 }
8539
8540 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
8541 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8542 it != itEnd;
8543 ++it )
8544 (*it)->testRunEnded( testRunStats );
8545 }
8546
8547 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
8548 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8549 it != itEnd;
8550 ++it )
8551 (*it)->skipTest( testInfo );
8552 }
8553
8554 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
8555 return this;
8556 }
8557
8558 };
8559
8560 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
8561 Ptr<IStreamingReporter> resultingReporter;
8562
8563 if( existingReporter ) {
8564 MultipleReporters* multi = existingReporter->tryAsMulti();
8565 if( !multi ) {
8566 multi = new MultipleReporters;
8567 resultingReporter = Ptr<IStreamingReporter>( multi );
8568 if( existingReporter )
8569 multi->add( existingReporter );
8570 }
8571 else
8572 resultingReporter = existingReporter;
8573 multi->add( additionalReporter );
8574 }
8575 else
8576 resultingReporter = additionalReporter;
8577
8578 return resultingReporter;
8579 }
8580
8581 } // end namespace Catch
8582
8583 // #included from: ../reporters/catch_reporter_xml.hpp
8584 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
8585
8586 // #included from: catch_reporter_bases.hpp
8587 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
8588
8589 #include <cstring>
8590
8591 namespace Catch {
8592
8593 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
8594
8595 StreamingReporterBase( ReporterConfig const& _config )
8596 : m_config( _config.fullConfig() ),
8597 stream( _config.stream() )
8598 {
8599 m_reporterPrefs.shouldRedirectStdOut = false;
8600 }
8601
8602 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8603 return m_reporterPrefs;
8604 }
8605
8606 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
8607
8608 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
8609
8610 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
8611 currentTestRunInfo = _testRunInfo;
8612 }
8613 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
8614 currentGroupInfo = _groupInfo;
8615 }
8616
8617 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
8618 currentTestCaseInfo = _testInfo;
8619 }
8620 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
8621 m_sectionStack.push_back( _sectionInfo );
8622 }
8623
8624 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
8625 m_sectionStack.pop_back();
8626 }
8627 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
8628 currentTestCaseInfo.reset();
8629 }
8630 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
8631 currentGroupInfo.reset();
8632 }
8633 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
8634 currentTestCaseInfo.reset();
8635 currentGroupInfo.reset();
8636 currentTestRunInfo.reset();
8637 }
8638
8639 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
8640 // Don't do anything with this by default.
8641 // It can optionally be overridden in the derived class.
8642 }
8643
8644 Ptr<IConfig const> m_config;
8645 std::ostream& stream;
8646
8647 LazyStat<TestRunInfo> currentTestRunInfo;
8648 LazyStat<GroupInfo> currentGroupInfo;
8649 LazyStat<TestCaseInfo> currentTestCaseInfo;
8650
8651 std::vector<SectionInfo> m_sectionStack;
8652 ReporterPreferences m_reporterPrefs;
8653 };
8654
8655 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
8656 template<typename T, typename ChildNodeT>
8657 struct Node : SharedImpl<> {
8658 explicit Node( T const& _value ) : value( _value ) {}
8659 virtual ~Node() {}
8660
8661 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
8662 T value;
8663 ChildNodes children;
8664 };
8665 struct SectionNode : SharedImpl<> {
8666 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
8667 virtual ~SectionNode();
8668
8669 bool operator == ( SectionNode const& other ) const {
8670 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
8671 }
8672 bool operator == ( Ptr<SectionNode> const& other ) const {
8673 return operator==( *other );
8674 }
8675
8676 SectionStats stats;
8677 typedef std::vector<Ptr<SectionNode> > ChildSections;
8678 typedef std::vector<AssertionStats> Assertions;
8679 ChildSections childSections;
8680 Assertions assertions;
8681 std::string stdOut;
8682 std::string stdErr;
8683 };
8684
8685 struct BySectionInfo {
8686 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
8687 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
8688 bool operator() ( Ptr<SectionNode> const& node ) const {
8689 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
8690 }
8691 private:
8692 void operator=( BySectionInfo const& );
8693 SectionInfo const& m_other;
8694 };
8695
8696 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
8697 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
8698 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
8699
8700 CumulativeReporterBase( ReporterConfig const& _config )
8701 : m_config( _config.fullConfig() ),
8702 stream( _config.stream() )
8703 {
8704 m_reporterPrefs.shouldRedirectStdOut = false;
8705 }
8706 ~CumulativeReporterBase();
8707
8708 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8709 return m_reporterPrefs;
8710 }
8711
8712 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
8713 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
8714
8715 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
8716
8717 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
8718 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
8719 Ptr<SectionNode> node;
8720 if( m_sectionStack.empty() ) {
8721 if( !m_rootSection )
8722 m_rootSection = new SectionNode( incompleteStats );
8723 node = m_rootSection;
8724 }
8725 else {
8726 SectionNode& parentNode = *m_sectionStack.back();
8727 SectionNode::ChildSections::const_iterator it =
8728 std::find_if( parentNode.childSections.begin(),
8729 parentNode.childSections.end(),
8730 BySectionInfo( sectionInfo ) );
8731 if( it == parentNode.childSections.end() ) {
8732 node = new SectionNode( incompleteStats );
8733 parentNode.childSections.push_back( node );
8734 }
8735 else
8736 node = *it;
8737 }
8738 m_sectionStack.push_back( node );
8739 m_deepestSection = node;
8740 }
8741
8742 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
8743
8744 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
8745 assert( !m_sectionStack.empty() );
8746 SectionNode& sectionNode = *m_sectionStack.back();
8747 sectionNode.assertions.push_back( assertionStats );
8748 return true;
8749 }
8750 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
8751 assert( !m_sectionStack.empty() );
8752 SectionNode& node = *m_sectionStack.back();
8753 node.stats = sectionStats;
8754 m_sectionStack.pop_back();
8755 }
8756 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
8757 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
8758 assert( m_sectionStack.size() == 0 );
8759 node->children.push_back( m_rootSection );
8760 m_testCases.push_back( node );
8761 m_rootSection.reset();
8762
8763 assert( m_deepestSection );
8764 m_deepestSection->stdOut = testCaseStats.stdOut;
8765 m_deepestSection->stdErr = testCaseStats.stdErr;
8766 }
8767 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
8768 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
8769 node->children.swap( m_testCases );
8770 m_testGroups.push_back( node );
8771 }
8772 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
8773 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
8774 node->children.swap( m_testGroups );
8775 m_testRuns.push_back( node );
8776 testRunEndedCumulative();
8777 }
8778 virtual void testRunEndedCumulative() = 0;
8779
8780 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
8781
8782 Ptr<IConfig const> m_config;
8783 std::ostream& stream;
8784 std::vector<AssertionStats> m_assertions;
8785 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
8786 std::vector<Ptr<TestCaseNode> > m_testCases;
8787 std::vector<Ptr<TestGroupNode> > m_testGroups;
8788
8789 std::vector<Ptr<TestRunNode> > m_testRuns;
8790
8791 Ptr<SectionNode> m_rootSection;
8792 Ptr<SectionNode> m_deepestSection;
8793 std::vector<Ptr<SectionNode> > m_sectionStack;
8794 ReporterPreferences m_reporterPrefs;
8795
8796 };
8797
8798 template<char C>
8799 char const* getLineOfChars() {
8800 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
8801 if( !*line ) {
8802 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
8803 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
8804 }
8805 return line;
8806 }
8807
8808 struct TestEventListenerBase : StreamingReporterBase {
8809 TestEventListenerBase( ReporterConfig const& _config )
8810 : StreamingReporterBase( _config )
8811 {}
8812
8813 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
8814 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
8815 return false;
8816 }
8817 };
8818
8819 } // end namespace Catch
8820
8821 // #included from: ../internal/catch_reporter_registrars.hpp
8822 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
8823
8824 namespace Catch {
8825
8826 template<typename T>
8827 class LegacyReporterRegistrar {
8828
8829 class ReporterFactory : public IReporterFactory {
8830 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
8831 return new LegacyReporterAdapter( new T( config ) );
8832 }
8833
8834 virtual std::string getDescription() const {
8835 return T::getDescription();
8836 }
8837 };
8838
3547 public: 8839 public:
3548 CommandParser( int argc, char const * const * argv ) : m_argc( static_cast<std::size_t>( argc ) ), m_argv( argv ) {} 8840
3549 8841 LegacyReporterRegistrar( std::string const& name ) {
3550 Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const { 8842 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
3551 return find( arg1 ) + find( arg2 ) + find( arg3 ); 8843 }
3552 } 8844 };
3553
3554 Command find( const std::string& shortArg, const std::string& longArg ) const {
3555 return find( shortArg ) + find( longArg );
3556 }
3557 Command find( const std::string& arg ) const {
3558 for( std::size_t i = 0; i < m_argc; ++i )
3559 if( m_argv[i] == arg )
3560 return getArgs( i );
3561 return Command();
3562 }
3563
3564 private:
3565 Command getArgs( std::size_t from ) const {
3566 Command command( m_argv[from] );
3567 for( std::size_t i = from+1; i < m_argc && m_argv[i][0] != '-'; ++i )
3568 command += m_argv[i];
3569 return command;
3570 }
3571
3572 std::size_t m_argc;
3573 char const * const * m_argv;
3574 };
3575
3576 inline bool parseIntoConfig( const CommandParser& parser, Config& config ) {
3577
3578 try {
3579 if( Command cmd = parser.find( "-l", "--list" ) ) {
3580 if( cmd.argsCount() > 2 )
3581 cmd.raiseError( "Expected upto 2 arguments" );
3582
3583 List::What listSpec = List::All;
3584 if( cmd.argsCount() >= 1 ) {
3585 if( cmd[0] == "tests" )
3586 listSpec = List::Tests;
3587 else if( cmd[0] == "reporters" )
3588 listSpec = List::Reports;
3589 else
3590 cmd.raiseError( "Expected [tests] or [reporters]" );
3591 }
3592 if( cmd.argsCount() >= 2 ) {
3593 if( cmd[1] == "xml" )
3594 listSpec = static_cast<List::What>( listSpec | List::AsXml );
3595 else if( cmd[1] == "text" )
3596 listSpec = static_cast<List::What>( listSpec | List::AsText );
3597 else
3598 cmd.raiseError( "Expected [xml] or [text]" );
3599 }
3600 config.setListSpec( static_cast<List::What>( config.getListSpec() | listSpec ) );
3601 }
3602
3603 if( Command cmd = parser.find( "-t", "--test" ) ) {
3604 if( cmd.argsCount() == 0 )
3605 cmd.raiseError( "Expected at least one argument" );
3606 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3607 config.addTestSpec( cmd[i] );
3608 }
3609
3610 if( Command cmd = parser.find( "-r", "--reporter" ) ) {
3611 if( cmd.argsCount() != 1 )
3612 cmd.raiseError( "Expected one argument" );
3613 config.setReporter( cmd[0] );
3614 }
3615
3616 if( Command cmd = parser.find( "-o", "--out" ) ) {
3617 if( cmd.argsCount() == 0 )
3618 cmd.raiseError( "Expected filename" );
3619 if( cmd[0][0] == '%' )
3620 config.useStream( cmd[0].substr( 1 ) );
3621 else
3622 config.setFilename( cmd[0] );
3623 }
3624
3625 if( Command cmd = parser.find( "-s", "--success" ) ) {
3626 if( cmd.argsCount() != 0 )
3627 cmd.raiseError( "Does not accept arguments" );
3628 config.setIncludeWhichResults( Include::SuccessfulResults );
3629 }
3630
3631 if( Command cmd = parser.find( "-b", "--break" ) ) {
3632 if( cmd.argsCount() != 0 )
3633 cmd.raiseError( "Does not accept arguments" );
3634 config.setShouldDebugBreak( true );
3635 }
3636
3637 if( Command cmd = parser.find( "-n", "--name" ) ) {
3638 if( cmd.argsCount() != 1 )
3639 cmd.raiseError( "Expected a name" );
3640 config.setName( cmd[0] );
3641 }
3642
3643 if( Command cmd = parser.find( "-h", "-?", "--help" ) ) {
3644 if( cmd.argsCount() != 0 )
3645 cmd.raiseError( "Does not accept arguments" );
3646 config.setShowHelp( true );
3647 }
3648
3649 if( Command cmd = parser.find( "-a", "--abort" ) ) {
3650 if( cmd.argsCount() > 1 )
3651 cmd.raiseError( "Only accepts 0-1 arguments" );
3652 int threshold = 1;
3653 if( cmd.argsCount() == 1 )
3654 {
3655 std::stringstream ss;
3656 ss << cmd[0];
3657 ss >> threshold;
3658 }
3659 config.setCutoff( threshold );
3660 }
3661
3662 if( Command cmd = parser.find( "-nt", "--nothrow" ) ) {
3663 if( cmd.argsCount() != 0 )
3664 cmd.raiseError( "Does not accept arguments" );
3665 config.setAllowThrows( false );
3666 }
3667
3668 }
3669 catch( std::exception& ex ) {
3670 config.setError( ex.what() );
3671 return false;
3672 }
3673 return true;
3674 }
3675
3676 } // end namespace Catch
3677
3678 // #included from: internal/catch_list.hpp
3679
3680 #include <limits>
3681
3682 namespace Catch {
3683 inline int List( Config& config ) {
3684
3685 IContext& context = getCurrentContext();
3686 if( config.listWhat() & List::Reports ) {
3687 std::cout << "Available reports:\n";
3688 IReporterRegistry::FactoryMap::const_iterator it = context.getReporterRegistry().getFactories().begin();
3689 IReporterRegistry::FactoryMap::const_iterator itEnd = context.getReporterRegistry().getFactories().end();
3690 for(; it != itEnd; ++it ) {
3691 // !TBD: consider listAs()
3692 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
3693 }
3694 std::cout << std::endl;
3695 }
3696
3697 if( config.listWhat() & List::Tests ) {
3698 std::cout << "Available tests:\n";
3699 std::vector<TestCaseInfo>::const_iterator it = context.getTestCaseRegistry().getAllTests().begin();
3700 std::vector<TestCaseInfo>::const_iterator itEnd = context.getTestCaseRegistry().getAllTests().end();
3701 for(; it != itEnd; ++it ) {
3702 // !TBD: consider listAs()
3703 std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n";
3704 }
3705 std::cout << std::endl;
3706 }
3707
3708 if( ( config.listWhat() & List::All ) == 0 ) {
3709 std::cerr << "Unknown list type" << std::endl;
3710 return (std::numeric_limits<int>::max)();
3711 }
3712
3713 if( config.getReporter().get() )
3714 std::cerr << "Reporters ignored when listing" << std::endl;
3715 if( !config.testsSpecified() )
3716 std::cerr << "Test specs ignored when listing" << std::endl;
3717 return 0;
3718 }
3719
3720 } // end namespace Catch
3721
3722 // #included from: reporters/catch_reporter_basic.hpp
3723
3724 // #included from: ../internal/catch_reporter_registrars.hpp
3725
3726 namespace Catch {
3727 8845
3728 template<typename T> 8846 template<typename T>
3729 class ReporterRegistrar { 8847 class ReporterRegistrar {
3730 8848
3731 class ReporterFactory : public IReporterFactory { 8849 class ReporterFactory : public SharedImpl<IReporterFactory> {
3732 8850
3733 virtual IReporter* create( const IReporterConfig& config ) const { 8851 // *** Please Note ***:
8852 // - If you end up here looking at a compiler error because it's trying to register
8853 // your custom reporter class be aware that the native reporter interface has changed
8854 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
8855 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
8856 // However please consider updating to the new interface as the old one is now
8857 // deprecated and will probably be removed quite soon!
8858 // Please contact me via github if you have any questions at all about this.
8859 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
8860 // no idea who is actually using custom reporters at all (possibly no-one!).
8861 // The new interface is designed to minimise exposure to interface changes in the future.
8862 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
3734 return new T( config ); 8863 return new T( config );
3735 } 8864 }
3736 8865
3737 virtual std::string getDescription() const { 8866 virtual std::string getDescription() const {
3738 return T::getDescription(); 8867 return T::getDescription();
3739 } 8868 }
3740 }; 8869 };
3741 8870
3742 public: 8871 public:
3743 8872
3744 ReporterRegistrar( const std::string& name ) { 8873 ReporterRegistrar( std::string const& name ) {
3745 getCurrentContext().getReporterRegistry().registerReporter( name, new ReporterFactory() ); 8874 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
8875 }
8876 };
8877
8878 template<typename T>
8879 class ListenerRegistrar {
8880
8881 class ListenerFactory : public SharedImpl<IReporterFactory> {
8882
8883 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
8884 return new T( config );
8885 }
8886 virtual std::string getDescription() const {
8887 return "";
8888 }
8889 };
8890
8891 public:
8892
8893 ListenerRegistrar() {
8894 getMutableRegistryHub().registerListener( new ListenerFactory() );
3746 } 8895 }
3747 }; 8896 };
3748 } 8897 }
3749 8898
8899 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
8900 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
8901
3750 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ 8902 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
3751 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); 8903 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
3752 8904
3753 namespace Catch { 8905 #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
3754 8906 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
3755 struct pluralise {
3756 pluralise( std::size_t count, const std::string& label )
3757 : m_count( count ),
3758 m_label( label )
3759 {}
3760
3761 friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) {
3762 os << pluraliser.m_count << " " << pluraliser.m_label;
3763 if( pluraliser.m_count != 1 )
3764 os << "s";
3765 return os;
3766 }
3767
3768 std::size_t m_count;
3769 std::string m_label;
3770 };
3771
3772 class BasicReporter : public SharedImpl<IReporter> {
3773
3774 struct SpanInfo {
3775
3776 SpanInfo()
3777 : emitted( false )
3778 {}
3779
3780 SpanInfo( const std::string& spanName )
3781 : name( spanName ),
3782 emitted( false )
3783 {}
3784
3785 SpanInfo( const SpanInfo& other )
3786 : name( other.name ),
3787 emitted( other.emitted )
3788 {}
3789
3790 std::string name;
3791 bool emitted;
3792 };
3793
3794 public:
3795 BasicReporter( const IReporterConfig& config )
3796 : m_config( config ),
3797 m_firstSectionInTestCase( true ),
3798 m_aborted( false )
3799 {}
3800
3801 static std::string getDescription() {
3802 return "Reports test results as lines of text";
3803 }
3804
3805 private:
3806
3807 void ReportCounts( const std::string& label, const Counts& counts, const std::string& allPrefix = "All " ) {
3808 if( counts.passed )
3809 m_config.stream() << counts.failed << " of " << counts.total() << " " << label << "s failed";
3810 else
3811 m_config.stream() << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
3812 }
3813
3814 void ReportCounts( const Totals& totals, const std::string& allPrefix = "All " ) {
3815 if( totals.assertions.total() == 0 ) {
3816 m_config.stream() << "No tests ran";
3817 }
3818 else if( totals.assertions.failed ) {
3819 TextColour colour( TextColour::ResultError );
3820 ReportCounts( "test case", totals.testCases, allPrefix );
3821 if( totals.testCases.failed > 0 ) {
3822 m_config.stream() << " (";
3823 ReportCounts( "assertion", totals.assertions, allPrefix );
3824 m_config.stream() << ")";
3825 }
3826 }
3827 else {
3828 TextColour colour( TextColour::ResultSuccess );
3829 m_config.stream() << allPrefix << "tests passed ("
3830 << pluralise( totals.assertions.passed, "assertion" ) << " in "
3831 << pluralise( totals.testCases.passed, "test case" ) << ")";
3832 }
3833 }
3834
3835 private: // IReporter
3836
3837 virtual bool shouldRedirectStdout() const {
3838 return false;
3839 }
3840
3841 virtual void StartTesting() {
3842 m_testingSpan = SpanInfo();
3843 }
3844
3845 virtual void Aborted() {
3846 m_aborted = true;
3847 }
3848
3849 virtual void EndTesting( const Totals& totals ) {
3850 // Output the overall test results even if "Started Testing" was not emitted
3851 if( m_aborted ) {
3852 m_config.stream() << "\n[Testing aborted. ";
3853 ReportCounts( totals, "The first " );
3854 }
3855 else {
3856 m_config.stream() << "\n[Testing completed. ";
3857 ReportCounts( totals );
3858 }
3859 m_config.stream() << "]\n" << std::endl;
3860 }
3861
3862 virtual void StartGroup( const std::string& groupName ) {
3863 m_groupSpan = groupName;
3864 }
3865
3866 virtual void EndGroup( const std::string& groupName, const Totals& totals ) {
3867 if( m_groupSpan.emitted && !groupName.empty() ) {
3868 m_config.stream() << "[End of group: '" << groupName << "'. ";
3869 ReportCounts( totals );
3870 m_config.stream() << "]\n" << std::endl;
3871 m_groupSpan = SpanInfo();
3872 }
3873 }
3874
3875 virtual void StartTestCase( const TestCaseInfo& testInfo ) {
3876 m_testSpan = testInfo.getName();
3877 }
3878
3879 virtual void StartSection( const std::string& sectionName, const std::string& ) {
3880 m_sectionSpans.push_back( SpanInfo( sectionName ) );
3881 }
3882
3883 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
3884 SpanInfo& sectionSpan = m_sectionSpans.back();
3885 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
3886 m_config.stream() << "[End of section: '" << sectionName << "' ";
3887
3888 if( assertions.failed ) {
3889 TextColour colour( TextColour::ResultError );
3890 ReportCounts( "assertion", assertions);
3891 }
3892 else {
3893 TextColour colour( TextColour::ResultSuccess );
3894 m_config.stream() << ( assertions.passed > 1 ? "All " : "" )
3895 << pluralise( assertions.passed, "assertion" ) << "passed" ;
3896 }
3897 m_config.stream() << "]\n" << std::endl;
3898 }
3899 m_sectionSpans.pop_back();
3900 }
3901
3902 virtual void Result( const ResultInfo& resultInfo ) {
3903 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
3904 return;
3905
3906 StartSpansLazily();
3907
3908 if( !resultInfo.getFilename().empty() ) {
3909 TextColour colour( TextColour::FileName );
3910 m_config.stream() << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
3911 }
3912
3913 if( resultInfo.hasExpression() ) {
3914 TextColour colour( TextColour::OriginalExpression );
3915 m_config.stream() << resultInfo.getExpression();
3916 if( resultInfo.ok() ) {
3917 TextColour successColour( TextColour::Success );
3918 m_config.stream() << " succeeded";
3919 }
3920 else {
3921 TextColour errorColour( TextColour::Error );
3922 m_config.stream() << " failed";
3923 }
3924 }
3925 switch( resultInfo.getResultType() ) {
3926 case ResultWas::ThrewException:
3927 {
3928 TextColour colour( TextColour::Error );
3929 if( resultInfo.hasExpression() )
3930 m_config.stream() << " with unexpected";
3931 else
3932 m_config.stream() << "Unexpected";
3933 m_config.stream() << " exception with message: '" << resultInfo.getMessage() << "'";
3934 }
3935 break;
3936 case ResultWas::DidntThrowException:
3937 {
3938 TextColour colour( TextColour::Error );
3939 if( resultInfo.hasExpression() )
3940 m_config.stream() << " because no exception was thrown where one was expected";
3941 else
3942 m_config.stream() << "No exception thrown where one was expected";
3943 }
3944 break;
3945 case ResultWas::Info:
3946 streamVariableLengthText( "info", resultInfo.getMessage() );
3947 break;
3948 case ResultWas::Warning:
3949 m_config.stream() << "warning:\n'" << resultInfo.getMessage() << "'";
3950 break;
3951 case ResultWas::ExplicitFailure:
3952 {
3953 TextColour colour( TextColour::Error );
3954 m_config.stream() << "failed with message: '" << resultInfo.getMessage() << "'";
3955 }
3956 break;
3957 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
3958 case ResultWas::Ok:
3959 case ResultWas::FailureBit:
3960 case ResultWas::ExpressionFailed:
3961 case ResultWas::Exception:
3962 default:
3963 if( !resultInfo.hasExpression() ) {
3964 if( resultInfo.ok() ) {
3965 TextColour colour( TextColour::Success );
3966 m_config.stream() << " succeeded";
3967 }
3968 else {
3969 TextColour colour( TextColour::Error );
3970 m_config.stream() << " failed";
3971 }
3972 }
3973 break;
3974 }
3975
3976 if( resultInfo.hasExpandedExpression() ) {
3977 m_config.stream() << " for: ";
3978 TextColour colour( TextColour::ReconstructedExpression );
3979 m_config.stream() << resultInfo.getExpandedExpression();
3980 }
3981 m_config.stream() << std::endl;
3982 }
3983
3984 virtual void EndTestCase( const TestCaseInfo& testInfo,
3985 const Totals& totals,
3986 const std::string& stdOut,
3987 const std::string& stdErr ) {
3988 if( !stdOut.empty() ) {
3989 StartSpansLazily();
3990 streamVariableLengthText( "stdout", stdOut );
3991 }
3992
3993 if( !stdErr.empty() ) {
3994 StartSpansLazily();
3995 streamVariableLengthText( "stderr", stdErr );
3996 }
3997
3998 if( m_testSpan.emitted ) {
3999 m_config.stream() << "[Finished: '" << testInfo.getName() << "' ";
4000 ReportCounts( totals );
4001 m_config.stream() << "]" << std::endl;
4002 }
4003 }
4004
4005 private: // helpers
4006
4007 void StartSpansLazily() {
4008 if( !m_testingSpan.emitted ) {
4009 if( m_config.getName().empty() )
4010 m_config.stream() << "[Started testing]" << std::endl;
4011 else
4012 m_config.stream() << "[Started testing: " << m_config.getName() << "]" << std::endl;
4013 m_testingSpan.emitted = true;
4014 }
4015
4016 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
4017 m_config.stream() << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
4018 m_groupSpan.emitted = true;
4019 }
4020
4021 if( !m_testSpan.emitted ) {
4022 m_config.stream() << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
4023 m_testSpan.emitted = true;
4024 }
4025
4026 if( !m_sectionSpans.empty() ) {
4027 SpanInfo& sectionSpan = m_sectionSpans.back();
4028 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
4029 if( m_firstSectionInTestCase ) {
4030 m_config.stream() << "\n";
4031 m_firstSectionInTestCase = false;
4032 }
4033 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
4034 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
4035 for(; it != itEnd; ++it ) {
4036 SpanInfo& prevSpan = *it;
4037 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
4038 m_config.stream() << "[Started section: '" << prevSpan.name << "']" << std::endl;
4039 prevSpan.emitted = true;
4040 }
4041 }
4042 }
4043 }
4044 }
4045
4046 void streamVariableLengthText( const std::string& prefix, const std::string& text ) {
4047 std::string trimmed = trim( text );
4048 if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) {
4049 m_config.stream() << "[" << prefix << ": " << trimmed << "]\n";
4050 }
4051 else {
4052 m_config.stream() << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
4053 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
4054 }
4055 }
4056
4057 private:
4058 const IReporterConfig& m_config;
4059 bool m_firstSectionInTestCase;
4060
4061 SpanInfo m_testingSpan;
4062 SpanInfo m_groupSpan;
4063 SpanInfo m_testSpan;
4064 std::vector<SpanInfo> m_sectionSpans;
4065 bool m_aborted;
4066 };
4067
4068 } // end namespace Catch
4069
4070 // #included from: reporters/catch_reporter_xml.hpp
4071 8907
4072 // #included from: ../internal/catch_xmlwriter.hpp 8908 // #included from: ../internal/catch_xmlwriter.hpp
8909 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
4073 8910
4074 #include <sstream> 8911 #include <sstream>
4075 #include <string> 8912 #include <string>
4076 #include <vector> 8913 #include <vector>
8914 #include <iomanip>
4077 8915
4078 namespace Catch { 8916 namespace Catch {
8917
8918 class XmlEncode {
8919 public:
8920 enum ForWhat { ForTextNodes, ForAttributes };
8921
8922 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
8923 : m_str( str ),
8924 m_forWhat( forWhat )
8925 {}
8926
8927 void encodeTo( std::ostream& os ) const {
8928
8929 // Apostrophe escaping not necessary if we always use " to write attributes
8930 // (see: http://www.w3.org/TR/xml/#syntax)
8931
8932 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
8933 char c = m_str[i];
8934 switch( c ) {
8935 case '<': os << "&lt;"; break;
8936 case '&': os << "&amp;"; break;
8937
8938 case '>':
8939 // See: http://www.w3.org/TR/xml/#syntax
8940 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
8941 os << "&gt;";
8942 else
8943 os << c;
8944 break;
8945
8946 case '\"':
8947 if( m_forWhat == ForAttributes )
8948 os << "&quot;";
8949 else
8950 os << c;
8951 break;
8952
8953 default:
8954 // Escape control chars - based on contribution by @espenalb in PR #465
8955 if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
8956 os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
8957 else
8958 os << c;
8959 }
8960 }
8961 }
8962
8963 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
8964 xmlEncode.encodeTo( os );
8965 return os;
8966 }
8967
8968 private:
8969 std::string m_str;
8970 ForWhat m_forWhat;
8971 };
4079 8972
4080 class XmlWriter { 8973 class XmlWriter {
4081 public: 8974 public:
4082 8975
4083 class ScopedElement { 8976 class ScopedElement {
4084 public: 8977 public:
4085 ScopedElement( XmlWriter* writer ) 8978 ScopedElement( XmlWriter* writer )
4086 : m_writer( writer ) 8979 : m_writer( writer )
4087 {} 8980 {}
4088 8981
4089 ScopedElement( const ScopedElement& other ) 8982 ScopedElement( ScopedElement const& other )
4090 : m_writer( other.m_writer ){ 8983 : m_writer( other.m_writer ){
4091 other.m_writer = NULL; 8984 other.m_writer = CATCH_NULL;
4092 } 8985 }
4093 8986
4094 ~ScopedElement() { 8987 ~ScopedElement() {
4095 if( m_writer ) 8988 if( m_writer )
4096 m_writer->endElement(); 8989 m_writer->endElement();
4097 } 8990 }
4098 8991
4099 ScopedElement& writeText( const std::string& text ) { 8992 ScopedElement& writeText( std::string const& text, bool indent = true ) {
4100 m_writer->writeText( text ); 8993 m_writer->writeText( text, indent );
4101 return *this; 8994 return *this;
4102 } 8995 }
4103 8996
4104 template<typename T> 8997 template<typename T>
4105 ScopedElement& writeAttribute( const std::string& name, const T& attribute ) { 8998 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
4106 m_writer->writeAttribute( name, attribute ); 8999 m_writer->writeAttribute( name, attribute );
4107 return *this; 9000 return *this;
4108 } 9001 }
4109 9002
4110 private: 9003 private:
4112 }; 9005 };
4113 9006
4114 XmlWriter() 9007 XmlWriter()
4115 : m_tagIsOpen( false ), 9008 : m_tagIsOpen( false ),
4116 m_needsNewline( false ), 9009 m_needsNewline( false ),
4117 m_os( &std::cout ) 9010 m_os( &Catch::cout() )
4118 {} 9011 {}
4119 9012
4120 XmlWriter( std::ostream& os ) 9013 XmlWriter( std::ostream& os )
4121 : m_tagIsOpen( false ), 9014 : m_tagIsOpen( false ),
4122 m_needsNewline( false ), 9015 m_needsNewline( false ),
4126 ~XmlWriter() { 9019 ~XmlWriter() {
4127 while( !m_tags.empty() ) 9020 while( !m_tags.empty() )
4128 endElement(); 9021 endElement();
4129 } 9022 }
4130 9023
4131 XmlWriter& operator = ( const XmlWriter& other ) { 9024 XmlWriter& startElement( std::string const& name ) {
4132 XmlWriter temp( other );
4133 swap( temp );
4134 return *this;
4135 }
4136
4137 void swap( XmlWriter& other ) {
4138 std::swap( m_tagIsOpen, other.m_tagIsOpen );
4139 std::swap( m_needsNewline, other.m_needsNewline );
4140 std::swap( m_tags, other.m_tags );
4141 std::swap( m_indent, other.m_indent );
4142 std::swap( m_os, other.m_os );
4143 }
4144
4145 XmlWriter& startElement( const std::string& name ) {
4146 ensureTagClosed(); 9025 ensureTagClosed();
4147 newlineIfNecessary(); 9026 newlineIfNecessary();
4148 stream() << m_indent << "<" << name; 9027 stream() << m_indent << "<" << name;
4149 m_tags.push_back( name ); 9028 m_tags.push_back( name );
4150 m_indent += " "; 9029 m_indent += " ";
4151 m_tagIsOpen = true; 9030 m_tagIsOpen = true;
4152 return *this; 9031 return *this;
4153 } 9032 }
4154 9033
4155 ScopedElement scopedElement( const std::string& name ) { 9034 ScopedElement scopedElement( std::string const& name ) {
4156 ScopedElement scoped( this ); 9035 ScopedElement scoped( this );
4157 startElement( name ); 9036 startElement( name );
4158 return scoped; 9037 return scoped;
4159 } 9038 }
4160 9039
4170 } 9049 }
4171 m_tags.pop_back(); 9050 m_tags.pop_back();
4172 return *this; 9051 return *this;
4173 } 9052 }
4174 9053
4175 XmlWriter& writeAttribute( const std::string& name, const std::string& attribute ) { 9054 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
4176 if( !name.empty() && !attribute.empty() ) { 9055 if( !name.empty() && !attribute.empty() )
4177 stream() << " " << name << "=\""; 9056 stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\"";
4178 writeEncodedText( attribute );
4179 stream() << "\"";
4180 }
4181 return *this; 9057 return *this;
4182 } 9058 }
4183 9059
4184 XmlWriter& writeAttribute( const std::string& name, bool attribute ) { 9060 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
4185 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; 9061 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
4186 return *this; 9062 return *this;
4187 } 9063 }
4188 9064
4189 template<typename T> 9065 template<typename T>
4190 XmlWriter& writeAttribute( const std::string& name, const T& attribute ) { 9066 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
4191 if( !name.empty() ) 9067 std::ostringstream oss;
4192 stream() << " " << name << "=\"" << attribute << "\""; 9068 oss << attribute;
4193 return *this; 9069 return writeAttribute( name, oss.str() );
4194 } 9070 }
4195 9071
4196 XmlWriter& writeText( const std::string& text ) { 9072 XmlWriter& writeText( std::string const& text, bool indent = true ) {
4197 if( !text.empty() ){ 9073 if( !text.empty() ){
4198 bool tagWasOpen = m_tagIsOpen; 9074 bool tagWasOpen = m_tagIsOpen;
4199 ensureTagClosed(); 9075 ensureTagClosed();
4200 if( tagWasOpen ) 9076 if( tagWasOpen && indent )
4201 stream() << m_indent; 9077 stream() << m_indent;
4202 writeEncodedText( text ); 9078 stream() << XmlEncode( text );
4203 m_needsNewline = true; 9079 m_needsNewline = true;
4204 } 9080 }
4205 return *this; 9081 return *this;
4206 } 9082 }
4207 9083
4208 XmlWriter& writeComment( const std::string& text ) { 9084 XmlWriter& writeComment( std::string const& text ) {
4209 ensureTagClosed(); 9085 ensureTagClosed();
4210 stream() << m_indent << "<!--" << text << "-->"; 9086 stream() << m_indent << "<!--" << text << "-->";
4211 m_needsNewline = true; 9087 m_needsNewline = true;
4212 return *this; 9088 return *this;
4213 } 9089 }
4216 ensureTagClosed(); 9092 ensureTagClosed();
4217 stream() << "\n"; 9093 stream() << "\n";
4218 return *this; 9094 return *this;
4219 } 9095 }
4220 9096
9097 void setStream( std::ostream& os ) {
9098 m_os = &os;
9099 }
9100
4221 private: 9101 private:
9102 XmlWriter( XmlWriter const& );
9103 void operator=( XmlWriter const& );
4222 9104
4223 std::ostream& stream() { 9105 std::ostream& stream() {
4224 return *m_os; 9106 return *m_os;
4225 } 9107 }
4226 9108
4234 void newlineIfNecessary() { 9116 void newlineIfNecessary() {
4235 if( m_needsNewline ) { 9117 if( m_needsNewline ) {
4236 stream() << "\n"; 9118 stream() << "\n";
4237 m_needsNewline = false; 9119 m_needsNewline = false;
4238 } 9120 }
4239 }
4240
4241 void writeEncodedText( const std::string& text ) {
4242 static const char* charsToEncode = "<&\"";
4243 std::string mtext = text;
4244 std::string::size_type pos = mtext.find_first_of( charsToEncode );
4245 while( pos != std::string::npos ) {
4246 stream() << mtext.substr( 0, pos );
4247
4248 switch( mtext[pos] ) {
4249 case '<':
4250 stream() << "&lt;";
4251 break;
4252 case '&':
4253 stream() << "&amp;";
4254 break;
4255 case '\"':
4256 stream() << "&quot;";
4257 break;
4258 }
4259 mtext = mtext.substr( pos+1 );
4260 pos = mtext.find_first_of( charsToEncode );
4261 }
4262 stream() << mtext;
4263 } 9121 }
4264 9122
4265 bool m_tagIsOpen; 9123 bool m_tagIsOpen;
4266 bool m_needsNewline; 9124 bool m_needsNewline;
4267 std::vector<std::string> m_tags; 9125 std::vector<std::string> m_tags;
4268 std::string m_indent; 9126 std::string m_indent;
4269 std::ostream* m_os; 9127 std::ostream* m_os;
4270 }; 9128 };
4271 9129
4272 } 9130 }
9131 // #included from: catch_reenable_warnings.h
9132
9133 #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
9134
9135 #ifdef __clang__
9136 # ifdef __ICC // icpc defines the __clang__ macro
9137 # pragma warning(pop)
9138 # else
9139 # pragma clang diagnostic pop
9140 # endif
9141 #elif defined __GNUC__
9142 # pragma GCC diagnostic pop
9143 #endif
9144
9145
4273 namespace Catch { 9146 namespace Catch {
4274 class XmlReporter : public SharedImpl<IReporter> { 9147 class XmlReporter : public StreamingReporterBase {
4275 public: 9148 public:
4276 XmlReporter( const IReporterConfig& config ) : m_config( config ) {} 9149 XmlReporter( ReporterConfig const& _config )
9150 : StreamingReporterBase( _config ),
9151 m_sectionDepth( 0 )
9152 {
9153 m_reporterPrefs.shouldRedirectStdOut = true;
9154 }
9155
9156 virtual ~XmlReporter() CATCH_OVERRIDE;
4277 9157
4278 static std::string getDescription() { 9158 static std::string getDescription() {
4279 return "Reports test results as an XML document"; 9159 return "Reports test results as an XML document";
4280 } 9160 }
4281 9161
4282 private: // IReporter 9162 public: // StreamingReporterBase
4283 9163
4284 virtual bool shouldRedirectStdout() const { 9164 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
4285 return true; 9165 StreamingReporterBase::noMatchingTestCases( s );
4286 } 9166 }
4287 9167
4288 virtual void StartTesting() { 9168 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
4289 m_xml = XmlWriter( m_config.stream() ); 9169 StreamingReporterBase::testRunStarting( testInfo );
9170 m_xml.setStream( stream );
4290 m_xml.startElement( "Catch" ); 9171 m_xml.startElement( "Catch" );
4291 if( !m_config.getName().empty() ) 9172 if( !m_config->name().empty() )
4292 m_xml.writeAttribute( "name", m_config.getName() ); 9173 m_xml.writeAttribute( "name", m_config->name() );
4293 } 9174 }
4294 9175
4295 virtual void EndTesting( const Totals& totals ) { 9176 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
4296 m_xml.scopedElement( "OverallResults" ) 9177 StreamingReporterBase::testGroupStarting( groupInfo );
4297 .writeAttribute( "successes", totals.assertions.passed )
4298 .writeAttribute( "failures", totals.assertions.failed );
4299 m_xml.endElement();
4300 }
4301
4302 virtual void StartGroup( const std::string& groupName ) {
4303 m_xml.startElement( "Group" ) 9178 m_xml.startElement( "Group" )
4304 .writeAttribute( "name", groupName ); 9179 .writeAttribute( "name", groupInfo.name );
4305 } 9180 }
4306 9181
4307 virtual void EndGroup( const std::string&, const Totals& totals ) { 9182 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
4308 m_xml.scopedElement( "OverallResults" ) 9183 StreamingReporterBase::testCaseStarting(testInfo);
4309 .writeAttribute( "successes", totals.assertions.passed ) 9184 m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
4310 .writeAttribute( "failures", totals.assertions.failed ); 9185
4311 m_xml.endElement(); 9186 if ( m_config->showDurations() == ShowDurations::Always )
4312 } 9187 m_testCaseTimer.start();
4313 9188 }
4314 virtual void StartSection( const std::string& sectionName, const std::string& description ) { 9189
4315 m_xml.startElement( "Section" ) 9190 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
4316 .writeAttribute( "name", sectionName ) 9191 StreamingReporterBase::sectionStarting( sectionInfo );
4317 .writeAttribute( "description", description ); 9192 if( m_sectionDepth++ > 0 ) {
4318 } 9193 m_xml.startElement( "Section" )
4319 9194 .writeAttribute( "name", trim( sectionInfo.name ) )
4320 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { 9195 .writeAttribute( "description", sectionInfo.description );
4321 m_xml.scopedElement( "OverallResults" ) 9196 }
4322 .writeAttribute( "successes", assertions.passed ) 9197 }
4323 .writeAttribute( "failures", assertions.failed ); 9198
4324 m_xml.endElement(); 9199 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
4325 } 9200
4326 9201 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
4327 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { 9202 const AssertionResult& assertionResult = assertionStats.assertionResult;
4328 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() ); 9203
4329 m_currentTestSuccess = true; 9204 // Print any info messages in <Info> tags.
4330 } 9205 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
4331 9206 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
4332 virtual void Result( const Catch::ResultInfo& resultInfo ) { 9207 it != itEnd;
4333 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok ) 9208 ++it ) {
4334 return; 9209 if( it->type == ResultWas::Info ) {
4335 9210 m_xml.scopedElement( "Info" )
4336 if( resultInfo.hasExpression() ) { 9211 .writeText( it->message );
9212 } else if ( it->type == ResultWas::Warning ) {
9213 m_xml.scopedElement( "Warning" )
9214 .writeText( it->message );
9215 }
9216 }
9217 }
9218
9219 // Drop out if result was successful but we're not printing them.
9220 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
9221 return true;
9222
9223 // Print the expression if there is one.
9224 if( assertionResult.hasExpression() ) {
4337 m_xml.startElement( "Expression" ) 9225 m_xml.startElement( "Expression" )
4338 .writeAttribute( "success", resultInfo.ok() ) 9226 .writeAttribute( "success", assertionResult.succeeded() )
4339 .writeAttribute( "filename", resultInfo.getFilename() ) 9227 .writeAttribute( "type", assertionResult.getTestMacroName() )
4340 .writeAttribute( "line", resultInfo.getLine() ); 9228 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9229 .writeAttribute( "line", assertionResult.getSourceInfo().line );
4341 9230
4342 m_xml.scopedElement( "Original" ) 9231 m_xml.scopedElement( "Original" )
4343 .writeText( resultInfo.getExpression() ); 9232 .writeText( assertionResult.getExpression() );
4344 m_xml.scopedElement( "Expanded" ) 9233 m_xml.scopedElement( "Expanded" )
4345 .writeText( resultInfo.getExpandedExpression() ); 9234 .writeText( assertionResult.getExpandedExpression() );
4346 m_currentTestSuccess &= resultInfo.ok(); 9235 }
4347 } 9236
4348 9237 // And... Print a result applicable to each result type.
4349 switch( resultInfo.getResultType() ) { 9238 switch( assertionResult.getResultType() ) {
4350 case ResultWas::ThrewException: 9239 case ResultWas::ThrewException:
4351 m_xml.scopedElement( "Exception" ) 9240 m_xml.scopedElement( "Exception" )
4352 .writeAttribute( "filename", resultInfo.getFilename() ) 9241 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
4353 .writeAttribute( "line", resultInfo.getLine() ) 9242 .writeAttribute( "line", assertionResult.getSourceInfo().line )
4354 .writeText( resultInfo.getMessage() ); 9243 .writeText( assertionResult.getMessage() );
4355 m_currentTestSuccess = false; 9244 break;
9245 case ResultWas::FatalErrorCondition:
9246 m_xml.scopedElement( "Fatal Error Condition" )
9247 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9248 .writeAttribute( "line", assertionResult.getSourceInfo().line )
9249 .writeText( assertionResult.getMessage() );
4356 break; 9250 break;
4357 case ResultWas::Info: 9251 case ResultWas::Info:
4358 m_xml.scopedElement( "Info" ) 9252 m_xml.scopedElement( "Info" )
4359 .writeText( resultInfo.getMessage() ); 9253 .writeText( assertionResult.getMessage() );
4360 break; 9254 break;
4361 case ResultWas::Warning: 9255 case ResultWas::Warning:
4362 m_xml.scopedElement( "Warning" ) 9256 // Warning will already have been written
4363 .writeText( resultInfo.getMessage() );
4364 break; 9257 break;
4365 case ResultWas::ExplicitFailure: 9258 case ResultWas::ExplicitFailure:
4366 m_xml.scopedElement( "Failure" ) 9259 m_xml.scopedElement( "Failure" )
4367 .writeText( resultInfo.getMessage() ); 9260 .writeText( assertionResult.getMessage() );
4368 m_currentTestSuccess = false;
4369 break; 9261 break;
4370 case ResultWas::Unknown:
4371 case ResultWas::Ok:
4372 case ResultWas::FailureBit:
4373 case ResultWas::ExpressionFailed:
4374 case ResultWas::Exception:
4375 case ResultWas::DidntThrowException:
4376 default: 9262 default:
4377 break; 9263 break;
4378 } 9264 }
4379 if( resultInfo.hasExpression() ) 9265
9266 if( assertionResult.hasExpression() )
4380 m_xml.endElement(); 9267 m_xml.endElement();
4381 } 9268
4382 9269 return true;
4383 virtual void Aborted() { 9270 }
4384 // !TBD 9271
4385 } 9272 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
4386 9273 StreamingReporterBase::sectionEnded( sectionStats );
4387 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { 9274 if( --m_sectionDepth > 0 ) {
4388 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); 9275 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
9276 e.writeAttribute( "successes", sectionStats.assertions.passed );
9277 e.writeAttribute( "failures", sectionStats.assertions.failed );
9278 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
9279
9280 if ( m_config->showDurations() == ShowDurations::Always )
9281 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
9282
9283 m_xml.endElement();
9284 }
9285 }
9286
9287 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
9288 StreamingReporterBase::testCaseEnded( testCaseStats );
9289 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
9290 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
9291
9292 if ( m_config->showDurations() == ShowDurations::Always )
9293 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
9294
4389 m_xml.endElement(); 9295 m_xml.endElement();
4390 } 9296 }
4391 9297
9298 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
9299 StreamingReporterBase::testGroupEnded( testGroupStats );
9300 // TODO: Check testGroupStats.aborting and act accordingly.
9301 m_xml.scopedElement( "OverallResults" )
9302 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
9303 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
9304 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
9305 m_xml.endElement();
9306 }
9307
9308 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9309 StreamingReporterBase::testRunEnded( testRunStats );
9310 m_xml.scopedElement( "OverallResults" )
9311 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
9312 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
9313 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
9314 m_xml.endElement();
9315 }
9316
4392 private: 9317 private:
4393 const IReporterConfig& m_config; 9318 Timer m_testCaseTimer;
4394 bool m_currentTestSuccess;
4395 XmlWriter m_xml; 9319 XmlWriter m_xml;
4396 }; 9320 int m_sectionDepth;
9321 };
9322
9323 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
4397 9324
4398 } // end namespace Catch 9325 } // end namespace Catch
4399 9326
4400 // #included from: reporters/catch_reporter_junit.hpp 9327 // #included from: ../reporters/catch_reporter_junit.hpp
9328 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
9329
9330 #include <assert.h>
4401 9331
4402 namespace Catch { 9332 namespace Catch {
4403 9333
4404 class JunitReporter : public SharedImpl<IReporter> { 9334 class JunitReporter : public CumulativeReporterBase {
4405
4406 struct TestStats {
4407 std::string m_element;
4408 std::string m_resultType;
4409 std::string m_message;
4410 std::string m_content;
4411 };
4412
4413 struct TestCaseStats {
4414
4415 TestCaseStats( const std::string& name = std::string() ) :m_name( name ){}
4416
4417 double m_timeInSeconds;
4418 std::string m_status;
4419 std::string m_className;
4420 std::string m_name;
4421 std::vector<TestStats> m_testStats;
4422 };
4423
4424 struct Stats {
4425
4426 Stats( const std::string& name = std::string() )
4427 : m_testsCount( 0 ),
4428 m_failuresCount( 0 ),
4429 m_disabledCount( 0 ),
4430 m_errorsCount( 0 ),
4431 m_timeInSeconds( 0 ),
4432 m_name( name )
4433 {}
4434
4435 std::size_t m_testsCount;
4436 std::size_t m_failuresCount;
4437 std::size_t m_disabledCount;
4438 std::size_t m_errorsCount;
4439 double m_timeInSeconds;
4440 std::string m_name;
4441
4442 std::vector<TestCaseStats> m_testCaseStats;
4443 };
4444
4445 public: 9335 public:
4446 JunitReporter( const IReporterConfig& config ) 9336 JunitReporter( ReporterConfig const& _config )
4447 : m_config( config ), 9337 : CumulativeReporterBase( _config ),
4448 m_testSuiteStats( "AllTests" ), 9338 xml( _config.stream() )
4449 m_currentStats( &m_testSuiteStats ) 9339 {
4450 {} 9340 m_reporterPrefs.shouldRedirectStdOut = true;
9341 }
9342
9343 virtual ~JunitReporter() CATCH_OVERRIDE;
4451 9344
4452 static std::string getDescription() { 9345 static std::string getDescription() {
4453 return "Reports test results in an XML format that looks like Ant's junitreport target"; 9346 return "Reports test results in an XML format that looks like Ant's junitreport target";
4454 } 9347 }
4455 9348
4456 private: // IReporter 9349 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
4457 9350
4458 virtual bool shouldRedirectStdout() const { 9351 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
4459 return true; 9352 CumulativeReporterBase::testRunStarting( runInfo );
4460 } 9353 xml.startElement( "testsuites" );
4461 9354 }
4462 virtual void StartTesting(){} 9355
4463 9356 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
4464 virtual void StartGroup( const std::string& groupName ) { 9357 suiteTimer.start();
4465 m_statsForSuites.push_back( Stats( groupName ) ); 9358 stdOutForSuite.str("");
4466 m_currentStats = &m_statsForSuites.back(); 9359 stdErrForSuite.str("");
4467 } 9360 unexpectedExceptions = 0;
4468 9361 CumulativeReporterBase::testGroupStarting( groupInfo );
4469 virtual void EndGroup( const std::string&, const Totals& totals ) { 9362 }
4470 m_currentStats->m_testsCount = totals.assertions.total(); 9363
4471 m_currentStats = &m_testSuiteStats; 9364 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
4472 } 9365 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
4473 9366 unexpectedExceptions++;
4474 virtual void StartSection( const std::string&, const std::string& ){} 9367 return CumulativeReporterBase::assertionEnded( assertionStats );
4475 9368 }
4476 virtual void EndSection( const std::string&, const Counts& ){} 9369
4477 9370 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
4478 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { 9371 stdOutForSuite << testCaseStats.stdOut;
4479 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) ); 9372 stdErrForSuite << testCaseStats.stdErr;
4480 } 9373 CumulativeReporterBase::testCaseEnded( testCaseStats );
4481 9374 }
4482 virtual void Result( const Catch::ResultInfo& resultInfo ) { 9375
4483 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults() ) { 9376 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
4484 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back(); 9377 double suiteTime = suiteTimer.getElapsedSeconds();
4485 TestStats stats; 9378 CumulativeReporterBase::testGroupEnded( testGroupStats );
4486 std::ostringstream oss; 9379 writeGroup( *m_testGroups.back(), suiteTime );
4487 if( !resultInfo.getMessage().empty() ) 9380 }
4488 oss << resultInfo.getMessage() << " at "; 9381
4489 oss << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() ); 9382 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
4490 stats.m_content = oss.str(); 9383 xml.endElement();
4491 stats.m_message = resultInfo.getExpandedExpression(); 9384 }
4492 stats.m_resultType = resultInfo.getTestMacroName(); 9385
4493 9386 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
4494 switch( resultInfo.getResultType() ) { 9387 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
9388 TestGroupStats const& stats = groupNode.value;
9389 xml.writeAttribute( "name", stats.groupInfo.name );
9390 xml.writeAttribute( "errors", unexpectedExceptions );
9391 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
9392 xml.writeAttribute( "tests", stats.totals.assertions.total() );
9393 xml.writeAttribute( "hostname", "tbd" ); // !TBD
9394 if( m_config->showDurations() == ShowDurations::Never )
9395 xml.writeAttribute( "time", "" );
9396 else
9397 xml.writeAttribute( "time", suiteTime );
9398 xml.writeAttribute( "timestamp", "tbd" ); // !TBD
9399
9400 // Write test cases
9401 for( TestGroupNode::ChildNodes::const_iterator
9402 it = groupNode.children.begin(), itEnd = groupNode.children.end();
9403 it != itEnd;
9404 ++it )
9405 writeTestCase( **it );
9406
9407 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
9408 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
9409 }
9410
9411 void writeTestCase( TestCaseNode const& testCaseNode ) {
9412 TestCaseStats const& stats = testCaseNode.value;
9413
9414 // All test cases have exactly one section - which represents the
9415 // test case itself. That section may have 0-n nested sections
9416 assert( testCaseNode.children.size() == 1 );
9417 SectionNode const& rootSection = *testCaseNode.children.front();
9418
9419 std::string className = stats.testInfo.className;
9420
9421 if( className.empty() ) {
9422 if( rootSection.childSections.empty() )
9423 className = "global";
9424 }
9425 writeSection( className, "", rootSection );
9426 }
9427
9428 void writeSection( std::string const& className,
9429 std::string const& rootName,
9430 SectionNode const& sectionNode ) {
9431 std::string name = trim( sectionNode.stats.sectionInfo.name );
9432 if( !rootName.empty() )
9433 name = rootName + "/" + name;
9434
9435 if( !sectionNode.assertions.empty() ||
9436 !sectionNode.stdOut.empty() ||
9437 !sectionNode.stdErr.empty() ) {
9438 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
9439 if( className.empty() ) {
9440 xml.writeAttribute( "classname", name );
9441 xml.writeAttribute( "name", "root" );
9442 }
9443 else {
9444 xml.writeAttribute( "classname", className );
9445 xml.writeAttribute( "name", name );
9446 }
9447 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
9448
9449 writeAssertions( sectionNode );
9450
9451 if( !sectionNode.stdOut.empty() )
9452 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
9453 if( !sectionNode.stdErr.empty() )
9454 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
9455 }
9456 for( SectionNode::ChildSections::const_iterator
9457 it = sectionNode.childSections.begin(),
9458 itEnd = sectionNode.childSections.end();
9459 it != itEnd;
9460 ++it )
9461 if( className.empty() )
9462 writeSection( name, "", **it );
9463 else
9464 writeSection( className, name, **it );
9465 }
9466
9467 void writeAssertions( SectionNode const& sectionNode ) {
9468 for( SectionNode::Assertions::const_iterator
9469 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
9470 it != itEnd;
9471 ++it )
9472 writeAssertion( *it );
9473 }
9474 void writeAssertion( AssertionStats const& stats ) {
9475 AssertionResult const& result = stats.assertionResult;
9476 if( !result.isOk() ) {
9477 std::string elementName;
9478 switch( result.getResultType() ) {
4495 case ResultWas::ThrewException: 9479 case ResultWas::ThrewException:
4496 stats.m_element = "error"; 9480 case ResultWas::FatalErrorCondition:
4497 m_currentStats->m_errorsCount++; 9481 elementName = "error";
4498 break;
4499 case ResultWas::Info:
4500 stats.m_element = "info"; // !TBD ?
4501 break;
4502 case ResultWas::Warning:
4503 stats.m_element = "warning"; // !TBD ?
4504 break; 9482 break;
4505 case ResultWas::ExplicitFailure: 9483 case ResultWas::ExplicitFailure:
4506 stats.m_element = "failure"; 9484 elementName = "failure";
4507 m_currentStats->m_failuresCount++;
4508 break; 9485 break;
4509 case ResultWas::ExpressionFailed: 9486 case ResultWas::ExpressionFailed:
4510 stats.m_element = "failure"; 9487 elementName = "failure";
4511 m_currentStats->m_failuresCount++;
4512 break; 9488 break;
9489 case ResultWas::DidntThrowException:
9490 elementName = "failure";
9491 break;
9492
9493 // We should never see these here:
9494 case ResultWas::Info:
9495 case ResultWas::Warning:
4513 case ResultWas::Ok: 9496 case ResultWas::Ok:
4514 stats.m_element = "success";
4515 break;
4516 case ResultWas::Unknown: 9497 case ResultWas::Unknown:
4517 case ResultWas::FailureBit: 9498 case ResultWas::FailureBit:
4518 case ResultWas::Exception: 9499 case ResultWas::Exception:
4519 case ResultWas::DidntThrowException: 9500 elementName = "internalError";
4520 default:
4521 stats.m_element = "unknown";
4522 break; 9501 break;
4523 } 9502 }
4524 testCaseStats.m_testStats.push_back( stats ); 9503
4525 } 9504 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
4526 } 9505
4527 9506 xml.writeAttribute( "message", result.getExpandedExpression() );
4528 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string& stdOut, const std::string& stdErr ) { 9507 xml.writeAttribute( "type", result.getTestMacroName() );
4529 if( !stdOut.empty() ) 9508
4530 m_stdOut << stdOut << "\n"; 9509 std::ostringstream oss;
4531 if( !stdErr.empty() ) 9510 if( !result.getMessage().empty() )
4532 m_stdErr << stdErr << "\n"; 9511 oss << result.getMessage() << "\n";
4533 } 9512 for( std::vector<MessageInfo>::const_iterator
4534 9513 it = stats.infoMessages.begin(),
4535 virtual void Aborted() { 9514 itEnd = stats.infoMessages.end();
4536 // !TBD 9515 it != itEnd;
4537 } 9516 ++it )
4538 9517 if( it->type == ResultWas::Info )
4539 virtual void EndTesting( const Totals& ) { 9518 oss << it->message << "\n";
4540 std::ostream& str = m_config.stream(); 9519
9520 oss << "at " << result.getSourceInfo();
9521 xml.writeText( oss.str(), false );
9522 }
9523 }
9524
9525 XmlWriter xml;
9526 Timer suiteTimer;
9527 std::ostringstream stdOutForSuite;
9528 std::ostringstream stdErrForSuite;
9529 unsigned int unexpectedExceptions;
9530 };
9531
9532 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
9533
9534 } // end namespace Catch
9535
9536 // #included from: ../reporters/catch_reporter_console.hpp
9537 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
9538
9539 namespace Catch {
9540
9541 struct ConsoleReporter : StreamingReporterBase {
9542 ConsoleReporter( ReporterConfig const& _config )
9543 : StreamingReporterBase( _config ),
9544 m_headerPrinted( false )
9545 {}
9546
9547 virtual ~ConsoleReporter() CATCH_OVERRIDE;
9548 static std::string getDescription() {
9549 return "Reports test results as plain lines of text";
9550 }
9551
9552 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
9553 stream << "No test cases matched '" << spec << "'" << std::endl;
9554 }
9555
9556 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
9557 }
9558
9559 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
9560 AssertionResult const& result = _assertionStats.assertionResult;
9561
9562 bool printInfoMessages = true;
9563
9564 // Drop out if result was successful and we're not printing those
9565 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
9566 if( result.getResultType() != ResultWas::Warning )
9567 return false;
9568 printInfoMessages = false;
9569 }
9570
9571 lazyPrint();
9572
9573 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
9574 printer.print();
9575 stream << std::endl;
9576 return true;
9577 }
9578
9579 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
9580 m_headerPrinted = false;
9581 StreamingReporterBase::sectionStarting( _sectionInfo );
9582 }
9583 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
9584 if( _sectionStats.missingAssertions ) {
9585 lazyPrint();
9586 Colour colour( Colour::ResultError );
9587 if( m_sectionStack.size() > 1 )
9588 stream << "\nNo assertions in section";
9589 else
9590 stream << "\nNo assertions in test case";
9591 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
9592 }
9593 if( m_headerPrinted ) {
9594 if( m_config->showDurations() == ShowDurations::Always )
9595 stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
9596 m_headerPrinted = false;
9597 }
9598 else {
9599 if( m_config->showDurations() == ShowDurations::Always )
9600 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
9601 }
9602 StreamingReporterBase::sectionEnded( _sectionStats );
9603 }
9604
9605 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
9606 StreamingReporterBase::testCaseEnded( _testCaseStats );
9607 m_headerPrinted = false;
9608 }
9609 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
9610 if( currentGroupInfo.used ) {
9611 printSummaryDivider();
9612 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
9613 printTotals( _testGroupStats.totals );
9614 stream << "\n" << std::endl;
9615 }
9616 StreamingReporterBase::testGroupEnded( _testGroupStats );
9617 }
9618 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
9619 printTotalsDivider( _testRunStats.totals );
9620 printTotals( _testRunStats.totals );
9621 stream << std::endl;
9622 StreamingReporterBase::testRunEnded( _testRunStats );
9623 }
9624
9625 private:
9626
9627 class AssertionPrinter {
9628 void operator= ( AssertionPrinter const& );
9629 public:
9630 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
9631 : stream( _stream ),
9632 stats( _stats ),
9633 result( _stats.assertionResult ),
9634 colour( Colour::None ),
9635 message( result.getMessage() ),
9636 messages( _stats.infoMessages ),
9637 printInfoMessages( _printInfoMessages )
4541 { 9638 {
4542 XmlWriter xml( str ); 9639 switch( result.getResultType() ) {
4543 9640 case ResultWas::Ok:
4544 if( m_statsForSuites.size() > 0 ) 9641 colour = Colour::Success;
4545 xml.startElement( "testsuites" ); 9642 passOrFail = "PASSED";
4546 9643 //if( result.hasMessage() )
4547 std::vector<Stats>::const_iterator it = m_statsForSuites.begin(); 9644 if( _stats.infoMessages.size() == 1 )
4548 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end(); 9645 messageLabel = "with message";
4549 9646 if( _stats.infoMessages.size() > 1 )
4550 for(; it != itEnd; ++it ) { 9647 messageLabel = "with messages";
4551 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); 9648 break;
4552 xml.writeAttribute( "name", it->m_name ); 9649 case ResultWas::ExpressionFailed:
4553 xml.writeAttribute( "errors", it->m_errorsCount ); 9650 if( result.isOk() ) {
4554 xml.writeAttribute( "failures", it->m_failuresCount ); 9651 colour = Colour::Success;
4555 xml.writeAttribute( "tests", it->m_testsCount ); 9652 passOrFail = "FAILED - but was ok";
4556 xml.writeAttribute( "hostname", "tbd" ); 9653 }
4557 xml.writeAttribute( "time", "tbd" ); 9654 else {
4558 xml.writeAttribute( "timestamp", "tbd" ); 9655 colour = Colour::Error;
4559 9656 passOrFail = "FAILED";
4560 OutputTestCases( xml, *it ); 9657 }
9658 if( _stats.infoMessages.size() == 1 )
9659 messageLabel = "with message";
9660 if( _stats.infoMessages.size() > 1 )
9661 messageLabel = "with messages";
9662 break;
9663 case ResultWas::ThrewException:
9664 colour = Colour::Error;
9665 passOrFail = "FAILED";
9666 messageLabel = "due to unexpected exception with message";
9667 break;
9668 case ResultWas::FatalErrorCondition:
9669 colour = Colour::Error;
9670 passOrFail = "FAILED";
9671 messageLabel = "due to a fatal error condition";
9672 break;
9673 case ResultWas::DidntThrowException:
9674 colour = Colour::Error;
9675 passOrFail = "FAILED";
9676 messageLabel = "because no exception was thrown where one was expected";
9677 break;
9678 case ResultWas::Info:
9679 messageLabel = "info";
9680 break;
9681 case ResultWas::Warning:
9682 messageLabel = "warning";
9683 break;
9684 case ResultWas::ExplicitFailure:
9685 passOrFail = "FAILED";
9686 colour = Colour::Error;
9687 if( _stats.infoMessages.size() == 1 )
9688 messageLabel = "explicitly with message";
9689 if( _stats.infoMessages.size() > 1 )
9690 messageLabel = "explicitly with messages";
9691 break;
9692 // These cases are here to prevent compiler warnings
9693 case ResultWas::Unknown:
9694 case ResultWas::FailureBit:
9695 case ResultWas::Exception:
9696 passOrFail = "** internal error **";
9697 colour = Colour::Error;
9698 break;
4561 } 9699 }
4562 9700 }
4563 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) ); 9701
4564 xml.scopedElement( "system-err" ).writeText( trim( m_stdErr.str() ) ); 9702 void print() const {
4565 } 9703 printSourceInfo();
4566 } 9704 if( stats.totals.assertions.total() > 0 ) {
4567 9705 if( result.isOk() )
4568 void OutputTestCases( XmlWriter& xml, const Stats& stats ) { 9706 stream << "\n";
4569 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin(); 9707 printResultType();
4570 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end(); 9708 printOriginalExpression();
4571 for(; it != itEnd; ++it ) { 9709 printReconstructedExpression();
4572 xml.writeBlankLine();
4573 xml.writeComment( "Test case" );
4574
4575 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
4576 xml.writeAttribute( "classname", it->m_className );
4577 xml.writeAttribute( "name", it->m_name );
4578 xml.writeAttribute( "time", "tbd" );
4579
4580 OutputTestResult( xml, *it );
4581 }
4582 }
4583
4584 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats ) {
4585 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
4586 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
4587 for(; it != itEnd; ++it ) {
4588 if( it->m_element != "success" ) {
4589 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
4590
4591 xml.writeAttribute( "message", it->m_message );
4592 xml.writeAttribute( "type", it->m_resultType );
4593 if( !it->m_content.empty() )
4594 xml.writeText( it->m_content );
4595 } 9710 }
4596 } 9711 else {
9712 stream << "\n";
9713 }
9714 printMessage();
9715 }
9716
9717 private:
9718 void printResultType() const {
9719 if( !passOrFail.empty() ) {
9720 Colour colourGuard( colour );
9721 stream << passOrFail << ":\n";
9722 }
9723 }
9724 void printOriginalExpression() const {
9725 if( result.hasExpression() ) {
9726 Colour colourGuard( Colour::OriginalExpression );
9727 stream << " ";
9728 stream << result.getExpressionInMacro();
9729 stream << "\n";
9730 }
9731 }
9732 void printReconstructedExpression() const {
9733 if( result.hasExpandedExpression() ) {
9734 stream << "with expansion:\n";
9735 Colour colourGuard( Colour::ReconstructedExpression );
9736 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
9737 }
9738 }
9739 void printMessage() const {
9740 if( !messageLabel.empty() )
9741 stream << messageLabel << ":" << "\n";
9742 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
9743 it != itEnd;
9744 ++it ) {
9745 // If this assertion is a warning ignore any INFO messages
9746 if( printInfoMessages || it->type != ResultWas::Info )
9747 stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
9748 }
9749 }
9750 void printSourceInfo() const {
9751 Colour colourGuard( Colour::FileName );
9752 stream << result.getSourceInfo() << ": ";
9753 }
9754
9755 std::ostream& stream;
9756 AssertionStats const& stats;
9757 AssertionResult const& result;
9758 Colour::Code colour;
9759 std::string passOrFail;
9760 std::string messageLabel;
9761 std::string message;
9762 std::vector<MessageInfo> messages;
9763 bool printInfoMessages;
9764 };
9765
9766 void lazyPrint() {
9767
9768 if( !currentTestRunInfo.used )
9769 lazyPrintRunInfo();
9770 if( !currentGroupInfo.used )
9771 lazyPrintGroupInfo();
9772
9773 if( !m_headerPrinted ) {
9774 printTestCaseAndSectionHeader();
9775 m_headerPrinted = true;
9776 }
9777 }
9778 void lazyPrintRunInfo() {
9779 stream << "\n" << getLineOfChars<'~'>() << "\n";
9780 Colour colour( Colour::SecondaryText );
9781 stream << currentTestRunInfo->name
9782 << " is a Catch v" << libraryVersion << " host application.\n"
9783 << "Run with -? for options\n\n";
9784
9785 if( m_config->rngSeed() != 0 )
9786 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
9787
9788 currentTestRunInfo.used = true;
9789 }
9790 void lazyPrintGroupInfo() {
9791 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
9792 printClosedHeader( "Group: " + currentGroupInfo->name );
9793 currentGroupInfo.used = true;
9794 }
9795 }
9796 void printTestCaseAndSectionHeader() {
9797 assert( !m_sectionStack.empty() );
9798 printOpenHeader( currentTestCaseInfo->name );
9799
9800 if( m_sectionStack.size() > 1 ) {
9801 Colour colourGuard( Colour::Headers );
9802
9803 std::vector<SectionInfo>::const_iterator
9804 it = m_sectionStack.begin()+1, // Skip first section (test case)
9805 itEnd = m_sectionStack.end();
9806 for( ; it != itEnd; ++it )
9807 printHeaderString( it->name, 2 );
9808 }
9809
9810 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
9811
9812 if( !lineInfo.empty() ){
9813 stream << getLineOfChars<'-'>() << "\n";
9814 Colour colourGuard( Colour::FileName );
9815 stream << lineInfo << "\n";
9816 }
9817 stream << getLineOfChars<'.'>() << "\n" << std::endl;
9818 }
9819
9820 void printClosedHeader( std::string const& _name ) {
9821 printOpenHeader( _name );
9822 stream << getLineOfChars<'.'>() << "\n";
9823 }
9824 void printOpenHeader( std::string const& _name ) {
9825 stream << getLineOfChars<'-'>() << "\n";
9826 {
9827 Colour colourGuard( Colour::Headers );
9828 printHeaderString( _name );
9829 }
9830 }
9831
9832 // if string has a : in first line will set indent to follow it on
9833 // subsequent lines
9834 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
9835 std::size_t i = _string.find( ": " );
9836 if( i != std::string::npos )
9837 i+=2;
9838 else
9839 i = 0;
9840 stream << Text( _string, TextAttributes()
9841 .setIndent( indent+i)
9842 .setInitialIndent( indent ) ) << "\n";
9843 }
9844
9845 struct SummaryColumn {
9846
9847 SummaryColumn( std::string const& _label, Colour::Code _colour )
9848 : label( _label ),
9849 colour( _colour )
9850 {}
9851 SummaryColumn addRow( std::size_t count ) {
9852 std::ostringstream oss;
9853 oss << count;
9854 std::string row = oss.str();
9855 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
9856 while( it->size() < row.size() )
9857 *it = " " + *it;
9858 while( it->size() > row.size() )
9859 row = " " + row;
9860 }
9861 rows.push_back( row );
9862 return *this;
9863 }
9864
9865 std::string label;
9866 Colour::Code colour;
9867 std::vector<std::string> rows;
9868
9869 };
9870
9871 void printTotals( Totals const& totals ) {
9872 if( totals.testCases.total() == 0 ) {
9873 stream << Colour( Colour::Warning ) << "No tests ran\n";
9874 }
9875 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
9876 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
9877 stream << " ("
9878 << pluralise( totals.assertions.passed, "assertion" ) << " in "
9879 << pluralise( totals.testCases.passed, "test case" ) << ")"
9880 << "\n";
9881 }
9882 else {
9883
9884 std::vector<SummaryColumn> columns;
9885 columns.push_back( SummaryColumn( "", Colour::None )
9886 .addRow( totals.testCases.total() )
9887 .addRow( totals.assertions.total() ) );
9888 columns.push_back( SummaryColumn( "passed", Colour::Success )
9889 .addRow( totals.testCases.passed )
9890 .addRow( totals.assertions.passed ) );
9891 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
9892 .addRow( totals.testCases.failed )
9893 .addRow( totals.assertions.failed ) );
9894 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
9895 .addRow( totals.testCases.failedButOk )
9896 .addRow( totals.assertions.failedButOk ) );
9897
9898 printSummaryRow( "test cases", columns, 0 );
9899 printSummaryRow( "assertions", columns, 1 );
9900 }
9901 }
9902 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
9903 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
9904 std::string value = it->rows[row];
9905 if( it->label.empty() ) {
9906 stream << label << ": ";
9907 if( value != "0" )
9908 stream << value;
9909 else
9910 stream << Colour( Colour::Warning ) << "- none -";
9911 }
9912 else if( value != "0" ) {
9913 stream << Colour( Colour::LightGrey ) << " | ";
9914 stream << Colour( it->colour )
9915 << value << " " << it->label;
9916 }
9917 }
9918 stream << "\n";
9919 }
9920
9921 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
9922 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
9923 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
9924 }
9925 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
9926 if( i > j && i > k )
9927 return i;
9928 else if( j > k )
9929 return j;
9930 else
9931 return k;
9932 }
9933
9934 void printTotalsDivider( Totals const& totals ) {
9935 if( totals.testCases.total() > 0 ) {
9936 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
9937 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
9938 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
9939 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
9940 findMax( failedRatio, failedButOkRatio, passedRatio )++;
9941 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
9942 findMax( failedRatio, failedButOkRatio, passedRatio )--;
9943
9944 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
9945 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
9946 if( totals.testCases.allPassed() )
9947 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
9948 else
9949 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
9950 }
9951 else {
9952 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
9953 }
9954 stream << "\n";
9955 }
9956 void printSummaryDivider() {
9957 stream << getLineOfChars<'-'>() << "\n";
4597 } 9958 }
4598 9959
4599 private: 9960 private:
4600 const IReporterConfig& m_config; 9961 bool m_headerPrinted;
4601 bool m_currentTestSuccess; 9962 };
4602 9963
4603 Stats m_testSuiteStats; 9964 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
4604 Stats* m_currentStats;
4605 std::vector<Stats> m_statsForSuites;
4606 std::ostringstream m_stdOut;
4607 std::ostringstream m_stdErr;
4608 };
4609 9965
4610 } // end namespace Catch 9966 } // end namespace Catch
4611 9967
4612 #include <fstream> 9968 // #included from: ../reporters/catch_reporter_compact.hpp
4613 #include <stdlib.h> 9969 #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
4614 #include <limits>
4615 9970
4616 namespace Catch { 9971 namespace Catch {
4617 9972
4618 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter ) 9973 struct CompactReporter : StreamingReporterBase {
4619 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) 9974
4620 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) 9975 CompactReporter( ReporterConfig const& _config )
4621 9976 : StreamingReporterBase( _config )
4622 inline int Main( Config& config ) { 9977 {}
4623 9978
4624 // Handle list request 9979 virtual ~CompactReporter();
4625 if( config.listWhat() != List::None ) 9980
4626 return List( config ); 9981 static std::string getDescription() {
4627 9982 return "Reports test results on a single line, suitable for IDEs";
4628 // Open output file, if specified 9983 }
4629 std::ofstream ofs; 9984
4630 if( !config.getFilename().empty() ) { 9985 virtual ReporterPreferences getPreferences() const {
4631 ofs.open( config.getFilename().c_str() ); 9986 ReporterPreferences prefs;
4632 if( ofs.fail() ) { 9987 prefs.shouldRedirectStdOut = false;
4633 std::cerr << "Unable to open file: '" << config.getFilename() << "'" << std::endl; 9988 return prefs;
4634 return (std::numeric_limits<int>::max)(); 9989 }
4635 } 9990
4636 config.setStreamBuf( ofs.rdbuf() ); 9991 virtual void noMatchingTestCases( std::string const& spec ) {
4637 } 9992 stream << "No test cases matched '" << spec << "'" << std::endl;
4638 9993 }
4639 int result = 0; 9994
4640 9995 virtual void assertionStarting( AssertionInfo const& ) {
4641 // Scope here for the Runner so it can use the context before it is cleaned-up 9996 }
4642 { 9997
4643 Runner runner( config ); 9998 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
4644 9999 AssertionResult const& result = _assertionStats.assertionResult;
4645 // Run test specs specified on the command line - or default to all 10000
4646 if( !config.testsSpecified() ) { 10001 bool printInfoMessages = true;
4647 config.getReporter()->StartGroup( "" ); 10002
4648 runner.runAll(); 10003 // Drop out if result was successful and we're not printing those
4649 config.getReporter()->EndGroup( "", runner.getTotals() ); 10004 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10005 if( result.getResultType() != ResultWas::Warning )
10006 return false;
10007 printInfoMessages = false;
10008 }
10009
10010 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
10011 printer.print();
10012
10013 stream << std::endl;
10014 return true;
10015 }
10016
10017 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
10018 printTotals( _testRunStats.totals );
10019 stream << "\n" << std::endl;
10020 StreamingReporterBase::testRunEnded( _testRunStats );
10021 }
10022
10023 private:
10024 class AssertionPrinter {
10025 void operator= ( AssertionPrinter const& );
10026 public:
10027 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10028 : stream( _stream )
10029 , stats( _stats )
10030 , result( _stats.assertionResult )
10031 , messages( _stats.infoMessages )
10032 , itMessage( _stats.infoMessages.begin() )
10033 , printInfoMessages( _printInfoMessages )
10034 {}
10035
10036 void print() {
10037 printSourceInfo();
10038
10039 itMessage = messages.begin();
10040
10041 switch( result.getResultType() ) {
10042 case ResultWas::Ok:
10043 printResultType( Colour::ResultSuccess, passedString() );
10044 printOriginalExpression();
10045 printReconstructedExpression();
10046 if ( ! result.hasExpression() )
10047 printRemainingMessages( Colour::None );
10048 else
10049 printRemainingMessages();
10050 break;
10051 case ResultWas::ExpressionFailed:
10052 if( result.isOk() )
10053 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
10054 else
10055 printResultType( Colour::Error, failedString() );
10056 printOriginalExpression();
10057 printReconstructedExpression();
10058 printRemainingMessages();
10059 break;
10060 case ResultWas::ThrewException:
10061 printResultType( Colour::Error, failedString() );
10062 printIssue( "unexpected exception with message:" );
10063 printMessage();
10064 printExpressionWas();
10065 printRemainingMessages();
10066 break;
10067 case ResultWas::FatalErrorCondition:
10068 printResultType( Colour::Error, failedString() );
10069 printIssue( "fatal error condition with message:" );
10070 printMessage();
10071 printExpressionWas();
10072 printRemainingMessages();
10073 break;
10074 case ResultWas::DidntThrowException:
10075 printResultType( Colour::Error, failedString() );
10076 printIssue( "expected exception, got none" );
10077 printExpressionWas();
10078 printRemainingMessages();
10079 break;
10080 case ResultWas::Info:
10081 printResultType( Colour::None, "info" );
10082 printMessage();
10083 printRemainingMessages();
10084 break;
10085 case ResultWas::Warning:
10086 printResultType( Colour::None, "warning" );
10087 printMessage();
10088 printRemainingMessages();
10089 break;
10090 case ResultWas::ExplicitFailure:
10091 printResultType( Colour::Error, failedString() );
10092 printIssue( "explicitly" );
10093 printRemainingMessages( Colour::None );
10094 break;
10095 // These cases are here to prevent compiler warnings
10096 case ResultWas::Unknown:
10097 case ResultWas::FailureBit:
10098 case ResultWas::Exception:
10099 printResultType( Colour::Error, "** internal error **" );
10100 break;
10101 }
10102 }
10103
10104 private:
10105 // Colour::LightGrey
10106
10107 static Colour::Code dimColour() { return Colour::FileName; }
10108
10109 #ifdef CATCH_PLATFORM_MAC
10110 static const char* failedString() { return "FAILED"; }
10111 static const char* passedString() { return "PASSED"; }
10112 #else
10113 static const char* failedString() { return "failed"; }
10114 static const char* passedString() { return "passed"; }
10115 #endif
10116
10117 void printSourceInfo() const {
10118 Colour colourGuard( Colour::FileName );
10119 stream << result.getSourceInfo() << ":";
10120 }
10121
10122 void printResultType( Colour::Code colour, std::string passOrFail ) const {
10123 if( !passOrFail.empty() ) {
10124 {
10125 Colour colourGuard( colour );
10126 stream << " " << passOrFail;
10127 }
10128 stream << ":";
10129 }
10130 }
10131
10132 void printIssue( std::string issue ) const {
10133 stream << " " << issue;
10134 }
10135
10136 void printExpressionWas() {
10137 if( result.hasExpression() ) {
10138 stream << ";";
10139 {
10140 Colour colour( dimColour() );
10141 stream << " expression was:";
10142 }
10143 printOriginalExpression();
10144 }
10145 }
10146
10147 void printOriginalExpression() const {
10148 if( result.hasExpression() ) {
10149 stream << " " << result.getExpression();
10150 }
10151 }
10152
10153 void printReconstructedExpression() const {
10154 if( result.hasExpandedExpression() ) {
10155 {
10156 Colour colour( dimColour() );
10157 stream << " for: ";
10158 }
10159 stream << result.getExpandedExpression();
10160 }
10161 }
10162
10163 void printMessage() {
10164 if ( itMessage != messages.end() ) {
10165 stream << " '" << itMessage->message << "'";
10166 ++itMessage;
10167 }
10168 }
10169
10170 void printRemainingMessages( Colour::Code colour = dimColour() ) {
10171 if ( itMessage == messages.end() )
10172 return;
10173
10174 // using messages.end() directly yields compilation error:
10175 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
10176 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
10177
10178 {
10179 Colour colourGuard( colour );
10180 stream << " with " << pluralise( N, "message" ) << ":";
10181 }
10182
10183 for(; itMessage != itEnd; ) {
10184 // If this assertion is a warning ignore any INFO messages
10185 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
10186 stream << " '" << itMessage->message << "'";
10187 if ( ++itMessage != itEnd ) {
10188 Colour colourGuard( dimColour() );
10189 stream << " and";
10190 }
10191 }
10192 }
10193 }
10194
10195 private:
10196 std::ostream& stream;
10197 AssertionStats const& stats;
10198 AssertionResult const& result;
10199 std::vector<MessageInfo> messages;
10200 std::vector<MessageInfo>::const_iterator itMessage;
10201 bool printInfoMessages;
10202 };
10203
10204 // Colour, message variants:
10205 // - white: No tests ran.
10206 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
10207 // - white: Passed [both/all] N test cases (no assertions).
10208 // - red: Failed N tests cases, failed M assertions.
10209 // - green: Passed [both/all] N tests cases with M assertions.
10210
10211 std::string bothOrAll( std::size_t count ) const {
10212 return count == 1 ? "" : count == 2 ? "both " : "all " ;
10213 }
10214
10215 void printTotals( const Totals& totals ) const {
10216 if( totals.testCases.total() == 0 ) {
10217 stream << "No tests ran.";
10218 }
10219 else if( totals.testCases.failed == totals.testCases.total() ) {
10220 Colour colour( Colour::ResultError );
10221 const std::string qualify_assertions_failed =
10222 totals.assertions.failed == totals.assertions.total() ?
10223 bothOrAll( totals.assertions.failed ) : "";
10224 stream <<
10225 "Failed " << bothOrAll( totals.testCases.failed )
10226 << pluralise( totals.testCases.failed, "test case" ) << ", "
10227 "failed " << qualify_assertions_failed <<
10228 pluralise( totals.assertions.failed, "assertion" ) << ".";
10229 }
10230 else if( totals.assertions.total() == 0 ) {
10231 stream <<
10232 "Passed " << bothOrAll( totals.testCases.total() )
10233 << pluralise( totals.testCases.total(), "test case" )
10234 << " (no assertions).";
10235 }
10236 else if( totals.assertions.failed ) {
10237 Colour colour( Colour::ResultError );
10238 stream <<
10239 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
10240 "failed " << pluralise( totals.assertions.failed, "assertion" ) << ".";
4650 } 10241 }
4651 else { 10242 else {
4652 // !TBD We should get all the testcases upfront, report any missing, 10243 Colour colour( Colour::ResultSuccess );
4653 // then just run them 10244 stream <<
4654 std::vector<std::string>::const_iterator it = config.getTestSpecs().begin(); 10245 "Passed " << bothOrAll( totals.testCases.passed )
4655 std::vector<std::string>::const_iterator itEnd = config.getTestSpecs().end(); 10246 << pluralise( totals.testCases.passed, "test case" ) <<
4656 for(; it != itEnd; ++it ) { 10247 " with " << pluralise( totals.assertions.passed, "assertion" ) << ".";
4657 Totals prevTotals = runner.getTotals(); 10248 }
4658 config.getReporter()->StartGroup( *it ); 10249 }
4659 if( runner.runMatching( *it ) == 0 ) { 10250 };
4660 // Use reporter? 10251
4661 // std::cerr << "\n[Unable to match any test cases with: " << *it << "]" << std::endl; 10252 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
4662 }
4663 config.getReporter()->EndGroup( *it, runner.getTotals() - prevTotals );
4664 }
4665 }
4666 result = static_cast<int>( runner.getTotals().assertions.failed );
4667 }
4668 Catch::Context::cleanUp();
4669 return result;
4670 }
4671
4672 inline void showUsage( std::ostream& os ) {
4673 os << "\t-l, --list <tests | reporters> [xml]\n"
4674 << "\t-t, --test <testspec> [<testspec>...]\n"
4675 << "\t-r, --reporter <reporter name>\n"
4676 << "\t-o, --out <file name>|<%stream name>\n"
4677 << "\t-s, --success\n"
4678 << "\t-b, --break\n"
4679 << "\t-n, --name <name>\n"
4680 << "\t-a, --abort [#]\n\n"
4681 << "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
4682 }
4683 inline void showHelp( std::string exeName ) {
4684 std::string::size_type pos = exeName.find_last_of( "/\\" );
4685 if( pos != std::string::npos ) {
4686 exeName = exeName.substr( pos+1 );
4687 }
4688
4689 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n";
4690 showUsage( std::cout );
4691 }
4692
4693 inline int Main( int argc, char* const argv[], Config& config ) {
4694
4695 parseIntoConfig( CommandParser( argc, argv ), config );
4696
4697 if( !config.getMessage().empty() ) {
4698 std::cerr << config.getMessage() << + "\n\nUsage: ...\n\n";
4699 showUsage( std::cerr );
4700 Catch::Context::cleanUp();
4701 return (std::numeric_limits<int>::max)();
4702 }
4703
4704 // Handle help
4705 if( config.showHelp() ) {
4706 showHelp( argv[0] );
4707 Catch::Context::cleanUp();
4708 return 0;
4709 }
4710 return Main( config );
4711 }
4712
4713 inline int Main( int argc, char* const argv[] ) {
4714 Config config;
4715 // !TBD: This doesn't always work, for some reason
4716 // if( isDebuggerActive() )
4717 // config.useStream( "debug" );
4718 return Main( argc, argv, config );
4719 }
4720 10253
4721 } // end namespace Catch 10254 } // end namespace Catch
10255
10256 namespace Catch {
10257 // These are all here to avoid warnings about not having any out of line
10258 // virtual methods
10259 NonCopyable::~NonCopyable() {}
10260 IShared::~IShared() {}
10261 IStream::~IStream() CATCH_NOEXCEPT {}
10262 FileStream::~FileStream() CATCH_NOEXCEPT {}
10263 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
10264 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
10265 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
10266 IContext::~IContext() {}
10267 IResultCapture::~IResultCapture() {}
10268 ITestCase::~ITestCase() {}
10269 ITestCaseRegistry::~ITestCaseRegistry() {}
10270 IRegistryHub::~IRegistryHub() {}
10271 IMutableRegistryHub::~IMutableRegistryHub() {}
10272 IExceptionTranslator::~IExceptionTranslator() {}
10273 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
10274 IReporter::~IReporter() {}
10275 IReporterFactory::~IReporterFactory() {}
10276 IReporterRegistry::~IReporterRegistry() {}
10277 IStreamingReporter::~IStreamingReporter() {}
10278 AssertionStats::~AssertionStats() {}
10279 SectionStats::~SectionStats() {}
10280 TestCaseStats::~TestCaseStats() {}
10281 TestGroupStats::~TestGroupStats() {}
10282 TestRunStats::~TestRunStats() {}
10283 CumulativeReporterBase::SectionNode::~SectionNode() {}
10284 CumulativeReporterBase::~CumulativeReporterBase() {}
10285
10286 StreamingReporterBase::~StreamingReporterBase() {}
10287 ConsoleReporter::~ConsoleReporter() {}
10288 CompactReporter::~CompactReporter() {}
10289 IRunner::~IRunner() {}
10290 IMutableContext::~IMutableContext() {}
10291 IConfig::~IConfig() {}
10292 XmlReporter::~XmlReporter() {}
10293 JunitReporter::~JunitReporter() {}
10294 TestRegistry::~TestRegistry() {}
10295 FreeFunctionTestCase::~FreeFunctionTestCase() {}
10296 IGeneratorInfo::~IGeneratorInfo() {}
10297 IGeneratorsForTest::~IGeneratorsForTest() {}
10298 WildcardPattern::~WildcardPattern() {}
10299 TestSpec::Pattern::~Pattern() {}
10300 TestSpec::NamePattern::~NamePattern() {}
10301 TestSpec::TagPattern::~TagPattern() {}
10302 TestSpec::ExcludedPattern::~ExcludedPattern() {}
10303
10304 Matchers::Impl::StdString::Equals::~Equals() {}
10305 Matchers::Impl::StdString::Contains::~Contains() {}
10306 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
10307 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
10308
10309 void Config::dummy() {}
10310
10311 namespace TestCaseTracking {
10312 ITracker::~ITracker() {}
10313 TrackerBase::~TrackerBase() {}
10314 SectionTracker::~SectionTracker() {}
10315 IndexTracker::~IndexTracker() {}
10316 }
10317 }
10318
10319 #ifdef __clang__
10320 #pragma clang diagnostic pop
10321 #endif
4722 10322
4723 #endif 10323 #endif
4724 10324
4725 #ifdef CATCH_CONFIG_MAIN 10325 #ifdef CATCH_CONFIG_MAIN
4726 // #included from: internal/catch_default_main.hpp 10326 // #included from: internal/catch_default_main.hpp
10327 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
4727 10328
4728 #ifndef __OBJC__ 10329 #ifndef __OBJC__
4729 10330
4730 // Standard C/C++ main entry point 10331 // Standard C/C++ main entry point
4731 int main (int argc, char * const argv[]) { 10332 int main (int argc, char * argv[]) {
4732 return Catch::Main( argc, argv ); 10333 return Catch::Session().run( argc, argv );
4733 } 10334 }
4734 10335
4735 #else // __OBJC__ 10336 #else // __OBJC__
4736 10337
4737 // Objective-C entry point 10338 // Objective-C entry point
4739 #if !CATCH_ARC_ENABLED 10340 #if !CATCH_ARC_ENABLED
4740 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 10341 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
4741 #endif 10342 #endif
4742 10343
4743 Catch::registerTestMethods(); 10344 Catch::registerTestMethods();
4744 int result = Catch::Main( argc, (char* const*)argv ); 10345 int result = Catch::Session().run( argc, (char* const*)argv );
4745 10346
4746 #if !CATCH_ARC_ENABLED 10347 #if !CATCH_ARC_ENABLED
4747 [pool drain]; 10348 [pool drain];
4748 #endif 10349 #endif
4749 10350
4752 10353
4753 #endif // __OBJC__ 10354 #endif // __OBJC__
4754 10355
4755 #endif 10356 #endif
4756 10357
10358 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
10359 # undef CLARA_CONFIG_MAIN
10360 #endif
10361
4757 ////// 10362 //////
4758 10363
4759 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" ) 10364 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
4760 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" ) 10365 #ifdef CATCH_CONFIG_PREFIX_ALL
4761 10366
4762 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" ) 10367 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
4763 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" ) 10368 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
4764 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" ) 10369
4765 10370 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
4766 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" ) 10371 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
4767 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" ) 10372 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
4768 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" ) 10373 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
4769 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" ) 10374
4770 10375 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
4771 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" ) 10376 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
4772 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" ) 10377 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
4773 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" ) 10378 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
4774 10379 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
4775 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CHECK_THAT" ) 10380
4776 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "REQUIRE_THAT" ) 10381 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
4777 10382 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
4778 #define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" ) 10383 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
4779 #define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" ) 10384 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
4780 #define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" ) 10385
4781 #define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg ) 10386 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
4782 #define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" ) 10387 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
4783 10388
4784 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) 10389 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
4785 10390 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
4786 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) 10391 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
4787 #define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description ) 10392 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
4788 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" ) 10393 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
4789 #define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description ) 10394
10395 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10396 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
10397 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
10398 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
10399 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
10400 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
10401 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
10402 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
10403 #else
10404 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
10405 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
10406 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
10407 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
10408 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
10409 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
10410 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
10411 #endif
10412 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
10413
10414 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
10415 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
10416
10417 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10418
10419 // "BDD-style" convenience wrappers
10420 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10421 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
10422 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
10423 #else
10424 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
10425 #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
10426 #endif
10427 #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
10428 #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
10429 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10430 #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
10431 #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10432
10433 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
10434 #else
10435
10436 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
10437 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
10438
10439 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
10440 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
10441 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
10442 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
10443
10444 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
10445 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
10446 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
10447 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
10448 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
10449
10450 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
10451 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
10452 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
10453 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
10454
10455 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
10456 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
10457
10458 #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
10459 #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
10460 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
10461 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
10462 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
10463
10464 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10465 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
10466 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
10467 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
10468 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
10469 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
10470 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
10471 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
10472 #else
10473 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
10474 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
10475 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
10476 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
10477 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
10478 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
10479 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
10480 #endif
10481 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
4790 10482
4791 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) 10483 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
10484 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
10485
10486 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10487
10488 #endif
10489
4792 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 10490 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
4793 10491
4794 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) 10492 // "BDD-style" convenience wrappers
4795 10493 #ifdef CATCH_CONFIG_VARIADIC_MACROS
4796 /////////////// 10494 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
4797 // Still to be implemented 10495 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
4798 #define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test 10496 #else
10497 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
10498 #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
10499 #endif
10500 #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
10501 #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
10502 #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
10503 #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
10504 #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
4799 10505
4800 using Catch::Detail::Approx; 10506 using Catch::Detail::Approx;
4801 10507
4802 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 10508 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
4803 10509