1 /*
2 * CATCH v1.0 build 47 (master branch)
3 * Generated: 2014-05-20 19:02:15.946806
4 * ----------------------------------------------------------
5 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
7 *
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 */
11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
13
14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
15
16 // #included from: internal/catch_suppress_warnings.h
17
18 #define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
19
20 #ifdef __clang__
21 #pragma clang diagnostic ignored "-Wglobal-constructors"
22 #pragma clang diagnostic ignored "-Wvariadic-macros"
23 #pragma clang diagnostic ignored "-Wc99-extensions"
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wpadded"
26 #pragma clang diagnostic ignored "-Wc++98-compat"
27 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
28 #endif
29
30 #ifdef CATCH_CONFIG_MAIN
31 # define CATCH_CONFIG_RUNNER
32 #endif
33
34 #ifdef CATCH_CONFIG_RUNNER
35 # ifndef CLARA_CONFIG_MAIN
36 # define CLARA_CONFIG_MAIN_NOT_DEFINED
37 # define CLARA_CONFIG_MAIN
38 # endif
39 #endif
40
41 // #included from: internal/catch_notimplemented_exception.h
42 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
43
44 // #included from: catch_common.h
45 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
46
47 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
48 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
49 #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
50
51 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
52 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
53
54 #include <sstream>
55 #include <stdexcept>
56 #include <algorithm>
57
58 // #included from: catch_compiler_capabilities.h
59 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
60
61 // Much of the following code is based on Boost (1.53)
62
63 #ifdef __clang__
64
65 # if __has_feature(cxx_nullptr)
66 # define CATCH_CONFIG_CPP11_NULLPTR
67 # endif
68
69 # if __has_feature(cxx_noexcept)
70 # define CATCH_CONFIG_CPP11_NOEXCEPT
71 # endif
72
73 #endif // __clang__
74
75 ////////////////////////////////////////////////////////////////////////////////
76 // Borland
77 #ifdef __BORLANDC__
78
79 #if (__BORLANDC__ > 0x582 )
80 //#define CATCH_CONFIG_SFINAE // Not confirmed
81 #endif
82
83 #endif // __BORLANDC__
84
85 ////////////////////////////////////////////////////////////////////////////////
86 // EDG
87 #ifdef __EDG_VERSION__
88
89 #if (__EDG_VERSION__ > 238 )
90 //#define CATCH_CONFIG_SFINAE // Not confirmed
91 #endif
92
93 #endif // __EDG_VERSION__
94
95 ////////////////////////////////////////////////////////////////////////////////
96 // Digital Mars
97 #ifdef __DMC__
98
99 #if (__DMC__ > 0x840 )
100 //#define CATCH_CONFIG_SFINAE // Not confirmed
101 #endif
102
103 #endif // __DMC__
104
105 ////////////////////////////////////////////////////////////////////////////////
106 // GCC
107 #ifdef __GNUC__
108
109 #if __GNUC__ < 3
110
111 #if (__GNUC_MINOR__ >= 96 )
112 //#define CATCH_CONFIG_SFINAE
113 #endif
114
115 #elif __GNUC__ >= 3
116
117 // #define CATCH_CONFIG_SFINAE // Taking this out completely for now
118
119 #endif // __GNUC__ < 3
120
121 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
122
123 #define CATCH_CONFIG_CPP11_NULLPTR
124 #endif
125
126 #endif // __GNUC__
127
128 ////////////////////////////////////////////////////////////////////////////////
129 // Visual C++
130 #ifdef _MSC_VER
131
132 #if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
133 //#define CATCH_CONFIG_SFINAE // Not confirmed
134 #endif
135
136 #endif // _MSC_VER
137
138 // Use variadic macros if the compiler supports them
139 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
140 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
141 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
142 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
143
144 #ifndef CATCH_CONFIG_NO_VARIADIC_MACROS
145 #define CATCH_CONFIG_VARIADIC_MACROS
146 #endif
147
148 #endif
149
150 ////////////////////////////////////////////////////////////////////////////////
151 // C++ language feature support
152
153 // detect language version:
154 #if (__cplusplus == 201103L)
155 # define CATCH_CPP11
156 # define CATCH_CPP11_OR_GREATER
157 #elif (__cplusplus >= 201103L)
158 # define CATCH_CPP11_OR_GREATER
159 #endif
160
161 // noexcept support:
162 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
163 # define CATCH_NOEXCEPT noexcept
164 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
165 #else
166 # define CATCH_NOEXCEPT throw()
167 # define CATCH_NOEXCEPT_IS(x)
168 #endif
169
170 namespace Catch {
171
172 class NonCopyable {
173 NonCopyable( NonCopyable const& );
174 void operator = ( NonCopyable const& );
175 protected:
NonCopyable()176 NonCopyable() {}
177 virtual ~NonCopyable();
178 };
179
180 class SafeBool {
181 public:
182 typedef void (SafeBool::*type)() const;
183
makeSafe(bool value)184 static type makeSafe( bool value ) {
185 return value ? &SafeBool::trueValue : 0;
186 }
187 private:
trueValue() const188 void trueValue() const {}
189 };
190
191 template<typename ContainerT>
deleteAll(ContainerT & container)192 inline void deleteAll( ContainerT& container ) {
193 typename ContainerT::const_iterator it = container.begin();
194 typename ContainerT::const_iterator itEnd = container.end();
195 for(; it != itEnd; ++it )
196 delete *it;
197 }
198 template<typename AssociativeContainerT>
deleteAllValues(AssociativeContainerT & container)199 inline void deleteAllValues( AssociativeContainerT& container ) {
200 typename AssociativeContainerT::const_iterator it = container.begin();
201 typename AssociativeContainerT::const_iterator itEnd = container.end();
202 for(; it != itEnd; ++it )
203 delete it->second;
204 }
205
206 bool startsWith( std::string const& s, std::string const& prefix );
207 bool endsWith( std::string const& s, std::string const& suffix );
208 bool contains( std::string const& s, std::string const& infix );
209 void toLowerInPlace( std::string& s );
210 std::string toLower( std::string const& s );
211 std::string trim( std::string const& str );
212
213 struct pluralise {
214 pluralise( std::size_t count, std::string const& label );
215
216 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
217
218 std::size_t m_count;
219 std::string m_label;
220 };
221
222 struct SourceLineInfo {
223
224 SourceLineInfo();
225 SourceLineInfo( char const* _file, std::size_t _line );
226 SourceLineInfo( SourceLineInfo const& other );
227 # ifdef CATCH_CPP11_OR_GREATER
228 SourceLineInfo( SourceLineInfo && ) = default;
229 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
230 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
231 # endif
232 bool empty() const;
233 bool operator == ( SourceLineInfo const& other ) const;
234
235 std::string file;
236 std::size_t line;
237 };
238
239 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
240
241 // This is just here to avoid compiler warnings with macro constants and boolean literals
isTrue(bool value)242 inline bool isTrue( bool value ){ return value; }
243
244 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
245
246 // Use this in variadic streaming macros to allow
247 // >> +StreamEndStop
248 // as well as
249 // >> stuff +StreamEndStop
250 struct StreamEndStop {
operator +Catch::StreamEndStop251 std::string operator+() {
252 return std::string();
253 }
254 };
255 template<typename T>
operator +(T const & value,StreamEndStop)256 T const& operator + ( T const& value, StreamEndStop ) {
257 return value;
258 }
259 }
260
261 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
262 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
263
264 #include <ostream>
265
266 namespace Catch {
267
268 class NotImplementedException : public std::exception
269 {
270 public:
271 NotImplementedException( SourceLineInfo const& lineInfo );
NotImplementedException(NotImplementedException const &)272 NotImplementedException( NotImplementedException const& ) {}
273
~NotImplementedException()274 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
275
276 virtual const char* what() const CATCH_NOEXCEPT;
277
278 private:
279 std::string m_what;
280 SourceLineInfo m_lineInfo;
281 };
282
283 } // end namespace Catch
284
285 ///////////////////////////////////////////////////////////////////////////////
286 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
287
288 // #included from: internal/catch_context.h
289 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
290
291 // #included from: catch_interfaces_generators.h
292 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
293
294 #include <string>
295
296 namespace Catch {
297
298 struct IGeneratorInfo {
299 virtual ~IGeneratorInfo();
300 virtual bool moveNext() = 0;
301 virtual std::size_t getCurrentIndex() const = 0;
302 };
303
304 struct IGeneratorsForTest {
305 virtual ~IGeneratorsForTest();
306
307 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
308 virtual bool moveNext() = 0;
309 };
310
311 IGeneratorsForTest* createGeneratorsForTest();
312
313 } // end namespace Catch
314
315 // #included from: catch_ptr.hpp
316 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
317
318 #ifdef __clang__
319 #pragma clang diagnostic push
320 #pragma clang diagnostic ignored "-Wpadded"
321 #endif
322
323 namespace Catch {
324
325 // An intrusive reference counting smart pointer.
326 // T must implement addRef() and release() methods
327 // typically implementing the IShared interface
328 template<typename T>
329 class Ptr {
330 public:
Ptr()331 Ptr() : m_p( NULL ){}
Ptr(T * p)332 Ptr( T* p ) : m_p( p ){
333 if( m_p )
334 m_p->addRef();
335 }
Ptr(Ptr const & other)336 Ptr( Ptr const& other ) : m_p( other.m_p ){
337 if( m_p )
338 m_p->addRef();
339 }
~Ptr()340 ~Ptr(){
341 if( m_p )
342 m_p->release();
343 }
reset()344 void reset() {
345 if( m_p )
346 m_p->release();
347 m_p = NULL;
348 }
operator =(T * p)349 Ptr& operator = ( T* p ){
350 Ptr temp( p );
351 swap( temp );
352 return *this;
353 }
operator =(Ptr const & other)354 Ptr& operator = ( Ptr const& other ){
355 Ptr temp( other );
356 swap( temp );
357 return *this;
358 }
swap(Ptr & other)359 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
get()360 T* get() { return m_p; }
get() const361 const T* get() const{ return m_p; }
operator *() const362 T& operator*() const { return *m_p; }
operator ->() const363 T* operator->() const { return m_p; }
operator !() const364 bool operator !() const { return m_p == NULL; }
operator SafeBool::type() const365 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
366
367 private:
368 T* m_p;
369 };
370
371 struct IShared : NonCopyable {
372 virtual ~IShared();
373 virtual void addRef() const = 0;
374 virtual void release() const = 0;
375 };
376
377 template<typename T = IShared>
378 struct SharedImpl : T {
379
SharedImplCatch::SharedImpl380 SharedImpl() : m_rc( 0 ){}
381
addRefCatch::SharedImpl382 virtual void addRef() const {
383 ++m_rc;
384 }
releaseCatch::SharedImpl385 virtual void release() const {
386 if( --m_rc == 0 )
387 delete this;
388 }
389
390 mutable unsigned int m_rc;
391 };
392
393 } // end namespace Catch
394
395 #ifdef __clang__
396 #pragma clang diagnostic pop
397 #endif
398
399 #include <memory>
400 #include <vector>
401 #include <stdlib.h>
402
403 namespace Catch {
404
405 class TestCase;
406 class Stream;
407 struct IResultCapture;
408 struct IRunner;
409 struct IGeneratorsForTest;
410 struct IConfig;
411
412 struct IContext
413 {
414 virtual ~IContext();
415
416 virtual IResultCapture* getResultCapture() = 0;
417 virtual IRunner* getRunner() = 0;
418 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
419 virtual bool advanceGeneratorsForCurrentTest() = 0;
420 virtual Ptr<IConfig const> getConfig() const = 0;
421 };
422
423 struct IMutableContext : IContext
424 {
425 virtual ~IMutableContext();
426 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
427 virtual void setRunner( IRunner* runner ) = 0;
428 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
429 };
430
431 IContext& getCurrentContext();
432 IMutableContext& getCurrentMutableContext();
433 void cleanUpContext();
434 Stream createStream( std::string const& streamName );
435
436 }
437
438 // #included from: internal/catch_test_registry.hpp
439 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
440
441 // #included from: catch_interfaces_testcase.h
442 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
443
444 #include <vector>
445
446 namespace Catch {
447
448 class TestSpec;
449
450 struct ITestCase : IShared {
451 virtual void invoke () const = 0;
452 protected:
453 virtual ~ITestCase();
454 };
455
456 class TestCase;
457 struct IConfig;
458
459 struct ITestCaseRegistry {
460 virtual ~ITestCaseRegistry();
461 virtual std::vector<TestCase> const& getAllTests() const = 0;
462 virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0;
463
464 };
465 }
466
467 namespace Catch {
468
469 template<typename C>
470 class MethodTestCase : public SharedImpl<ITestCase> {
471
472 public:
MethodTestCase(void (C::* method)())473 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
474
invoke() const475 virtual void invoke() const {
476 C obj;
477 (obj.*m_method)();
478 }
479
480 private:
~MethodTestCase()481 virtual ~MethodTestCase() {}
482
483 void (C::*m_method)();
484 };
485
486 typedef void(*TestFunction)();
487
488 struct NameAndDesc {
NameAndDescCatch::NameAndDesc489 NameAndDesc( const char* _name = "", const char* _description= "" )
490 : name( _name ), description( _description )
491 {}
492
493 const char* name;
494 const char* description;
495 };
496
497 struct AutoReg {
498
499 AutoReg( TestFunction function,
500 SourceLineInfo const& lineInfo,
501 NameAndDesc const& nameAndDesc );
502
503 template<typename C>
AutoRegCatch::AutoReg504 AutoReg( void (C::*method)(),
505 char const* className,
506 NameAndDesc const& nameAndDesc,
507 SourceLineInfo const& lineInfo ) {
508 registerTestCase( new MethodTestCase<C>( method ),
509 className,
510 nameAndDesc,
511 lineInfo );
512 }
513
514 void registerTestCase( ITestCase* testCase,
515 char const* className,
516 NameAndDesc const& nameAndDesc,
517 SourceLineInfo const& lineInfo );
518
519 ~AutoReg();
520
521 private:
522 AutoReg( AutoReg const& );
523 void operator= ( AutoReg const& );
524 };
525
526 } // end namespace Catch
527
528 #ifdef CATCH_CONFIG_VARIADIC_MACROS
529 ///////////////////////////////////////////////////////////////////////////////
530 #define INTERNAL_CATCH_TESTCASE( ... ) \
531 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
532 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
533 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
534
535 ///////////////////////////////////////////////////////////////////////////////
536 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
537 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
538
539 ///////////////////////////////////////////////////////////////////////////////
540 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
541 namespace{ \
542 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
543 void test(); \
544 }; \
545 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
546 } \
547 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
548
549 #else
550 ///////////////////////////////////////////////////////////////////////////////
551 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
552 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
553 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
554 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
555
556 ///////////////////////////////////////////////////////////////////////////////
557 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
558 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
559
560 ///////////////////////////////////////////////////////////////////////////////
561 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
562 namespace{ \
563 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
564 void test(); \
565 }; \
566 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
567 } \
568 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
569
570 #endif
571
572 // #included from: internal/catch_capture.hpp
573 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
574
575 // #included from: catch_expression_decomposer.hpp
576 #define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
577
578 // #included from: catch_expression_lhs.hpp
579 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
580
581 // #included from: catch_expressionresult_builder.h
582 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
583
584 // #included from: catch_tostring.h
585 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
586
587 // #included from: catch_sfinae.hpp
588 #define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
589
590 // Try to detect if the current compiler supports SFINAE
591
592 namespace Catch {
593
594 struct TrueType {
595 static const bool value = true;
596 typedef void Enable;
597 char sizer[1];
598 };
599 struct FalseType {
600 static const bool value = false;
601 typedef void Disable;
602 char sizer[2];
603 };
604
605 #ifdef CATCH_CONFIG_SFINAE
606
607 template<bool> struct NotABooleanExpression;
608
609 template<bool c> struct If : NotABooleanExpression<c> {};
610 template<> struct If<true> : TrueType {};
611 template<> struct If<false> : FalseType {};
612
613 template<int size> struct SizedIf;
614 template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
615 template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
616
617 #endif // CATCH_CONFIG_SFINAE
618
619 } // end namespace Catch
620
621 #include <sstream>
622 #include <iomanip>
623 #include <limits>
624 #include <vector>
625 #include <cstddef>
626
627 #ifdef __OBJC__
628 // #included from: catch_objc_arc.hpp
629 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
630
631 #import <Foundation/Foundation.h>
632
633 #ifdef __has_feature
634 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
635 #else
636 #define CATCH_ARC_ENABLED 0
637 #endif
638
639 void arcSafeRelease( NSObject* obj );
640 id performOptionalSelector( id obj, SEL sel );
641
642 #if !CATCH_ARC_ENABLED
arcSafeRelease(NSObject * obj)643 inline void arcSafeRelease( NSObject* obj ) {
644 [obj release];
645 }
performOptionalSelector(id obj,SEL sel)646 inline id performOptionalSelector( id obj, SEL sel ) {
647 if( [obj respondsToSelector: sel] )
648 return [obj performSelector: sel];
649 return nil;
650 }
651 #define CATCH_UNSAFE_UNRETAINED
652 #define CATCH_ARC_STRONG
653 #else
arcSafeRelease(NSObject *)654 inline void arcSafeRelease( NSObject* ){}
performOptionalSelector(id obj,SEL sel)655 inline id performOptionalSelector( id obj, SEL sel ) {
656 #ifdef __clang__
657 #pragma clang diagnostic push
658 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
659 #endif
660 if( [obj respondsToSelector: sel] )
661 return [obj performSelector: sel];
662 #ifdef __clang__
663 #pragma clang diagnostic pop
664 #endif
665 return nil;
666 }
667 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
668 #define CATCH_ARC_STRONG __strong
669 #endif
670
671 #endif
672
673 namespace Catch {
674 namespace Detail {
675
676 // SFINAE is currently disabled by default for all compilers.
677 // If the non SFINAE version of IsStreamInsertable is ambiguous for you
678 // and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
679 #ifdef CATCH_CONFIG_SFINAE
680
681 template<typename T>
682 class IsStreamInsertableHelper {
683 template<int N> struct TrueIfSizeable : TrueType {};
684
685 template<typename T2>
686 static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
687 static FalseType dummy(...);
688
689 public:
690 typedef SizedIf<sizeof(dummy((T*)0))> type;
691 };
692
693 template<typename T>
694 struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
695
696 #else
697
698 struct BorgType {
699 template<typename T> BorgType( T const& );
700 };
701
702 TrueType& testStreamable( std::ostream& );
703 FalseType testStreamable( FalseType );
704
705 FalseType operator<<( std::ostream const&, BorgType const& );
706
707 template<typename T>
708 struct IsStreamInsertable {
709 static std::ostream &s;
710 static T const&t;
711 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
712 };
713
714 #endif
715
716 template<bool C>
717 struct StringMakerBase {
718 template<typename T>
convertCatch::Detail::StringMakerBase719 static std::string convert( T const& ) { return "{?}"; }
720 };
721
722 template<>
723 struct StringMakerBase<true> {
724 template<typename T>
convertCatch::Detail::StringMakerBase725 static std::string convert( T const& _value ) {
726 std::ostringstream oss;
727 oss << _value;
728 return oss.str();
729 }
730 };
731
732 struct Endianness {
733 enum Arch { Big, Little };
734
whichCatch::Detail::Endianness735 static Arch which() {
736 union _{
737 int asInt;
738 char asChar[sizeof (int)];
739 } u;
740
741 u.asInt = 1;
742 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
743 }
744 };
745
746 // Writes the raw memory into a string, considering endianness
747 template<typename T>
rawMemoryToString(T value)748 std::string rawMemoryToString( T value ) {
749 union _ {
750 T typedValue;
751 unsigned char bytes[sizeof(T)];
752 } u;
753
754 u.typedValue = value;
755
756 std::ostringstream oss;
757 oss << "0x";
758
759 int i = 0, end = sizeof(T), inc = 1;
760 if( Endianness::which() == Endianness::Little ) {
761 i = end-1;
762 end = inc = -1;
763 }
764 for( ; i != end; i += inc )
765 oss << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)u.bytes[i];
766 return oss.str();
767 }
768
769 } // end namespace Detail
770
771 template<typename T>
772 std::string toString( T const& value );
773
774 template<typename T>
775 struct StringMaker :
776 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
777
778 template<typename T>
779 struct StringMaker<T*> {
780 template<typename U>
convertCatch::StringMaker781 static std::string convert( U* p ) {
782 if( !p )
783 return INTERNAL_CATCH_STRINGIFY( NULL );
784 else
785 return Detail::rawMemoryToString( p );
786 }
787 };
788
789 template<typename R, typename C>
790 struct StringMaker<R C::*> {
convertCatch::StringMaker791 static std::string convert( R C::* p ) {
792 if( !p )
793 return INTERNAL_CATCH_STRINGIFY( NULL );
794 else
795 return Detail::rawMemoryToString( p );
796 }
797 };
798
799 namespace Detail {
800 template<typename InputIterator>
801 std::string rangeToString( InputIterator first, InputIterator last );
802 }
803
804 template<typename T, typename Allocator>
805 struct StringMaker<std::vector<T, Allocator> > {
convertCatch::StringMaker806 static std::string convert( std::vector<T,Allocator> const& v ) {
807 return Detail::rangeToString( v.begin(), v.end() );
808 }
809 };
810
811 namespace Detail {
812 template<typename T>
makeString(T const & value)813 std::string makeString( T const& value ) {
814 return StringMaker<T>::convert( value );
815 }
816 } // end namespace Detail
817
818 /// \brief converts any type to a string
819 ///
820 /// The default template forwards on to ostringstream - except when an
821 /// ostringstream overload does not exist - in which case it attempts to detect
822 /// that and writes {?}.
823 /// Overload (not specialise) this template for custom typs that you don't want
824 /// to provide an ostream overload for.
825 template<typename T>
toString(T const & value)826 std::string toString( T const& value ) {
827 return StringMaker<T>::convert( value );
828 }
829
830 // Built in overloads
831
832 std::string toString( std::string const& value );
833 std::string toString( std::wstring const& value );
834 std::string toString( const char* const value );
835 std::string toString( char* const value );
836 std::string toString( int value );
837 std::string toString( unsigned long value );
838 std::string toString( unsigned int value );
839 std::string toString( const double value );
840 std::string toString( bool value );
841 std::string toString( char value );
842 std::string toString( signed char value );
843 std::string toString( unsigned char value );
844
845 #ifdef CATCH_CONFIG_CPP11_NULLPTR
846 std::string toString( std::nullptr_t );
847 #endif
848
849 #ifdef __OBJC__
850 std::string toString( NSString const * const& nsstring );
851 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
852 std::string toString( NSObject* const& nsObject );
853 #endif
854
855 namespace Detail {
856 template<typename InputIterator>
rangeToString(InputIterator first,InputIterator last)857 std::string rangeToString( InputIterator first, InputIterator last ) {
858 std::ostringstream oss;
859 oss << "{ ";
860 if( first != last ) {
861 oss << toString( *first );
862 for( ++first ; first != last ; ++first ) {
863 oss << ", " << toString( *first );
864 }
865 }
866 oss << " }";
867 return oss.str();
868 }
869 }
870
871 } // end namespace Catch
872
873 // #included from: catch_assertionresult.h
874 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
875
876 #include <string>
877 // #included from: catch_result_type.h
878 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
879
880 namespace Catch {
881
882 // ResultWas::OfType enum
883 struct ResultWas { enum OfType {
884 Unknown = -1,
885 Ok = 0,
886 Info = 1,
887 Warning = 2,
888
889 FailureBit = 0x10,
890
891 ExpressionFailed = FailureBit | 1,
892 ExplicitFailure = FailureBit | 2,
893
894 Exception = 0x100 | FailureBit,
895
896 ThrewException = Exception | 1,
897 DidntThrowException = Exception | 2
898
899 }; };
900
isOk(ResultWas::OfType resultType)901 inline bool isOk( ResultWas::OfType resultType ) {
902 return ( resultType & ResultWas::FailureBit ) == 0;
903 }
isJustInfo(int flags)904 inline bool isJustInfo( int flags ) {
905 return flags == ResultWas::Info;
906 }
907
908 // ResultAction::Value enum
909 struct ResultAction { enum Value {
910 None,
911 Failed = 1, // Failure - but no debug break if Debug bit not set
912 Debug = 2, // If this bit is set, invoke the debugger
913 Abort = 4 // Test run should abort
914 }; };
915
916 // ResultDisposition::Flags enum
917 struct ResultDisposition { enum Flags {
918 Normal = 0x00,
919
920 ContinueOnFailure = 0x01, // Failures fail test, but execution continues
921 NegateResult = 0x02, // Prefix expressiom with !
922 SuppressFail = 0x04 // Failures are reported but do not fail the test
923 }; };
924
operator |(ResultDisposition::Flags lhs,ResultDisposition::Flags rhs)925 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
926 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
927 }
928
shouldContinueOnFailure(int flags)929 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
shouldNegate(int flags)930 inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; }
shouldSuppressFailure(int flags)931 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
932
933 } // end namespace Catch
934
935
936 namespace Catch {
937
938 struct AssertionInfo
939 {
AssertionInfoCatch::AssertionInfo940 AssertionInfo() {}
941 AssertionInfo( std::string const& _macroName,
942 SourceLineInfo const& _lineInfo,
943 std::string const& _capturedExpression,
944 ResultDisposition::Flags _resultDisposition );
945
946 std::string macroName;
947 SourceLineInfo lineInfo;
948 std::string capturedExpression;
949 ResultDisposition::Flags resultDisposition;
950 };
951
952 struct AssertionResultData
953 {
AssertionResultDataCatch::AssertionResultData954 AssertionResultData() : resultType( ResultWas::Unknown ) {}
955
956 std::string reconstructedExpression;
957 std::string message;
958 ResultWas::OfType resultType;
959 };
960
961 class AssertionResult {
962 public:
963 AssertionResult();
964 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
965 ~AssertionResult();
966 # ifdef CATCH_CPP11_OR_GREATER
967 AssertionResult( AssertionResult const& ) = default;
968 AssertionResult( AssertionResult && ) = default;
969 AssertionResult& operator = ( AssertionResult const& ) = default;
970 AssertionResult& operator = ( AssertionResult && ) = default;
971 # endif
972
973 bool isOk() const;
974 bool succeeded() const;
975 ResultWas::OfType getResultType() const;
976 bool hasExpression() const;
977 bool hasMessage() const;
978 std::string getExpression() const;
979 std::string getExpressionInMacro() const;
980 bool hasExpandedExpression() const;
981 std::string getExpandedExpression() const;
982 std::string getMessage() const;
983 SourceLineInfo getSourceInfo() const;
984 std::string getTestMacroName() const;
985
986 protected:
987 AssertionInfo m_info;
988 AssertionResultData m_resultData;
989 };
990
991 } // end namespace Catch
992
993 // #included from: catch_evaluate.hpp
994 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
995
996 #ifdef _MSC_VER
997 #pragma warning(push)
998 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
999 #endif
1000
1001 #include <cstddef>
1002
1003 namespace Catch {
1004 namespace Internal {
1005
1006 enum Operator {
1007 IsEqualTo,
1008 IsNotEqualTo,
1009 IsLessThan,
1010 IsGreaterThan,
1011 IsLessThanOrEqualTo,
1012 IsGreaterThanOrEqualTo
1013 };
1014
getNameCatch::Internal::OperatorTraits1015 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
getNameCatch::Internal::OperatorTraits1016 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
getNameCatch::Internal::OperatorTraits1017 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
getNameCatch::Internal::OperatorTraits1018 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
getNameCatch::Internal::OperatorTraits1019 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
getNameCatch::Internal::OperatorTraits1020 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
getNameCatch::Internal::OperatorTraits1021 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1022
1023 template<typename T>
opCast(T const & t)1024 inline T& opCast(T const& t) { return const_cast<T&>(t); }
1025
1026 // nullptr_t support based on pull request #154 from Konstantin Baumann
1027 #ifdef CATCH_CONFIG_CPP11_NULLPTR
opCast(std::nullptr_t)1028 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1029 #endif // CATCH_CONFIG_CPP11_NULLPTR
1030
1031 // So the compare overloads can be operator agnostic we convey the operator as a template
1032 // enum, which is used to specialise an Evaluator for doing the comparison.
1033 template<typename T1, typename T2, Operator Op>
1034 class Evaluator{};
1035
1036 template<typename T1, typename T2>
1037 struct Evaluator<T1, T2, IsEqualTo> {
evaluateCatch::Internal::Evaluator1038 static bool evaluate( T1 const& lhs, T2 const& rhs) {
1039 return opCast( lhs ) == opCast( rhs );
1040 }
1041 };
1042 template<typename T1, typename T2>
1043 struct Evaluator<T1, T2, IsNotEqualTo> {
evaluateCatch::Internal::Evaluator1044 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1045 return opCast( lhs ) != opCast( rhs );
1046 }
1047 };
1048 template<typename T1, typename T2>
1049 struct Evaluator<T1, T2, IsLessThan> {
evaluateCatch::Internal::Evaluator1050 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1051 return opCast( lhs ) < opCast( rhs );
1052 }
1053 };
1054 template<typename T1, typename T2>
1055 struct Evaluator<T1, T2, IsGreaterThan> {
evaluateCatch::Internal::Evaluator1056 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1057 return opCast( lhs ) > opCast( rhs );
1058 }
1059 };
1060 template<typename T1, typename T2>
1061 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1062 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1063 return opCast( lhs ) >= opCast( rhs );
1064 }
1065 };
1066 template<typename T1, typename T2>
1067 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1068 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1069 return opCast( lhs ) <= opCast( rhs );
1070 }
1071 };
1072
1073 template<Operator Op, typename T1, typename T2>
applyEvaluator(T1 const & lhs,T2 const & rhs)1074 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
1075 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1076 }
1077
1078 // This level of indirection allows us to specialise for integer types
1079 // to avoid signed/ unsigned warnings
1080
1081 // "base" overload
1082 template<Operator Op, typename T1, typename T2>
compare(T1 const & lhs,T2 const & rhs)1083 bool compare( T1 const& lhs, T2 const& rhs ) {
1084 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1085 }
1086
1087 // unsigned X to int
compare(unsigned int lhs,int rhs)1088 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
1089 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1090 }
compare(unsigned long lhs,int rhs)1091 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
1092 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1093 }
compare(unsigned char lhs,int rhs)1094 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
1095 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1096 }
1097
1098 // unsigned X to long
compare(unsigned int lhs,long rhs)1099 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
1100 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1101 }
compare(unsigned long lhs,long rhs)1102 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
1103 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1104 }
compare(unsigned char lhs,long rhs)1105 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
1106 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1107 }
1108
1109 // int to unsigned X
compare(int lhs,unsigned int rhs)1110 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
1111 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1112 }
compare(int lhs,unsigned long rhs)1113 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
1114 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1115 }
compare(int lhs,unsigned char rhs)1116 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
1117 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1118 }
1119
1120 // long to unsigned X
compare(long lhs,unsigned int rhs)1121 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
1122 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1123 }
compare(long lhs,unsigned long rhs)1124 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
1125 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1126 }
compare(long lhs,unsigned char rhs)1127 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
1128 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1129 }
1130
1131 // pointer to long (when comparing against NULL)
compare(long lhs,T * rhs)1132 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
1133 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1134 }
compare(T * lhs,long rhs)1135 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
1136 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1137 }
1138
1139 // pointer to int (when comparing against NULL)
compare(int lhs,T * rhs)1140 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
1141 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1142 }
compare(T * lhs,int rhs)1143 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
1144 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1145 }
1146
1147 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1148 // pointer to nullptr_t (when comparing against nullptr)
compare(std::nullptr_t,T * rhs)1149 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1150 return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
1151 }
compare(T * lhs,std::nullptr_t)1152 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1153 return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
1154 }
1155 #endif // CATCH_CONFIG_CPP11_NULLPTR
1156
1157 } // end of namespace Internal
1158 } // end of namespace Catch
1159
1160 #ifdef _MSC_VER
1161 #pragma warning(pop)
1162 #endif
1163
1164 namespace Catch {
1165
1166 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1167
1168 // Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
1169 // the result of evaluating it. This is used to build an AssertionResult object
1170 class ExpressionResultBuilder {
1171 public:
1172
1173 ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown );
1174 ExpressionResultBuilder( ExpressionResultBuilder const& other );
1175 ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other );
1176
1177 ExpressionResultBuilder& setResultType( ResultWas::OfType result );
1178 ExpressionResultBuilder& setResultType( bool result );
1179 ExpressionResultBuilder& setLhs( std::string const& lhs );
1180 ExpressionResultBuilder& setRhs( std::string const& rhs );
1181 ExpressionResultBuilder& setOp( std::string const& op );
1182
1183 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition );
1184
1185 template<typename T>
operator <<(T const & value)1186 ExpressionResultBuilder& operator << ( T const& value ) {
1187 m_stream << value;
1188 return *this;
1189 }
1190
1191 std::string reconstructExpression( AssertionInfo const& info ) const;
1192
1193 AssertionResult buildResult( AssertionInfo const& info ) const;
1194
1195 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1196 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1197
1198 private:
1199 AssertionResultData m_data;
1200 struct ExprComponents {
ExprComponentsCatch::ExpressionResultBuilder::ExprComponents1201 ExprComponents() : shouldNegate( false ) {}
1202 bool shouldNegate;
1203 std::string lhs, rhs, op;
1204 } m_exprComponents;
1205 std::ostringstream m_stream;
1206 };
1207
1208 } // end namespace Catch
1209
1210 namespace Catch {
1211
1212 // Wraps the LHS of an expression and captures the operator and RHS (if any) -
1213 // wrapping them all in an ExpressionResultBuilder object
1214 template<typename T>
1215 class ExpressionLhs {
1216 ExpressionLhs& operator = ( ExpressionLhs const& );
1217 # ifdef CATCH_CPP11_OR_GREATER
1218 ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
1219 # endif
1220
1221 public:
ExpressionLhs(T lhs)1222 ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
1223 # ifdef CATCH_CPP11_OR_GREATER
1224 ExpressionLhs( ExpressionLhs const& ) = default;
1225 ExpressionLhs( ExpressionLhs && ) = default;
1226 # endif
1227
1228 template<typename RhsT>
operator ==(RhsT const & rhs)1229 ExpressionResultBuilder& operator == ( RhsT const& rhs ) {
1230 return captureExpression<Internal::IsEqualTo>( rhs );
1231 }
1232
1233 template<typename RhsT>
operator !=(RhsT const & rhs)1234 ExpressionResultBuilder& operator != ( RhsT const& rhs ) {
1235 return captureExpression<Internal::IsNotEqualTo>( rhs );
1236 }
1237
1238 template<typename RhsT>
operator <(RhsT const & rhs)1239 ExpressionResultBuilder& operator < ( RhsT const& rhs ) {
1240 return captureExpression<Internal::IsLessThan>( rhs );
1241 }
1242
1243 template<typename RhsT>
operator >(RhsT const & rhs)1244 ExpressionResultBuilder& operator > ( RhsT const& rhs ) {
1245 return captureExpression<Internal::IsGreaterThan>( rhs );
1246 }
1247
1248 template<typename RhsT>
operator <=(RhsT const & rhs)1249 ExpressionResultBuilder& operator <= ( RhsT const& rhs ) {
1250 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1251 }
1252
1253 template<typename RhsT>
operator >=(RhsT const & rhs)1254 ExpressionResultBuilder& operator >= ( RhsT const& rhs ) {
1255 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1256 }
1257
operator ==(bool rhs)1258 ExpressionResultBuilder& operator == ( bool rhs ) {
1259 return captureExpression<Internal::IsEqualTo>( rhs );
1260 }
1261
operator !=(bool rhs)1262 ExpressionResultBuilder& operator != ( bool rhs ) {
1263 return captureExpression<Internal::IsNotEqualTo>( rhs );
1264 }
1265
endExpression(ResultDisposition::Flags resultDisposition)1266 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) {
1267 bool value = m_lhs ? true : false;
1268 return m_result
1269 .setLhs( Catch::toString( value ) )
1270 .setResultType( value )
1271 .endExpression( resultDisposition );
1272 }
1273
1274 // Only simple binary expressions are allowed on the LHS.
1275 // If more complex compositions are required then place the sub expression in parentheses
1276 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1277 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1278 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1279 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
1280 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1281 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1282
1283 private:
1284 template<Internal::Operator Op, typename RhsT>
captureExpression(RhsT const & rhs)1285 ExpressionResultBuilder& captureExpression( RhsT const& rhs ) {
1286 return m_result
1287 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1288 .setLhs( Catch::toString( m_lhs ) )
1289 .setRhs( Catch::toString( rhs ) )
1290 .setOp( Internal::OperatorTraits<Op>::getName() );
1291 }
1292
1293 private:
1294 ExpressionResultBuilder m_result;
1295 T m_lhs;
1296 };
1297
1298 } // end namespace Catch
1299
1300 namespace Catch {
1301
1302 // Captures the LHS of the expression and wraps it in an Expression Lhs object
1303 class ExpressionDecomposer {
1304 public:
1305
1306 template<typename T>
operator ->*(T const & operand)1307 ExpressionLhs<T const&> operator->* ( T const& operand ) {
1308 return ExpressionLhs<T const&>( operand );
1309 }
1310
operator ->*(bool value)1311 ExpressionLhs<bool> operator->* ( bool value ) {
1312 return ExpressionLhs<bool>( value );
1313 }
1314 };
1315
1316 } // end namespace Catch
1317
1318 // #included from: catch_message.h
1319 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1320
1321 #include <string>
1322
1323 namespace Catch {
1324
1325 struct MessageInfo {
1326 MessageInfo( std::string const& _macroName,
1327 SourceLineInfo const& _lineInfo,
1328 ResultWas::OfType _type );
1329
1330 std::string macroName;
1331 SourceLineInfo lineInfo;
1332 ResultWas::OfType type;
1333 std::string message;
1334 unsigned int sequence;
1335
operator ==Catch::MessageInfo1336 bool operator == ( MessageInfo const& other ) const {
1337 return sequence == other.sequence;
1338 }
operator <Catch::MessageInfo1339 bool operator < ( MessageInfo const& other ) const {
1340 return sequence < other.sequence;
1341 }
1342 private:
1343 static unsigned int globalCount;
1344 };
1345
1346 struct MessageBuilder {
MessageBuilderCatch::MessageBuilder1347 MessageBuilder( std::string const& macroName,
1348 SourceLineInfo const& lineInfo,
1349 ResultWas::OfType type )
1350 : m_info( macroName, lineInfo, type )
1351 {}
1352
1353 template<typename T>
operator <<Catch::MessageBuilder1354 MessageBuilder& operator << ( T const& value ) {
1355 m_stream << value;
1356 return *this;
1357 }
1358
1359 MessageInfo m_info;
1360 std::ostringstream m_stream;
1361 };
1362
1363 class ScopedMessage {
1364 public:
1365 ScopedMessage( MessageBuilder const& builder );
1366 ScopedMessage( ScopedMessage const& other );
1367 ~ScopedMessage();
1368
1369 MessageInfo m_info;
1370 };
1371
1372 } // end namespace Catch
1373
1374 // #included from: catch_interfaces_capture.h
1375 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1376
1377 #include <string>
1378
1379 namespace Catch {
1380
1381 class TestCase;
1382 class ExpressionResultBuilder;
1383 class AssertionResult;
1384 struct AssertionInfo;
1385 struct SectionInfo;
1386 struct MessageInfo;
1387 class ScopedMessageBuilder;
1388 struct Counts;
1389
1390 struct IResultCapture {
1391
1392 virtual ~IResultCapture();
1393
1394 virtual void assertionEnded( AssertionResult const& result ) = 0;
1395 virtual bool sectionStarted( SectionInfo const& sectionInfo,
1396 Counts& assertions ) = 0;
1397 virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
1398 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1399 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1400
1401 virtual bool shouldDebugBreak() const = 0;
1402
1403 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0;
1404
1405 virtual std::string getCurrentTestName() const = 0;
1406 virtual const AssertionResult* getLastResult() const = 0;
1407 };
1408 }
1409
1410 // #included from: catch_debugger.h
1411 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1412
1413 // #included from: catch_platform.h
1414 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1415
1416 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1417 #define CATCH_PLATFORM_MAC
1418 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1419 #define CATCH_PLATFORM_IPHONE
1420 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1421 #define CATCH_PLATFORM_WINDOWS
1422 #endif
1423
1424 #include <string>
1425
1426 namespace Catch{
1427
1428 bool isDebuggerActive();
1429 void writeToDebugConsole( std::string const& text );
1430 }
1431
1432 #ifdef CATCH_PLATFORM_MAC
1433
1434 // The following code snippet based on:
1435 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1436 #ifdef DEBUG
1437 #if defined(__ppc64__) || defined(__ppc__)
1438 #define CATCH_BREAK_INTO_DEBUGGER() \
1439 if( Catch::isDebuggerActive() ) { \
1440 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1441 : : : "memory","r0","r3","r4" ); \
1442 }
1443 #else
1444 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1445 #endif
1446 #endif
1447
1448 #elif defined(_MSC_VER)
1449 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
1450 #elif defined(__MINGW32__)
1451 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1452 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
1453 #endif
1454
1455 #ifndef CATCH_BREAK_INTO_DEBUGGER
1456 #define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true );
1457 #endif
1458
1459 // #included from: catch_interfaces_registry_hub.h
1460 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1461
1462 #include <string>
1463
1464 namespace Catch {
1465
1466 class TestCase;
1467 struct ITestCaseRegistry;
1468 struct IExceptionTranslatorRegistry;
1469 struct IExceptionTranslator;
1470 struct IReporterRegistry;
1471 struct IReporterFactory;
1472
1473 struct IRegistryHub {
1474 virtual ~IRegistryHub();
1475
1476 virtual IReporterRegistry const& getReporterRegistry() const = 0;
1477 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
1478 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
1479 };
1480
1481 struct IMutableRegistryHub {
1482 virtual ~IMutableRegistryHub();
1483 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
1484 virtual void registerTest( TestCase const& testInfo ) = 0;
1485 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
1486 };
1487
1488 IRegistryHub& getRegistryHub();
1489 IMutableRegistryHub& getMutableRegistryHub();
1490 void cleanUp();
1491 std::string translateActiveException();
1492
1493 }
1494
1495 // #included from: catch_interfaces_config.h
1496 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
1497
1498 #include <iostream>
1499 #include <string>
1500 #include <vector>
1501
1502 namespace Catch {
1503
1504 struct Verbosity { enum Level {
1505 NoOutput = 0,
1506 Quiet,
1507 Normal
1508 }; };
1509
1510 struct WarnAbout { enum What {
1511 Nothing = 0x00,
1512 NoAssertions = 0x01
1513 }; };
1514
1515 struct ShowDurations { enum OrNot {
1516 DefaultForReporter,
1517 Always,
1518 Never
1519 }; };
1520
1521 class TestSpec;
1522
1523 struct IConfig : IShared {
1524
1525 virtual ~IConfig();
1526
1527 virtual bool allowThrows() const = 0;
1528 virtual std::ostream& stream() const = 0;
1529 virtual std::string name() const = 0;
1530 virtual bool includeSuccessfulResults() const = 0;
1531 virtual bool shouldDebugBreak() const = 0;
1532 virtual bool warnAboutMissingAssertions() const = 0;
1533 virtual int abortAfter() const = 0;
1534 virtual bool showInvisibles() const = 0;
1535 virtual ShowDurations::OrNot showDurations() const = 0;
1536 virtual TestSpec const& testSpec() const = 0;
1537 };
1538 }
1539
1540 #include <ostream>
1541
1542 namespace Catch {
1543
getResultCapture()1544 inline IResultCapture& getResultCapture() {
1545 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
1546 return *capture;
1547 else
1548 throw std::logic_error( "No result capture instance" );
1549 }
1550
1551 template<typename MatcherT>
expressionResultBuilderFromMatcher(MatcherT const & matcher,std::string const & matcherCallAsString)1552 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
1553 std::string const& matcherCallAsString ) {
1554 std::string matcherAsString = matcher.toString();
1555 if( matcherAsString == "{?}" )
1556 matcherAsString = matcherCallAsString;
1557 return ExpressionResultBuilder()
1558 .setRhs( matcherAsString )
1559 .setOp( "matches" );
1560 }
1561
1562 template<typename MatcherT, typename ArgT>
expressionResultBuilderFromMatcher(MatcherT const & matcher,ArgT const & arg,std::string const & matcherCallAsString)1563 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
1564 ArgT const& arg,
1565 std::string const& matcherCallAsString ) {
1566 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
1567 .setLhs( Catch::toString( arg ) )
1568 .setResultType( matcher.match( arg ) );
1569 }
1570
1571 template<typename MatcherT, typename ArgT>
expressionResultBuilderFromMatcher(MatcherT const & matcher,ArgT * arg,std::string const & matcherCallAsString)1572 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
1573 ArgT* arg,
1574 std::string const& matcherCallAsString ) {
1575 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
1576 .setLhs( Catch::toString( arg ) )
1577 .setResultType( matcher.match( arg ) );
1578 }
1579
1580 struct TestFailureException{};
1581
1582 } // end namespace Catch
1583
1584 ///////////////////////////////////////////////////////////////////////////////
1585 #define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
1586 if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, __assertionInfo ) ) { \
1587 if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
1588 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
1589 if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
1590 Catch::isTrue( false && originalExpr ); \
1591 }
1592
1593 ///////////////////////////////////////////////////////////////////////////////
1594 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
1595 do { \
1596 Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1597 try { \
1598 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
1599 } catch( Catch::TestFailureException& ) { \
1600 throw; \
1601 } catch( ... ) { \
1602 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
1603 Catch::ResultDisposition::Normal, expr ); \
1604 } \
1605 } while( Catch::isTrue( false ) )
1606
1607 ///////////////////////////////////////////////////////////////////////////////
1608 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
1609 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1610 if( Catch::getResultCapture().getLastResult()->succeeded() )
1611
1612 ///////////////////////////////////////////////////////////////////////////////
1613 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
1614 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1615 if( !Catch::getResultCapture().getLastResult()->succeeded() )
1616
1617 ///////////////////////////////////////////////////////////////////////////////
1618 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
1619 do { \
1620 Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1621 try { \
1622 expr; \
1623 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
1624 } \
1625 catch( ... ) { \
1626 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
1627 } \
1628 } while( Catch::isTrue( false ) )
1629
1630 ///////////////////////////////////////////////////////////////////////////////
1631 #define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
1632 try { \
1633 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1634 expr; \
1635 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
1636 } \
1637 } \
1638 catch( Catch::TestFailureException& ) { \
1639 throw; \
1640 } \
1641 catch( exceptionType ) { \
1642 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
1643 }
1644
1645 ///////////////////////////////////////////////////////////////////////////////
1646 #define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
1647 do { \
1648 Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1649 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
1650 } while( Catch::isTrue( false ) )
1651
1652 ///////////////////////////////////////////////////////////////////////////////
1653 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
1654 do { \
1655 Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1656 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
1657 catch( ... ) { \
1658 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
1659 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
1660 } \
1661 } while( Catch::isTrue( false ) )
1662
1663 ///////////////////////////////////////////////////////////////////////////////
1664 #ifdef CATCH_CONFIG_VARIADIC_MACROS
1665 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
1666 do { \
1667 Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1668 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \
1669 } while( Catch::isTrue( false ) )
1670 #else
1671 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
1672 do { \
1673 Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1674 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
1675 } while( Catch::isTrue( false ) )
1676 #endif
1677
1678 ///////////////////////////////////////////////////////////////////////////////
1679 #define INTERNAL_CATCH_INFO( log, macroName ) \
1680 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
1681
1682 ///////////////////////////////////////////////////////////////////////////////
1683 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
1684 do { \
1685 Catch::AssertionInfo __assertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
1686 try { \
1687 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
1688 } catch( Catch::TestFailureException& ) { \
1689 throw; \
1690 } catch( ... ) { \
1691 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
1692 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
1693 } \
1694 } while( Catch::isTrue( false ) )
1695
1696 // #included from: internal/catch_section.h
1697 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
1698
1699 // #included from: catch_section_info.h
1700 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
1701
1702 namespace Catch {
1703
1704 struct SectionInfo {
SectionInfoCatch::SectionInfo1705 SectionInfo( std::string const& _name,
1706 std::string const& _description,
1707 SourceLineInfo const& _lineInfo )
1708 : name( _name ),
1709 description( _description ),
1710 lineInfo( _lineInfo )
1711 {}
1712
1713 std::string name;
1714 std::string description;
1715 SourceLineInfo lineInfo;
1716 };
1717
1718 } // end namespace Catch
1719
1720 // #included from: catch_totals.hpp
1721 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1722
1723 #include <cstddef>
1724
1725 namespace Catch {
1726
1727 struct Counts {
CountsCatch::Counts1728 Counts() : passed( 0 ), failed( 0 ) {}
1729
operator -Catch::Counts1730 Counts operator - ( Counts const& other ) const {
1731 Counts diff;
1732 diff.passed = passed - other.passed;
1733 diff.failed = failed - other.failed;
1734 return diff;
1735 }
operator +=Catch::Counts1736 Counts& operator += ( Counts const& other ) {
1737 passed += other.passed;
1738 failed += other.failed;
1739 return *this;
1740 }
1741
totalCatch::Counts1742 std::size_t total() const {
1743 return passed + failed;
1744 }
1745
1746 std::size_t passed;
1747 std::size_t failed;
1748 };
1749
1750 struct Totals {
1751
operator -Catch::Totals1752 Totals operator - ( Totals const& other ) const {
1753 Totals diff;
1754 diff.assertions = assertions - other.assertions;
1755 diff.testCases = testCases - other.testCases;
1756 return diff;
1757 }
1758
deltaCatch::Totals1759 Totals delta( Totals const& prevTotals ) const {
1760 Totals diff = *this - prevTotals;
1761 if( diff.assertions.failed > 0 )
1762 ++diff.testCases.failed;
1763 else
1764 ++diff.testCases.passed;
1765 return diff;
1766 }
1767
operator +=Catch::Totals1768 Totals& operator += ( Totals const& other ) {
1769 assertions += other.assertions;
1770 testCases += other.testCases;
1771 return *this;
1772 }
1773
1774 Counts assertions;
1775 Counts testCases;
1776 };
1777 }
1778
1779 // #included from: catch_timer.h
1780 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
1781
1782 #ifdef CATCH_PLATFORM_WINDOWS
1783 typedef unsigned long long uint64_t;
1784 #else
1785 #include <stdint.h>
1786 #endif
1787
1788 namespace Catch {
1789
1790 class Timer {
1791 public:
Timer()1792 Timer() : m_ticks( 0 ) {}
1793 void start();
1794 unsigned int getElapsedNanoseconds() const;
1795 unsigned int getElapsedMilliseconds() const;
1796 double getElapsedSeconds() const;
1797
1798 private:
1799 uint64_t m_ticks;
1800 };
1801
1802 } // namespace Catch
1803
1804 #include <string>
1805
1806 namespace Catch {
1807
1808 class Section {
1809 public:
1810 Section( SourceLineInfo const& lineInfo,
1811 std::string const& name,
1812 std::string const& description = "" );
1813 ~Section();
1814 # ifdef CATCH_CPP11_OR_GREATER
1815 Section( Section const& ) = default;
1816 Section( Section && ) = default;
1817 Section& operator = ( Section const& ) = default;
1818 Section& operator = ( Section && ) = default;
1819 # endif
1820
1821 // This indicates whether the section should be executed or not
1822 operator bool();
1823
1824 private:
1825
1826 SectionInfo m_info;
1827
1828 std::string m_name;
1829 Counts m_assertions;
1830 bool m_sectionIncluded;
1831 Timer m_timer;
1832 };
1833
1834 } // end namespace Catch
1835
1836 #ifdef CATCH_CONFIG_VARIADIC_MACROS
1837 #define INTERNAL_CATCH_SECTION( ... ) \
1838 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
1839 #else
1840 #define INTERNAL_CATCH_SECTION( name, desc ) \
1841 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
1842 #endif
1843
1844 // #included from: internal/catch_generators.hpp
1845 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1846
1847 #include <iterator>
1848 #include <vector>
1849 #include <string>
1850 #include <stdlib.h>
1851
1852 namespace Catch {
1853
1854 template<typename T>
1855 struct IGenerator {
~IGeneratorCatch::IGenerator1856 virtual ~IGenerator() {}
1857 virtual T getValue( std::size_t index ) const = 0;
1858 virtual std::size_t size () const = 0;
1859 };
1860
1861 template<typename T>
1862 class BetweenGenerator : public IGenerator<T> {
1863 public:
BetweenGenerator(T from,T to)1864 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
1865
getValue(std::size_t index) const1866 virtual T getValue( std::size_t index ) const {
1867 return m_from+static_cast<int>( index );
1868 }
1869
size() const1870 virtual std::size_t size() const {
1871 return static_cast<std::size_t>( 1+m_to-m_from );
1872 }
1873
1874 private:
1875
1876 T m_from;
1877 T m_to;
1878 };
1879
1880 template<typename T>
1881 class ValuesGenerator : public IGenerator<T> {
1882 public:
ValuesGenerator()1883 ValuesGenerator(){}
1884
add(T value)1885 void add( T value ) {
1886 m_values.push_back( value );
1887 }
1888
getValue(std::size_t index) const1889 virtual T getValue( std::size_t index ) const {
1890 return m_values[index];
1891 }
1892
size() const1893 virtual std::size_t size() const {
1894 return m_values.size();
1895 }
1896
1897 private:
1898 std::vector<T> m_values;
1899 };
1900
1901 template<typename T>
1902 class CompositeGenerator {
1903 public:
CompositeGenerator()1904 CompositeGenerator() : m_totalSize( 0 ) {}
1905
1906 // *** Move semantics, similar to auto_ptr ***
CompositeGenerator(CompositeGenerator & other)1907 CompositeGenerator( CompositeGenerator& other )
1908 : m_fileInfo( other.m_fileInfo ),
1909 m_totalSize( 0 )
1910 {
1911 move( other );
1912 }
1913
setFileInfo(const char * fileInfo)1914 CompositeGenerator& setFileInfo( const char* fileInfo ) {
1915 m_fileInfo = fileInfo;
1916 return *this;
1917 }
1918
~CompositeGenerator()1919 ~CompositeGenerator() {
1920 deleteAll( m_composed );
1921 }
1922
operator T() const1923 operator T () const {
1924 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
1925
1926 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1927 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1928 for( size_t index = 0; it != itEnd; ++it )
1929 {
1930 const IGenerator<T>* generator = *it;
1931 if( overallIndex >= index && overallIndex < index + generator->size() )
1932 {
1933 return generator->getValue( overallIndex-index );
1934 }
1935 index += generator->size();
1936 }
1937 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
1938 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
1939 }
1940
add(const IGenerator<T> * generator)1941 void add( const IGenerator<T>* generator ) {
1942 m_totalSize += generator->size();
1943 m_composed.push_back( generator );
1944 }
1945
then(CompositeGenerator & other)1946 CompositeGenerator& then( CompositeGenerator& other ) {
1947 move( other );
1948 return *this;
1949 }
1950
then(T value)1951 CompositeGenerator& then( T value ) {
1952 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1953 valuesGen->add( value );
1954 add( valuesGen );
1955 return *this;
1956 }
1957
1958 private:
1959
move(CompositeGenerator & other)1960 void move( CompositeGenerator& other ) {
1961 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1962 m_totalSize += other.m_totalSize;
1963 other.m_composed.clear();
1964 }
1965
1966 std::vector<const IGenerator<T>*> m_composed;
1967 std::string m_fileInfo;
1968 size_t m_totalSize;
1969 };
1970
1971 namespace Generators
1972 {
1973 template<typename T>
between(T from,T to)1974 CompositeGenerator<T> between( T from, T to ) {
1975 CompositeGenerator<T> generators;
1976 generators.add( new BetweenGenerator<T>( from, to ) );
1977 return generators;
1978 }
1979
1980 template<typename T>
values(T val1,T val2)1981 CompositeGenerator<T> values( T val1, T val2 ) {
1982 CompositeGenerator<T> generators;
1983 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1984 valuesGen->add( val1 );
1985 valuesGen->add( val2 );
1986 generators.add( valuesGen );
1987 return generators;
1988 }
1989
1990 template<typename T>
values(T val1,T val2,T val3)1991 CompositeGenerator<T> values( T val1, T val2, T val3 ){
1992 CompositeGenerator<T> generators;
1993 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1994 valuesGen->add( val1 );
1995 valuesGen->add( val2 );
1996 valuesGen->add( val3 );
1997 generators.add( valuesGen );
1998 return generators;
1999 }
2000
2001 template<typename T>
values(T val1,T val2,T val3,T val4)2002 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2003 CompositeGenerator<T> generators;
2004 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2005 valuesGen->add( val1 );
2006 valuesGen->add( val2 );
2007 valuesGen->add( val3 );
2008 valuesGen->add( val4 );
2009 generators.add( valuesGen );
2010 return generators;
2011 }
2012
2013 } // end namespace Generators
2014
2015 using namespace Generators;
2016
2017 } // end namespace Catch
2018
2019 #define INTERNAL_CATCH_LINESTR2( line ) #line
2020 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2021
2022 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2023
2024 // #included from: internal/catch_interfaces_exception.h
2025 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2026
2027 #include <string>
2028
2029 namespace Catch {
2030
2031 typedef std::string(*exceptionTranslateFunction)();
2032
2033 struct IExceptionTranslator {
2034 virtual ~IExceptionTranslator();
2035 virtual std::string translate() const = 0;
2036 };
2037
2038 struct IExceptionTranslatorRegistry {
2039 virtual ~IExceptionTranslatorRegistry();
2040
2041 virtual std::string translateActiveException() const = 0;
2042 };
2043
2044 class ExceptionTranslatorRegistrar {
2045 template<typename T>
2046 class ExceptionTranslator : public IExceptionTranslator {
2047 public:
2048
ExceptionTranslator(std::string (* translateFunction)(T &))2049 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2050 : m_translateFunction( translateFunction )
2051 {}
2052
translate() const2053 virtual std::string translate() const {
2054 try {
2055 throw;
2056 }
2057 catch( T& ex ) {
2058 return m_translateFunction( ex );
2059 }
2060 }
2061
2062 protected:
2063 std::string(*m_translateFunction)( T& );
2064 };
2065
2066 public:
2067 template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))2068 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2069 getMutableRegistryHub().registerTranslator
2070 ( new ExceptionTranslator<T>( translateFunction ) );
2071 }
2072 };
2073 }
2074
2075 ///////////////////////////////////////////////////////////////////////////////
2076 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2077 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2078 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2079 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2080
2081 // #included from: internal/catch_approx.hpp
2082 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2083
2084 #include <cmath>
2085 #include <limits>
2086
2087 namespace Catch {
2088 namespace Detail {
2089
2090 class Approx {
2091 public:
Approx(double value)2092 explicit Approx ( double value )
2093 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2094 m_scale( 1.0 ),
2095 m_value( value )
2096 {}
2097
Approx(Approx const & other)2098 Approx( Approx const& other )
2099 : m_epsilon( other.m_epsilon ),
2100 m_scale( other.m_scale ),
2101 m_value( other.m_value )
2102 {}
2103
custom()2104 static Approx custom() {
2105 return Approx( 0 );
2106 }
2107
operator ()(double value)2108 Approx operator()( double value ) {
2109 Approx approx( value );
2110 approx.epsilon( m_epsilon );
2111 approx.scale( m_scale );
2112 return approx;
2113 }
2114
operator ==(double lhs,Approx const & rhs)2115 friend bool operator == ( double lhs, Approx const& rhs ) {
2116 // Thanks to Richard Harris for his help refining this formula
2117 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2118 }
2119
operator ==(Approx const & lhs,double rhs)2120 friend bool operator == ( Approx const& lhs, double rhs ) {
2121 return operator==( rhs, lhs );
2122 }
2123
operator !=(double lhs,Approx const & rhs)2124 friend bool operator != ( double lhs, Approx const& rhs ) {
2125 return !operator==( lhs, rhs );
2126 }
2127
operator !=(Approx const & lhs,double rhs)2128 friend bool operator != ( Approx const& lhs, double rhs ) {
2129 return !operator==( rhs, lhs );
2130 }
2131
epsilon(double newEpsilon)2132 Approx& epsilon( double newEpsilon ) {
2133 m_epsilon = newEpsilon;
2134 return *this;
2135 }
2136
scale(double newScale)2137 Approx& scale( double newScale ) {
2138 m_scale = newScale;
2139 return *this;
2140 }
2141
toString() const2142 std::string toString() const {
2143 std::ostringstream oss;
2144 oss << "Approx( " << Catch::toString( m_value ) << " )";
2145 return oss.str();
2146 }
2147
2148 private:
2149 double m_epsilon;
2150 double m_scale;
2151 double m_value;
2152 };
2153 }
2154
2155 template<>
toString(Detail::Approx const & value)2156 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
2157 return value.toString();
2158 }
2159
2160 } // end namespace Catch
2161
2162 // #included from: internal/catch_matchers.hpp
2163 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2164
2165 namespace Catch {
2166 namespace Matchers {
2167 namespace Impl {
2168
2169 template<typename ExpressionT>
2170 struct Matcher : SharedImpl<IShared>
2171 {
2172 typedef ExpressionT ExpressionType;
2173
~MatcherCatch::Matchers::Impl::Matcher2174 virtual ~Matcher() {}
2175 virtual Ptr<Matcher> clone() const = 0;
2176 virtual bool match( ExpressionT const& expr ) const = 0;
2177 virtual std::string toString() const = 0;
2178 };
2179
2180 template<typename DerivedT, typename ExpressionT>
2181 struct MatcherImpl : Matcher<ExpressionT> {
2182
cloneCatch::Matchers::Impl::MatcherImpl2183 virtual Ptr<Matcher<ExpressionT> > clone() const {
2184 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
2185 }
2186 };
2187
2188 namespace Generic {
2189
2190 template<typename ExpressionT>
2191 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
2192 public:
2193
AllOf()2194 AllOf() {}
AllOf(AllOf const & other)2195 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
2196
add(Matcher<ExpressionT> const & matcher)2197 AllOf& add( Matcher<ExpressionT> const& matcher ) {
2198 m_matchers.push_back( matcher.clone() );
2199 return *this;
2200 }
match(ExpressionT const & expr) const2201 virtual bool match( ExpressionT const& expr ) const
2202 {
2203 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2204 if( !m_matchers[i]->match( expr ) )
2205 return false;
2206 return true;
2207 }
toString() const2208 virtual std::string toString() const {
2209 std::ostringstream oss;
2210 oss << "( ";
2211 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2212 if( i != 0 )
2213 oss << " and ";
2214 oss << m_matchers[i]->toString();
2215 }
2216 oss << " )";
2217 return oss.str();
2218 }
2219
2220 private:
2221 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2222 };
2223
2224 template<typename ExpressionT>
2225 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
2226 public:
2227
AnyOf()2228 AnyOf() {}
AnyOf(AnyOf const & other)2229 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
2230
add(Matcher<ExpressionT> const & matcher)2231 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
2232 m_matchers.push_back( matcher.clone() );
2233 return *this;
2234 }
match(ExpressionT const & expr) const2235 virtual bool match( ExpressionT const& expr ) const
2236 {
2237 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2238 if( m_matchers[i]->match( expr ) )
2239 return true;
2240 return false;
2241 }
toString() const2242 virtual std::string toString() const {
2243 std::ostringstream oss;
2244 oss << "( ";
2245 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2246 if( i != 0 )
2247 oss << " or ";
2248 oss << m_matchers[i]->toString();
2249 }
2250 oss << " )";
2251 return oss.str();
2252 }
2253
2254 private:
2255 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2256 };
2257
2258 }
2259
2260 namespace StdString {
2261
makeString(std::string const & str)2262 inline std::string makeString( std::string const& str ) { return str; }
makeString(const char * str)2263 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
2264
2265 struct Equals : MatcherImpl<Equals, std::string> {
EqualsCatch::Matchers::Impl::StdString::Equals2266 Equals( std::string const& str ) : m_str( str ){}
EqualsCatch::Matchers::Impl::StdString::Equals2267 Equals( Equals const& other ) : m_str( other.m_str ){}
2268
2269 virtual ~Equals();
2270
matchCatch::Matchers::Impl::StdString::Equals2271 virtual bool match( std::string const& expr ) const {
2272 return m_str == expr;
2273 }
toStringCatch::Matchers::Impl::StdString::Equals2274 virtual std::string toString() const {
2275 return "equals: \"" + m_str + "\"";
2276 }
2277
2278 std::string m_str;
2279 };
2280
2281 struct Contains : MatcherImpl<Contains, std::string> {
ContainsCatch::Matchers::Impl::StdString::Contains2282 Contains( std::string const& substr ) : m_substr( substr ){}
ContainsCatch::Matchers::Impl::StdString::Contains2283 Contains( Contains const& other ) : m_substr( other.m_substr ){}
2284
2285 virtual ~Contains();
2286
matchCatch::Matchers::Impl::StdString::Contains2287 virtual bool match( std::string const& expr ) const {
2288 return expr.find( m_substr ) != std::string::npos;
2289 }
toStringCatch::Matchers::Impl::StdString::Contains2290 virtual std::string toString() const {
2291 return "contains: \"" + m_substr + "\"";
2292 }
2293
2294 std::string m_substr;
2295 };
2296
2297 struct StartsWith : MatcherImpl<StartsWith, std::string> {
StartsWithCatch::Matchers::Impl::StdString::StartsWith2298 StartsWith( std::string const& substr ) : m_substr( substr ){}
StartsWithCatch::Matchers::Impl::StdString::StartsWith2299 StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
2300
2301 virtual ~StartsWith();
2302
matchCatch::Matchers::Impl::StdString::StartsWith2303 virtual bool match( std::string const& expr ) const {
2304 return expr.find( m_substr ) == 0;
2305 }
toStringCatch::Matchers::Impl::StdString::StartsWith2306 virtual std::string toString() const {
2307 return "starts with: \"" + m_substr + "\"";
2308 }
2309
2310 std::string m_substr;
2311 };
2312
2313 struct EndsWith : MatcherImpl<EndsWith, std::string> {
EndsWithCatch::Matchers::Impl::StdString::EndsWith2314 EndsWith( std::string const& substr ) : m_substr( substr ){}
EndsWithCatch::Matchers::Impl::StdString::EndsWith2315 EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
2316
2317 virtual ~EndsWith();
2318
matchCatch::Matchers::Impl::StdString::EndsWith2319 virtual bool match( std::string const& expr ) const {
2320 return expr.find( m_substr ) == expr.size() - m_substr.size();
2321 }
toStringCatch::Matchers::Impl::StdString::EndsWith2322 virtual std::string toString() const {
2323 return "ends with: \"" + m_substr + "\"";
2324 }
2325
2326 std::string m_substr;
2327 };
2328 } // namespace StdString
2329 } // namespace Impl
2330
2331 // The following functions create the actual matcher objects.
2332 // This allows the types to be inferred
2333 template<typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)2334 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
2335 Impl::Matcher<ExpressionT> const& m2 ) {
2336 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
2337 }
2338 template<typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)2339 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
2340 Impl::Matcher<ExpressionT> const& m2,
2341 Impl::Matcher<ExpressionT> const& m3 ) {
2342 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2343 }
2344 template<typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)2345 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
2346 Impl::Matcher<ExpressionT> const& m2 ) {
2347 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
2348 }
2349 template<typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)2350 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
2351 Impl::Matcher<ExpressionT> const& m2,
2352 Impl::Matcher<ExpressionT> const& m3 ) {
2353 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2354 }
2355
Equals(std::string const & str)2356 inline Impl::StdString::Equals Equals( std::string const& str ) {
2357 return Impl::StdString::Equals( str );
2358 }
Equals(const char * str)2359 inline Impl::StdString::Equals Equals( const char* str ) {
2360 return Impl::StdString::Equals( Impl::StdString::makeString( str ) );
2361 }
Contains(std::string const & substr)2362 inline Impl::StdString::Contains Contains( std::string const& substr ) {
2363 return Impl::StdString::Contains( substr );
2364 }
Contains(const char * substr)2365 inline Impl::StdString::Contains Contains( const char* substr ) {
2366 return Impl::StdString::Contains( Impl::StdString::makeString( substr ) );
2367 }
StartsWith(std::string const & substr)2368 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
2369 return Impl::StdString::StartsWith( substr );
2370 }
StartsWith(const char * substr)2371 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
2372 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
2373 }
EndsWith(std::string const & substr)2374 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
2375 return Impl::StdString::EndsWith( substr );
2376 }
EndsWith(const char * substr)2377 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
2378 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
2379 }
2380
2381 } // namespace Matchers
2382
2383 using namespace Matchers;
2384
2385 } // namespace Catch
2386
2387 // These files are included here so the single_include script doesn't put them
2388 // in the conditionally compiled sections
2389 // #included from: internal/catch_test_case_info.h
2390 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2391
2392 #include <string>
2393 #include <set>
2394
2395 #ifdef __clang__
2396 #pragma clang diagnostic push
2397 #pragma clang diagnostic ignored "-Wpadded"
2398 #endif
2399
2400 namespace Catch {
2401
2402 struct ITestCase;
2403
2404 struct TestCaseInfo {
2405 TestCaseInfo( std::string const& _name,
2406 std::string const& _className,
2407 std::string const& _description,
2408 std::set<std::string> const& _tags,
2409 bool _isHidden,
2410 SourceLineInfo const& _lineInfo );
2411
2412 TestCaseInfo( TestCaseInfo const& other );
2413
2414 std::string name;
2415 std::string className;
2416 std::string description;
2417 std::set<std::string> tags;
2418 std::set<std::string> lcaseTags;
2419 std::string tagsAsString;
2420 SourceLineInfo lineInfo;
2421 bool isHidden;
2422 bool throws;
2423 };
2424
2425 class TestCase : public TestCaseInfo {
2426 public:
2427
2428 TestCase( ITestCase* testCase, TestCaseInfo const& info );
2429 TestCase( TestCase const& other );
2430
2431 TestCase withName( std::string const& _newName ) const;
2432
2433 void invoke() const;
2434
2435 TestCaseInfo const& getTestCaseInfo() const;
2436
2437 bool isHidden() const;
2438 bool throws() const;
2439
2440 void swap( TestCase& other );
2441 bool operator == ( TestCase const& other ) const;
2442 bool operator < ( TestCase const& other ) const;
2443 TestCase& operator = ( TestCase const& other );
2444
2445 private:
2446 Ptr<ITestCase> test;
2447 };
2448
2449 TestCase makeTestCase( ITestCase* testCase,
2450 std::string const& className,
2451 std::string const& name,
2452 std::string const& description,
2453 SourceLineInfo const& lineInfo );
2454 }
2455
2456 #ifdef __clang__
2457 #pragma clang diagnostic pop
2458 #endif
2459
2460 // #included from: internal/catch_interfaces_runner.h
2461 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2462
2463 namespace Catch {
2464 class TestCase;
2465
2466 struct IRunner {
2467 virtual ~IRunner();
2468 };
2469 }
2470
2471
2472 #ifdef __OBJC__
2473 // #included from: internal/catch_objc.hpp
2474 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2475
2476 #import <objc/runtime.h>
2477
2478 #include <string>
2479
2480 // NB. Any general catch headers included here must be included
2481 // in catch.hpp first to make sure they are included by the single
2482 // header for non obj-usage
2483
2484 ///////////////////////////////////////////////////////////////////////////////
2485 // This protocol is really only here for (self) documenting purposes, since
2486 // all its methods are optional.
2487 @protocol OcFixture
2488
2489 @optional
2490
2491 -(void) setUp;
2492 -(void) tearDown;
2493
2494 @end
2495
2496 namespace Catch {
2497
2498 class OcMethod : public SharedImpl<ITestCase> {
2499
2500 public:
OcMethod(Class cls,SEL sel)2501 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2502
invoke() const2503 virtual void invoke() const {
2504 id obj = [[m_cls alloc] init];
2505
2506 performOptionalSelector( obj, @selector(setUp) );
2507 performOptionalSelector( obj, m_sel );
2508 performOptionalSelector( obj, @selector(tearDown) );
2509
2510 arcSafeRelease( obj );
2511 }
2512 private:
~OcMethod()2513 virtual ~OcMethod() {}
2514
2515 Class m_cls;
2516 SEL m_sel;
2517 };
2518
2519 namespace Detail{
2520
getAnnotation(Class cls,std::string const & annotationName,std::string const & testCaseName)2521 inline std::string getAnnotation( Class cls,
2522 std::string const& annotationName,
2523 std::string const& testCaseName ) {
2524 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2525 SEL sel = NSSelectorFromString( selStr );
2526 arcSafeRelease( selStr );
2527 id value = performOptionalSelector( cls, sel );
2528 if( value )
2529 return [(NSString*)value UTF8String];
2530 return "";
2531 }
2532 }
2533
registerTestMethods()2534 inline size_t registerTestMethods() {
2535 size_t noTestMethods = 0;
2536 int noClasses = objc_getClassList( NULL, 0 );
2537
2538 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
2539 objc_getClassList( classes, noClasses );
2540
2541 for( int c = 0; c < noClasses; c++ ) {
2542 Class cls = classes[c];
2543 {
2544 u_int count;
2545 Method* methods = class_copyMethodList( cls, &count );
2546 for( u_int m = 0; m < count ; m++ ) {
2547 SEL selector = method_getName(methods[m]);
2548 std::string methodName = sel_getName(selector);
2549 if( startsWith( methodName, "Catch_TestCase_" ) ) {
2550 std::string testCaseName = methodName.substr( 15 );
2551 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2552 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
2553 const char* className = class_getName( cls );
2554
2555 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
2556 noTestMethods++;
2557 }
2558 }
2559 free(methods);
2560 }
2561 }
2562 return noTestMethods;
2563 }
2564
2565 namespace Matchers {
2566 namespace Impl {
2567 namespace NSStringMatchers {
2568
2569 template<typename MatcherT>
2570 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2571 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2572 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2573 StringHolder() {
2574 arcSafeRelease( m_substr );
2575 }
2576
2577 NSString* m_substr;
2578 };
2579
2580 struct Equals : StringHolder<Equals> {
EqualsCatch::Matchers::Impl::NSStringMatchers::Equals2581 Equals( NSString* substr ) : StringHolder( substr ){}
2582
matchCatch::Matchers::Impl::NSStringMatchers::Equals2583 virtual bool match( ExpressionType const& str ) const {
2584 return (str != nil || m_substr == nil ) &&
2585 [str isEqualToString:m_substr];
2586 }
2587
toStringCatch::Matchers::Impl::NSStringMatchers::Equals2588 virtual std::string toString() const {
2589 return "equals string: \"" + Catch::toString( m_substr ) + "\"";
2590 }
2591 };
2592
2593 struct Contains : StringHolder<Contains> {
ContainsCatch::Matchers::Impl::NSStringMatchers::Contains2594 Contains( NSString* substr ) : StringHolder( substr ){}
2595
matchCatch::Matchers::Impl::NSStringMatchers::Contains2596 virtual bool match( ExpressionType const& str ) const {
2597 return (str != nil || m_substr == nil ) &&
2598 [str rangeOfString:m_substr].location != NSNotFound;
2599 }
2600
toStringCatch::Matchers::Impl::NSStringMatchers::Contains2601 virtual std::string toString() const {
2602 return "contains string: \"" + Catch::toString( m_substr ) + "\"";
2603 }
2604 };
2605
2606 struct StartsWith : StringHolder<StartsWith> {
StartsWithCatch::Matchers::Impl::NSStringMatchers::StartsWith2607 StartsWith( NSString* substr ) : StringHolder( substr ){}
2608
matchCatch::Matchers::Impl::NSStringMatchers::StartsWith2609 virtual bool match( ExpressionType const& str ) const {
2610 return (str != nil || m_substr == nil ) &&
2611 [str rangeOfString:m_substr].location == 0;
2612 }
2613
toStringCatch::Matchers::Impl::NSStringMatchers::StartsWith2614 virtual std::string toString() const {
2615 return "starts with: \"" + Catch::toString( m_substr ) + "\"";
2616 }
2617 };
2618 struct EndsWith : StringHolder<EndsWith> {
EndsWithCatch::Matchers::Impl::NSStringMatchers::EndsWith2619 EndsWith( NSString* substr ) : StringHolder( substr ){}
2620
matchCatch::Matchers::Impl::NSStringMatchers::EndsWith2621 virtual bool match( ExpressionType const& str ) const {
2622 return (str != nil || m_substr == nil ) &&
2623 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2624 }
2625
toStringCatch::Matchers::Impl::NSStringMatchers::EndsWith2626 virtual std::string toString() const {
2627 return "ends with: \"" + Catch::toString( m_substr ) + "\"";
2628 }
2629 };
2630
2631 } // namespace NSStringMatchers
2632 } // namespace Impl
2633
2634 inline Impl::NSStringMatchers::Equals
Equals(NSString * substr)2635 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2636
2637 inline Impl::NSStringMatchers::Contains
Contains(NSString * substr)2638 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
2639
2640 inline Impl::NSStringMatchers::StartsWith
StartsWith(NSString * substr)2641 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
2642
2643 inline Impl::NSStringMatchers::EndsWith
EndsWith(NSString * substr)2644 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2645
2646 } // namespace Matchers
2647
2648 using namespace Matchers;
2649
2650 } // namespace Catch
2651
2652 ///////////////////////////////////////////////////////////////////////////////
2653 #define OC_TEST_CASE( name, desc )\
2654 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2655 {\
2656 return @ name; \
2657 }\
2658 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2659 { \
2660 return @ desc; \
2661 } \
2662 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2663
2664 #endif
2665
2666 #ifdef CATCH_CONFIG_RUNNER
2667 // #included from: internal/catch_impl.hpp
2668 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2669
2670 // Collect all the implementation files together here
2671 // These are the equivalent of what would usually be cpp files
2672
2673 #ifdef __clang__
2674 #pragma clang diagnostic push
2675 #pragma clang diagnostic ignored "-Wweak-vtables"
2676 #endif
2677
2678 // #included from: catch_runner.hpp
2679 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2680
2681 // #included from: internal/catch_commandline.hpp
2682 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2683
2684 // #included from: catch_config.hpp
2685 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2686
2687 // #included from: catch_test_spec_parser.hpp
2688 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
2689
2690 #ifdef __clang__
2691 #pragma clang diagnostic push
2692 #pragma clang diagnostic ignored "-Wpadded"
2693 #endif
2694
2695 // #included from: catch_test_spec.hpp
2696 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
2697
2698 #ifdef __clang__
2699 #pragma clang diagnostic push
2700 #pragma clang diagnostic ignored "-Wpadded"
2701 #endif
2702
2703 #include <string>
2704 #include <vector>
2705
2706 namespace Catch {
2707
2708 class TestSpec {
2709 struct Pattern : SharedImpl<> {
2710 virtual ~Pattern();
2711 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
2712 };
2713 class NamePattern : public Pattern {
2714 enum WildcardPosition {
2715 NoWildcard = 0,
2716 WildcardAtStart = 1,
2717 WildcardAtEnd = 2,
2718 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
2719 };
2720
2721 public:
NamePattern(std::string const & name)2722 NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) {
2723 if( startsWith( m_name, "*" ) ) {
2724 m_name = m_name.substr( 1 );
2725 m_wildcard = WildcardAtStart;
2726 }
2727 if( endsWith( m_name, "*" ) ) {
2728 m_name = m_name.substr( 0, m_name.size()-1 );
2729 m_wildcard = (WildcardPosition)( m_wildcard | WildcardAtEnd );
2730 }
2731 }
2732 virtual ~NamePattern();
matches(TestCaseInfo const & testCase) const2733 virtual bool matches( TestCaseInfo const& testCase ) const {
2734 switch( m_wildcard ) {
2735 case NoWildcard:
2736 return m_name == toLower( testCase.name );
2737 case WildcardAtStart:
2738 return endsWith( toLower( testCase.name ), m_name );
2739 case WildcardAtEnd:
2740 return startsWith( toLower( testCase.name ), m_name );
2741 case WildcardAtBothEnds:
2742 return contains( toLower( testCase.name ), m_name );
2743 }
2744
2745 #ifdef __clang__
2746 #pragma clang diagnostic push
2747 #pragma clang diagnostic ignored "-Wunreachable-code"
2748 #endif
2749 throw std::logic_error( "Unknown enum" );
2750 #ifdef __clang__
2751 #pragma clang diagnostic pop
2752 #endif
2753 }
2754 private:
2755 std::string m_name;
2756 WildcardPosition m_wildcard;
2757 };
2758 class TagPattern : public Pattern {
2759 public:
TagPattern(std::string const & tag)2760 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
2761 virtual ~TagPattern();
matches(TestCaseInfo const & testCase) const2762 virtual bool matches( TestCaseInfo const& testCase ) const {
2763 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
2764 }
2765 private:
2766 std::string m_tag;
2767 };
2768 class ExcludedPattern : public Pattern {
2769 public:
ExcludedPattern(Ptr<Pattern> const & underlyingPattern)2770 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
2771 virtual ~ExcludedPattern();
matches(TestCaseInfo const & testCase) const2772 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
2773 private:
2774 Ptr<Pattern> m_underlyingPattern;
2775 };
2776
2777 struct Filter {
2778 std::vector<Ptr<Pattern> > m_patterns;
2779
matchesCatch::TestSpec::Filter2780 bool matches( TestCaseInfo const& testCase ) const {
2781 // All patterns in a filter must match for the filter to be a match
2782 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
2783 if( !(*it)->matches( testCase ) )
2784 return false;
2785 return true;
2786 }
2787 };
2788
2789 public:
hasFilters() const2790 bool hasFilters() const {
2791 return !m_filters.empty();
2792 }
matches(TestCaseInfo const & testCase) const2793 bool matches( TestCaseInfo const& testCase ) const {
2794 // A TestSpec matches if any filter matches
2795 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
2796 if( it->matches( testCase ) )
2797 return true;
2798 return false;
2799 }
2800
2801 private:
2802 std::vector<Filter> m_filters;
2803
2804 friend class TestSpecParser;
2805 };
2806 }
2807
2808 #ifdef __clang__
2809 #pragma clang diagnostic pop
2810 #endif
2811
2812 namespace Catch {
2813
2814 class TestSpecParser {
2815 enum Mode{ None, Name, QuotedName, Tag };
2816 Mode m_mode;
2817 bool m_exclusion;
2818 std::size_t m_start, m_pos;
2819 std::string m_arg;
2820 TestSpec::Filter m_currentFilter;
2821 TestSpec m_testSpec;
2822
2823 public:
parse(std::string const & arg)2824 TestSpecParser parse( std::string const& arg ) {
2825 m_mode = None;
2826 m_exclusion = false;
2827 m_start = std::string::npos;
2828 m_arg = arg;
2829 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
2830 visitChar( m_arg[m_pos] );
2831 if( m_mode == Name )
2832 addPattern<TestSpec::NamePattern>();
2833 return *this;
2834 }
testSpec()2835 TestSpec testSpec() {
2836 addFilter();
2837 return m_testSpec;
2838 }
2839 private:
visitChar(char c)2840 void visitChar( char c ) {
2841 if( m_mode == None ) {
2842 switch( c ) {
2843 case ' ': return;
2844 case '~': m_exclusion = true; return;
2845 case '[': return startNewMode( Tag, ++m_pos );
2846 case '"': return startNewMode( QuotedName, ++m_pos );
2847 default: startNewMode( Name, m_pos ); break;
2848 }
2849 }
2850 if( m_mode == Name ) {
2851 if( c == ',' ) {
2852 addPattern<TestSpec::NamePattern>();
2853 addFilter();
2854 }
2855 else if( c == '[' ) {
2856 if( subString() == "exclude:" )
2857 m_exclusion = true;
2858 else
2859 addPattern<TestSpec::NamePattern>();
2860 startNewMode( Tag, ++m_pos );
2861 }
2862 }
2863 else if( m_mode == QuotedName && c == '"' )
2864 addPattern<TestSpec::NamePattern>();
2865 else if( m_mode == Tag && c == ']' )
2866 addPattern<TestSpec::TagPattern>();
2867 }
startNewMode(Mode mode,std::size_t start)2868 void startNewMode( Mode mode, std::size_t start ) {
2869 m_mode = mode;
2870 m_start = start;
2871 }
subString() const2872 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
2873 template<typename T>
addPattern()2874 void addPattern() {
2875 std::string token = subString();
2876 if( startsWith( token, "exclude:" ) ) {
2877 m_exclusion = true;
2878 token = token.substr( 8 );
2879 }
2880 if( !token.empty() ) {
2881 Ptr<TestSpec::Pattern> pattern = new T( token );
2882 if( m_exclusion )
2883 pattern = new TestSpec::ExcludedPattern( pattern );
2884 m_currentFilter.m_patterns.push_back( pattern );
2885 }
2886 m_exclusion = false;
2887 m_mode = None;
2888 }
addFilter()2889 void addFilter() {
2890 if( !m_currentFilter.m_patterns.empty() ) {
2891 m_testSpec.m_filters.push_back( m_currentFilter );
2892 m_currentFilter = TestSpec::Filter();
2893 }
2894 }
2895 };
parseTestSpec(std::string const & arg)2896 inline TestSpec parseTestSpec( std::string const& arg ) {
2897 return TestSpecParser().parse( arg ).testSpec();
2898 }
2899
2900 } // namespace Catch
2901
2902 #ifdef __clang__
2903 #pragma clang diagnostic pop
2904 #endif
2905
2906 // #included from: catch_stream.h
2907 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
2908
2909 #include <streambuf>
2910
2911 #ifdef __clang__
2912 #pragma clang diagnostic ignored "-Wpadded"
2913 #endif
2914
2915 namespace Catch {
2916
2917 class Stream {
2918 public:
2919 Stream();
2920 Stream( std::streambuf* _streamBuf, bool _isOwned );
2921 void release();
2922
2923 std::streambuf* streamBuf;
2924
2925 private:
2926 bool isOwned;
2927 };
2928 }
2929
2930 #include <memory>
2931 #include <vector>
2932 #include <string>
2933 #include <iostream>
2934
2935 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
2936 #define CATCH_CONFIG_CONSOLE_WIDTH 80
2937 #endif
2938
2939 namespace Catch {
2940
2941 struct ConfigData {
2942
ConfigDataCatch::ConfigData2943 ConfigData()
2944 : listTests( false ),
2945 listTags( false ),
2946 listReporters( false ),
2947 listTestNamesOnly( false ),
2948 showSuccessfulTests( false ),
2949 shouldDebugBreak( false ),
2950 noThrow( false ),
2951 showHelp( false ),
2952 showInvisibles( false ),
2953 abortAfter( -1 ),
2954 verbosity( Verbosity::Normal ),
2955 warnings( WarnAbout::Nothing ),
2956 showDurations( ShowDurations::DefaultForReporter )
2957 {}
2958
2959 bool listTests;
2960 bool listTags;
2961 bool listReporters;
2962 bool listTestNamesOnly;
2963
2964 bool showSuccessfulTests;
2965 bool shouldDebugBreak;
2966 bool noThrow;
2967 bool showHelp;
2968 bool showInvisibles;
2969
2970 int abortAfter;
2971
2972 Verbosity::Level verbosity;
2973 WarnAbout::What warnings;
2974 ShowDurations::OrNot showDurations;
2975
2976 std::string reporterName;
2977 std::string outputFilename;
2978 std::string name;
2979 std::string processName;
2980
2981 std::vector<std::string> testsOrTags;
2982 };
2983
2984 class Config : public SharedImpl<IConfig> {
2985 private:
2986 Config( Config const& other );
2987 Config& operator = ( Config const& other );
2988 virtual void dummy();
2989 public:
2990
Config()2991 Config()
2992 : m_os( std::cout.rdbuf() )
2993 {}
2994
Config(ConfigData const & data)2995 Config( ConfigData const& data )
2996 : m_data( data ),
2997 m_os( std::cout.rdbuf() )
2998 {
2999 if( !data.testsOrTags.empty() ) {
3000 TestSpecParser parser;
3001 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3002 parser.parse( data.testsOrTags[i] );
3003 m_testSpec = parser.testSpec();
3004 }
3005 }
3006
~Config()3007 virtual ~Config() {
3008 m_os.rdbuf( std::cout.rdbuf() );
3009 m_stream.release();
3010 }
3011
setFilename(std::string const & filename)3012 void setFilename( std::string const& filename ) {
3013 m_data.outputFilename = filename;
3014 }
3015
getFilename() const3016 std::string const& getFilename() const {
3017 return m_data.outputFilename ;
3018 }
3019
listTests() const3020 bool listTests() const { return m_data.listTests; }
listTestNamesOnly() const3021 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
listTags() const3022 bool listTags() const { return m_data.listTags; }
listReporters() const3023 bool listReporters() const { return m_data.listReporters; }
3024
getProcessName() const3025 std::string getProcessName() const { return m_data.processName; }
3026
shouldDebugBreak() const3027 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
3028
setStreamBuf(std::streambuf * buf)3029 void setStreamBuf( std::streambuf* buf ) {
3030 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
3031 }
3032
useStream(std::string const & streamName)3033 void useStream( std::string const& streamName ) {
3034 Stream stream = createStream( streamName );
3035 setStreamBuf( stream.streamBuf );
3036 m_stream.release();
3037 m_stream = stream;
3038 }
3039
getReporterName() const3040 std::string getReporterName() const { return m_data.reporterName; }
3041
abortAfter() const3042 int abortAfter() const { return m_data.abortAfter; }
3043
testSpec() const3044 TestSpec const& testSpec() const { return m_testSpec; }
3045
showHelp() const3046 bool showHelp() const { return m_data.showHelp; }
showInvisibles() const3047 bool showInvisibles() const { return m_data.showInvisibles; }
3048
3049 // IConfig interface
allowThrows() const3050 virtual bool allowThrows() const { return !m_data.noThrow; }
stream() const3051 virtual std::ostream& stream() const { return m_os; }
name() const3052 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
includeSuccessfulResults() const3053 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
warnAboutMissingAssertions() const3054 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
showDurations() const3055 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
3056
3057 private:
3058 ConfigData m_data;
3059
3060 Stream m_stream;
3061 mutable std::ostream m_os;
3062 TestSpec m_testSpec;
3063 };
3064
3065 } // end namespace Catch
3066
3067 // #included from: catch_clara.h
3068 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3069
3070 // Use Catch's value for console width (store Clara's off to the side, if present)
3071 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
3072 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3073 #undef CLARA_CONFIG_CONSOLE_WIDTH
3074 #endif
3075 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3076
3077 // Declare Clara inside the Catch namespace
3078 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3079 // #included from: ../external/clara.h
3080
3081 // Only use header guard if we are not using an outer namespace
3082 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3083
3084 #ifndef STITCH_CLARA_OPEN_NAMESPACE
3085 #define TWOBLUECUBES_CLARA_H_INCLUDED
3086 #define STITCH_CLARA_OPEN_NAMESPACE
3087 #define STITCH_CLARA_CLOSE_NAMESPACE
3088 #else
3089 #define STITCH_CLARA_CLOSE_NAMESPACE }
3090 #endif
3091
3092 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3093
3094 // ----------- #included from tbc_text_format.h -----------
3095
3096 // Only use header guard if we are not using an outer namespace
3097 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3098 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3099 #define TBC_TEXT_FORMAT_H_INCLUDED
3100 #endif
3101
3102 #include <string>
3103 #include <vector>
3104 #include <sstream>
3105
3106 // Use optional outer namespace
3107 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3108 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3109 #endif
3110
3111 namespace Tbc {
3112
3113 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3114 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3115 #else
3116 const unsigned int consoleWidth = 80;
3117 #endif
3118
3119 struct TextAttributes {
TextAttributesSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3120 TextAttributes()
3121 : initialIndent( std::string::npos ),
3122 indent( 0 ),
3123 width( consoleWidth-1 ),
3124 tabChar( '\t' )
3125 {}
3126
setInitialIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3127 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
setIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3128 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
setWidthSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3129 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
setTabCharSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3130 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
3131
3132 std::size_t initialIndent; // indent of first line, or npos
3133 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3134 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3135 char tabChar; // If this char is seen the indent is changed to current pos
3136 };
3137
3138 class Text {
3139 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())3140 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
3141 : attr( _attr )
3142 {
3143 std::string wrappableChars = " [({.,/|\\-";
3144 std::size_t indent = _attr.initialIndent != std::string::npos
3145 ? _attr.initialIndent
3146 : _attr.indent;
3147 std::string remainder = _str;
3148
3149 while( !remainder.empty() ) {
3150 if( lines.size() >= 1000 ) {
3151 lines.push_back( "... message truncated due to excessive size" );
3152 return;
3153 }
3154 std::size_t tabPos = std::string::npos;
3155 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3156 std::size_t pos = remainder.find_first_of( '\n' );
3157 if( pos <= width ) {
3158 width = pos;
3159 }
3160 pos = remainder.find_last_of( _attr.tabChar, width );
3161 if( pos != std::string::npos ) {
3162 tabPos = pos;
3163 if( remainder[width] == '\n' )
3164 width--;
3165 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3166 }
3167
3168 if( width == remainder.size() ) {
3169 spliceLine( indent, remainder, width );
3170 }
3171 else if( remainder[width] == '\n' ) {
3172 spliceLine( indent, remainder, width );
3173 if( width <= 1 || remainder.size() != 1 )
3174 remainder = remainder.substr( 1 );
3175 indent = _attr.indent;
3176 }
3177 else {
3178 pos = remainder.find_last_of( wrappableChars, width );
3179 if( pos != std::string::npos && pos > 0 ) {
3180 spliceLine( indent, remainder, pos );
3181 if( remainder[0] == ' ' )
3182 remainder = remainder.substr( 1 );
3183 }
3184 else {
3185 spliceLine( indent, remainder, width-1 );
3186 lines.back() += "-";
3187 }
3188 if( lines.size() == 1 )
3189 indent = _attr.indent;
3190 if( tabPos != std::string::npos )
3191 indent += tabPos;
3192 }
3193 }
3194 }
3195
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)3196 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3197 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
3198 _remainder = _remainder.substr( _pos );
3199 }
3200
3201 typedef std::vector<std::string>::const_iterator const_iterator;
3202
begin() const3203 const_iterator begin() const { return lines.begin(); }
end() const3204 const_iterator end() const { return lines.end(); }
last() const3205 std::string const& last() const { return lines.back(); }
size() const3206 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const3207 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
toString() const3208 std::string toString() const {
3209 std::ostringstream oss;
3210 oss << *this;
3211 return oss.str();
3212 }
3213
operator <<(std::ostream & _stream,Text const & _text)3214 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
3215 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3216 it != itEnd; ++it ) {
3217 if( it != _text.begin() )
3218 _stream << "\n";
3219 _stream << *it;
3220 }
3221 return _stream;
3222 }
3223
3224 private:
3225 std::string str;
3226 TextAttributes attr;
3227 std::vector<std::string> lines;
3228 };
3229
3230 } // end namespace Tbc
3231
3232 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3233 } // end outer namespace
3234 #endif
3235
3236 #endif // TBC_TEXT_FORMAT_H_INCLUDED
3237
3238 // ----------- end of #include from tbc_text_format.h -----------
3239 // ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
3240
3241 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3242
3243 #include <map>
3244 #include <algorithm>
3245 #include <stdexcept>
3246 #include <memory>
3247
3248 // Use optional outer namespace
3249 #ifdef STITCH_CLARA_OPEN_NAMESPACE
3250 STITCH_CLARA_OPEN_NAMESPACE
3251 #endif
3252
3253 namespace Clara {
3254
3255 struct UnpositionalTag {};
3256
3257 extern UnpositionalTag _;
3258
3259 #ifdef CLARA_CONFIG_MAIN
3260 UnpositionalTag _;
3261 #endif
3262
3263 namespace Detail {
3264
3265 #ifdef CLARA_CONSOLE_WIDTH
3266 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3267 #else
3268 const unsigned int consoleWidth = 80;
3269 #endif
3270
3271 using namespace Tbc;
3272
startsWith(std::string const & str,std::string const & prefix)3273 inline bool startsWith( std::string const& str, std::string const& prefix ) {
3274 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3275 }
3276
3277 template<typename T> struct RemoveConstRef{ typedef T type; };
3278 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3279 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3280 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3281
3282 template<typename T> struct IsBool { static const bool value = false; };
3283 template<> struct IsBool<bool> { static const bool value = true; };
3284
3285 template<typename T>
convertInto(std::string const & _source,T & _dest)3286 void convertInto( std::string const& _source, T& _dest ) {
3287 std::stringstream ss;
3288 ss << _source;
3289 ss >> _dest;
3290 if( ss.fail() )
3291 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
3292 }
convertInto(std::string const & _source,std::string & _dest)3293 inline void convertInto( std::string const& _source, std::string& _dest ) {
3294 _dest = _source;
3295 }
convertInto(std::string const & _source,bool & _dest)3296 inline void convertInto( std::string const& _source, bool& _dest ) {
3297 std::string sourceLC = _source;
3298 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3299 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
3300 _dest = true;
3301 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
3302 _dest = false;
3303 else
3304 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
3305 }
convertInto(bool _source,bool & _dest)3306 inline void convertInto( bool _source, bool& _dest ) {
3307 _dest = _source;
3308 }
3309 template<typename T>
convertInto(bool,T &)3310 inline void convertInto( bool, T& ) {
3311 throw std::runtime_error( "Invalid conversion" );
3312 }
3313
3314 template<typename ConfigT>
3315 struct IArgFunction {
~IArgFunctionClara::Detail::IArgFunction3316 virtual ~IArgFunction() {}
3317 # ifdef CATCH_CPP11_OR_GREATER
3318 IArgFunction() = default;
3319 IArgFunction( IArgFunction const& ) = default;
3320 # endif
3321 virtual void set( ConfigT& config, std::string const& value ) const = 0;
3322 virtual void setFlag( ConfigT& config ) const = 0;
3323 virtual bool takesArg() const = 0;
3324 virtual IArgFunction* clone() const = 0;
3325 };
3326
3327 template<typename ConfigT>
3328 class BoundArgFunction {
3329 public:
BoundArgFunction()3330 BoundArgFunction() : functionObj( NULL ) {}
BoundArgFunction(IArgFunction<ConfigT> * _functionObj)3331 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
BoundArgFunction(BoundArgFunction const & other)3332 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
operator =(BoundArgFunction const & other)3333 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
3334 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;
3335 delete functionObj;
3336 functionObj = newFunctionObj;
3337 return *this;
3338 }
~BoundArgFunction()3339 ~BoundArgFunction() { delete functionObj; }
3340
set(ConfigT & config,std::string const & value) const3341 void set( ConfigT& config, std::string const& value ) const {
3342 functionObj->set( config, value );
3343 }
setFlag(ConfigT & config) const3344 void setFlag( ConfigT& config ) const {
3345 functionObj->setFlag( config );
3346 }
takesArg() const3347 bool takesArg() const { return functionObj->takesArg(); }
3348
isSet() const3349 bool isSet() const {
3350 return functionObj != NULL;
3351 }
3352 private:
3353 IArgFunction<ConfigT>* functionObj;
3354 };
3355
3356 template<typename C>
3357 struct NullBinder : IArgFunction<C>{
setClara::Detail::NullBinder3358 virtual void set( C&, std::string const& ) const {}
setFlagClara::Detail::NullBinder3359 virtual void setFlag( C& ) const {}
takesArgClara::Detail::NullBinder3360 virtual bool takesArg() const { return true; }
cloneClara::Detail::NullBinder3361 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
3362 };
3363
3364 template<typename C, typename M>
3365 struct BoundDataMember : IArgFunction<C>{
BoundDataMemberClara::Detail::BoundDataMember3366 BoundDataMember( M C::* _member ) : member( _member ) {}
setClara::Detail::BoundDataMember3367 virtual void set( C& p, std::string const& stringValue ) const {
3368 convertInto( stringValue, p.*member );
3369 }
setFlagClara::Detail::BoundDataMember3370 virtual void setFlag( C& p ) const {
3371 convertInto( true, p.*member );
3372 }
takesArgClara::Detail::BoundDataMember3373 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundDataMember3374 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
3375 M C::* member;
3376 };
3377 template<typename C, typename M>
3378 struct BoundUnaryMethod : IArgFunction<C>{
BoundUnaryMethodClara::Detail::BoundUnaryMethod3379 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
setClara::Detail::BoundUnaryMethod3380 virtual void set( C& p, std::string const& stringValue ) const {
3381 typename RemoveConstRef<M>::type value;
3382 convertInto( stringValue, value );
3383 (p.*member)( value );
3384 }
setFlagClara::Detail::BoundUnaryMethod3385 virtual void setFlag( C& p ) const {
3386 typename RemoveConstRef<M>::type value;
3387 convertInto( true, value );
3388 (p.*member)( value );
3389 }
takesArgClara::Detail::BoundUnaryMethod3390 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundUnaryMethod3391 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
3392 void (C::*member)( M );
3393 };
3394 template<typename C>
3395 struct BoundNullaryMethod : IArgFunction<C>{
BoundNullaryMethodClara::Detail::BoundNullaryMethod3396 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
setClara::Detail::BoundNullaryMethod3397 virtual void set( C& p, std::string const& stringValue ) const {
3398 bool value;
3399 convertInto( stringValue, value );
3400 if( value )
3401 (p.*member)();
3402 }
setFlagClara::Detail::BoundNullaryMethod3403 virtual void setFlag( C& p ) const {
3404 (p.*member)();
3405 }
takesArgClara::Detail::BoundNullaryMethod3406 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundNullaryMethod3407 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
3408 void (C::*member)();
3409 };
3410
3411 template<typename C>
3412 struct BoundUnaryFunction : IArgFunction<C>{
BoundUnaryFunctionClara::Detail::BoundUnaryFunction3413 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
setClara::Detail::BoundUnaryFunction3414 virtual void set( C& obj, std::string const& stringValue ) const {
3415 bool value;
3416 convertInto( stringValue, value );
3417 if( value )
3418 function( obj );
3419 }
setFlagClara::Detail::BoundUnaryFunction3420 virtual void setFlag( C& p ) const {
3421 function( p );
3422 }
takesArgClara::Detail::BoundUnaryFunction3423 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundUnaryFunction3424 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
3425 void (*function)( C& );
3426 };
3427
3428 template<typename C, typename T>
3429 struct BoundBinaryFunction : IArgFunction<C>{
BoundBinaryFunctionClara::Detail::BoundBinaryFunction3430 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
setClara::Detail::BoundBinaryFunction3431 virtual void set( C& obj, std::string const& stringValue ) const {
3432 typename RemoveConstRef<T>::type value;
3433 convertInto( stringValue, value );
3434 function( obj, value );
3435 }
setFlagClara::Detail::BoundBinaryFunction3436 virtual void setFlag( C& obj ) const {
3437 typename RemoveConstRef<T>::type value;
3438 convertInto( true, value );
3439 function( obj, value );
3440 }
takesArgClara::Detail::BoundBinaryFunction3441 virtual bool takesArg() const { return !IsBool<T>::value; }
cloneClara::Detail::BoundBinaryFunction3442 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
3443 void (*function)( C&, T );
3444 };
3445
3446 } // namespace Detail
3447
3448 struct Parser {
ParserClara::Parser3449 Parser() : separators( " \t=:" ) {}
3450
3451 struct Token {
3452 enum Type { Positional, ShortOpt, LongOpt };
TokenClara::Parser::Token3453 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
3454 Type type;
3455 std::string data;
3456 };
3457
parseIntoTokensClara::Parser3458 void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
3459 const std::string doubleDash = "--";
3460 for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
3461 parseIntoTokens( argv[i] , tokens);
3462 }
parseIntoTokensClara::Parser3463 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
3464 while( !arg.empty() ) {
3465 Parser::Token token( Parser::Token::Positional, arg );
3466 arg = "";
3467 if( token.data[0] == '-' ) {
3468 if( token.data.size() > 1 && token.data[1] == '-' ) {
3469 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
3470 }
3471 else {
3472 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
3473 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
3474 arg = "-" + token.data.substr( 1 );
3475 token.data = token.data.substr( 0, 1 );
3476 }
3477 }
3478 }
3479 if( token.type != Parser::Token::Positional ) {
3480 std::size_t pos = token.data.find_first_of( separators );
3481 if( pos != std::string::npos ) {
3482 arg = token.data.substr( pos+1 );
3483 token.data = token.data.substr( 0, pos );
3484 }
3485 }
3486 tokens.push_back( token );
3487 }
3488 }
3489 std::string separators;
3490 };
3491
3492 template<typename ConfigT>
3493 struct CommonArgProperties {
CommonArgPropertiesClara::CommonArgProperties3494 CommonArgProperties() {}
CommonArgPropertiesClara::CommonArgProperties3495 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
3496
3497 Detail::BoundArgFunction<ConfigT> boundField;
3498 std::string description;
3499 std::string detail;
3500 std::string placeholder; // Only value if boundField takes an arg
3501
takesArgClara::CommonArgProperties3502 bool takesArg() const {
3503 return !placeholder.empty();
3504 }
validateClara::CommonArgProperties3505 void validate() const {
3506 if( !boundField.isSet() )
3507 throw std::logic_error( "option not bound" );
3508 }
3509 };
3510 struct OptionArgProperties {
3511 std::vector<std::string> shortNames;
3512 std::string longName;
3513
hasShortNameClara::OptionArgProperties3514 bool hasShortName( std::string const& shortName ) const {
3515 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
3516 }
hasLongNameClara::OptionArgProperties3517 bool hasLongName( std::string const& _longName ) const {
3518 return _longName == longName;
3519 }
3520 };
3521 struct PositionalArgProperties {
PositionalArgPropertiesClara::PositionalArgProperties3522 PositionalArgProperties() : position( -1 ) {}
3523 int position; // -1 means non-positional (floating)
3524
isFixedPositionalClara::PositionalArgProperties3525 bool isFixedPositional() const {
3526 return position != -1;
3527 }
3528 };
3529
3530 template<typename ConfigT>
3531 class CommandLine {
3532
3533 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
ArgClara::CommandLine::Arg3534 Arg() {}
ArgClara::CommandLine::Arg3535 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
3536
3537 using CommonArgProperties<ConfigT>::placeholder; // !TBD
3538
dbgNameClara::CommandLine::Arg3539 std::string dbgName() const {
3540 if( !longName.empty() )
3541 return "--" + longName;
3542 if( !shortNames.empty() )
3543 return "-" + shortNames[0];
3544 return "positional args";
3545 }
commandsClara::CommandLine::Arg3546 std::string commands() const {
3547 std::ostringstream oss;
3548 bool first = true;
3549 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
3550 for(; it != itEnd; ++it ) {
3551 if( first )
3552 first = false;
3553 else
3554 oss << ", ";
3555 oss << "-" << *it;
3556 }
3557 if( !longName.empty() ) {
3558 if( !first )
3559 oss << ", ";
3560 oss << "--" << longName;
3561 }
3562 if( !placeholder.empty() )
3563 oss << " <" << placeholder << ">";
3564 return oss.str();
3565 }
3566 };
3567
3568 // NOTE: std::auto_ptr is deprecated in c++11/c++0x
3569 #if defined(__cplusplus) && __cplusplus > 199711L
3570 typedef std::unique_ptr<Arg> ArgAutoPtr;
3571 #else
3572 typedef std::auto_ptr<Arg> ArgAutoPtr;
3573 #endif
3574
addOptName(Arg & arg,std::string const & optName)3575 friend void addOptName( Arg& arg, std::string const& optName )
3576 {
3577 if( optName.empty() )
3578 return;
3579 if( Detail::startsWith( optName, "--" ) ) {
3580 if( !arg.longName.empty() )
3581 throw std::logic_error( "Only one long opt may be specified. '"
3582 + arg.longName
3583 + "' already specified, now attempting to add '"
3584 + optName + "'" );
3585 arg.longName = optName.substr( 2 );
3586 }
3587 else if( Detail::startsWith( optName, "-" ) )
3588 arg.shortNames.push_back( optName.substr( 1 ) );
3589 else
3590 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
3591 }
setPositionalArg(Arg & arg,int position)3592 friend void setPositionalArg( Arg& arg, int position )
3593 {
3594 arg.position = position;
3595 }
3596
3597 class ArgBuilder {
3598 public:
ArgBuilder(Arg * arg)3599 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
3600
3601 // Bind a non-boolean data member (requires placeholder string)
3602 template<typename C, typename M>
bind(M C::* field,std::string const & placeholder)3603 void bind( M C::* field, std::string const& placeholder ) {
3604 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
3605 m_arg->placeholder = placeholder;
3606 }
3607 // Bind a boolean data member (no placeholder required)
3608 template<typename C>
bind(bool C::* field)3609 void bind( bool C::* field ) {
3610 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
3611 }
3612
3613 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
3614 template<typename C, typename M>
bind(void (C::* unaryMethod)(M),std::string const & placeholder)3615 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
3616 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
3617 m_arg->placeholder = placeholder;
3618 }
3619
3620 // Bind a method taking a single, boolean argument (no placeholder string required)
3621 template<typename C>
bind(void (C::* unaryMethod)(bool))3622 void bind( void (C::* unaryMethod)( bool ) ) {
3623 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
3624 }
3625
3626 // Bind a method that takes no arguments (will be called if opt is present)
3627 template<typename C>
bind(void (C::* nullaryMethod)())3628 void bind( void (C::* nullaryMethod)() ) {
3629 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
3630 }
3631
3632 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
3633 template<typename C>
bind(void (* unaryFunction)(C &))3634 void bind( void (* unaryFunction)( C& ) ) {
3635 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
3636 }
3637
3638 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
3639 template<typename C, typename T>
bind(void (* binaryFunction)(C &,T),std::string const & placeholder)3640 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
3641 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
3642 m_arg->placeholder = placeholder;
3643 }
3644
describe(std::string const & description)3645 ArgBuilder& describe( std::string const& description ) {
3646 m_arg->description = description;
3647 return *this;
3648 }
detail(std::string const & detail)3649 ArgBuilder& detail( std::string const& detail ) {
3650 m_arg->detail = detail;
3651 return *this;
3652 }
3653
3654 protected:
3655 Arg* m_arg;
3656 };
3657
3658 class OptBuilder : public ArgBuilder {
3659 public:
OptBuilder(Arg * arg)3660 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
OptBuilder(OptBuilder & other)3661 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
3662
operator [](std::string const & optName)3663 OptBuilder& operator[]( std::string const& optName ) {
3664 addOptName( *ArgBuilder::m_arg, optName );
3665 return *this;
3666 }
3667 };
3668
3669 public:
3670
CommandLine()3671 CommandLine()
3672 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
3673 m_highestSpecifiedArgPosition( 0 ),
3674 m_throwOnUnrecognisedTokens( false )
3675 {}
CommandLine(CommandLine const & other)3676 CommandLine( CommandLine const& other )
3677 : m_boundProcessName( other.m_boundProcessName ),
3678 m_options ( other.m_options ),
3679 m_positionalArgs( other.m_positionalArgs ),
3680 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
3681 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
3682 {
3683 if( other.m_floatingArg.get() )
3684 m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) );
3685 }
3686
setThrowOnUnrecognisedTokens(bool shouldThrow=true)3687 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
3688 m_throwOnUnrecognisedTokens = shouldThrow;
3689 return *this;
3690 }
3691
operator [](std::string const & optName)3692 OptBuilder operator[]( std::string const& optName ) {
3693 m_options.push_back( Arg() );
3694 addOptName( m_options.back(), optName );
3695 OptBuilder builder( &m_options.back() );
3696 return builder;
3697 }
3698
operator [](int position)3699 ArgBuilder operator[]( int position ) {
3700 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
3701 if( position > m_highestSpecifiedArgPosition )
3702 m_highestSpecifiedArgPosition = position;
3703 setPositionalArg( m_positionalArgs[position], position );
3704 ArgBuilder builder( &m_positionalArgs[position] );
3705 return builder;
3706 }
3707
3708 // Invoke this with the _ instance
operator [](UnpositionalTag)3709 ArgBuilder operator[]( UnpositionalTag ) {
3710 if( m_floatingArg.get() )
3711 throw std::logic_error( "Only one unpositional argument can be added" );
3712 m_floatingArg = ArgAutoPtr( new Arg() );
3713 ArgBuilder builder( m_floatingArg.get() );
3714 return builder;
3715 }
3716
3717 template<typename C, typename M>
bindProcessName(M C::* field)3718 void bindProcessName( M C::* field ) {
3719 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
3720 }
3721 template<typename C, typename M>
bindProcessName(void (C::* _unaryMethod)(M))3722 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
3723 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
3724 }
3725
optUsage(std::ostream & os,std::size_t indent=0,std::size_t width=Detail::consoleWidth) const3726 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
3727 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
3728 std::size_t maxWidth = 0;
3729 for( it = itBegin; it != itEnd; ++it )
3730 maxWidth = (std::max)( maxWidth, it->commands().size() );
3731
3732 for( it = itBegin; it != itEnd; ++it ) {
3733 Detail::Text usage( it->commands(), Detail::TextAttributes()
3734 .setWidth( maxWidth+indent )
3735 .setIndent( indent ) );
3736 Detail::Text desc( it->description, Detail::TextAttributes()
3737 .setWidth( width - maxWidth - 3 ) );
3738
3739 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
3740 std::string usageCol = i < usage.size() ? usage[i] : "";
3741 os << usageCol;
3742
3743 if( i < desc.size() && !desc[i].empty() )
3744 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
3745 << desc[i];
3746 os << "\n";
3747 }
3748 }
3749 }
optUsage() const3750 std::string optUsage() const {
3751 std::ostringstream oss;
3752 optUsage( oss );
3753 return oss.str();
3754 }
3755
argSynopsis(std::ostream & os) const3756 void argSynopsis( std::ostream& os ) const {
3757 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
3758 if( i > 1 )
3759 os << " ";
3760 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
3761 if( it != m_positionalArgs.end() )
3762 os << "<" << it->second.placeholder << ">";
3763 else if( m_floatingArg.get() )
3764 os << "<" << m_floatingArg->placeholder << ">";
3765 else
3766 throw std::logic_error( "non consecutive positional arguments with no floating args" );
3767 }
3768 // !TBD No indication of mandatory args
3769 if( m_floatingArg.get() ) {
3770 if( m_highestSpecifiedArgPosition > 1 )
3771 os << " ";
3772 os << "[<" << m_floatingArg->placeholder << "> ...]";
3773 }
3774 }
argSynopsis() const3775 std::string argSynopsis() const {
3776 std::ostringstream oss;
3777 argSynopsis( oss );
3778 return oss.str();
3779 }
3780
usage(std::ostream & os,std::string const & procName) const3781 void usage( std::ostream& os, std::string const& procName ) const {
3782 validate();
3783 os << "usage:\n " << procName << " ";
3784 argSynopsis( os );
3785 if( !m_options.empty() ) {
3786 os << " [options]\n\nwhere options are: \n";
3787 optUsage( os, 2 );
3788 }
3789 os << "\n";
3790 }
usage(std::string const & procName) const3791 std::string usage( std::string const& procName ) const {
3792 std::ostringstream oss;
3793 usage( oss, procName );
3794 return oss.str();
3795 }
3796
parse(int argc,char const * const * argv) const3797 ConfigT parse( int argc, char const * const * argv ) const {
3798 ConfigT config;
3799 parseInto( argc, argv, config );
3800 return config;
3801 }
3802
parseInto(int argc,char const * const * argv,ConfigT & config) const3803 std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
3804 std::string processName = argv[0];
3805 std::size_t lastSlash = processName.find_last_of( "/\\" );
3806 if( lastSlash != std::string::npos )
3807 processName = processName.substr( lastSlash+1 );
3808 m_boundProcessName.set( config, processName );
3809 std::vector<Parser::Token> tokens;
3810 Parser parser;
3811 parser.parseIntoTokens( argc, argv, tokens );
3812 return populate( tokens, config );
3813 }
3814
populate(std::vector<Parser::Token> const & tokens,ConfigT & config) const3815 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3816 validate();
3817 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
3818 unusedTokens = populateFixedArgs( unusedTokens, config );
3819 unusedTokens = populateFloatingArgs( unusedTokens, config );
3820 return unusedTokens;
3821 }
3822
populateOptions(std::vector<Parser::Token> const & tokens,ConfigT & config) const3823 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3824 std::vector<Parser::Token> unusedTokens;
3825 std::vector<std::string> errors;
3826 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3827 Parser::Token const& token = tokens[i];
3828 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
3829 for(; it != itEnd; ++it ) {
3830 Arg const& arg = *it;
3831
3832 try {
3833 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
3834 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
3835 if( arg.takesArg() ) {
3836 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
3837 errors.push_back( "Expected argument to option: " + token.data );
3838 else
3839 arg.boundField.set( config, tokens[++i].data );
3840 }
3841 else {
3842 arg.boundField.setFlag( config );
3843 }
3844 break;
3845 }
3846 }
3847 catch( std::exception& ex ) {
3848 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
3849 }
3850 }
3851 if( it == itEnd ) {
3852 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
3853 unusedTokens.push_back( token );
3854 else if( m_throwOnUnrecognisedTokens )
3855 errors.push_back( "unrecognised option: " + token.data );
3856 }
3857 }
3858 if( !errors.empty() ) {
3859 std::ostringstream oss;
3860 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
3861 it != itEnd;
3862 ++it ) {
3863 if( it != errors.begin() )
3864 oss << "\n";
3865 oss << *it;
3866 }
3867 throw std::runtime_error( oss.str() );
3868 }
3869 return unusedTokens;
3870 }
populateFixedArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const3871 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3872 std::vector<Parser::Token> unusedTokens;
3873 int position = 1;
3874 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3875 Parser::Token const& token = tokens[i];
3876 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
3877 if( it != m_positionalArgs.end() )
3878 it->second.boundField.set( config, token.data );
3879 else
3880 unusedTokens.push_back( token );
3881 if( token.type == Parser::Token::Positional )
3882 position++;
3883 }
3884 return unusedTokens;
3885 }
populateFloatingArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const3886 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3887 if( !m_floatingArg.get() )
3888 return tokens;
3889 std::vector<Parser::Token> unusedTokens;
3890 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3891 Parser::Token const& token = tokens[i];
3892 if( token.type == Parser::Token::Positional )
3893 m_floatingArg->boundField.set( config, token.data );
3894 else
3895 unusedTokens.push_back( token );
3896 }
3897 return unusedTokens;
3898 }
3899
validate() const3900 void validate() const
3901 {
3902 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
3903 throw std::logic_error( "No options or arguments specified" );
3904
3905 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
3906 itEnd = m_options.end();
3907 it != itEnd; ++it )
3908 it->validate();
3909 }
3910
3911 private:
3912 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
3913 std::vector<Arg> m_options;
3914 std::map<int, Arg> m_positionalArgs;
3915 ArgAutoPtr m_floatingArg;
3916 int m_highestSpecifiedArgPosition;
3917 bool m_throwOnUnrecognisedTokens;
3918 };
3919
3920 } // end namespace Clara
3921
3922 STITCH_CLARA_CLOSE_NAMESPACE
3923 #undef STITCH_CLARA_OPEN_NAMESPACE
3924 #undef STITCH_CLARA_CLOSE_NAMESPACE
3925
3926 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
3927 #undef STITCH_CLARA_OPEN_NAMESPACE
3928
3929 // Restore Clara's value for console width, if present
3930 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
3931 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
3932 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
3933 #endif
3934
3935 #include <fstream>
3936
3937 namespace Catch {
3938
abortAfterFirst(ConfigData & config)3939 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
abortAfterX(ConfigData & config,int x)3940 inline void abortAfterX( ConfigData& config, int x ) {
3941 if( x < 1 )
3942 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
3943 config.abortAfter = x;
3944 }
addTestOrTags(ConfigData & config,std::string const & _testSpec)3945 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
3946
addWarning(ConfigData & config,std::string const & _warning)3947 inline void addWarning( ConfigData& config, std::string const& _warning ) {
3948 if( _warning == "NoAssertions" )
3949 config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions );
3950 else
3951 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
3952
3953 }
setVerbosity(ConfigData & config,int level)3954 inline void setVerbosity( ConfigData& config, int level ) {
3955 // !TBD: accept strings?
3956 config.verbosity = (Verbosity::Level)level;
3957 }
setShowDurations(ConfigData & config,bool _showDurations)3958 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
3959 config.showDurations = _showDurations
3960 ? ShowDurations::Always
3961 : ShowDurations::Never;
3962 }
loadTestNamesFromFile(ConfigData & config,std::string const & _filename)3963 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
3964 std::ifstream f( _filename.c_str() );
3965 if( !f.is_open() )
3966 throw std::domain_error( "Unable to load input file: " + _filename );
3967
3968 std::string line;
3969 while( std::getline( f, line ) ) {
3970 line = trim(line);
3971 if( !line.empty() && !startsWith( line, "#" ) )
3972 addTestOrTags( config, "\"" + line + "\"," );
3973 }
3974 }
3975
makeCommandLineParser()3976 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
3977
3978 using namespace Clara;
3979 CommandLine<ConfigData> cli;
3980
3981 cli.bindProcessName( &ConfigData::processName );
3982
3983 cli["-?"]["-h"]["--help"]
3984 .describe( "display usage information" )
3985 .bind( &ConfigData::showHelp );
3986
3987 cli["-l"]["--list-tests"]
3988 .describe( "list all/matching test cases" )
3989 .bind( &ConfigData::listTests );
3990
3991 cli["-t"]["--list-tags"]
3992 .describe( "list all/matching tags" )
3993 .bind( &ConfigData::listTags );
3994
3995 cli["-s"]["--success"]
3996 .describe( "include successful tests in output" )
3997 .bind( &ConfigData::showSuccessfulTests );
3998
3999 cli["-b"]["--break"]
4000 .describe( "break into debugger on failure" )
4001 .bind( &ConfigData::shouldDebugBreak );
4002
4003 cli["-e"]["--nothrow"]
4004 .describe( "skip exception tests" )
4005 .bind( &ConfigData::noThrow );
4006
4007 cli["-i"]["--invisibles"]
4008 .describe( "show invisibles (tabs, newlines)" )
4009 .bind( &ConfigData::showInvisibles );
4010
4011 cli["-o"]["--out"]
4012 .describe( "output filename" )
4013 .bind( &ConfigData::outputFilename, "filename" );
4014
4015 cli["-r"]["--reporter"]
4016 // .placeholder( "name[:filename]" )
4017 .describe( "reporter to use (defaults to console)" )
4018 .bind( &ConfigData::reporterName, "name" );
4019
4020 cli["-n"]["--name"]
4021 .describe( "suite name" )
4022 .bind( &ConfigData::name, "name" );
4023
4024 cli["-a"]["--abort"]
4025 .describe( "abort at first failure" )
4026 .bind( &abortAfterFirst );
4027
4028 cli["-x"]["--abortx"]
4029 .describe( "abort after x failures" )
4030 .bind( &abortAfterX, "no. failures" );
4031
4032 cli["-w"]["--warn"]
4033 .describe( "enable warnings" )
4034 .bind( &addWarning, "warning name" );
4035
4036 // - needs updating if reinstated
4037 // cli.into( &setVerbosity )
4038 // .describe( "level of verbosity (0=no output)" )
4039 // .shortOpt( "v")
4040 // .longOpt( "verbosity" )
4041 // .placeholder( "level" );
4042
4043 cli[_]
4044 .describe( "which test or tests to use" )
4045 .bind( &addTestOrTags, "test name, pattern or tags" );
4046
4047 cli["-d"]["--durations"]
4048 .describe( "show test durations" )
4049 .bind( &setShowDurations, "yes/no" );
4050
4051 cli["-f"]["--input-file"]
4052 .describe( "load test names to run from a file" )
4053 .bind( &loadTestNamesFromFile, "filename" );
4054
4055 // Less common commands which don't have a short form
4056 cli["--list-test-names-only"]
4057 .describe( "list all/matching test cases names only" )
4058 .bind( &ConfigData::listTestNamesOnly );
4059
4060 cli["--list-reporters"]
4061 .describe( "list all reporters" )
4062 .bind( &ConfigData::listReporters );
4063
4064 return cli;
4065 }
4066
4067 } // end namespace Catch
4068
4069 // #included from: internal/catch_list.hpp
4070 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4071
4072 // #included from: catch_text.h
4073 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4074
4075 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4076
4077 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4078 // #included from: ../external/tbc_text_format.h
4079 // Only use header guard if we are not using an outer namespace
4080 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4081 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4082 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4083 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4084 # endif
4085 # else
4086 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4087 # endif
4088 #endif
4089 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4090 #include <string>
4091 #include <vector>
4092 #include <sstream>
4093
4094 // Use optional outer namespace
4095 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4096 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4097 #endif
4098
4099 namespace Tbc {
4100
4101 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4102 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4103 #else
4104 const unsigned int consoleWidth = 80;
4105 #endif
4106
4107 struct TextAttributes {
TextAttributesCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4108 TextAttributes()
4109 : initialIndent( std::string::npos ),
4110 indent( 0 ),
4111 width( consoleWidth-1 ),
4112 tabChar( '\t' )
4113 {}
4114
setInitialIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4115 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
setIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4116 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
setWidthCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4117 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
setTabCharCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4118 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4119
4120 std::size_t initialIndent; // indent of first line, or npos
4121 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4122 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4123 char tabChar; // If this char is seen the indent is changed to current pos
4124 };
4125
4126 class Text {
4127 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())4128 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4129 : attr( _attr )
4130 {
4131 std::string wrappableChars = " [({.,/|\\-";
4132 std::size_t indent = _attr.initialIndent != std::string::npos
4133 ? _attr.initialIndent
4134 : _attr.indent;
4135 std::string remainder = _str;
4136
4137 while( !remainder.empty() ) {
4138 if( lines.size() >= 1000 ) {
4139 lines.push_back( "... message truncated due to excessive size" );
4140 return;
4141 }
4142 std::size_t tabPos = std::string::npos;
4143 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4144 std::size_t pos = remainder.find_first_of( '\n' );
4145 if( pos <= width ) {
4146 width = pos;
4147 }
4148 pos = remainder.find_last_of( _attr.tabChar, width );
4149 if( pos != std::string::npos ) {
4150 tabPos = pos;
4151 if( remainder[width] == '\n' )
4152 width--;
4153 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4154 }
4155
4156 if( width == remainder.size() ) {
4157 spliceLine( indent, remainder, width );
4158 }
4159 else if( remainder[width] == '\n' ) {
4160 spliceLine( indent, remainder, width );
4161 if( width <= 1 || remainder.size() != 1 )
4162 remainder = remainder.substr( 1 );
4163 indent = _attr.indent;
4164 }
4165 else {
4166 pos = remainder.find_last_of( wrappableChars, width );
4167 if( pos != std::string::npos && pos > 0 ) {
4168 spliceLine( indent, remainder, pos );
4169 if( remainder[0] == ' ' )
4170 remainder = remainder.substr( 1 );
4171 }
4172 else {
4173 spliceLine( indent, remainder, width-1 );
4174 lines.back() += "-";
4175 }
4176 if( lines.size() == 1 )
4177 indent = _attr.indent;
4178 if( tabPos != std::string::npos )
4179 indent += tabPos;
4180 }
4181 }
4182 }
4183
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)4184 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4185 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4186 _remainder = _remainder.substr( _pos );
4187 }
4188
4189 typedef std::vector<std::string>::const_iterator const_iterator;
4190
begin() const4191 const_iterator begin() const { return lines.begin(); }
end() const4192 const_iterator end() const { return lines.end(); }
last() const4193 std::string const& last() const { return lines.back(); }
size() const4194 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const4195 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
toString() const4196 std::string toString() const {
4197 std::ostringstream oss;
4198 oss << *this;
4199 return oss.str();
4200 }
4201
operator <<(std::ostream & _stream,Text const & _text)4202 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4203 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4204 it != itEnd; ++it ) {
4205 if( it != _text.begin() )
4206 _stream << "\n";
4207 _stream << *it;
4208 }
4209 return _stream;
4210 }
4211
4212 private:
4213 std::string str;
4214 TextAttributes attr;
4215 std::vector<std::string> lines;
4216 };
4217
4218 } // end namespace Tbc
4219
4220 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4221 } // end outer namespace
4222 #endif
4223
4224 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4225 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4226
4227 namespace Catch {
4228 using Tbc::Text;
4229 using Tbc::TextAttributes;
4230 }
4231
4232 // #included from: catch_console_colour.hpp
4233 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4234
4235 namespace Catch {
4236
4237 namespace Detail {
4238 struct IColourImpl;
4239 }
4240
4241 struct Colour {
4242 enum Code {
4243 None = 0,
4244
4245 White,
4246 Red,
4247 Green,
4248 Blue,
4249 Cyan,
4250 Yellow,
4251 Grey,
4252
4253 Bright = 0x10,
4254
4255 BrightRed = Bright | Red,
4256 BrightGreen = Bright | Green,
4257 LightGrey = Bright | Grey,
4258 BrightWhite = Bright | White,
4259
4260 // By intention
4261 FileName = LightGrey,
4262 ResultError = BrightRed,
4263 ResultSuccess = BrightGreen,
4264
4265 Error = BrightRed,
4266 Success = Green,
4267
4268 OriginalExpression = Cyan,
4269 ReconstructedExpression = Yellow,
4270
4271 SecondaryText = LightGrey,
4272 Headers = White
4273 };
4274
4275 // Use constructed object for RAII guard
4276 Colour( Code _colourCode );
4277 ~Colour();
4278
4279 // Use static method for one-shot changes
4280 static void use( Code _colourCode );
4281
4282 private:
4283 Colour( Colour const& other );
4284 static Detail::IColourImpl* impl();
4285 };
4286
4287 } // end namespace Catch
4288
4289 // #included from: catch_interfaces_reporter.h
4290 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
4291
4292 // #included from: catch_option.hpp
4293 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
4294
4295 namespace Catch {
4296
4297 // An optional type
4298 template<typename T>
4299 class Option {
4300 public:
Option()4301 Option() : nullableValue( NULL ) {}
Option(T const & _value)4302 Option( T const& _value )
4303 : nullableValue( new( storage ) T( _value ) )
4304 {}
Option(Option const & _other)4305 Option( Option const& _other )
4306 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
4307 {}
4308
~Option()4309 ~Option() {
4310 reset();
4311 }
4312
operator =(Option const & _other)4313 Option& operator= ( Option const& _other ) {
4314 if( &_other != this ) {
4315 reset();
4316 if( _other )
4317 nullableValue = new( storage ) T( *_other );
4318 }
4319 return *this;
4320 }
operator =(T const & _value)4321 Option& operator = ( T const& _value ) {
4322 reset();
4323 nullableValue = new( storage ) T( _value );
4324 return *this;
4325 }
4326
reset()4327 void reset() {
4328 if( nullableValue )
4329 nullableValue->~T();
4330 nullableValue = NULL;
4331 }
4332
operator *()4333 T& operator*() { return *nullableValue; }
operator *() const4334 T const& operator*() const { return *nullableValue; }
operator ->()4335 T* operator->() { return nullableValue; }
operator ->() const4336 const T* operator->() const { return nullableValue; }
4337
valueOr(T const & defaultValue) const4338 T valueOr( T const& defaultValue ) const {
4339 return nullableValue ? *nullableValue : defaultValue;
4340 }
4341
some() const4342 bool some() const { return nullableValue != NULL; }
none() const4343 bool none() const { return nullableValue == NULL; }
4344
operator !() const4345 bool operator !() const { return nullableValue == NULL; }
operator SafeBool::type() const4346 operator SafeBool::type() const {
4347 return SafeBool::makeSafe( some() );
4348 }
4349
4350 private:
4351 T* nullableValue;
4352 char storage[sizeof(T)];
4353 };
4354
4355 } // end namespace Catch
4356
4357 #include <string>
4358 #include <ostream>
4359 #include <map>
4360 #include <assert.h>
4361
4362 namespace Catch
4363 {
4364 struct ReporterConfig {
ReporterConfigCatch::ReporterConfig4365 explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
4366 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
4367
ReporterConfigCatch::ReporterConfig4368 ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
4369 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
4370
streamCatch::ReporterConfig4371 std::ostream& stream() const { return *m_stream; }
fullConfigCatch::ReporterConfig4372 Ptr<IConfig> fullConfig() const { return m_fullConfig; }
4373
4374 private:
4375 std::ostream* m_stream;
4376 Ptr<IConfig> m_fullConfig;
4377 };
4378
4379 struct ReporterPreferences {
ReporterPreferencesCatch::ReporterPreferences4380 ReporterPreferences()
4381 : shouldRedirectStdOut( false )
4382 {}
4383
4384 bool shouldRedirectStdOut;
4385 };
4386
4387 template<typename T>
4388 struct LazyStat : Option<T> {
LazyStatCatch::LazyStat4389 LazyStat() : used( false ) {}
operator =Catch::LazyStat4390 LazyStat& operator=( T const& _value ) {
4391 Option<T>::operator=( _value );
4392 used = false;
4393 return *this;
4394 }
resetCatch::LazyStat4395 void reset() {
4396 Option<T>::reset();
4397 used = false;
4398 }
4399 bool used;
4400 };
4401
4402 struct TestRunInfo {
TestRunInfoCatch::TestRunInfo4403 TestRunInfo( std::string const& _name ) : name( _name ) {}
4404 std::string name;
4405 };
4406 struct GroupInfo {
GroupInfoCatch::GroupInfo4407 GroupInfo( std::string const& _name,
4408 std::size_t _groupIndex,
4409 std::size_t _groupsCount )
4410 : name( _name ),
4411 groupIndex( _groupIndex ),
4412 groupsCounts( _groupsCount )
4413 {}
4414
4415 std::string name;
4416 std::size_t groupIndex;
4417 std::size_t groupsCounts;
4418 };
4419
4420 struct AssertionStats {
AssertionStatsCatch::AssertionStats4421 AssertionStats( AssertionResult const& _assertionResult,
4422 std::vector<MessageInfo> const& _infoMessages,
4423 Totals const& _totals )
4424 : assertionResult( _assertionResult ),
4425 infoMessages( _infoMessages ),
4426 totals( _totals )
4427 {
4428 if( assertionResult.hasMessage() ) {
4429 // Copy message into messages list.
4430 // !TBD This should have been done earlier, somewhere
4431 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
4432 builder << assertionResult.getMessage();
4433 builder.m_info.message = builder.m_stream.str();
4434
4435 infoMessages.push_back( builder.m_info );
4436 }
4437 }
4438 virtual ~AssertionStats();
4439
4440 # ifdef CATCH_CPP11_OR_GREATER
4441 AssertionStats( AssertionStats const& ) = default;
4442 AssertionStats( AssertionStats && ) = default;
4443 AssertionStats& operator = ( AssertionStats const& ) = default;
4444 AssertionStats& operator = ( AssertionStats && ) = default;
4445 # endif
4446
4447 AssertionResult assertionResult;
4448 std::vector<MessageInfo> infoMessages;
4449 Totals totals;
4450 };
4451
4452 struct SectionStats {
SectionStatsCatch::SectionStats4453 SectionStats( SectionInfo const& _sectionInfo,
4454 Counts const& _assertions,
4455 double _durationInSeconds,
4456 bool _missingAssertions )
4457 : sectionInfo( _sectionInfo ),
4458 assertions( _assertions ),
4459 durationInSeconds( _durationInSeconds ),
4460 missingAssertions( _missingAssertions )
4461 {}
4462 virtual ~SectionStats();
4463 # ifdef CATCH_CPP11_OR_GREATER
4464 SectionStats( SectionStats const& ) = default;
4465 SectionStats( SectionStats && ) = default;
4466 SectionStats& operator = ( SectionStats const& ) = default;
4467 SectionStats& operator = ( SectionStats && ) = default;
4468 # endif
4469
4470 SectionInfo sectionInfo;
4471 Counts assertions;
4472 double durationInSeconds;
4473 bool missingAssertions;
4474 };
4475
4476 struct TestCaseStats {
TestCaseStatsCatch::TestCaseStats4477 TestCaseStats( TestCaseInfo const& _testInfo,
4478 Totals const& _totals,
4479 std::string const& _stdOut,
4480 std::string const& _stdErr,
4481 bool _aborting )
4482 : testInfo( _testInfo ),
4483 totals( _totals ),
4484 stdOut( _stdOut ),
4485 stdErr( _stdErr ),
4486 aborting( _aborting )
4487 {}
4488 virtual ~TestCaseStats();
4489
4490 # ifdef CATCH_CPP11_OR_GREATER
4491 TestCaseStats( TestCaseStats const& ) = default;
4492 TestCaseStats( TestCaseStats && ) = default;
4493 TestCaseStats& operator = ( TestCaseStats const& ) = default;
4494 TestCaseStats& operator = ( TestCaseStats && ) = default;
4495 # endif
4496
4497 TestCaseInfo testInfo;
4498 Totals totals;
4499 std::string stdOut;
4500 std::string stdErr;
4501 bool aborting;
4502 };
4503
4504 struct TestGroupStats {
TestGroupStatsCatch::TestGroupStats4505 TestGroupStats( GroupInfo const& _groupInfo,
4506 Totals const& _totals,
4507 bool _aborting )
4508 : groupInfo( _groupInfo ),
4509 totals( _totals ),
4510 aborting( _aborting )
4511 {}
TestGroupStatsCatch::TestGroupStats4512 TestGroupStats( GroupInfo const& _groupInfo )
4513 : groupInfo( _groupInfo ),
4514 aborting( false )
4515 {}
4516 virtual ~TestGroupStats();
4517
4518 # ifdef CATCH_CPP11_OR_GREATER
4519 TestGroupStats( TestGroupStats const& ) = default;
4520 TestGroupStats( TestGroupStats && ) = default;
4521 TestGroupStats& operator = ( TestGroupStats const& ) = default;
4522 TestGroupStats& operator = ( TestGroupStats && ) = default;
4523 # endif
4524
4525 GroupInfo groupInfo;
4526 Totals totals;
4527 bool aborting;
4528 };
4529
4530 struct TestRunStats {
TestRunStatsCatch::TestRunStats4531 TestRunStats( TestRunInfo const& _runInfo,
4532 Totals const& _totals,
4533 bool _aborting )
4534 : runInfo( _runInfo ),
4535 totals( _totals ),
4536 aborting( _aborting )
4537 {}
4538 virtual ~TestRunStats();
4539
4540 # ifndef CATCH_CPP11_OR_GREATER
TestRunStatsCatch::TestRunStats4541 TestRunStats( TestRunStats const& _other )
4542 : runInfo( _other.runInfo ),
4543 totals( _other.totals ),
4544 aborting( _other.aborting )
4545 {}
4546 # else
4547 TestRunStats( TestRunStats const& ) = default;
4548 TestRunStats( TestRunStats && ) = default;
4549 TestRunStats& operator = ( TestRunStats const& ) = default;
4550 TestRunStats& operator = ( TestRunStats && ) = default;
4551 # endif
4552
4553 TestRunInfo runInfo;
4554 Totals totals;
4555 bool aborting;
4556 };
4557
4558 struct IStreamingReporter : IShared {
4559 virtual ~IStreamingReporter();
4560
4561 // Implementing class must also provide the following static method:
4562 // static std::string getDescription();
4563
4564 virtual ReporterPreferences getPreferences() const = 0;
4565
4566 virtual void noMatchingTestCases( std::string const& spec ) = 0;
4567
4568 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
4569 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
4570
4571 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
4572 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
4573
4574 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
4575
4576 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
4577 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
4578 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
4579 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
4580 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
4581 };
4582
4583 struct IReporterFactory {
4584 virtual ~IReporterFactory();
4585 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
4586 virtual std::string getDescription() const = 0;
4587 };
4588
4589 struct IReporterRegistry {
4590 typedef std::map<std::string, IReporterFactory*> FactoryMap;
4591
4592 virtual ~IReporterRegistry();
4593 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
4594 virtual FactoryMap const& getFactories() const = 0;
4595 };
4596
4597 }
4598
4599 #include <limits>
4600 #include <algorithm>
4601
4602 namespace Catch {
4603
listTests(Config const & config)4604 inline std::size_t listTests( Config const& config ) {
4605
4606 TestSpec testSpec = config.testSpec();
4607 if( config.testSpec().hasFilters() )
4608 std::cout << "Matching test cases:\n";
4609 else {
4610 std::cout << "All available test cases:\n";
4611 testSpec = TestSpecParser().parse( "*" ).testSpec();
4612 }
4613
4614 std::size_t matchedTests = 0;
4615 TextAttributes nameAttr, tagsAttr;
4616 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
4617 tagsAttr.setIndent( 6 );
4618
4619 std::vector<TestCase> matchedTestCases;
4620 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
4621 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
4622 it != itEnd;
4623 ++it ) {
4624 matchedTests++;
4625 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
4626 Colour::Code colour = testCaseInfo.isHidden
4627 ? Colour::SecondaryText
4628 : Colour::None;
4629 Colour colourGuard( colour );
4630
4631 std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
4632 if( !testCaseInfo.tags.empty() )
4633 std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
4634 }
4635
4636 if( !config.testSpec().hasFilters() )
4637 std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
4638 else
4639 std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
4640 return matchedTests;
4641 }
4642
listTestsNamesOnly(Config const & config)4643 inline std::size_t listTestsNamesOnly( Config const& config ) {
4644 TestSpec testSpec = config.testSpec();
4645 if( !config.testSpec().hasFilters() )
4646 testSpec = TestSpecParser().parse( "*" ).testSpec();
4647 std::size_t matchedTests = 0;
4648 std::vector<TestCase> matchedTestCases;
4649 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
4650 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
4651 it != itEnd;
4652 ++it ) {
4653 matchedTests++;
4654 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
4655 std::cout << testCaseInfo.name << std::endl;
4656 }
4657 return matchedTests;
4658 }
4659
4660 struct TagInfo {
TagInfoCatch::TagInfo4661 TagInfo() : count ( 0 ) {}
addCatch::TagInfo4662 void add( std::string const& spelling ) {
4663 ++count;
4664 spellings.insert( spelling );
4665 }
allCatch::TagInfo4666 std::string all() const {
4667 std::string out;
4668 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
4669 it != itEnd;
4670 ++it )
4671 out += "[" + *it + "]";
4672 return out;
4673 }
4674 std::set<std::string> spellings;
4675 std::size_t count;
4676 };
4677
listTags(Config const & config)4678 inline std::size_t listTags( Config const& config ) {
4679 TestSpec testSpec = config.testSpec();
4680 if( config.testSpec().hasFilters() )
4681 std::cout << "Tags for matching test cases:\n";
4682 else {
4683 std::cout << "All available tags:\n";
4684 testSpec = TestSpecParser().parse( "*" ).testSpec();
4685 }
4686
4687 std::map<std::string, TagInfo> tagCounts;
4688
4689 std::vector<TestCase> matchedTestCases;
4690 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
4691 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
4692 it != itEnd;
4693 ++it ) {
4694 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4695 tagItEnd = it->getTestCaseInfo().tags.end();
4696 tagIt != tagItEnd;
4697 ++tagIt ) {
4698 std::string tagName = *tagIt;
4699 std::string lcaseTagName = toLower( tagName );
4700 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
4701 if( countIt == tagCounts.end() )
4702 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
4703 countIt->second.add( tagName );
4704 }
4705 }
4706
4707 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
4708 countItEnd = tagCounts.end();
4709 countIt != countItEnd;
4710 ++countIt ) {
4711 std::ostringstream oss;
4712 oss << " " << std::setw(2) << countIt->second.count << " ";
4713 Text wrapper( countIt->second.all(), TextAttributes()
4714 .setInitialIndent( 0 )
4715 .setIndent( oss.str().size() )
4716 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
4717 std::cout << oss.str() << wrapper << "\n";
4718 }
4719 std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
4720 return tagCounts.size();
4721 }
4722
listReporters(Config const &)4723 inline std::size_t listReporters( Config const& /*config*/ ) {
4724 std::cout << "Available reports:\n";
4725 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
4726 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
4727 std::size_t maxNameLen = 0;
4728 for(it = itBegin; it != itEnd; ++it )
4729 maxNameLen = (std::max)( maxNameLen, it->first.size() );
4730
4731 for(it = itBegin; it != itEnd; ++it ) {
4732 Text wrapper( it->second->getDescription(), TextAttributes()
4733 .setInitialIndent( 0 )
4734 .setIndent( 7+maxNameLen )
4735 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
4736 std::cout << " "
4737 << it->first
4738 << ":"
4739 << std::string( maxNameLen - it->first.size() + 2, ' ' )
4740 << wrapper << "\n";
4741 }
4742 std::cout << std::endl;
4743 return factories.size();
4744 }
4745
list(Config const & config)4746 inline Option<std::size_t> list( Config const& config ) {
4747 Option<std::size_t> listedCount;
4748 if( config.listTests() )
4749 listedCount = listedCount.valueOr(0) + listTests( config );
4750 if( config.listTestNamesOnly() )
4751 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
4752 if( config.listTags() )
4753 listedCount = listedCount.valueOr(0) + listTags( config );
4754 if( config.listReporters() )
4755 listedCount = listedCount.valueOr(0) + listReporters( config );
4756 return listedCount;
4757 }
4758
4759 } // end namespace Catch
4760
4761 // #included from: internal/catch_runner_impl.hpp
4762 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
4763
4764 // #included from: catch_test_case_tracker.hpp
4765 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
4766
4767 #include <map>
4768 #include <string>
4769 #include <assert.h>
4770
4771 namespace Catch {
4772 namespace SectionTracking {
4773
4774 class TrackedSection {
4775
4776 typedef std::map<std::string, TrackedSection> TrackedSections;
4777
4778 public:
4779 enum RunState {
4780 NotStarted,
4781 Executing,
4782 ExecutingChildren,
4783 Completed
4784 };
4785
TrackedSection(std::string const & name,TrackedSection * parent)4786 TrackedSection( std::string const& name, TrackedSection* parent )
4787 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
4788 {}
4789
runState() const4790 RunState runState() const { return m_runState; }
4791
findChild(std::string const & childName)4792 TrackedSection* findChild( std::string const& childName ) {
4793 TrackedSections::iterator it = m_children.find( childName );
4794 return it != m_children.end()
4795 ? &it->second
4796 : NULL;
4797 }
acquireChild(std::string const & childName)4798 TrackedSection* acquireChild( std::string const& childName ) {
4799 if( TrackedSection* child = findChild( childName ) )
4800 return child;
4801 m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
4802 return findChild( childName );
4803 }
enter()4804 void enter() {
4805 if( m_runState == NotStarted )
4806 m_runState = Executing;
4807 }
leave()4808 void leave() {
4809 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
4810 it != itEnd;
4811 ++it )
4812 if( it->second.runState() != Completed ) {
4813 m_runState = ExecutingChildren;
4814 return;
4815 }
4816 m_runState = Completed;
4817 }
getParent()4818 TrackedSection* getParent() {
4819 return m_parent;
4820 }
hasChildren() const4821 bool hasChildren() const {
4822 return !m_children.empty();
4823 }
4824
4825 private:
4826 std::string m_name;
4827 RunState m_runState;
4828 TrackedSections m_children;
4829 TrackedSection* m_parent;
4830
4831 };
4832
4833 class TestCaseTracker {
4834 public:
TestCaseTracker(std::string const & testCaseName)4835 TestCaseTracker( std::string const& testCaseName )
4836 : m_testCase( testCaseName, NULL ),
4837 m_currentSection( &m_testCase ),
4838 m_completedASectionThisRun( false )
4839 {}
4840
enterSection(std::string const & name)4841 bool enterSection( std::string const& name ) {
4842 TrackedSection* child = m_currentSection->acquireChild( name );
4843 if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
4844 return false;
4845
4846 m_currentSection = child;
4847 m_currentSection->enter();
4848 return true;
4849 }
leaveSection()4850 void leaveSection() {
4851 m_currentSection->leave();
4852 m_currentSection = m_currentSection->getParent();
4853 assert( m_currentSection != NULL );
4854 m_completedASectionThisRun = true;
4855 }
4856
currentSectionHasChildren() const4857 bool currentSectionHasChildren() const {
4858 return m_currentSection->hasChildren();
4859 }
isCompleted() const4860 bool isCompleted() const {
4861 return m_testCase.runState() == TrackedSection::Completed;
4862 }
4863
4864 class Guard {
4865 public:
Guard(TestCaseTracker & tracker)4866 Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
4867 m_tracker.enterTestCase();
4868 }
~Guard()4869 ~Guard() {
4870 m_tracker.leaveTestCase();
4871 }
4872 private:
4873 Guard( Guard const& );
4874 void operator = ( Guard const& );
4875 TestCaseTracker& m_tracker;
4876 };
4877
4878 private:
enterTestCase()4879 void enterTestCase() {
4880 m_currentSection = &m_testCase;
4881 m_completedASectionThisRun = false;
4882 m_testCase.enter();
4883 }
leaveTestCase()4884 void leaveTestCase() {
4885 m_testCase.leave();
4886 }
4887
4888 TrackedSection m_testCase;
4889 TrackedSection* m_currentSection;
4890 bool m_completedASectionThisRun;
4891 };
4892
4893 } // namespace SectionTracking
4894
4895 using SectionTracking::TestCaseTracker;
4896
4897 } // namespace Catch
4898
4899 #include <set>
4900 #include <string>
4901
4902 namespace Catch {
4903
4904 class StreamRedirect {
4905
4906 public:
StreamRedirect(std::ostream & stream,std::string & targetString)4907 StreamRedirect( std::ostream& stream, std::string& targetString )
4908 : m_stream( stream ),
4909 m_prevBuf( stream.rdbuf() ),
4910 m_targetString( targetString )
4911 {
4912 stream.rdbuf( m_oss.rdbuf() );
4913 }
4914
~StreamRedirect()4915 ~StreamRedirect() {
4916 m_targetString += m_oss.str();
4917 m_stream.rdbuf( m_prevBuf );
4918 }
4919
4920 private:
4921 std::ostream& m_stream;
4922 std::streambuf* m_prevBuf;
4923 std::ostringstream m_oss;
4924 std::string& m_targetString;
4925 };
4926
4927 ///////////////////////////////////////////////////////////////////////////
4928
4929 class RunContext : public IResultCapture, public IRunner {
4930
4931 RunContext( RunContext const& );
4932 void operator =( RunContext const& );
4933
4934 public:
4935
RunContext(Ptr<IConfig const> const & config,Ptr<IStreamingReporter> const & reporter)4936 explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter )
4937 : m_runInfo( config->name() ),
4938 m_context( getCurrentMutableContext() ),
4939 m_activeTestCase( NULL ),
4940 m_config( config ),
4941 m_reporter( reporter ),
4942 m_prevRunner( m_context.getRunner() ),
4943 m_prevResultCapture( m_context.getResultCapture() ),
4944 m_prevConfig( m_context.getConfig() )
4945 {
4946 m_context.setRunner( this );
4947 m_context.setConfig( m_config );
4948 m_context.setResultCapture( this );
4949 m_reporter->testRunStarting( m_runInfo );
4950 }
4951
~RunContext()4952 virtual ~RunContext() {
4953 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
4954 m_context.setRunner( m_prevRunner );
4955 m_context.setConfig( NULL );
4956 m_context.setResultCapture( m_prevResultCapture );
4957 m_context.setConfig( m_prevConfig );
4958 }
4959
testGroupStarting(std::string const & testSpec,std::size_t groupIndex,std::size_t groupsCount)4960 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4961 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
4962 }
testGroupEnded(std::string const & testSpec,Totals const & totals,std::size_t groupIndex,std::size_t groupsCount)4963 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
4964 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
4965 }
4966
runTest(TestCase const & testCase)4967 Totals runTest( TestCase const& testCase ) {
4968 Totals prevTotals = m_totals;
4969
4970 std::string redirectedCout;
4971 std::string redirectedCerr;
4972
4973 TestCaseInfo testInfo = testCase.getTestCaseInfo();
4974
4975 m_reporter->testCaseStarting( testInfo );
4976
4977 m_activeTestCase = &testCase;
4978 m_testCaseTracker = TestCaseTracker( testInfo.name );
4979
4980 do {
4981 do {
4982 runCurrentTest( redirectedCout, redirectedCerr );
4983 }
4984 while( !m_testCaseTracker->isCompleted() && !aborting() );
4985 }
4986 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
4987
4988 Totals deltaTotals = m_totals.delta( prevTotals );
4989 m_totals.testCases += deltaTotals.testCases;
4990 m_reporter->testCaseEnded( TestCaseStats( testInfo,
4991 deltaTotals,
4992 redirectedCout,
4993 redirectedCerr,
4994 aborting() ) );
4995
4996 m_activeTestCase = NULL;
4997 m_testCaseTracker.reset();
4998
4999 return deltaTotals;
5000 }
5001
config() const5002 Ptr<IConfig const> config() const {
5003 return m_config;
5004 }
5005
5006 private: // IResultCapture
5007
acceptExpression(ExpressionResultBuilder const & assertionResult,AssertionInfo const & assertionInfo)5008 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) {
5009 m_lastAssertionInfo = assertionInfo;
5010 return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
5011 }
5012
assertionEnded(AssertionResult const & result)5013 virtual void assertionEnded( AssertionResult const& result ) {
5014 if( result.getResultType() == ResultWas::Ok ) {
5015 m_totals.assertions.passed++;
5016 }
5017 else if( !result.isOk() ) {
5018 m_totals.assertions.failed++;
5019 }
5020
5021 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5022 m_messages.clear();
5023
5024 // Reset working state
5025 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
5026 }
5027
sectionStarted(SectionInfo const & sectionInfo,Counts & assertions)5028 virtual bool sectionStarted (
5029 SectionInfo const& sectionInfo,
5030 Counts& assertions
5031 )
5032 {
5033 std::ostringstream oss;
5034 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
5035
5036 if( !m_testCaseTracker->enterSection( oss.str() ) )
5037 return false;
5038
5039 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
5040
5041 m_reporter->sectionStarting( sectionInfo );
5042
5043 assertions = m_totals.assertions;
5044
5045 return true;
5046 }
testForMissingAssertions(Counts & assertions)5047 bool testForMissingAssertions( Counts& assertions ) {
5048 if( assertions.total() != 0 ||
5049 !m_config->warnAboutMissingAssertions() ||
5050 m_testCaseTracker->currentSectionHasChildren() )
5051 return false;
5052 m_totals.assertions.failed++;
5053 assertions.failed++;
5054 return true;
5055 }
5056
sectionEnded(SectionInfo const & info,Counts const & prevAssertions,double _durationInSeconds)5057 virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
5058 if( std::uncaught_exception() ) {
5059 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
5060 return;
5061 }
5062
5063 Counts assertions = m_totals.assertions - prevAssertions;
5064 bool missingAssertions = testForMissingAssertions( assertions );
5065
5066 m_testCaseTracker->leaveSection();
5067
5068 m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
5069 m_messages.clear();
5070 }
5071
pushScopedMessage(MessageInfo const & message)5072 virtual void pushScopedMessage( MessageInfo const& message ) {
5073 m_messages.push_back( message );
5074 }
5075
popScopedMessage(MessageInfo const & message)5076 virtual void popScopedMessage( MessageInfo const& message ) {
5077 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
5078 }
5079
shouldDebugBreak() const5080 virtual bool shouldDebugBreak() const {
5081 return m_config->shouldDebugBreak();
5082 }
5083
getCurrentTestName() const5084 virtual std::string getCurrentTestName() const {
5085 return m_activeTestCase
5086 ? m_activeTestCase->getTestCaseInfo().name
5087 : "";
5088 }
5089
getLastResult() const5090 virtual const AssertionResult* getLastResult() const {
5091 return &m_lastResult;
5092 }
5093
5094 public:
5095 // !TBD We need to do this another way!
aborting() const5096 bool aborting() const {
5097 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
5098 }
5099
5100 private:
5101
actOnCurrentResult(AssertionResult const & result)5102 ResultAction::Value actOnCurrentResult( AssertionResult const& result ) {
5103 m_lastResult = result;
5104 assertionEnded( m_lastResult );
5105
5106 ResultAction::Value action = ResultAction::None;
5107
5108 if( !m_lastResult.isOk() ) {
5109 action = ResultAction::Failed;
5110 if( shouldDebugBreak() )
5111 action = (ResultAction::Value)( action | ResultAction::Debug );
5112 if( aborting() )
5113 action = (ResultAction::Value)( action | ResultAction::Abort );
5114 }
5115 return action;
5116 }
5117
runCurrentTest(std::string & redirectedCout,std::string & redirectedCerr)5118 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
5119 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5120 SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
5121 m_reporter->sectionStarting( testCaseSection );
5122 Counts prevAssertions = m_totals.assertions;
5123 double duration = 0;
5124 try {
5125 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
5126 TestCaseTracker::Guard guard( *m_testCaseTracker );
5127
5128 Timer timer;
5129 timer.start();
5130 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
5131 StreamRedirect coutRedir( std::cout, redirectedCout );
5132 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
5133 m_activeTestCase->invoke();
5134 }
5135 else {
5136 m_activeTestCase->invoke();
5137 }
5138 duration = timer.getElapsedSeconds();
5139 }
5140 catch( TestFailureException& ) {
5141 // This just means the test was aborted due to failure
5142 }
5143 catch(...) {
5144 ExpressionResultBuilder exResult( ResultWas::ThrewException );
5145 exResult << translateActiveException();
5146 actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
5147 }
5148 // If sections ended prematurely due to an exception we stored their
5149 // infos here so we can tear them down outside the unwind process.
5150 for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
5151 itEnd = m_unfinishedSections.rend();
5152 it != itEnd;
5153 ++it )
5154 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
5155 m_unfinishedSections.clear();
5156 m_messages.clear();
5157
5158 Counts assertions = m_totals.assertions - prevAssertions;
5159 bool missingAssertions = testForMissingAssertions( assertions );
5160
5161 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
5162 m_reporter->sectionEnded( testCaseSectionStats );
5163 }
5164
5165 private:
5166 struct UnfinishedSections {
UnfinishedSectionsCatch::RunContext::UnfinishedSections5167 UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
5168 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
5169 {}
5170
5171 SectionInfo info;
5172 Counts prevAssertions;
5173 double durationInSeconds;
5174 };
5175
5176 TestRunInfo m_runInfo;
5177 IMutableContext& m_context;
5178 TestCase const* m_activeTestCase;
5179 Option<TestCaseTracker> m_testCaseTracker;
5180 AssertionResult m_lastResult;
5181
5182 Ptr<IConfig const> m_config;
5183 Totals m_totals;
5184 Ptr<IStreamingReporter> m_reporter;
5185 std::vector<MessageInfo> m_messages;
5186 IRunner* m_prevRunner;
5187 IResultCapture* m_prevResultCapture;
5188 Ptr<IConfig const> m_prevConfig;
5189 AssertionInfo m_lastAssertionInfo;
5190 std::vector<UnfinishedSections> m_unfinishedSections;
5191 };
5192
5193 } // end namespace Catch
5194
5195 // #included from: internal/catch_version.h
5196 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
5197
5198 namespace Catch {
5199
5200 // Versioning information
5201 struct Version {
VersionCatch::Version5202 Version( unsigned int _majorVersion,
5203 unsigned int _minorVersion,
5204 unsigned int _buildNumber,
5205 char const* const _branchName )
5206 : majorVersion( _majorVersion ),
5207 minorVersion( _minorVersion ),
5208 buildNumber( _buildNumber ),
5209 branchName( _branchName )
5210 {}
5211
5212 unsigned int const majorVersion;
5213 unsigned int const minorVersion;
5214 unsigned int const buildNumber;
5215 char const* const branchName;
5216
5217 private:
5218 void operator=( Version const& );
5219 };
5220
5221 extern Version libraryVersion;
5222 }
5223
5224 #include <fstream>
5225 #include <stdlib.h>
5226 #include <limits>
5227
5228 namespace Catch {
5229
5230 class Runner {
5231
5232 public:
Runner(Ptr<Config> const & config)5233 Runner( Ptr<Config> const& config )
5234 : m_config( config )
5235 {
5236 openStream();
5237 makeReporter();
5238 }
5239
runTests()5240 Totals runTests() {
5241
5242 RunContext context( m_config.get(), m_reporter );
5243
5244 Totals totals;
5245
5246 context.testGroupStarting( "", 1, 1 ); // deprecated?
5247
5248 TestSpec testSpec = m_config->testSpec();
5249 if( !testSpec.hasFilters() )
5250 testSpec = TestSpecParser().parse( "~[.]" ).testSpec(); // All not hidden tests
5251
5252 std::vector<TestCase> testCases;
5253 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
5254
5255 int testsRunForGroup = 0;
5256 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
5257 it != itEnd;
5258 ++it ) {
5259 testsRunForGroup++;
5260 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
5261
5262 if( context.aborting() )
5263 break;
5264
5265 totals += context.runTest( *it );
5266 m_testsAlreadyRun.insert( *it );
5267 }
5268 }
5269 context.testGroupEnded( "", totals, 1, 1 );
5270 return totals;
5271 }
5272
5273 private:
openStream()5274 void openStream() {
5275 // Open output file, if specified
5276 if( !m_config->getFilename().empty() ) {
5277 m_ofs.open( m_config->getFilename().c_str() );
5278 if( m_ofs.fail() ) {
5279 std::ostringstream oss;
5280 oss << "Unable to open file: '" << m_config->getFilename() << "'";
5281 throw std::domain_error( oss.str() );
5282 }
5283 m_config->setStreamBuf( m_ofs.rdbuf() );
5284 }
5285 }
makeReporter()5286 void makeReporter() {
5287 std::string reporterName = m_config->getReporterName().empty()
5288 ? "console"
5289 : m_config->getReporterName();
5290
5291 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
5292 if( !m_reporter ) {
5293 std::ostringstream oss;
5294 oss << "No reporter registered with name: '" << reporterName << "'";
5295 throw std::domain_error( oss.str() );
5296 }
5297 }
5298
5299 private:
5300 Ptr<Config> m_config;
5301 std::ofstream m_ofs;
5302 Ptr<IStreamingReporter> m_reporter;
5303 std::set<TestCase> m_testsAlreadyRun;
5304 };
5305
5306 class Session {
5307 static bool alreadyInstantiated;
5308
5309 public:
5310
5311 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
5312
Session()5313 Session()
5314 : m_cli( makeCommandLineParser() ) {
5315 if( alreadyInstantiated ) {
5316 std::string msg = "Only one instance of Catch::Session can ever be used";
5317 std::cerr << msg << std::endl;
5318 throw std::logic_error( msg );
5319 }
5320 alreadyInstantiated = true;
5321 }
~Session()5322 ~Session() {
5323 Catch::cleanUp();
5324 }
5325
showHelp(std::string const & processName)5326 void showHelp( std::string const& processName ) {
5327 std::cout << "\nCatch v" << libraryVersion.majorVersion << "."
5328 << libraryVersion.minorVersion << " build "
5329 << libraryVersion.buildNumber;
5330 if( libraryVersion.branchName != std::string( "master" ) )
5331 std::cout << " (" << libraryVersion.branchName << " branch)";
5332 std::cout << "\n";
5333
5334 m_cli.usage( std::cout, processName );
5335 std::cout << "For more detail usage please see the project docs\n" << std::endl;
5336 }
5337
applyCommandLine(int argc,char * const argv[],OnUnusedOptions::DoWhat unusedOptionBehaviour=OnUnusedOptions::Fail)5338 int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
5339 try {
5340 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
5341 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
5342 if( m_configData.showHelp )
5343 showHelp( m_configData.processName );
5344 m_config.reset();
5345 }
5346 catch( std::exception& ex ) {
5347 {
5348 Colour colourGuard( Colour::Red );
5349 std::cerr << "\nError(s) in input:\n"
5350 << Text( ex.what(), TextAttributes().setIndent(2) )
5351 << "\n\n";
5352 }
5353 m_cli.usage( std::cout, m_configData.processName );
5354 return (std::numeric_limits<int>::max)();
5355 }
5356 return 0;
5357 }
5358
useConfigData(ConfigData const & _configData)5359 void useConfigData( ConfigData const& _configData ) {
5360 m_configData = _configData;
5361 m_config.reset();
5362 }
5363
run(int argc,char * const argv[])5364 int run( int argc, char* const argv[] ) {
5365
5366 int returnCode = applyCommandLine( argc, argv );
5367 if( returnCode == 0 )
5368 returnCode = run();
5369 return returnCode;
5370 }
5371
run()5372 int run() {
5373 if( m_configData.showHelp )
5374 return 0;
5375
5376 try
5377 {
5378 config(); // Force config to be constructed
5379 Runner runner( m_config );
5380
5381 // Handle list request
5382 if( Option<std::size_t> listed = list( config() ) )
5383 return static_cast<int>( *listed );
5384
5385 return static_cast<int>( runner.runTests().assertions.failed );
5386 }
5387 catch( std::exception& ex ) {
5388 std::cerr << ex.what() << std::endl;
5389 return (std::numeric_limits<int>::max)();
5390 }
5391 }
5392
cli() const5393 Clara::CommandLine<ConfigData> const& cli() const {
5394 return m_cli;
5395 }
unusedTokens() const5396 std::vector<Clara::Parser::Token> const& unusedTokens() const {
5397 return m_unusedTokens;
5398 }
configData()5399 ConfigData& configData() {
5400 return m_configData;
5401 }
config()5402 Config& config() {
5403 if( !m_config )
5404 m_config = new Config( m_configData );
5405 return *m_config;
5406 }
5407
5408 private:
5409 Clara::CommandLine<ConfigData> m_cli;
5410 std::vector<Clara::Parser::Token> m_unusedTokens;
5411 ConfigData m_configData;
5412 Ptr<Config> m_config;
5413 };
5414
5415 bool Session::alreadyInstantiated = false;
5416
5417 } // end namespace Catch
5418
5419 // #included from: catch_registry_hub.hpp
5420 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
5421
5422 // #included from: catch_test_case_registry_impl.hpp
5423 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
5424
5425 #include <vector>
5426 #include <set>
5427 #include <sstream>
5428 #include <iostream>
5429
5430 namespace Catch {
5431
5432 class TestRegistry : public ITestCaseRegistry {
5433 public:
TestRegistry()5434 TestRegistry() : m_unnamedCount( 0 ) {}
5435 virtual ~TestRegistry();
5436
registerTest(TestCase const & testCase)5437 virtual void registerTest( TestCase const& testCase ) {
5438 std::string name = testCase.getTestCaseInfo().name;
5439 if( name == "" ) {
5440 std::ostringstream oss;
5441 oss << "Anonymous test case " << ++m_unnamedCount;
5442 return registerTest( testCase.withName( oss.str() ) );
5443 }
5444
5445 if( m_functions.find( testCase ) == m_functions.end() ) {
5446 m_functions.insert( testCase );
5447 m_functionsInOrder.push_back( testCase );
5448 if( !testCase.isHidden() )
5449 m_nonHiddenFunctions.push_back( testCase );
5450 }
5451 else {
5452 TestCase const& prev = *m_functions.find( testCase );
5453 {
5454 Colour colourGuard( Colour::Red );
5455 std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
5456 << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
5457 << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
5458 }
5459 exit(1);
5460 }
5461 }
5462
getAllTests() const5463 virtual std::vector<TestCase> const& getAllTests() const {
5464 return m_functionsInOrder;
5465 }
5466
getAllNonHiddenTests() const5467 virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
5468 return m_nonHiddenFunctions;
5469 }
5470
getFilteredTests(TestSpec const & testSpec,IConfig const & config,std::vector<TestCase> & matchingTestCases) const5471 virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const {
5472 for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
5473 itEnd = m_functionsInOrder.end();
5474 it != itEnd;
5475 ++it ) {
5476 if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) )
5477 matchingTestCases.push_back( *it );
5478 }
5479 }
5480
5481 private:
5482
5483 std::set<TestCase> m_functions;
5484 std::vector<TestCase> m_functionsInOrder;
5485 std::vector<TestCase> m_nonHiddenFunctions;
5486 size_t m_unnamedCount;
5487 };
5488
5489 ///////////////////////////////////////////////////////////////////////////
5490
5491 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
5492 public:
5493
FreeFunctionTestCase(TestFunction fun)5494 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
5495
invoke() const5496 virtual void invoke() const {
5497 m_fun();
5498 }
5499
5500 private:
5501 virtual ~FreeFunctionTestCase();
5502
5503 TestFunction m_fun;
5504 };
5505
extractClassName(std::string const & classOrQualifiedMethodName)5506 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
5507 std::string className = classOrQualifiedMethodName;
5508 if( startsWith( className, "&" ) )
5509 {
5510 std::size_t lastColons = className.rfind( "::" );
5511 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
5512 if( penultimateColons == std::string::npos )
5513 penultimateColons = 1;
5514 className = className.substr( penultimateColons, lastColons-penultimateColons );
5515 }
5516 return className;
5517 }
5518
5519 ///////////////////////////////////////////////////////////////////////////
5520
AutoReg(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)5521 AutoReg::AutoReg( TestFunction function,
5522 SourceLineInfo const& lineInfo,
5523 NameAndDesc const& nameAndDesc ) {
5524 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
5525 }
5526
~AutoReg()5527 AutoReg::~AutoReg() {}
5528
registerTestCase(ITestCase * testCase,char const * classOrQualifiedMethodName,NameAndDesc const & nameAndDesc,SourceLineInfo const & lineInfo)5529 void AutoReg::registerTestCase( ITestCase* testCase,
5530 char const* classOrQualifiedMethodName,
5531 NameAndDesc const& nameAndDesc,
5532 SourceLineInfo const& lineInfo ) {
5533
5534 getMutableRegistryHub().registerTest
5535 ( makeTestCase( testCase,
5536 extractClassName( classOrQualifiedMethodName ),
5537 nameAndDesc.name,
5538 nameAndDesc.description,
5539 lineInfo ) );
5540 }
5541
5542 } // end namespace Catch
5543
5544 // #included from: catch_reporter_registry.hpp
5545 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
5546
5547 #include <map>
5548
5549 namespace Catch {
5550
5551 class ReporterRegistry : public IReporterRegistry {
5552
5553 public:
5554
~ReporterRegistry()5555 virtual ~ReporterRegistry() {
5556 deleteAllValues( m_factories );
5557 }
5558
create(std::string const & name,Ptr<IConfig> const & config) const5559 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
5560 FactoryMap::const_iterator it = m_factories.find( name );
5561 if( it == m_factories.end() )
5562 return NULL;
5563 return it->second->create( ReporterConfig( config ) );
5564 }
5565
registerReporter(std::string const & name,IReporterFactory * factory)5566 void registerReporter( std::string const& name, IReporterFactory* factory ) {
5567 m_factories.insert( std::make_pair( name, factory ) );
5568 }
5569
getFactories() const5570 FactoryMap const& getFactories() const {
5571 return m_factories;
5572 }
5573
5574 private:
5575 FactoryMap m_factories;
5576 };
5577 }
5578
5579 // #included from: catch_exception_translator_registry.hpp
5580 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
5581
5582 #ifdef __OBJC__
5583 #import "Foundation/Foundation.h"
5584 #endif
5585
5586 namespace Catch {
5587
5588 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
5589 public:
~ExceptionTranslatorRegistry()5590 ~ExceptionTranslatorRegistry() {
5591 deleteAll( m_translators );
5592 }
5593
registerTranslator(const IExceptionTranslator * translator)5594 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5595 m_translators.push_back( translator );
5596 }
5597
translateActiveException() const5598 virtual std::string translateActiveException() const {
5599 try {
5600 #ifdef __OBJC__
5601 // In Objective-C try objective-c exceptions first
5602 @try {
5603 throw;
5604 }
5605 @catch (NSException *exception) {
5606 return toString( [exception description] );
5607 }
5608 #else
5609 throw;
5610 #endif
5611 }
5612 catch( std::exception& ex ) {
5613 return ex.what();
5614 }
5615 catch( std::string& msg ) {
5616 return msg;
5617 }
5618 catch( const char* msg ) {
5619 return msg;
5620 }
5621 catch(...) {
5622 return tryTranslators( m_translators.begin() );
5623 }
5624 }
5625
tryTranslators(std::vector<const IExceptionTranslator * >::const_iterator it) const5626 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
5627 if( it == m_translators.end() )
5628 return "Unknown exception";
5629
5630 try {
5631 return (*it)->translate();
5632 }
5633 catch(...) {
5634 return tryTranslators( it+1 );
5635 }
5636 }
5637
5638 private:
5639 std::vector<const IExceptionTranslator*> m_translators;
5640 };
5641 }
5642
5643 namespace Catch {
5644
5645 namespace {
5646
5647 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
5648
5649 RegistryHub( RegistryHub const& );
5650 void operator=( RegistryHub const& );
5651
5652 public: // IRegistryHub
RegistryHub()5653 RegistryHub() {
5654 }
getReporterRegistry() const5655 virtual IReporterRegistry const& getReporterRegistry() const {
5656 return m_reporterRegistry;
5657 }
getTestCaseRegistry() const5658 virtual ITestCaseRegistry const& getTestCaseRegistry() const {
5659 return m_testCaseRegistry;
5660 }
getExceptionTranslatorRegistry()5661 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
5662 return m_exceptionTranslatorRegistry;
5663 }
5664
5665 public: // IMutableRegistryHub
registerReporter(std::string const & name,IReporterFactory * factory)5666 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
5667 m_reporterRegistry.registerReporter( name, factory );
5668 }
registerTest(TestCase const & testInfo)5669 virtual void registerTest( TestCase const& testInfo ) {
5670 m_testCaseRegistry.registerTest( testInfo );
5671 }
registerTranslator(const IExceptionTranslator * translator)5672 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5673 m_exceptionTranslatorRegistry.registerTranslator( translator );
5674 }
5675
5676 private:
5677 TestRegistry m_testCaseRegistry;
5678 ReporterRegistry m_reporterRegistry;
5679 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5680 };
5681
5682 // Single, global, instance
getTheRegistryHub()5683 inline RegistryHub*& getTheRegistryHub() {
5684 static RegistryHub* theRegistryHub = NULL;
5685 if( !theRegistryHub )
5686 theRegistryHub = new RegistryHub();
5687 return theRegistryHub;
5688 }
5689 }
5690
getRegistryHub()5691 IRegistryHub& getRegistryHub() {
5692 return *getTheRegistryHub();
5693 }
getMutableRegistryHub()5694 IMutableRegistryHub& getMutableRegistryHub() {
5695 return *getTheRegistryHub();
5696 }
cleanUp()5697 void cleanUp() {
5698 delete getTheRegistryHub();
5699 getTheRegistryHub() = NULL;
5700 cleanUpContext();
5701 }
translateActiveException()5702 std::string translateActiveException() {
5703 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
5704 }
5705
5706 } // end namespace Catch
5707
5708 // #included from: catch_notimplemented_exception.hpp
5709 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
5710
5711 #include <ostream>
5712
5713 namespace Catch {
5714
NotImplementedException(SourceLineInfo const & lineInfo)5715 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
5716 : m_lineInfo( lineInfo ) {
5717 std::ostringstream oss;
5718 oss << lineInfo << ": function ";
5719 oss << "not implemented";
5720 m_what = oss.str();
5721 }
5722
what() const5723 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
5724 return m_what.c_str();
5725 }
5726
5727 } // end namespace Catch
5728
5729 // #included from: catch_context_impl.hpp
5730 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
5731
5732 // #included from: catch_stream.hpp
5733 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
5734
5735 // #included from: catch_streambuf.h
5736 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
5737
5738 #include <streambuf>
5739
5740 namespace Catch {
5741
5742 class StreamBufBase : public std::streambuf {
5743 public:
5744 virtual ~StreamBufBase() CATCH_NOEXCEPT;
5745 };
5746 }
5747
5748 #include <stdexcept>
5749 #include <cstdio>
5750
5751 namespace Catch {
5752
5753 template<typename WriterF, size_t bufferSize=256>
5754 class StreamBufImpl : public StreamBufBase {
5755 char data[bufferSize];
5756 WriterF m_writer;
5757
5758 public:
StreamBufImpl()5759 StreamBufImpl() {
5760 setp( data, data + sizeof(data) );
5761 }
5762
~StreamBufImpl()5763 ~StreamBufImpl() CATCH_NOEXCEPT {
5764 sync();
5765 }
5766
5767 private:
overflow(int c)5768 int overflow( int c ) {
5769 sync();
5770
5771 if( c != EOF ) {
5772 if( pbase() == epptr() )
5773 m_writer( std::string( 1, static_cast<char>( c ) ) );
5774 else
5775 sputc( static_cast<char>( c ) );
5776 }
5777 return 0;
5778 }
5779
sync()5780 int sync() {
5781 if( pbase() != pptr() ) {
5782 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
5783 setp( pbase(), epptr() );
5784 }
5785 return 0;
5786 }
5787 };
5788
5789 ///////////////////////////////////////////////////////////////////////////
5790
5791 struct OutputDebugWriter {
5792
operator ()Catch::OutputDebugWriter5793 void operator()( std::string const&str ) {
5794 writeToDebugConsole( str );
5795 }
5796 };
5797
Stream()5798 Stream::Stream()
5799 : streamBuf( NULL ), isOwned( false )
5800 {}
5801
Stream(std::streambuf * _streamBuf,bool _isOwned)5802 Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
5803 : streamBuf( _streamBuf ), isOwned( _isOwned )
5804 {}
5805
release()5806 void Stream::release() {
5807 if( isOwned ) {
5808 delete streamBuf;
5809 streamBuf = NULL;
5810 isOwned = false;
5811 }
5812 }
5813 }
5814
5815 namespace Catch {
5816
5817 class Context : public IMutableContext {
5818
Context()5819 Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
5820 Context( Context const& );
5821 void operator=( Context const& );
5822
5823 public: // IContext
getResultCapture()5824 virtual IResultCapture* getResultCapture() {
5825 return m_resultCapture;
5826 }
getRunner()5827 virtual IRunner* getRunner() {
5828 return m_runner;
5829 }
getGeneratorIndex(std::string const & fileInfo,size_t totalSize)5830 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
5831 return getGeneratorsForCurrentTest()
5832 .getGeneratorInfo( fileInfo, totalSize )
5833 .getCurrentIndex();
5834 }
advanceGeneratorsForCurrentTest()5835 virtual bool advanceGeneratorsForCurrentTest() {
5836 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5837 return generators && generators->moveNext();
5838 }
5839
getConfig() const5840 virtual Ptr<IConfig const> getConfig() const {
5841 return m_config;
5842 }
5843
5844 public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)5845 virtual void setResultCapture( IResultCapture* resultCapture ) {
5846 m_resultCapture = resultCapture;
5847 }
setRunner(IRunner * runner)5848 virtual void setRunner( IRunner* runner ) {
5849 m_runner = runner;
5850 }
setConfig(Ptr<IConfig const> const & config)5851 virtual void setConfig( Ptr<IConfig const> const& config ) {
5852 m_config = config;
5853 }
5854
5855 friend IMutableContext& getCurrentMutableContext();
5856
5857 private:
findGeneratorsForCurrentTest()5858 IGeneratorsForTest* findGeneratorsForCurrentTest() {
5859 std::string testName = getResultCapture()->getCurrentTestName();
5860
5861 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
5862 m_generatorsByTestName.find( testName );
5863 return it != m_generatorsByTestName.end()
5864 ? it->second
5865 : NULL;
5866 }
5867
getGeneratorsForCurrentTest()5868 IGeneratorsForTest& getGeneratorsForCurrentTest() {
5869 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5870 if( !generators ) {
5871 std::string testName = getResultCapture()->getCurrentTestName();
5872 generators = createGeneratorsForTest();
5873 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
5874 }
5875 return *generators;
5876 }
5877
5878 private:
5879 Ptr<IConfig const> m_config;
5880 IRunner* m_runner;
5881 IResultCapture* m_resultCapture;
5882 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
5883 };
5884
5885 namespace {
5886 Context* currentContext = NULL;
5887 }
getCurrentMutableContext()5888 IMutableContext& getCurrentMutableContext() {
5889 if( !currentContext )
5890 currentContext = new Context();
5891 return *currentContext;
5892 }
getCurrentContext()5893 IContext& getCurrentContext() {
5894 return getCurrentMutableContext();
5895 }
5896
createStream(std::string const & streamName)5897 Stream createStream( std::string const& streamName ) {
5898 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
5899 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
5900 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
5901
5902 throw std::domain_error( "Unknown stream: " + streamName );
5903 }
5904
cleanUpContext()5905 void cleanUpContext() {
5906 delete currentContext;
5907 currentContext = NULL;
5908 }
5909 }
5910
5911 // #included from: catch_console_colour_impl.hpp
5912 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
5913
5914 namespace Catch { namespace Detail {
5915 struct IColourImpl {
~IColourImplCatch::Detail::IColourImpl5916 virtual ~IColourImpl() {}
5917 virtual void use( Colour::Code _colourCode ) = 0;
5918 };
5919 }}
5920
5921 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
5922
5923 #ifndef NOMINMAX
5924 #define NOMINMAX
5925 #endif
5926
5927 #ifdef __AFXDLL
5928 #include <AfxWin.h>
5929 #else
5930 #include <windows.h>
5931 #endif
5932
5933 namespace Catch {
5934 namespace {
5935
5936 class Win32ColourImpl : public Detail::IColourImpl {
5937 public:
Win32ColourImpl()5938 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
5939 {
5940 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
5941 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
5942 originalAttributes = csbiInfo.wAttributes;
5943 }
5944
use(Colour::Code _colourCode)5945 virtual void use( Colour::Code _colourCode ) {
5946 switch( _colourCode ) {
5947 case Colour::None: return setTextAttribute( originalAttributes );
5948 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5949 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
5950 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
5951 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
5952 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
5953 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
5954 case Colour::Grey: return setTextAttribute( 0 );
5955
5956 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
5957 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
5958 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
5959 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5960
5961 case Colour::Bright: throw std::logic_error( "not a colour" );
5962 }
5963 }
5964
5965 private:
setTextAttribute(WORD _textAttribute)5966 void setTextAttribute( WORD _textAttribute ) {
5967 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
5968 }
5969 HANDLE stdoutHandle;
5970 WORD originalAttributes;
5971 };
5972
shouldUseColourForPlatform()5973 inline bool shouldUseColourForPlatform() {
5974 return true;
5975 }
5976
platformColourInstance()5977 static Detail::IColourImpl* platformColourInstance() {
5978 static Win32ColourImpl s_instance;
5979 return &s_instance;
5980 }
5981
5982 } // end anon namespace
5983 } // end namespace Catch
5984
5985 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
5986
5987 #include <unistd.h>
5988
5989 namespace Catch {
5990 namespace {
5991
5992 // use POSIX/ ANSI console terminal codes
5993 // Thanks to Adam Strzelecki for original contribution
5994 // (http://github.com/nanoant)
5995 // https://github.com/philsquared/Catch/pull/131
5996 class PosixColourImpl : public Detail::IColourImpl {
5997 public:
use(Colour::Code _colourCode)5998 virtual void use( Colour::Code _colourCode ) {
5999 switch( _colourCode ) {
6000 case Colour::None:
6001 case Colour::White: return setColour( "[0m" );
6002 case Colour::Red: return setColour( "[0;31m" );
6003 case Colour::Green: return setColour( "[0;32m" );
6004 case Colour::Blue: return setColour( "[0:34m" );
6005 case Colour::Cyan: return setColour( "[0;36m" );
6006 case Colour::Yellow: return setColour( "[0;33m" );
6007 case Colour::Grey: return setColour( "[1;30m" );
6008
6009 case Colour::LightGrey: return setColour( "[0;37m" );
6010 case Colour::BrightRed: return setColour( "[1;31m" );
6011 case Colour::BrightGreen: return setColour( "[1;32m" );
6012 case Colour::BrightWhite: return setColour( "[1;37m" );
6013
6014 case Colour::Bright: throw std::logic_error( "not a colour" );
6015 }
6016 }
6017 private:
setColour(const char * _escapeCode)6018 void setColour( const char* _escapeCode ) {
6019 std::cout << '\033' << _escapeCode;
6020 }
6021 };
6022
shouldUseColourForPlatform()6023 inline bool shouldUseColourForPlatform() {
6024 return isatty(STDOUT_FILENO);
6025 }
6026
platformColourInstance()6027 static Detail::IColourImpl* platformColourInstance() {
6028 static PosixColourImpl s_instance;
6029 return &s_instance;
6030 }
6031
6032 } // end anon namespace
6033 } // end namespace Catch
6034
6035 #endif // not Windows
6036
6037 namespace Catch {
6038
6039 namespace {
6040 struct NoColourImpl : Detail::IColourImpl {
useCatch::__anonb8ccb8a50511::NoColourImpl6041 void use( Colour::Code ) {}
6042
instanceCatch::__anonb8ccb8a50511::NoColourImpl6043 static IColourImpl* instance() {
6044 static NoColourImpl s_instance;
6045 return &s_instance;
6046 }
6047 };
shouldUseColour()6048 static bool shouldUseColour() {
6049 return shouldUseColourForPlatform() && !isDebuggerActive();
6050 }
6051 }
6052
Colour(Code _colourCode)6053 Colour::Colour( Code _colourCode ){ use( _colourCode ); }
~Colour()6054 Colour::~Colour(){ use( None ); }
use(Code _colourCode)6055 void Colour::use( Code _colourCode ) {
6056 impl()->use( _colourCode );
6057 }
6058
impl()6059 Detail::IColourImpl* Colour::impl() {
6060 return shouldUseColour()
6061 ? platformColourInstance()
6062 : NoColourImpl::instance();
6063 }
6064
6065 } // end namespace Catch
6066
6067 // #included from: catch_generators_impl.hpp
6068 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
6069
6070 #include <vector>
6071 #include <string>
6072 #include <map>
6073
6074 namespace Catch {
6075
6076 struct GeneratorInfo : IGeneratorInfo {
6077
GeneratorInfoCatch::GeneratorInfo6078 GeneratorInfo( std::size_t size )
6079 : m_size( size ),
6080 m_currentIndex( 0 )
6081 {}
6082
moveNextCatch::GeneratorInfo6083 bool moveNext() {
6084 if( ++m_currentIndex == m_size ) {
6085 m_currentIndex = 0;
6086 return false;
6087 }
6088 return true;
6089 }
6090
getCurrentIndexCatch::GeneratorInfo6091 std::size_t getCurrentIndex() const {
6092 return m_currentIndex;
6093 }
6094
6095 std::size_t m_size;
6096 std::size_t m_currentIndex;
6097 };
6098
6099 ///////////////////////////////////////////////////////////////////////////
6100
6101 class GeneratorsForTest : public IGeneratorsForTest {
6102
6103 public:
~GeneratorsForTest()6104 ~GeneratorsForTest() {
6105 deleteAll( m_generatorsInOrder );
6106 }
6107
getGeneratorInfo(std::string const & fileInfo,std::size_t size)6108 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
6109 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
6110 if( it == m_generatorsByName.end() ) {
6111 IGeneratorInfo* info = new GeneratorInfo( size );
6112 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
6113 m_generatorsInOrder.push_back( info );
6114 return *info;
6115 }
6116 return *it->second;
6117 }
6118
moveNext()6119 bool moveNext() {
6120 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
6121 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
6122 for(; it != itEnd; ++it ) {
6123 if( (*it)->moveNext() )
6124 return true;
6125 }
6126 return false;
6127 }
6128
6129 private:
6130 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
6131 std::vector<IGeneratorInfo*> m_generatorsInOrder;
6132 };
6133
createGeneratorsForTest()6134 IGeneratorsForTest* createGeneratorsForTest()
6135 {
6136 return new GeneratorsForTest();
6137 }
6138
6139 } // end namespace Catch
6140
6141 // #included from: catch_assertionresult.hpp
6142 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
6143
6144 namespace Catch {
6145
AssertionInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,std::string const & _capturedExpression,ResultDisposition::Flags _resultDisposition)6146 AssertionInfo::AssertionInfo( std::string const& _macroName,
6147 SourceLineInfo const& _lineInfo,
6148 std::string const& _capturedExpression,
6149 ResultDisposition::Flags _resultDisposition )
6150 : macroName( _macroName ),
6151 lineInfo( _lineInfo ),
6152 capturedExpression( _capturedExpression ),
6153 resultDisposition( _resultDisposition )
6154 {}
6155
AssertionResult()6156 AssertionResult::AssertionResult() {}
6157
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)6158 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
6159 : m_info( info ),
6160 m_resultData( data )
6161 {}
6162
~AssertionResult()6163 AssertionResult::~AssertionResult() {}
6164
6165 // Result was a success
succeeded() const6166 bool AssertionResult::succeeded() const {
6167 return Catch::isOk( m_resultData.resultType );
6168 }
6169
6170 // Result was a success, or failure is suppressed
isOk() const6171 bool AssertionResult::isOk() const {
6172 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
6173 }
6174
getResultType() const6175 ResultWas::OfType AssertionResult::getResultType() const {
6176 return m_resultData.resultType;
6177 }
6178
hasExpression() const6179 bool AssertionResult::hasExpression() const {
6180 return !m_info.capturedExpression.empty();
6181 }
6182
hasMessage() const6183 bool AssertionResult::hasMessage() const {
6184 return !m_resultData.message.empty();
6185 }
6186
getExpression() const6187 std::string AssertionResult::getExpression() const {
6188 if( shouldNegate( m_info.resultDisposition ) )
6189 return "!" + m_info.capturedExpression;
6190 else
6191 return m_info.capturedExpression;
6192 }
getExpressionInMacro() const6193 std::string AssertionResult::getExpressionInMacro() const {
6194 if( m_info.macroName.empty() )
6195 return m_info.capturedExpression;
6196 else
6197 return m_info.macroName + "( " + m_info.capturedExpression + " )";
6198 }
6199
hasExpandedExpression() const6200 bool AssertionResult::hasExpandedExpression() const {
6201 return hasExpression() && getExpandedExpression() != getExpression();
6202 }
6203
getExpandedExpression() const6204 std::string AssertionResult::getExpandedExpression() const {
6205 return m_resultData.reconstructedExpression;
6206 }
6207
getMessage() const6208 std::string AssertionResult::getMessage() const {
6209 return m_resultData.message;
6210 }
getSourceInfo() const6211 SourceLineInfo AssertionResult::getSourceInfo() const {
6212 return m_info.lineInfo;
6213 }
6214
getTestMacroName() const6215 std::string AssertionResult::getTestMacroName() const {
6216 return m_info.macroName;
6217 }
6218
6219 } // end namespace Catch
6220
6221 // #included from: catch_expressionresult_builder.hpp
6222 #define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
6223
6224 #include <assert.h>
6225
6226 namespace Catch {
6227
ExpressionResultBuilder(ResultWas::OfType resultType)6228 ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
6229 m_data.resultType = resultType;
6230 }
ExpressionResultBuilder(ExpressionResultBuilder const & other)6231 ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other )
6232 : m_data( other.m_data ),
6233 m_exprComponents( other.m_exprComponents )
6234 {
6235 m_stream << other.m_stream.str();
6236 }
operator =(ExpressionResultBuilder const & other)6237 ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) {
6238 m_data = other.m_data;
6239 m_exprComponents = other.m_exprComponents;
6240 m_stream.str("");
6241 m_stream << other.m_stream.str();
6242 return *this;
6243 }
setResultType(ResultWas::OfType result)6244 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) {
6245 m_data.resultType = result;
6246 return *this;
6247 }
setResultType(bool result)6248 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) {
6249 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
6250 return *this;
6251 }
endExpression(ResultDisposition::Flags resultDisposition)6252 ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
6253 m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
6254 return *this;
6255 }
setLhs(std::string const & lhs)6256 ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) {
6257 m_exprComponents.lhs = lhs;
6258 return *this;
6259 }
setRhs(std::string const & rhs)6260 ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) {
6261 m_exprComponents.rhs = rhs;
6262 return *this;
6263 }
setOp(std::string const & op)6264 ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) {
6265 m_exprComponents.op = op;
6266 return *this;
6267 }
buildResult(AssertionInfo const & info) const6268 AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const
6269 {
6270 assert( m_data.resultType != ResultWas::Unknown );
6271
6272 AssertionResultData data = m_data;
6273
6274 // Flip bool results if shouldNegate is set
6275 if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok )
6276 data.resultType = ResultWas::ExpressionFailed;
6277 else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed )
6278 data.resultType = ResultWas::Ok;
6279
6280 data.message = m_stream.str();
6281 data.reconstructedExpression = reconstructExpression( info );
6282 if( m_exprComponents.shouldNegate ) {
6283 if( m_exprComponents.op == "" )
6284 data.reconstructedExpression = "!" + data.reconstructedExpression;
6285 else
6286 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
6287 }
6288 return AssertionResult( info, data );
6289 }
reconstructExpression(AssertionInfo const & info) const6290 std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const {
6291 if( m_exprComponents.op == "" )
6292 return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
6293 else if( m_exprComponents.op == "matches" )
6294 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
6295 else if( m_exprComponents.op != "!" ) {
6296 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
6297 m_exprComponents.lhs.find("\n") == std::string::npos &&
6298 m_exprComponents.rhs.find("\n") == std::string::npos )
6299 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
6300 else
6301 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
6302 }
6303 else
6304 return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}";
6305 }
6306
6307 } // end namespace Catch
6308
6309 // #included from: catch_test_case_info.hpp
6310 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
6311
6312 namespace Catch {
6313
isSpecialTag(std::string const & tag)6314 inline bool isSpecialTag( std::string const& tag ) {
6315 return tag == "." ||
6316 tag == "hide" ||
6317 tag == "!hide" ||
6318 tag == "!throws";
6319 }
isReservedTag(std::string const & tag)6320 inline bool isReservedTag( std::string const& tag ) {
6321 return !isSpecialTag( tag ) && tag.size() > 0 && !isalnum( tag[0] );
6322 }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)6323 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
6324 if( isReservedTag( tag ) ) {
6325 {
6326 Colour colourGuard( Colour::Red );
6327 std::cerr
6328 << "Tag name [" << tag << "] not allowed.\n"
6329 << "Tag names starting with non alpha-numeric characters are reserved\n";
6330 }
6331 {
6332 Colour colourGuard( Colour::FileName );
6333 std::cerr << _lineInfo << std::endl;
6334 }
6335 exit(1);
6336 }
6337 }
6338
makeTestCase(ITestCase * _testCase,std::string const & _className,std::string const & _name,std::string const & _descOrTags,SourceLineInfo const & _lineInfo)6339 TestCase makeTestCase( ITestCase* _testCase,
6340 std::string const& _className,
6341 std::string const& _name,
6342 std::string const& _descOrTags,
6343 SourceLineInfo const& _lineInfo )
6344 {
6345 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
6346
6347 // Parse out tags
6348 std::set<std::string> tags;
6349 std::string desc, tag;
6350 bool inTag = false;
6351 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
6352 char c = _descOrTags[i];
6353 if( !inTag ) {
6354 if( c == '[' )
6355 inTag = true;
6356 else
6357 desc += c;
6358 }
6359 else {
6360 if( c == ']' ) {
6361 enforceNotReservedTag( tag, _lineInfo );
6362
6363 inTag = false;
6364 if( tag == "hide" || tag == "." )
6365 isHidden = true;
6366 else
6367 tags.insert( tag );
6368 tag.clear();
6369 }
6370 else
6371 tag += c;
6372 }
6373 }
6374 if( isHidden ) {
6375 tags.insert( "hide" );
6376 tags.insert( "." );
6377 }
6378
6379 TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );
6380 return TestCase( _testCase, info );
6381 }
6382
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::set<std::string> const & _tags,bool _isHidden,SourceLineInfo const & _lineInfo)6383 TestCaseInfo::TestCaseInfo( std::string const& _name,
6384 std::string const& _className,
6385 std::string const& _description,
6386 std::set<std::string> const& _tags,
6387 bool _isHidden,
6388 SourceLineInfo const& _lineInfo )
6389 : name( _name ),
6390 className( _className ),
6391 description( _description ),
6392 tags( _tags ),
6393 lineInfo( _lineInfo ),
6394 isHidden( _isHidden ),
6395 throws( false )
6396 {
6397 std::ostringstream oss;
6398 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
6399 oss << "[" << *it << "]";
6400 if( *it == "!throws" )
6401 throws = true;
6402 lcaseTags.insert( toLower( *it ) );
6403 }
6404 tagsAsString = oss.str();
6405 }
6406
TestCaseInfo(TestCaseInfo const & other)6407 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
6408 : name( other.name ),
6409 className( other.className ),
6410 description( other.description ),
6411 tags( other.tags ),
6412 lcaseTags( other.lcaseTags ),
6413 tagsAsString( other.tagsAsString ),
6414 lineInfo( other.lineInfo ),
6415 isHidden( other.isHidden ),
6416 throws( other.throws )
6417 {}
6418
TestCase(ITestCase * testCase,TestCaseInfo const & info)6419 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
6420
TestCase(TestCase const & other)6421 TestCase::TestCase( TestCase const& other )
6422 : TestCaseInfo( other ),
6423 test( other.test )
6424 {}
6425
withName(std::string const & _newName) const6426 TestCase TestCase::withName( std::string const& _newName ) const {
6427 TestCase other( *this );
6428 other.name = _newName;
6429 return other;
6430 }
6431
swap(TestCase & other)6432 void TestCase::swap( TestCase& other ) {
6433 test.swap( other.test );
6434 name.swap( other.name );
6435 className.swap( other.className );
6436 description.swap( other.description );
6437 tags.swap( other.tags );
6438 lcaseTags.swap( other.lcaseTags );
6439 tagsAsString.swap( other.tagsAsString );
6440 std::swap( TestCaseInfo::isHidden, static_cast<TestCaseInfo&>( other ).isHidden );
6441 std::swap( TestCaseInfo::throws, static_cast<TestCaseInfo&>( other ).throws );
6442 std::swap( lineInfo, other.lineInfo );
6443 }
6444
invoke() const6445 void TestCase::invoke() const {
6446 test->invoke();
6447 }
6448
isHidden() const6449 bool TestCase::isHidden() const {
6450 return TestCaseInfo::isHidden;
6451 }
throws() const6452 bool TestCase::throws() const {
6453 return TestCaseInfo::throws;
6454 }
6455
operator ==(TestCase const & other) const6456 bool TestCase::operator == ( TestCase const& other ) const {
6457 return test.get() == other.test.get() &&
6458 name == other.name &&
6459 className == other.className;
6460 }
6461
operator <(TestCase const & other) const6462 bool TestCase::operator < ( TestCase const& other ) const {
6463 return name < other.name;
6464 }
operator =(TestCase const & other)6465 TestCase& TestCase::operator = ( TestCase const& other ) {
6466 TestCase temp( other );
6467 swap( temp );
6468 return *this;
6469 }
6470
getTestCaseInfo() const6471 TestCaseInfo const& TestCase::getTestCaseInfo() const
6472 {
6473 return *this;
6474 }
6475
6476 } // end namespace Catch
6477
6478 // #included from: catch_version.hpp
6479 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
6480
6481 namespace Catch {
6482
6483 // These numbers are maintained by a script
6484 Version libraryVersion( 1, 0, 47, "master" );
6485 }
6486
6487 // #included from: catch_message.hpp
6488 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
6489
6490 namespace Catch {
6491
MessageInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)6492 MessageInfo::MessageInfo( std::string const& _macroName,
6493 SourceLineInfo const& _lineInfo,
6494 ResultWas::OfType _type )
6495 : macroName( _macroName ),
6496 lineInfo( _lineInfo ),
6497 type( _type ),
6498 sequence( ++globalCount )
6499 {}
6500
6501 // This may need protecting if threading support is added
6502 unsigned int MessageInfo::globalCount = 0;
6503
6504 ////////////////////////////////////////////////////////////////////////////
6505
ScopedMessage(MessageBuilder const & builder)6506 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
6507 : m_info( builder.m_info )
6508 {
6509 m_info.message = builder.m_stream.str();
6510 getResultCapture().pushScopedMessage( m_info );
6511 }
ScopedMessage(ScopedMessage const & other)6512 ScopedMessage::ScopedMessage( ScopedMessage const& other )
6513 : m_info( other.m_info )
6514 {}
6515
~ScopedMessage()6516 ScopedMessage::~ScopedMessage() {
6517 getResultCapture().popScopedMessage( m_info );
6518 }
6519
6520 } // end namespace Catch
6521
6522 // #included from: catch_legacy_reporter_adapter.hpp
6523 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
6524
6525 // #included from: catch_legacy_reporter_adapter.h
6526 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
6527
6528 namespace Catch
6529 {
6530 // Deprecated
6531 struct IReporter : IShared {
6532 virtual ~IReporter();
6533
6534 virtual bool shouldRedirectStdout() const = 0;
6535
6536 virtual void StartTesting() = 0;
6537 virtual void EndTesting( Totals const& totals ) = 0;
6538 virtual void StartGroup( std::string const& groupName ) = 0;
6539 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
6540 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
6541 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
6542 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
6543 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
6544 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
6545 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
6546 virtual void Aborted() = 0;
6547 virtual void Result( AssertionResult const& result ) = 0;
6548 };
6549
6550 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
6551 {
6552 public:
6553 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
6554 virtual ~LegacyReporterAdapter();
6555
6556 virtual ReporterPreferences getPreferences() const;
6557 virtual void noMatchingTestCases( std::string const& );
6558 virtual void testRunStarting( TestRunInfo const& );
6559 virtual void testGroupStarting( GroupInfo const& groupInfo );
6560 virtual void testCaseStarting( TestCaseInfo const& testInfo );
6561 virtual void sectionStarting( SectionInfo const& sectionInfo );
6562 virtual void assertionStarting( AssertionInfo const& );
6563 virtual bool assertionEnded( AssertionStats const& assertionStats );
6564 virtual void sectionEnded( SectionStats const& sectionStats );
6565 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
6566 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
6567 virtual void testRunEnded( TestRunStats const& testRunStats );
6568
6569 private:
6570 Ptr<IReporter> m_legacyReporter;
6571 };
6572 }
6573
6574 namespace Catch
6575 {
LegacyReporterAdapter(Ptr<IReporter> const & legacyReporter)6576 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
6577 : m_legacyReporter( legacyReporter )
6578 {}
~LegacyReporterAdapter()6579 LegacyReporterAdapter::~LegacyReporterAdapter() {}
6580
getPreferences() const6581 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
6582 ReporterPreferences prefs;
6583 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
6584 return prefs;
6585 }
6586
noMatchingTestCases(std::string const &)6587 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
testRunStarting(TestRunInfo const &)6588 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
6589 m_legacyReporter->StartTesting();
6590 }
testGroupStarting(GroupInfo const & groupInfo)6591 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
6592 m_legacyReporter->StartGroup( groupInfo.name );
6593 }
testCaseStarting(TestCaseInfo const & testInfo)6594 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
6595 m_legacyReporter->StartTestCase( testInfo );
6596 }
sectionStarting(SectionInfo const & sectionInfo)6597 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
6598 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
6599 }
assertionStarting(AssertionInfo const &)6600 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
6601 // Not on legacy interface
6602 }
6603
assertionEnded(AssertionStats const & assertionStats)6604 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
6605 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
6606 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
6607 it != itEnd;
6608 ++it ) {
6609 if( it->type == ResultWas::Info ) {
6610 ExpressionResultBuilder expressionBuilder( it->type );
6611 expressionBuilder << it->message;
6612 AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal );
6613 AssertionResult result = expressionBuilder.buildResult( info );
6614 m_legacyReporter->Result( result );
6615 }
6616 }
6617 }
6618 m_legacyReporter->Result( assertionStats.assertionResult );
6619 return true;
6620 }
sectionEnded(SectionStats const & sectionStats)6621 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
6622 if( sectionStats.missingAssertions )
6623 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
6624 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
6625 }
testCaseEnded(TestCaseStats const & testCaseStats)6626 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
6627 m_legacyReporter->EndTestCase
6628 ( testCaseStats.testInfo,
6629 testCaseStats.totals,
6630 testCaseStats.stdOut,
6631 testCaseStats.stdErr );
6632 }
testGroupEnded(TestGroupStats const & testGroupStats)6633 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
6634 if( testGroupStats.aborting )
6635 m_legacyReporter->Aborted();
6636 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
6637 }
testRunEnded(TestRunStats const & testRunStats)6638 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
6639 m_legacyReporter->EndTesting( testRunStats.totals );
6640 }
6641 }
6642
6643 // #included from: catch_timer.hpp
6644
6645 #ifdef __clang__
6646 #pragma clang diagnostic push
6647 #pragma clang diagnostic ignored "-Wc++11-long-long"
6648 #endif
6649
6650 #ifdef CATCH_PLATFORM_WINDOWS
6651 #include <windows.h>
6652 #else
6653 #include <sys/time.h>
6654 #endif
6655
6656 namespace Catch {
6657
6658 namespace {
6659 #ifdef CATCH_PLATFORM_WINDOWS
getCurrentTicks()6660 uint64_t getCurrentTicks() {
6661 static uint64_t hz=0, hzo=0;
6662 if (!hz) {
6663 QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
6664 QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
6665 }
6666 uint64_t t;
6667 QueryPerformanceCounter((LARGE_INTEGER*)&t);
6668 return ((t-hzo)*1000000)/hz;
6669 }
6670 #else
6671 uint64_t getCurrentTicks() {
6672 timeval t;
6673 gettimeofday(&t,NULL);
6674 return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec;
6675 }
6676 #endif
6677 }
6678
start()6679 void Timer::start() {
6680 m_ticks = getCurrentTicks();
6681 }
getElapsedNanoseconds() const6682 unsigned int Timer::getElapsedNanoseconds() const {
6683 return (unsigned int)(getCurrentTicks() - m_ticks);
6684 }
getElapsedMilliseconds() const6685 unsigned int Timer::getElapsedMilliseconds() const {
6686 return (unsigned int)((getCurrentTicks() - m_ticks)/1000);
6687 }
getElapsedSeconds() const6688 double Timer::getElapsedSeconds() const {
6689 return (getCurrentTicks() - m_ticks)/1000000.0;
6690 }
6691
6692 } // namespace Catch
6693
6694 #ifdef __clang__
6695 #pragma clang diagnostic pop
6696 #endif
6697 // #included from: catch_common.hpp
6698 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
6699
6700 namespace Catch {
6701
startsWith(std::string const & s,std::string const & prefix)6702 bool startsWith( std::string const& s, std::string const& prefix ) {
6703 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
6704 }
endsWith(std::string const & s,std::string const & suffix)6705 bool endsWith( std::string const& s, std::string const& suffix ) {
6706 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
6707 }
contains(std::string const & s,std::string const & infix)6708 bool contains( std::string const& s, std::string const& infix ) {
6709 return s.find( infix ) != std::string::npos;
6710 }
toLowerInPlace(std::string & s)6711 void toLowerInPlace( std::string& s ) {
6712 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
6713 }
toLower(std::string const & s)6714 std::string toLower( std::string const& s ) {
6715 std::string lc = s;
6716 toLowerInPlace( lc );
6717 return lc;
6718 }
trim(std::string const & str)6719 std::string trim( std::string const& str ) {
6720 static char const* whitespaceChars = "\n\r\t ";
6721 std::string::size_type start = str.find_first_not_of( whitespaceChars );
6722 std::string::size_type end = str.find_last_not_of( whitespaceChars );
6723
6724 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
6725 }
6726
pluralise(std::size_t count,std::string const & label)6727 pluralise::pluralise( std::size_t count, std::string const& label )
6728 : m_count( count ),
6729 m_label( label )
6730 {}
6731
operator <<(std::ostream & os,pluralise const & pluraliser)6732 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
6733 os << pluraliser.m_count << " " << pluraliser.m_label;
6734 if( pluraliser.m_count != 1 )
6735 os << "s";
6736 return os;
6737 }
6738
SourceLineInfo()6739 SourceLineInfo::SourceLineInfo() : line( 0 ){}
SourceLineInfo(char const * _file,std::size_t _line)6740 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
6741 : file( _file ),
6742 line( _line )
6743 {}
SourceLineInfo(SourceLineInfo const & other)6744 SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
6745 : file( other.file ),
6746 line( other.line )
6747 {}
empty() const6748 bool SourceLineInfo::empty() const {
6749 return file.empty();
6750 }
operator ==(SourceLineInfo const & other) const6751 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
6752 return line == other.line && file == other.file;
6753 }
6754
operator <<(std::ostream & os,SourceLineInfo const & info)6755 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
6756 #ifndef __GNUG__
6757 os << info.file << "(" << info.line << ")";
6758 #else
6759 os << info.file << ":" << info.line;
6760 #endif
6761 return os;
6762 }
6763
throwLogicError(std::string const & message,SourceLineInfo const & locationInfo)6764 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
6765 std::ostringstream oss;
6766 oss << locationInfo << ": Internal Catch error: '" << message << "'";
6767 if( isTrue( true ))
6768 throw std::logic_error( oss.str() );
6769 }
6770 }
6771
6772 // #included from: catch_section.hpp
6773 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
6774
6775 namespace Catch {
6776
Section(SourceLineInfo const & lineInfo,std::string const & name,std::string const & description)6777 Section::Section( SourceLineInfo const& lineInfo,
6778 std::string const& name,
6779 std::string const& description )
6780 : m_info( name, description, lineInfo ),
6781 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
6782 {
6783 m_timer.start();
6784 }
6785
~Section()6786 Section::~Section() {
6787 if( m_sectionIncluded )
6788 getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
6789 }
6790
6791 // This indicates whether the section should be executed or not
operator bool()6792 Section::operator bool() {
6793 return m_sectionIncluded;
6794 }
6795
6796 } // end namespace Catch
6797
6798 // #included from: catch_debugger.hpp
6799 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
6800
6801 #include <iostream>
6802
6803 #ifdef CATCH_PLATFORM_MAC
6804
6805 #include <assert.h>
6806 #include <stdbool.h>
6807 #include <sys/types.h>
6808 #include <unistd.h>
6809 #include <sys/sysctl.h>
6810
6811 namespace Catch{
6812
6813 // The following function is taken directly from the following technical note:
6814 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
6815
6816 // Returns true if the current process is being debugged (either
6817 // running under the debugger or has a debugger attached post facto).
isDebuggerActive()6818 bool isDebuggerActive(){
6819
6820 int mib[4];
6821 struct kinfo_proc info;
6822 size_t size;
6823
6824 // Initialize the flags so that, if sysctl fails for some bizarre
6825 // reason, we get a predictable result.
6826
6827 info.kp_proc.p_flag = 0;
6828
6829 // Initialize mib, which tells sysctl the info we want, in this case
6830 // we're looking for information about a specific process ID.
6831
6832 mib[0] = CTL_KERN;
6833 mib[1] = KERN_PROC;
6834 mib[2] = KERN_PROC_PID;
6835 mib[3] = getpid();
6836
6837 // Call sysctl.
6838
6839 size = sizeof(info);
6840 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
6841 std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
6842 return false;
6843 }
6844
6845 // We're being debugged if the P_TRACED flag is set.
6846
6847 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
6848 }
6849 } // namespace Catch
6850
6851 #elif defined(_MSC_VER)
6852 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
6853 namespace Catch {
isDebuggerActive()6854 bool isDebuggerActive() {
6855 return IsDebuggerPresent() != 0;
6856 }
6857 }
6858 #elif defined(__MINGW32__)
6859 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
6860 namespace Catch {
isDebuggerActive()6861 bool isDebuggerActive() {
6862 return IsDebuggerPresent() != 0;
6863 }
6864 }
6865 #else
6866 namespace Catch {
isDebuggerActive()6867 inline bool isDebuggerActive() { return false; }
6868 }
6869 #endif // Platform
6870
6871 #ifdef CATCH_PLATFORM_WINDOWS
6872 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
6873 namespace Catch {
writeToDebugConsole(std::string const & text)6874 void writeToDebugConsole( std::string const& text ) {
6875 ::OutputDebugStringA( text.c_str() );
6876 }
6877 }
6878 #else
6879 namespace Catch {
writeToDebugConsole(std::string const & text)6880 void writeToDebugConsole( std::string const& text ) {
6881 // !TBD: Need a version for Mac/ XCode and other IDEs
6882 std::cout << text;
6883 }
6884 }
6885 #endif // Platform
6886
6887 // #included from: catch_tostring.hpp
6888 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
6889
6890 namespace Catch {
6891
toString(std::string const & value)6892 std::string toString( std::string const& value ) {
6893 std::string s = value;
6894 if( getCurrentContext().getConfig()->showInvisibles() ) {
6895 for(size_t i = 0; i < s.size(); ++i ) {
6896 std::string subs;
6897 switch( s[i] ) {
6898 case '\n': subs = "\\n"; break;
6899 case '\t': subs = "\\t"; break;
6900 default: break;
6901 }
6902 if( !subs.empty() ) {
6903 s = s.substr( 0, i ) + subs + s.substr( i+1 );
6904 ++i;
6905 }
6906 }
6907 }
6908 return "\"" + s + "\"";
6909 }
toString(std::wstring const & value)6910 std::string toString( std::wstring const& value ) {
6911
6912 std::string s;
6913 s.reserve( value.size() );
6914 for(size_t i = 0; i < value.size(); ++i )
6915 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
6916 return toString( s );
6917 }
6918
toString(const char * const value)6919 std::string toString( const char* const value ) {
6920 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
6921 }
6922
toString(char * const value)6923 std::string toString( char* const value ) {
6924 return Catch::toString( static_cast<const char*>( value ) );
6925 }
6926
toString(int value)6927 std::string toString( int value ) {
6928 std::ostringstream oss;
6929 oss << value;
6930 return oss.str();
6931 }
6932
toString(unsigned long value)6933 std::string toString( unsigned long value ) {
6934 std::ostringstream oss;
6935 if( value > 8192 )
6936 oss << "0x" << std::hex << value;
6937 else
6938 oss << value;
6939 return oss.str();
6940 }
6941
toString(unsigned int value)6942 std::string toString( unsigned int value ) {
6943 return toString( static_cast<unsigned long>( value ) );
6944 }
6945
toString(const double value)6946 std::string toString( const double value ) {
6947 std::ostringstream oss;
6948 oss << std::setprecision( 10 )
6949 << std::fixed
6950 << value;
6951 std::string d = oss.str();
6952 std::size_t i = d.find_last_not_of( '0' );
6953 if( i != std::string::npos && i != d.size()-1 ) {
6954 if( d[i] == '.' )
6955 i++;
6956 d = d.substr( 0, i+1 );
6957 }
6958 return d;
6959 }
6960
toString(bool value)6961 std::string toString( bool value ) {
6962 return value ? "true" : "false";
6963 }
6964
toString(char value)6965 std::string toString( char value ) {
6966 return value < ' '
6967 ? toString( static_cast<unsigned int>( value ) )
6968 : Detail::makeString( value );
6969 }
6970
toString(signed char value)6971 std::string toString( signed char value ) {
6972 return toString( static_cast<char>( value ) );
6973 }
6974
toString(unsigned char value)6975 std::string toString( unsigned char value ) {
6976 return toString( static_cast<char>( value ) );
6977 }
6978
6979 #ifdef CATCH_CONFIG_CPP11_NULLPTR
toString(std::nullptr_t)6980 std::string toString( std::nullptr_t ) {
6981 return "nullptr";
6982 }
6983 #endif
6984
6985 #ifdef __OBJC__
toString(NSString const * const & nsstring)6986 std::string toString( NSString const * const& nsstring ) {
6987 if( !nsstring )
6988 return "nil";
6989 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
6990 }
toString(NSString * CATCH_ARC_STRONG const & nsstring)6991 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
6992 if( !nsstring )
6993 return "nil";
6994 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
6995 }
toString(NSObject * const & nsObject)6996 std::string toString( NSObject* const& nsObject ) {
6997 return toString( [nsObject description] );
6998 }
6999 #endif
7000
7001 } // end namespace Catch
7002
7003 // #included from: ../reporters/catch_reporter_xml.hpp
7004 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
7005
7006 // #included from: catch_reporter_bases.hpp
7007 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
7008
7009 namespace Catch {
7010
7011 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
7012
StreamingReporterBaseCatch::StreamingReporterBase7013 StreamingReporterBase( ReporterConfig const& _config )
7014 : m_config( _config.fullConfig() ),
7015 stream( _config.stream() )
7016 {}
7017
7018 virtual ~StreamingReporterBase();
7019
noMatchingTestCasesCatch::StreamingReporterBase7020 virtual void noMatchingTestCases( std::string const& ) {}
7021
testRunStartingCatch::StreamingReporterBase7022 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
7023 currentTestRunInfo = _testRunInfo;
7024 }
testGroupStartingCatch::StreamingReporterBase7025 virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
7026 currentGroupInfo = _groupInfo;
7027 }
7028
testCaseStartingCatch::StreamingReporterBase7029 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
7030 currentTestCaseInfo = _testInfo;
7031 }
sectionStartingCatch::StreamingReporterBase7032 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
7033 m_sectionStack.push_back( _sectionInfo );
7034 }
7035
sectionEndedCatch::StreamingReporterBase7036 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
7037 m_sectionStack.pop_back();
7038 }
testCaseEndedCatch::StreamingReporterBase7039 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
7040 currentTestCaseInfo.reset();
7041 assert( m_sectionStack.empty() );
7042 }
testGroupEndedCatch::StreamingReporterBase7043 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
7044 currentGroupInfo.reset();
7045 }
testRunEndedCatch::StreamingReporterBase7046 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
7047 currentTestCaseInfo.reset();
7048 currentGroupInfo.reset();
7049 currentTestRunInfo.reset();
7050 }
7051
7052 Ptr<IConfig> m_config;
7053 std::ostream& stream;
7054
7055 LazyStat<TestRunInfo> currentTestRunInfo;
7056 LazyStat<GroupInfo> currentGroupInfo;
7057 LazyStat<TestCaseInfo> currentTestCaseInfo;
7058
7059 std::vector<SectionInfo> m_sectionStack;
7060 };
7061
7062 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
7063 template<typename T, typename ChildNodeT>
7064 struct Node : SharedImpl<> {
NodeCatch::CumulativeReporterBase::Node7065 explicit Node( T const& _value ) : value( _value ) {}
~NodeCatch::CumulativeReporterBase::Node7066 virtual ~Node() {}
7067
7068 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
7069 T value;
7070 ChildNodes children;
7071 };
7072 struct SectionNode : SharedImpl<> {
SectionNodeCatch::CumulativeReporterBase::SectionNode7073 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
7074 virtual ~SectionNode();
7075
operator ==Catch::CumulativeReporterBase::SectionNode7076 bool operator == ( SectionNode const& other ) const {
7077 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
7078 }
operator ==Catch::CumulativeReporterBase::SectionNode7079 bool operator == ( Ptr<SectionNode> const& other ) const {
7080 return operator==( *other );
7081 }
7082
7083 SectionStats stats;
7084 typedef std::vector<Ptr<SectionNode> > ChildSections;
7085 typedef std::vector<AssertionStats> Assertions;
7086 ChildSections childSections;
7087 Assertions assertions;
7088 std::string stdOut;
7089 std::string stdErr;
7090 };
7091
7092 struct BySectionInfo {
BySectionInfoCatch::CumulativeReporterBase::BySectionInfo7093 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
BySectionInfoCatch::CumulativeReporterBase::BySectionInfo7094 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
operator ()Catch::CumulativeReporterBase::BySectionInfo7095 bool operator() ( Ptr<SectionNode> const& node ) const {
7096 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
7097 }
7098 private:
7099 void operator=( BySectionInfo const& );
7100 SectionInfo const& m_other;
7101 };
7102
7103 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
7104 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
7105 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
7106
CumulativeReporterBaseCatch::CumulativeReporterBase7107 CumulativeReporterBase( ReporterConfig const& _config )
7108 : m_config( _config.fullConfig() ),
7109 stream( _config.stream() )
7110 {}
7111 ~CumulativeReporterBase();
7112
testRunStartingCatch::CumulativeReporterBase7113 virtual void testRunStarting( TestRunInfo const& ) {}
testGroupStartingCatch::CumulativeReporterBase7114 virtual void testGroupStarting( GroupInfo const& ) {}
7115
testCaseStartingCatch::CumulativeReporterBase7116 virtual void testCaseStarting( TestCaseInfo const& ) {}
7117
sectionStartingCatch::CumulativeReporterBase7118 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
7119 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
7120 Ptr<SectionNode> node;
7121 if( m_sectionStack.empty() ) {
7122 if( !m_rootSection )
7123 m_rootSection = new SectionNode( incompleteStats );
7124 node = m_rootSection;
7125 }
7126 else {
7127 SectionNode& parentNode = *m_sectionStack.back();
7128 SectionNode::ChildSections::const_iterator it =
7129 std::find_if( parentNode.childSections.begin(),
7130 parentNode.childSections.end(),
7131 BySectionInfo( sectionInfo ) );
7132 if( it == parentNode.childSections.end() ) {
7133 node = new SectionNode( incompleteStats );
7134 parentNode.childSections.push_back( node );
7135 }
7136 else
7137 node = *it;
7138 }
7139 m_sectionStack.push_back( node );
7140 m_deepestSection = node;
7141 }
7142
assertionStartingCatch::CumulativeReporterBase7143 virtual void assertionStarting( AssertionInfo const& ) {}
7144
assertionEndedCatch::CumulativeReporterBase7145 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
7146 assert( !m_sectionStack.empty() );
7147 SectionNode& sectionNode = *m_sectionStack.back();
7148 sectionNode.assertions.push_back( assertionStats );
7149 return true;
7150 }
sectionEndedCatch::CumulativeReporterBase7151 virtual void sectionEnded( SectionStats const& sectionStats ) {
7152 assert( !m_sectionStack.empty() );
7153 SectionNode& node = *m_sectionStack.back();
7154 node.stats = sectionStats;
7155 m_sectionStack.pop_back();
7156 }
testCaseEndedCatch::CumulativeReporterBase7157 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
7158 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
7159 assert( m_sectionStack.size() == 0 );
7160 node->children.push_back( m_rootSection );
7161 m_testCases.push_back( node );
7162 m_rootSection.reset();
7163
7164 assert( m_deepestSection );
7165 m_deepestSection->stdOut = testCaseStats.stdOut;
7166 m_deepestSection->stdErr = testCaseStats.stdErr;
7167 }
testGroupEndedCatch::CumulativeReporterBase7168 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
7169 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
7170 node->children.swap( m_testCases );
7171 m_testGroups.push_back( node );
7172 }
testRunEndedCatch::CumulativeReporterBase7173 virtual void testRunEnded( TestRunStats const& testRunStats ) {
7174 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
7175 node->children.swap( m_testGroups );
7176 m_testRuns.push_back( node );
7177 testRunEndedCumulative();
7178 }
7179 virtual void testRunEndedCumulative() = 0;
7180
7181 Ptr<IConfig> m_config;
7182 std::ostream& stream;
7183 std::vector<AssertionStats> m_assertions;
7184 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
7185 std::vector<Ptr<TestCaseNode> > m_testCases;
7186 std::vector<Ptr<TestGroupNode> > m_testGroups;
7187
7188 std::vector<Ptr<TestRunNode> > m_testRuns;
7189
7190 Ptr<SectionNode> m_rootSection;
7191 Ptr<SectionNode> m_deepestSection;
7192 std::vector<Ptr<SectionNode> > m_sectionStack;
7193
7194 };
7195
7196 } // end namespace Catch
7197
7198 // #included from: ../internal/catch_reporter_registrars.hpp
7199 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
7200
7201 namespace Catch {
7202
7203 template<typename T>
7204 class LegacyReporterRegistrar {
7205
7206 class ReporterFactory : public IReporterFactory {
create(ReporterConfig const & config) const7207 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
7208 return new LegacyReporterAdapter( new T( config ) );
7209 }
7210
getDescription() const7211 virtual std::string getDescription() const {
7212 return T::getDescription();
7213 }
7214 };
7215
7216 public:
7217
LegacyReporterRegistrar(std::string const & name)7218 LegacyReporterRegistrar( std::string const& name ) {
7219 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
7220 }
7221 };
7222
7223 template<typename T>
7224 class ReporterRegistrar {
7225
7226 class ReporterFactory : public IReporterFactory {
7227
7228 // *** Please Note ***:
7229 // - If you end up here looking at a compiler error because it's trying to register
7230 // your custom reporter class be aware that the native reporter interface has changed
7231 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
7232 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
7233 // However please consider updating to the new interface as the old one is now
7234 // deprecated and will probably be removed quite soon!
7235 // Please contact me via github if you have any questions at all about this.
7236 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
7237 // no idea who is actually using custom reporters at all (possibly no-one!).
7238 // The new interface is designed to minimise exposure to interface changes in the future.
create(ReporterConfig const & config) const7239 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
7240 return new T( config );
7241 }
7242
getDescription() const7243 virtual std::string getDescription() const {
7244 return T::getDescription();
7245 }
7246 };
7247
7248 public:
7249
ReporterRegistrar(std::string const & name)7250 ReporterRegistrar( std::string const& name ) {
7251 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
7252 }
7253 };
7254 }
7255
7256 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
7257 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
7258 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
7259 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
7260
7261 // #included from: ../internal/catch_xmlwriter.hpp
7262 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
7263
7264 #include <sstream>
7265 #include <iostream>
7266 #include <string>
7267 #include <vector>
7268
7269 namespace Catch {
7270
7271 class XmlWriter {
7272 public:
7273
7274 class ScopedElement {
7275 public:
ScopedElement(XmlWriter * writer)7276 ScopedElement( XmlWriter* writer )
7277 : m_writer( writer )
7278 {}
7279
ScopedElement(ScopedElement const & other)7280 ScopedElement( ScopedElement const& other )
7281 : m_writer( other.m_writer ){
7282 other.m_writer = NULL;
7283 }
7284
~ScopedElement()7285 ~ScopedElement() {
7286 if( m_writer )
7287 m_writer->endElement();
7288 }
7289
writeText(std::string const & text,bool indent=true)7290 ScopedElement& writeText( std::string const& text, bool indent = true ) {
7291 m_writer->writeText( text, indent );
7292 return *this;
7293 }
7294
7295 template<typename T>
writeAttribute(std::string const & name,T const & attribute)7296 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
7297 m_writer->writeAttribute( name, attribute );
7298 return *this;
7299 }
7300
7301 private:
7302 mutable XmlWriter* m_writer;
7303 };
7304
XmlWriter()7305 XmlWriter()
7306 : m_tagIsOpen( false ),
7307 m_needsNewline( false ),
7308 m_os( &std::cout )
7309 {}
7310
XmlWriter(std::ostream & os)7311 XmlWriter( std::ostream& os )
7312 : m_tagIsOpen( false ),
7313 m_needsNewline( false ),
7314 m_os( &os )
7315 {}
7316
~XmlWriter()7317 ~XmlWriter() {
7318 while( !m_tags.empty() )
7319 endElement();
7320 }
7321
7322 //# ifndef CATCH_CPP11_OR_GREATER
7323 // XmlWriter& operator = ( XmlWriter const& other ) {
7324 // XmlWriter temp( other );
7325 // swap( temp );
7326 // return *this;
7327 // }
7328 //# else
7329 // XmlWriter( XmlWriter const& ) = default;
7330 // XmlWriter( XmlWriter && ) = default;
7331 // XmlWriter& operator = ( XmlWriter const& ) = default;
7332 // XmlWriter& operator = ( XmlWriter && ) = default;
7333 //# endif
7334 //
7335 // void swap( XmlWriter& other ) {
7336 // std::swap( m_tagIsOpen, other.m_tagIsOpen );
7337 // std::swap( m_needsNewline, other.m_needsNewline );
7338 // std::swap( m_tags, other.m_tags );
7339 // std::swap( m_indent, other.m_indent );
7340 // std::swap( m_os, other.m_os );
7341 // }
7342
startElement(std::string const & name)7343 XmlWriter& startElement( std::string const& name ) {
7344 ensureTagClosed();
7345 newlineIfNecessary();
7346 stream() << m_indent << "<" << name;
7347 m_tags.push_back( name );
7348 m_indent += " ";
7349 m_tagIsOpen = true;
7350 return *this;
7351 }
7352
scopedElement(std::string const & name)7353 ScopedElement scopedElement( std::string const& name ) {
7354 ScopedElement scoped( this );
7355 startElement( name );
7356 return scoped;
7357 }
7358
endElement()7359 XmlWriter& endElement() {
7360 newlineIfNecessary();
7361 m_indent = m_indent.substr( 0, m_indent.size()-2 );
7362 if( m_tagIsOpen ) {
7363 stream() << "/>\n";
7364 m_tagIsOpen = false;
7365 }
7366 else {
7367 stream() << m_indent << "</" << m_tags.back() << ">\n";
7368 }
7369 m_tags.pop_back();
7370 return *this;
7371 }
7372
writeAttribute(std::string const & name,std::string const & attribute)7373 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
7374 if( !name.empty() && !attribute.empty() ) {
7375 stream() << " " << name << "=\"";
7376 writeEncodedText( attribute );
7377 stream() << "\"";
7378 }
7379 return *this;
7380 }
7381
writeAttribute(std::string const & name,bool attribute)7382 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
7383 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
7384 return *this;
7385 }
7386
7387 template<typename T>
writeAttribute(std::string const & name,T const & attribute)7388 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
7389 if( !name.empty() )
7390 stream() << " " << name << "=\"" << attribute << "\"";
7391 return *this;
7392 }
7393
writeText(std::string const & text,bool indent=true)7394 XmlWriter& writeText( std::string const& text, bool indent = true ) {
7395 if( !text.empty() ){
7396 bool tagWasOpen = m_tagIsOpen;
7397 ensureTagClosed();
7398 if( tagWasOpen && indent )
7399 stream() << m_indent;
7400 writeEncodedText( text );
7401 m_needsNewline = true;
7402 }
7403 return *this;
7404 }
7405
writeComment(std::string const & text)7406 XmlWriter& writeComment( std::string const& text ) {
7407 ensureTagClosed();
7408 stream() << m_indent << "<!--" << text << "-->";
7409 m_needsNewline = true;
7410 return *this;
7411 }
7412
writeBlankLine()7413 XmlWriter& writeBlankLine() {
7414 ensureTagClosed();
7415 stream() << "\n";
7416 return *this;
7417 }
7418
setStream(std::ostream & os)7419 void setStream( std::ostream& os ) {
7420 m_os = &os;
7421 }
7422
7423 private:
7424 XmlWriter( XmlWriter const& );
7425 void operator=( XmlWriter const& );
7426
stream()7427 std::ostream& stream() {
7428 return *m_os;
7429 }
7430
ensureTagClosed()7431 void ensureTagClosed() {
7432 if( m_tagIsOpen ) {
7433 stream() << ">\n";
7434 m_tagIsOpen = false;
7435 }
7436 }
7437
newlineIfNecessary()7438 void newlineIfNecessary() {
7439 if( m_needsNewline ) {
7440 stream() << "\n";
7441 m_needsNewline = false;
7442 }
7443 }
7444
writeEncodedText(std::string const & text)7445 void writeEncodedText( std::string const& text ) {
7446 static const char* charsToEncode = "<&\"";
7447 std::string mtext = text;
7448 std::string::size_type pos = mtext.find_first_of( charsToEncode );
7449 while( pos != std::string::npos ) {
7450 stream() << mtext.substr( 0, pos );
7451
7452 switch( mtext[pos] ) {
7453 case '<':
7454 stream() << "<";
7455 break;
7456 case '&':
7457 stream() << "&";
7458 break;
7459 case '\"':
7460 stream() << """;
7461 break;
7462 }
7463 mtext = mtext.substr( pos+1 );
7464 pos = mtext.find_first_of( charsToEncode );
7465 }
7466 stream() << mtext;
7467 }
7468
7469 bool m_tagIsOpen;
7470 bool m_needsNewline;
7471 std::vector<std::string> m_tags;
7472 std::string m_indent;
7473 std::ostream* m_os;
7474 };
7475
7476 }
7477 namespace Catch {
7478 class XmlReporter : public SharedImpl<IReporter> {
7479 public:
XmlReporter(ReporterConfig const & config)7480 XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {}
7481
getDescription()7482 static std::string getDescription() {
7483 return "Reports test results as an XML document";
7484 }
7485 virtual ~XmlReporter();
7486
7487 private: // IReporter
7488
shouldRedirectStdout() const7489 virtual bool shouldRedirectStdout() const {
7490 return true;
7491 }
7492
StartTesting()7493 virtual void StartTesting() {
7494 m_xml.setStream( m_config.stream() );
7495 m_xml.startElement( "Catch" );
7496 if( !m_config.fullConfig()->name().empty() )
7497 m_xml.writeAttribute( "name", m_config.fullConfig()->name() );
7498 }
7499
EndTesting(const Totals & totals)7500 virtual void EndTesting( const Totals& totals ) {
7501 m_xml.scopedElement( "OverallResults" )
7502 .writeAttribute( "successes", totals.assertions.passed )
7503 .writeAttribute( "failures", totals.assertions.failed );
7504 m_xml.endElement();
7505 }
7506
StartGroup(const std::string & groupName)7507 virtual void StartGroup( const std::string& groupName ) {
7508 m_xml.startElement( "Group" )
7509 .writeAttribute( "name", groupName );
7510 }
7511
EndGroup(const std::string &,const Totals & totals)7512 virtual void EndGroup( const std::string&, const Totals& totals ) {
7513 m_xml.scopedElement( "OverallResults" )
7514 .writeAttribute( "successes", totals.assertions.passed )
7515 .writeAttribute( "failures", totals.assertions.failed );
7516 m_xml.endElement();
7517 }
7518
StartSection(const std::string & sectionName,const std::string & description)7519 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
7520 if( m_sectionDepth++ > 0 ) {
7521 m_xml.startElement( "Section" )
7522 .writeAttribute( "name", trim( sectionName ) )
7523 .writeAttribute( "description", description );
7524 }
7525 }
NoAssertionsInSection(const std::string &)7526 virtual void NoAssertionsInSection( const std::string& ) {}
NoAssertionsInTestCase(const std::string &)7527 virtual void NoAssertionsInTestCase( const std::string& ) {}
7528
EndSection(const std::string &,const Counts & assertions)7529 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
7530 if( --m_sectionDepth > 0 ) {
7531 m_xml.scopedElement( "OverallResults" )
7532 .writeAttribute( "successes", assertions.passed )
7533 .writeAttribute( "failures", assertions.failed );
7534 m_xml.endElement();
7535 }
7536 }
7537
StartTestCase(const Catch::TestCaseInfo & testInfo)7538 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
7539 m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
7540 m_currentTestSuccess = true;
7541 }
7542
Result(const Catch::AssertionResult & assertionResult)7543 virtual void Result( const Catch::AssertionResult& assertionResult ) {
7544 if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok )
7545 return;
7546
7547 if( assertionResult.hasExpression() ) {
7548 m_xml.startElement( "Expression" )
7549 .writeAttribute( "success", assertionResult.succeeded() )
7550 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
7551 .writeAttribute( "line", assertionResult.getSourceInfo().line );
7552
7553 m_xml.scopedElement( "Original" )
7554 .writeText( assertionResult.getExpression() );
7555 m_xml.scopedElement( "Expanded" )
7556 .writeText( assertionResult.getExpandedExpression() );
7557 m_currentTestSuccess &= assertionResult.succeeded();
7558 }
7559
7560 switch( assertionResult.getResultType() ) {
7561 case ResultWas::ThrewException:
7562 m_xml.scopedElement( "Exception" )
7563 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
7564 .writeAttribute( "line", assertionResult.getSourceInfo().line )
7565 .writeText( assertionResult.getMessage() );
7566 m_currentTestSuccess = false;
7567 break;
7568 case ResultWas::Info:
7569 m_xml.scopedElement( "Info" )
7570 .writeText( assertionResult.getMessage() );
7571 break;
7572 case ResultWas::Warning:
7573 m_xml.scopedElement( "Warning" )
7574 .writeText( assertionResult.getMessage() );
7575 break;
7576 case ResultWas::ExplicitFailure:
7577 m_xml.scopedElement( "Failure" )
7578 .writeText( assertionResult.getMessage() );
7579 m_currentTestSuccess = false;
7580 break;
7581 case ResultWas::Unknown:
7582 case ResultWas::Ok:
7583 case ResultWas::FailureBit:
7584 case ResultWas::ExpressionFailed:
7585 case ResultWas::Exception:
7586 case ResultWas::DidntThrowException:
7587 break;
7588 }
7589 if( assertionResult.hasExpression() )
7590 m_xml.endElement();
7591 }
7592
Aborted()7593 virtual void Aborted() {
7594 // !TBD
7595 }
7596
EndTestCase(const Catch::TestCaseInfo &,const Totals &,const std::string &,const std::string &)7597 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
7598 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
7599 m_xml.endElement();
7600 }
7601
7602 private:
7603 ReporterConfig m_config;
7604 bool m_currentTestSuccess;
7605 XmlWriter m_xml;
7606 int m_sectionDepth;
7607 };
7608
7609 } // end namespace Catch
7610
7611 // #included from: ../reporters/catch_reporter_junit.hpp
7612 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
7613
7614 #include <assert.h>
7615
7616 namespace Catch {
7617
7618 class JunitReporter : public CumulativeReporterBase {
7619 public:
JunitReporter(ReporterConfig const & _config)7620 JunitReporter( ReporterConfig const& _config )
7621 : CumulativeReporterBase( _config ),
7622 xml( _config.stream() )
7623 {}
7624
7625 ~JunitReporter();
7626
getDescription()7627 static std::string getDescription() {
7628 return "Reports test results in an XML format that looks like Ant's junitreport target";
7629 }
7630
noMatchingTestCases(std::string const &)7631 virtual void noMatchingTestCases( std::string const& /*spec*/ ) {}
7632
getPreferences() const7633 virtual ReporterPreferences getPreferences() const {
7634 ReporterPreferences prefs;
7635 prefs.shouldRedirectStdOut = true;
7636 return prefs;
7637 }
7638
testRunStarting(TestRunInfo const & runInfo)7639 virtual void testRunStarting( TestRunInfo const& runInfo ) {
7640 CumulativeReporterBase::testRunStarting( runInfo );
7641 xml.startElement( "testsuites" );
7642 }
7643
testGroupStarting(GroupInfo const & groupInfo)7644 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
7645 suiteTimer.start();
7646 stdOutForSuite.str("");
7647 stdErrForSuite.str("");
7648 unexpectedExceptions = 0;
7649 CumulativeReporterBase::testGroupStarting( groupInfo );
7650 }
7651
assertionEnded(AssertionStats const & assertionStats)7652 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
7653 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
7654 unexpectedExceptions++;
7655 return CumulativeReporterBase::assertionEnded( assertionStats );
7656 }
7657
testCaseEnded(TestCaseStats const & testCaseStats)7658 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
7659 stdOutForSuite << testCaseStats.stdOut;
7660 stdErrForSuite << testCaseStats.stdErr;
7661 CumulativeReporterBase::testCaseEnded( testCaseStats );
7662 }
7663
testGroupEnded(TestGroupStats const & testGroupStats)7664 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
7665 double suiteTime = suiteTimer.getElapsedSeconds();
7666 CumulativeReporterBase::testGroupEnded( testGroupStats );
7667 writeGroup( *m_testGroups.back(), suiteTime );
7668 }
7669
testRunEndedCumulative()7670 virtual void testRunEndedCumulative() {
7671 xml.endElement();
7672 }
7673
writeGroup(TestGroupNode const & groupNode,double suiteTime)7674 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
7675 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
7676 TestGroupStats const& stats = groupNode.value;
7677 xml.writeAttribute( "name", stats.groupInfo.name );
7678 xml.writeAttribute( "errors", unexpectedExceptions );
7679 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
7680 xml.writeAttribute( "tests", stats.totals.assertions.total() );
7681 xml.writeAttribute( "hostname", "tbd" ); // !TBD
7682 if( m_config->showDurations() == ShowDurations::Never )
7683 xml.writeAttribute( "time", "" );
7684 else
7685 xml.writeAttribute( "time", suiteTime );
7686 xml.writeAttribute( "timestamp", "tbd" ); // !TBD
7687
7688 // Write test cases
7689 for( TestGroupNode::ChildNodes::const_iterator
7690 it = groupNode.children.begin(), itEnd = groupNode.children.end();
7691 it != itEnd;
7692 ++it )
7693 writeTestCase( **it );
7694
7695 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
7696 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
7697 }
7698
writeTestCase(TestCaseNode const & testCaseNode)7699 void writeTestCase( TestCaseNode const& testCaseNode ) {
7700 TestCaseStats const& stats = testCaseNode.value;
7701
7702 // All test cases have exactly one section - which represents the
7703 // test case itself. That section may have 0-n nested sections
7704 assert( testCaseNode.children.size() == 1 );
7705 SectionNode const& rootSection = *testCaseNode.children.front();
7706
7707 std::string className = stats.testInfo.className;
7708
7709 if( className.empty() ) {
7710 if( rootSection.childSections.empty() )
7711 className = "global";
7712 }
7713 writeSection( className, "", rootSection );
7714 }
7715
writeSection(std::string const & className,std::string const & rootName,SectionNode const & sectionNode)7716 void writeSection( std::string const& className,
7717 std::string const& rootName,
7718 SectionNode const& sectionNode ) {
7719 std::string name = trim( sectionNode.stats.sectionInfo.name );
7720 if( !rootName.empty() )
7721 name = rootName + "/" + name;
7722
7723 if( !sectionNode.assertions.empty() ||
7724 !sectionNode.stdOut.empty() ||
7725 !sectionNode.stdErr.empty() ) {
7726 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
7727 if( className.empty() ) {
7728 xml.writeAttribute( "classname", name );
7729 xml.writeAttribute( "name", "root" );
7730 }
7731 else {
7732 xml.writeAttribute( "classname", className );
7733 xml.writeAttribute( "name", name );
7734 }
7735 xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) );
7736
7737 writeAssertions( sectionNode );
7738
7739 if( !sectionNode.stdOut.empty() )
7740 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
7741 if( !sectionNode.stdErr.empty() )
7742 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
7743 }
7744 for( SectionNode::ChildSections::const_iterator
7745 it = sectionNode.childSections.begin(),
7746 itEnd = sectionNode.childSections.end();
7747 it != itEnd;
7748 ++it )
7749 if( className.empty() )
7750 writeSection( name, "", **it );
7751 else
7752 writeSection( className, name, **it );
7753 }
7754
writeAssertions(SectionNode const & sectionNode)7755 void writeAssertions( SectionNode const& sectionNode ) {
7756 for( SectionNode::Assertions::const_iterator
7757 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
7758 it != itEnd;
7759 ++it )
7760 writeAssertion( *it );
7761 }
writeAssertion(AssertionStats const & stats)7762