CellModules
catch.hpp
Go to the documentation of this file.
1/*
2 * Catch v1.2.1
3 * Generated: 2015-06-30 18:23:27.961086
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#ifdef __clang__
17# pragma clang system_header
18#elif defined __GNUC__
19# pragma GCC system_header
20#endif
21
22// #included from: internal/catch_suppress_warnings.h
23
24#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
25
26#ifdef __clang__
27# ifdef __ICC // icpc defines the __clang__ macro
28# pragma warning(push)
29# pragma warning(disable: 161 1682)
30# else // __ICC
31# pragma clang diagnostic ignored "-Wglobal-constructors"
32# pragma clang diagnostic ignored "-Wvariadic-macros"
33# pragma clang diagnostic ignored "-Wc99-extensions"
34# pragma clang diagnostic ignored "-Wunused-variable"
35# pragma clang diagnostic push
36# pragma clang diagnostic ignored "-Wpadded"
37# pragma clang diagnostic ignored "-Wc++98-compat"
38# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
39# pragma clang diagnostic ignored "-Wswitch-enum"
40# endif
41#elif defined __GNUC__
42# pragma GCC diagnostic ignored "-Wvariadic-macros"
43# pragma GCC diagnostic ignored "-Wunused-variable"
44# pragma GCC diagnostic push
45# pragma GCC diagnostic ignored "-Wpadded"
46#endif
47
48#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
49# define CATCH_IMPL
50#endif
51
52#ifdef CATCH_IMPL
53# ifndef CLARA_CONFIG_MAIN
54# define CLARA_CONFIG_MAIN_NOT_DEFINED
55# define CLARA_CONFIG_MAIN
56# endif
57#endif
58
59// #included from: internal/catch_notimplemented_exception.h
60#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
61
62// #included from: catch_common.h
63#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
64
65#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
66#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
67#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
68
69#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
70#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
71
72#include <sstream>
73#include <stdexcept>
74#include <algorithm>
75
76// #included from: catch_compiler_capabilities.h
77#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
78
79// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
80// The following features are defined:
81//
82// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
83// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
84// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
85// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
86// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
87
88// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
89
90// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
91
92// In general each macro has a _NO_<feature name> form
93// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
94// Many features, at point of detection, define an _INTERNAL_ macro, so they
95// can be combined, en-mass, with the _NO_ forms later.
96
97// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
98
99#ifdef __clang__
100
101# if __has_feature(cxx_nullptr)
102# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
103# endif
104
105# if __has_feature(cxx_noexcept)
106# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
107# endif
108
109#endif // __clang__
110
112// Borland
113#ifdef __BORLANDC__
114
115#endif // __BORLANDC__
116
118// EDG
119#ifdef __EDG_VERSION__
120
121#endif // __EDG_VERSION__
122
124// Digital Mars
125#ifdef __DMC__
126
127#endif // __DMC__
128
130// GCC
131#ifdef __GNUC__
132
133#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
134# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
135#endif
136
137#endif // __GNUC__
138
140// Visual C++
141#ifdef _MSC_VER
142
143#if (_MSC_VER >= 1600)
144# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
145#endif
146
147#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
148#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
149#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
150#endif
151
152#endif // _MSC_VER
153
154// Use variadic macros if the compiler supports them
155#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
156 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
157 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
158 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
159
160#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
161
162#endif
163
165// C++ language feature support
166
167// catch all support for C++11
168#if (__cplusplus >= 201103L)
169
170# define CATCH_CPP11_OR_GREATER
171
172# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
173# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
174# endif
175
176# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
177# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
178# endif
179
180# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
181# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
182# endif
183
184# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
185# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
186# endif
187
188# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
189# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
190# endif
191
192# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
193# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
194# endif
195
196#endif // __cplusplus >= 201103L
197
198// Now set the actual defines based on the above + anything the user has configured
199#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
200# define CATCH_CONFIG_CPP11_NULLPTR
201#endif
202#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
203# define CATCH_CONFIG_CPP11_NOEXCEPT
204#endif
205#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
206# define CATCH_CONFIG_CPP11_GENERATED_METHODS
207#endif
208#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
209# define CATCH_CONFIG_CPP11_IS_ENUM
210#endif
211#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
212# define CATCH_CONFIG_CPP11_TUPLE
213#endif
214#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
215#define CATCH_CONFIG_VARIADIC_MACROS
216#endif
217
218// noexcept support:
219#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
220# define CATCH_NOEXCEPT noexcept
221# define CATCH_NOEXCEPT_IS(x) noexcept(x)
222#else
223# define CATCH_NOEXCEPT throw()
224# define CATCH_NOEXCEPT_IS(x)
225#endif
226
227namespace Catch {
228
230#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
231 NonCopyable( NonCopyable const& ) = delete;
232 NonCopyable( NonCopyable && ) = delete;
233 NonCopyable& operator = ( NonCopyable const& ) = delete;
234 NonCopyable& operator = ( NonCopyable && ) = delete;
235#else
236 NonCopyable( NonCopyable const& info );
238#endif
239
240 protected:
242 virtual ~NonCopyable();
243 };
244
245 class SafeBool {
246 public:
247 typedef void (SafeBool::*type)() const;
248
249 static type makeSafe( bool value ) {
250 return value ? &SafeBool::trueValue : 0;
251 }
252 private:
253 void trueValue() const {}
254 };
255
256 template<typename ContainerT>
257 inline void deleteAll( ContainerT& container ) {
258 typename ContainerT::const_iterator it = container.begin();
259 typename ContainerT::const_iterator itEnd = container.end();
260 for(; it != itEnd; ++it )
261 delete *it;
262 }
263 template<typename AssociativeContainerT>
264 inline void deleteAllValues( AssociativeContainerT& container ) {
265 typename AssociativeContainerT::const_iterator it = container.begin();
266 typename AssociativeContainerT::const_iterator itEnd = container.end();
267 for(; it != itEnd; ++it )
268 delete it->second;
269 }
270
271 bool startsWith( std::string const& s, std::string const& prefix );
272 bool endsWith( std::string const& s, std::string const& suffix );
273 bool contains( std::string const& s, std::string const& infix );
274 void toLowerInPlace( std::string& s );
275 std::string toLower( std::string const& s );
276 std::string trim( std::string const& str );
277 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
278
279 struct pluralise {
280 pluralise( std::size_t count, std::string const& label );
281
282 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
283
284 std::size_t m_count;
285 std::string m_label;
286 };
287
289
291 SourceLineInfo( char const* _file, std::size_t _line );
293# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
294 SourceLineInfo( SourceLineInfo && ) = default;
295 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
296 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
297# endif
298 bool empty() const;
299 bool operator == ( SourceLineInfo const& other ) const;
300 bool operator < ( SourceLineInfo const& other ) const;
301
302 std::string file;
303 std::size_t line;
304 };
305
306 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
307
308 // This is just here to avoid compiler warnings with macro constants and boolean literals
309 inline bool isTrue( bool value ){ return value; }
310 inline bool alwaysTrue() { return true; }
311 inline bool alwaysFalse() { return false; }
312
313 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
314
315 // Use this in variadic streaming macros to allow
316 // >> +StreamEndStop
317 // as well as
318 // >> stuff +StreamEndStop
320 std::string operator+() {
321 return std::string();
322 }
323 };
324 template<typename T>
325 T const& operator + ( T const& value, StreamEndStop ) {
326 return value;
327 }
328}
329
330#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
331#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
332
333#include <ostream>
334
335namespace Catch {
336
337 class NotImplementedException : public std::exception
338 {
339 public:
342
344
345 virtual const char* what() const CATCH_NOEXCEPT;
346
347 private:
348 std::string m_what;
350 };
351
352} // end namespace Catch
353
355#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
356
357// #included from: internal/catch_context.h
358#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
359
360// #included from: catch_interfaces_generators.h
361#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
362
363#include <string>
364
365namespace Catch {
366
369 virtual bool moveNext() = 0;
370 virtual std::size_t getCurrentIndex() const = 0;
371 };
372
375
376 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
377 virtual bool moveNext() = 0;
378 };
379
381
382} // end namespace Catch
383
384// #included from: catch_ptr.hpp
385#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
386
387#ifdef __clang__
388#pragma clang diagnostic push
389#pragma clang diagnostic ignored "-Wpadded"
390#endif
391
392namespace Catch {
393
394 // An intrusive reference counting smart pointer.
395 // T must implement addRef() and release() methods
396 // typically implementing the IShared interface
397 template<typename T>
398 class Ptr {
399 public:
400 Ptr() : m_p( NULL ){}
401 Ptr( T* p ) : m_p( p ){
402 if( m_p )
403 m_p->addRef();
404 }
405 Ptr( Ptr const& other ) : m_p( other.m_p ){
406 if( m_p )
407 m_p->addRef();
408 }
410 if( m_p )
411 m_p->release();
412 }
413 void reset() {
414 if( m_p )
415 m_p->release();
416 m_p = NULL;
417 }
418 Ptr& operator = ( T* p ){
419 Ptr temp( p );
420 swap( temp );
421 return *this;
422 }
423 Ptr& operator = ( Ptr const& other ){
424 Ptr temp( other );
425 swap( temp );
426 return *this;
427 }
428 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
429 T* get() { return m_p; }
430 const T* get() const{ return m_p; }
431 T& operator*() const { return *m_p; }
432 T* operator->() const { return m_p; }
433 bool operator !() const { return m_p == NULL; }
434 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
435
436 private:
437 T* m_p;
438 };
439
441 virtual ~IShared();
442 virtual void addRef() const = 0;
443 virtual void release() const = 0;
444 };
445
446 template<typename T = IShared>
447 struct SharedImpl : T {
448
449 SharedImpl() : m_rc( 0 ){}
450
451 virtual void addRef() const {
452 ++m_rc;
453 }
454 virtual void release() const {
455 if( --m_rc == 0 )
456 delete this;
457 }
458
459 mutable unsigned int m_rc;
460 };
461
462} // end namespace Catch
463
464#ifdef __clang__
465#pragma clang diagnostic pop
466#endif
467
468#include <memory>
469#include <vector>
470#include <stdlib.h>
471
472namespace Catch {
473
474 class TestCase;
475 class Stream;
476 struct IResultCapture;
477 struct IRunner;
478 struct IGeneratorsForTest;
479 struct IConfig;
480
481 struct IContext
482 {
483 virtual ~IContext();
484
486 virtual IRunner* getRunner() = 0;
487 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
489 virtual Ptr<IConfig const> getConfig() const = 0;
490 };
491
493 {
495 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
496 virtual void setRunner( IRunner* runner ) = 0;
497 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
498 };
499
503 Stream createStream( std::string const& streamName );
504
505}
506
507// #included from: internal/catch_test_registry.hpp
508#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
509
510// #included from: catch_interfaces_testcase.h
511#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
512
513#include <vector>
514
515namespace Catch {
516
517 class TestSpec;
518
520 virtual void invoke () const = 0;
521 protected:
522 virtual ~ITestCase();
523 };
524
525 class TestCase;
526 struct IConfig;
527
530 virtual std::vector<TestCase> const& getAllTests() const = 0;
531 virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const = 0;
532
533 };
534}
535
536namespace Catch {
537
538template<typename C>
539class MethodTestCase : public SharedImpl<ITestCase> {
540
541public:
542 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
543
544 virtual void invoke() const {
545 C obj;
546 (obj.*m_method)();
547 }
548
549private:
550 virtual ~MethodTestCase() {}
551
552 void (C::*m_method)();
553};
554
555typedef void(*TestFunction)();
556
558 NameAndDesc( const char* _name = "", const char* _description= "" )
559 : name( _name ), description( _description )
560 {}
561
562 const char* name;
563 const char* description;
564};
565
566struct AutoReg {
567
569 SourceLineInfo const& lineInfo,
570 NameAndDesc const& nameAndDesc );
571
572 template<typename C>
573 AutoReg( void (C::*method)(),
574 char const* className,
575 NameAndDesc const& nameAndDesc,
576 SourceLineInfo const& lineInfo ) {
577 registerTestCase( new MethodTestCase<C>( method ),
578 className,
579 nameAndDesc,
580 lineInfo );
581 }
582
584 char const* className,
585 NameAndDesc const& nameAndDesc,
586 SourceLineInfo const& lineInfo );
587
589
590private:
591 AutoReg( AutoReg const& );
592 void operator= ( AutoReg const& );
593};
594
595} // end namespace Catch
596
597#ifdef CATCH_CONFIG_VARIADIC_MACROS
599 #define INTERNAL_CATCH_TESTCASE( ... ) \
600 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
601 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__ ) ); }\
602 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
603
605 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
606 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
607
609 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
610 namespace{ \
611 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
612 void test(); \
613 }; \
614 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 ); \
615 } \
616 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
617
618#else
620 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
621 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
622 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 ) ); }\
623 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
624
626 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
627 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
628
630 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
631 namespace{ \
632 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
633 void test(); \
634 }; \
635 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 ); \
636 } \
637 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
638
639#endif
640
641// #included from: internal/catch_capture.hpp
642#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
643
644// #included from: catch_result_builder.h
645#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
646
647// #included from: catch_result_type.h
648#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
649
650namespace Catch {
651
652 // ResultWas::OfType enum
653 struct ResultWas { enum OfType {
654 Unknown = -1,
655 Ok = 0,
656 Info = 1,
657 Warning = 2,
658
659 FailureBit = 0x10,
660
661 ExpressionFailed = FailureBit | 1,
662 ExplicitFailure = FailureBit | 2,
663
664 Exception = 0x100 | FailureBit,
665
666 ThrewException = Exception | 1,
667 DidntThrowException = Exception | 2,
668
669 FatalErrorCondition = 0x200 | FailureBit
670
671 }; };
672
673 inline bool isOk( ResultWas::OfType resultType ) {
674 return ( resultType & ResultWas::FailureBit ) == 0;
675 }
676 inline bool isJustInfo( int flags ) {
677 return flags == ResultWas::Info;
678 }
679
680 // ResultDisposition::Flags enum
681 struct ResultDisposition { enum Flags {
682 Normal = 0x01,
683
684 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
685 FalseTest = 0x04, // Prefix expression with !
686 SuppressFail = 0x08 // Failures are reported but do not fail the test
687 }; };
688
690 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
691 }
692
693 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
694 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
695 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
696
697} // end namespace Catch
698
699// #included from: catch_assertionresult.h
700#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
701
702#include <string>
703
704namespace Catch {
705
707 {
709 AssertionInfo( std::string const& _macroName,
710 SourceLineInfo const& _lineInfo,
711 std::string const& _capturedExpression,
712 ResultDisposition::Flags _resultDisposition );
713
714 std::string macroName;
718 };
719
721 {
722 AssertionResultData() : resultType( ResultWas::Unknown ) {}
723
725 std::string message;
727 };
728
730 public:
734# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
735 AssertionResult( AssertionResult const& ) = default;
736 AssertionResult( AssertionResult && ) = default;
737 AssertionResult& operator = ( AssertionResult const& ) = default;
738 AssertionResult& operator = ( AssertionResult && ) = default;
739# endif
740
741 bool isOk() const;
742 bool succeeded() const;
744 bool hasExpression() const;
745 bool hasMessage() const;
746 std::string getExpression() const;
747 std::string getExpressionInMacro() const;
749 std::string getExpandedExpression() const;
750 std::string getMessage() const;
752 std::string getTestMacroName() const;
753
754 protected:
757 };
758
759} // end namespace Catch
760
761namespace Catch {
762
764
765 template<typename T> class ExpressionLhs;
766
767 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
768
772 oss << other.oss.str();
773 }
775 oss.str("");
776 oss << other.oss.str();
777 return *this;
778 }
779 std::ostringstream oss;
780 };
781
783 public:
784 ResultBuilder( char const* macroName,
785 SourceLineInfo const& lineInfo,
786 char const* capturedExpression,
787 ResultDisposition::Flags resultDisposition );
788
789 template<typename T>
790 ExpressionLhs<T const&> operator <= ( T const& operand );
791 ExpressionLhs<bool> operator <= ( bool value );
792
793 template<typename T>
794 ResultBuilder& operator << ( T const& value ) {
795 m_stream.oss << value;
796 return *this;
797 }
798
799 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
800 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
801
804 ResultBuilder& setLhs( std::string const& lhs );
805 ResultBuilder& setRhs( std::string const& rhs );
806 ResultBuilder& setOp( std::string const& op );
807
809
810 std::string reconstructExpression() const;
812
816 void react();
817 bool shouldDebugBreak() const;
818 bool allowThrows() const;
819
820 private:
824 ExprComponents() : testFalse( false ) {}
826 std::string lhs, rhs, op;
827 } m_exprComponents;
829
832 };
833
834} // namespace Catch
835
836// Include after due to circular dependency:
837// #included from: catch_expression_lhs.hpp
838#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
839
840// #included from: catch_evaluate.hpp
841#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
842
843#ifdef _MSC_VER
844#pragma warning(push)
845#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
846#endif
847
848#include <cstddef>
849
850namespace Catch {
851namespace Internal {
852
853 enum Operator {
860 };
861
862 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
863 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
864 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
865 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
866 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
867 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
868 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
869
870 template<typename T>
871 inline T& opCast(T const& t) { return const_cast<T&>(t); }
872
873// nullptr_t support based on pull request #154 from Konstantin Baumann
874#ifdef CATCH_CONFIG_CPP11_NULLPTR
875 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
876#endif // CATCH_CONFIG_CPP11_NULLPTR
877
878 // So the compare overloads can be operator agnostic we convey the operator as a template
879 // enum, which is used to specialise an Evaluator for doing the comparison.
880 template<typename T1, typename T2, Operator Op>
881 class Evaluator{};
882
883 template<typename T1, typename T2>
884 struct Evaluator<T1, T2, IsEqualTo> {
885 static bool evaluate( T1 const& lhs, T2 const& rhs) {
886 return opCast( lhs ) == opCast( rhs );
887 }
888 };
889 template<typename T1, typename T2>
890 struct Evaluator<T1, T2, IsNotEqualTo> {
891 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
892 return opCast( lhs ) != opCast( rhs );
893 }
894 };
895 template<typename T1, typename T2>
896 struct Evaluator<T1, T2, IsLessThan> {
897 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
898 return opCast( lhs ) < opCast( rhs );
899 }
900 };
901 template<typename T1, typename T2>
902 struct Evaluator<T1, T2, IsGreaterThan> {
903 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
904 return opCast( lhs ) > opCast( rhs );
905 }
906 };
907 template<typename T1, typename T2>
909 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
910 return opCast( lhs ) >= opCast( rhs );
911 }
912 };
913 template<typename T1, typename T2>
915 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
916 return opCast( lhs ) <= opCast( rhs );
917 }
918 };
919
920 template<Operator Op, typename T1, typename T2>
921 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
922 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
923 }
924
925 // This level of indirection allows us to specialise for integer types
926 // to avoid signed/ unsigned warnings
927
928 // "base" overload
929 template<Operator Op, typename T1, typename T2>
930 bool compare( T1 const& lhs, T2 const& rhs ) {
931 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
932 }
933
934 // unsigned X to int
935 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
936 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
937 }
938 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
939 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
940 }
941 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
942 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
943 }
944
945 // unsigned X to long
946 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
947 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
948 }
949 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
950 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
951 }
952 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
953 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
954 }
955
956 // int to unsigned X
957 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
958 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
959 }
960 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
961 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
962 }
963 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
964 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
965 }
966
967 // long to unsigned X
968 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
969 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
970 }
971 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
972 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
973 }
974 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
975 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
976 }
977
978 // pointer to long (when comparing against NULL)
979 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
980 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
981 }
982 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
983 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
984 }
985
986 // pointer to int (when comparing against NULL)
987 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
988 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
989 }
990 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
991 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
992 }
993
994#ifdef CATCH_CONFIG_CPP11_NULLPTR
995 // pointer to nullptr_t (when comparing against nullptr)
996 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
997 return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
998 }
999 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1000 return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
1001 }
1002#endif // CATCH_CONFIG_CPP11_NULLPTR
1003
1004} // end of namespace Internal
1005} // end of namespace Catch
1006
1007#ifdef _MSC_VER
1008#pragma warning(pop)
1009#endif
1010
1011// #included from: catch_tostring.h
1012#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1013
1014#include <sstream>
1015#include <iomanip>
1016#include <limits>
1017#include <vector>
1018#include <cstddef>
1019
1020#ifdef __OBJC__
1021// #included from: catch_objc_arc.hpp
1022#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1023
1024#import <Foundation/Foundation.h>
1025
1026#ifdef __has_feature
1027#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1028#else
1029#define CATCH_ARC_ENABLED 0
1030#endif
1031
1032void arcSafeRelease( NSObject* obj );
1033id performOptionalSelector( id obj, SEL sel );
1034
1035#if !CATCH_ARC_ENABLED
1036inline void arcSafeRelease( NSObject* obj ) {
1037 [obj release];
1038}
1039inline id performOptionalSelector( id obj, SEL sel ) {
1040 if( [obj respondsToSelector: sel] )
1041 return [obj performSelector: sel];
1042 return nil;
1043}
1044#define CATCH_UNSAFE_UNRETAINED
1045#define CATCH_ARC_STRONG
1046#else
1047inline void arcSafeRelease( NSObject* ){}
1048inline id performOptionalSelector( id obj, SEL sel ) {
1049#ifdef __clang__
1050#pragma clang diagnostic push
1051#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1052#endif
1053 if( [obj respondsToSelector: sel] )
1054 return [obj performSelector: sel];
1055#ifdef __clang__
1056#pragma clang diagnostic pop
1057#endif
1058 return nil;
1059}
1060#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1061#define CATCH_ARC_STRONG __strong
1062#endif
1063
1064#endif
1065
1066#ifdef CATCH_CONFIG_CPP11_TUPLE
1067#include <tuple>
1068#endif
1069
1070#ifdef CATCH_CONFIG_CPP11_IS_ENUM
1071#include <type_traits>
1072#endif
1073
1074namespace Catch {
1075
1076// Why we're here.
1077template<typename T>
1078std::string toString( T const& value );
1079
1080// Built in overloads
1081
1082std::string toString( std::string const& value );
1083std::string toString( std::wstring const& value );
1084std::string toString( const char* const value );
1085std::string toString( char* const value );
1086std::string toString( const wchar_t* const value );
1087std::string toString( wchar_t* const value );
1088std::string toString( int value );
1089std::string toString( unsigned long value );
1090std::string toString( unsigned int value );
1091std::string toString( const double value );
1092std::string toString( const float value );
1093std::string toString( bool value );
1094std::string toString( char value );
1095std::string toString( signed char value );
1096std::string toString( unsigned char value );
1097
1098#ifdef CATCH_CONFIG_CPP11_NULLPTR
1099std::string toString( std::nullptr_t );
1100#endif
1101
1102#ifdef __OBJC__
1103 std::string toString( NSString const * const& nsstring );
1104 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1105 std::string toString( NSObject* const& nsObject );
1106#endif
1107
1108namespace Detail {
1109
1110 extern std::string unprintableString;
1111
1112 struct BorgType {
1113 template<typename T> BorgType( T const& );
1114 };
1115
1116 struct TrueType { char sizer[1]; };
1117 struct FalseType { char sizer[2]; };
1118
1119 TrueType& testStreamable( std::ostream& );
1121
1122 FalseType operator<<( std::ostream const&, BorgType const& );
1123
1124 template<typename T>
1126 static std::ostream &s;
1127 static T const&t;
1128 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1129 };
1130
1131#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1132 template<typename T,
1133 bool IsEnum = std::is_enum<T>::value
1134 >
1135 struct EnumStringMaker
1136 {
1137 static std::string convert( T const& ) { return unprintableString; }
1138 };
1139
1140 template<typename T>
1141 struct EnumStringMaker<T,true>
1142 {
1143 static std::string convert( T const& v )
1144 {
1146 static_cast<typename std::underlying_type<T>::type>(v)
1147 );
1148 }
1149 };
1150#endif
1151 template<bool C>
1153#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1154 template<typename T>
1155 static std::string convert( T const& v )
1156 {
1157 return EnumStringMaker<T>::convert( v );
1158 }
1159#else
1160 template<typename T>
1161 static std::string convert( T const& ) { return unprintableString; }
1162#endif
1163 };
1164
1165 template<>
1166 struct StringMakerBase<true> {
1167 template<typename T>
1168 static std::string convert( T const& _value ) {
1169 std::ostringstream oss;
1170 oss << _value;
1171 return oss.str();
1172 }
1173 };
1174
1175 std::string rawMemoryToString( const void *object, std::size_t size );
1176
1177 template<typename T>
1178 inline std::string rawMemoryToString( const T& object ) {
1179 return rawMemoryToString( &object, sizeof(object) );
1180 }
1181
1182} // end namespace Detail
1183
1184template<typename T>
1186 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1187
1188template<typename T>
1189struct StringMaker<T*> {
1190 template<typename U>
1191 static std::string convert( U* p ) {
1192 if( !p )
1193 return INTERNAL_CATCH_STRINGIFY( NULL );
1194 else
1195 return Detail::rawMemoryToString( p );
1196 }
1197};
1198
1199template<typename R, typename C>
1200struct StringMaker<R C::*> {
1201 static std::string convert( R C::* p ) {
1202 if( !p )
1203 return INTERNAL_CATCH_STRINGIFY( NULL );
1204 else
1205 return Detail::rawMemoryToString( p );
1206 }
1207};
1208
1209namespace Detail {
1210 template<typename InputIterator>
1211 std::string rangeToString( InputIterator first, InputIterator last );
1212}
1213
1214//template<typename T, typename Allocator>
1215//struct StringMaker<std::vector<T, Allocator> > {
1216// static std::string convert( std::vector<T,Allocator> const& v ) {
1217// return Detail::rangeToString( v.begin(), v.end() );
1218// }
1219//};
1220
1221template<typename T, typename Allocator>
1222std::string toString( std::vector<T,Allocator> const& v ) {
1223 return Detail::rangeToString( v.begin(), v.end() );
1224}
1225
1226#ifdef CATCH_CONFIG_CPP11_TUPLE
1227
1228// toString for tuples
1229namespace TupleDetail {
1230 template<
1231 typename Tuple,
1232 std::size_t N = 0,
1233 bool = (N < std::tuple_size<Tuple>::value)
1234 >
1235 struct ElementPrinter {
1236 static void print( const Tuple& tuple, std::ostream& os )
1237 {
1238 os << ( N ? ", " : " " )
1239 << Catch::toString(std::get<N>(tuple));
1240 ElementPrinter<Tuple,N+1>::print(tuple,os);
1241 }
1242 };
1243
1244 template<
1245 typename Tuple,
1246 std::size_t N
1247 >
1248 struct ElementPrinter<Tuple,N,false> {
1249 static void print( const Tuple&, std::ostream& ) {}
1250 };
1251
1252}
1253
1254template<typename ...Types>
1255struct StringMaker<std::tuple<Types...>> {
1256
1257 static std::string convert( const std::tuple<Types...>& tuple )
1258 {
1259 std::ostringstream os;
1260 os << '{';
1261 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1262 os << " }";
1263 return os.str();
1264 }
1265};
1266#endif // CATCH_CONFIG_CPP11_TUPLE
1267
1268namespace Detail {
1269 template<typename T>
1270 std::string makeString( T const& value ) {
1271 return StringMaker<T>::convert( value );
1272 }
1273} // end namespace Detail
1274
1282template<typename T>
1283std::string toString( T const& value ) {
1284 return StringMaker<T>::convert( value );
1285}
1286
1287 namespace Detail {
1288 template<typename InputIterator>
1289 std::string rangeToString( InputIterator first, InputIterator last ) {
1290 std::ostringstream oss;
1291 oss << "{ ";
1292 if( first != last ) {
1293 oss << Catch::toString( *first );
1294 for( ++first ; first != last ; ++first )
1295 oss << ", " << Catch::toString( *first );
1296 }
1297 oss << " }";
1298 return oss.str();
1299 }
1300}
1301
1302} // end namespace Catch
1303
1304namespace Catch {
1305
1306// Wraps the LHS of an expression and captures the operator and RHS (if any) -
1307// wrapping them all in a ResultBuilder object
1308template<typename T>
1310 ExpressionLhs& operator = ( ExpressionLhs const& );
1311# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1312 ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
1313# endif
1314
1315public:
1316 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
1317# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1318 ExpressionLhs( ExpressionLhs const& ) = default;
1319 ExpressionLhs( ExpressionLhs && ) = default;
1320# endif
1321
1322 template<typename RhsT>
1323 ResultBuilder& operator == ( RhsT const& rhs ) {
1324 return captureExpression<Internal::IsEqualTo>( rhs );
1325 }
1326
1327 template<typename RhsT>
1328 ResultBuilder& operator != ( RhsT const& rhs ) {
1329 return captureExpression<Internal::IsNotEqualTo>( rhs );
1330 }
1331
1332 template<typename RhsT>
1333 ResultBuilder& operator < ( RhsT const& rhs ) {
1334 return captureExpression<Internal::IsLessThan>( rhs );
1335 }
1336
1337 template<typename RhsT>
1338 ResultBuilder& operator > ( RhsT const& rhs ) {
1339 return captureExpression<Internal::IsGreaterThan>( rhs );
1340 }
1341
1342 template<typename RhsT>
1343 ResultBuilder& operator <= ( RhsT const& rhs ) {
1344 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1345 }
1346
1347 template<typename RhsT>
1348 ResultBuilder& operator >= ( RhsT const& rhs ) {
1349 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1350 }
1351
1353 return captureExpression<Internal::IsEqualTo>( rhs );
1354 }
1355
1357 return captureExpression<Internal::IsNotEqualTo>( rhs );
1358 }
1359
1361 bool value = m_lhs ? true : false;
1362 m_rb
1363 .setLhs( Catch::toString( value ) )
1364 .setResultType( value )
1365 .endExpression();
1366 }
1367
1368 // Only simple binary expressions are allowed on the LHS.
1369 // If more complex compositions are required then place the sub expression in parentheses
1370 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1371 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1372 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1373 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
1374 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1375 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1376
1377private:
1378 template<Internal::Operator Op, typename RhsT>
1379 ResultBuilder& captureExpression( RhsT const& rhs ) {
1380 return m_rb
1381 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1382 .setLhs( Catch::toString( m_lhs ) )
1383 .setRhs( Catch::toString( rhs ) )
1385 }
1386
1387private:
1390};
1391
1392} // end namespace Catch
1393
1394
1395namespace Catch {
1396
1397 template<typename T>
1398 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
1399 return ExpressionLhs<T const&>( *this, operand );
1400 }
1401
1402 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
1403 return ExpressionLhs<bool>( *this, value );
1404 }
1405
1406} // namespace Catch
1407
1408// #included from: catch_message.h
1409#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1410
1411#include <string>
1412
1413namespace Catch {
1414
1416 MessageInfo( std::string const& _macroName,
1417 SourceLineInfo const& _lineInfo,
1418 ResultWas::OfType _type );
1419
1420 std::string macroName;
1423 std::string message;
1424 unsigned int sequence;
1425
1426 bool operator == ( MessageInfo const& other ) const {
1427 return sequence == other.sequence;
1428 }
1429 bool operator < ( MessageInfo const& other ) const {
1430 return sequence < other.sequence;
1431 }
1432 private:
1433 static unsigned int globalCount;
1434 };
1435
1437 MessageBuilder( std::string const& macroName,
1438 SourceLineInfo const& lineInfo,
1439 ResultWas::OfType type )
1440 : m_info( macroName, lineInfo, type )
1441 {}
1442
1443 template<typename T>
1444 MessageBuilder& operator << ( T const& value ) {
1445 m_stream << value;
1446 return *this;
1447 }
1448
1450 std::ostringstream m_stream;
1451 };
1452
1454 public:
1458
1460 };
1461
1462} // end namespace Catch
1463
1464// #included from: catch_interfaces_capture.h
1465#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1466
1467#include <string>
1468
1469namespace Catch {
1470
1471 class TestCase;
1472 class AssertionResult;
1473 struct AssertionInfo;
1474 struct SectionInfo;
1475 struct MessageInfo;
1476 class ScopedMessageBuilder;
1477 struct Counts;
1478
1480
1482
1483 virtual void assertionEnded( AssertionResult const& result ) = 0;
1484 virtual bool sectionStarted( SectionInfo const& sectionInfo,
1485 Counts& assertions ) = 0;
1486 virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
1487 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1488 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1489
1490 virtual std::string getCurrentTestName() const = 0;
1491 virtual const AssertionResult* getLastResult() const = 0;
1492
1493 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
1494 };
1495
1497}
1498
1499// #included from: catch_debugger.h
1500#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1501
1502// #included from: catch_platform.h
1503#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1504
1505#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1506#define CATCH_PLATFORM_MAC
1507#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1508#define CATCH_PLATFORM_IPHONE
1509#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1510#define CATCH_PLATFORM_WINDOWS
1511#endif
1512
1513#include <string>
1514
1515namespace Catch{
1516
1518 void writeToDebugConsole( std::string const& text );
1519}
1520
1521#ifdef CATCH_PLATFORM_MAC
1522
1523 // The following code snippet based on:
1524 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1525 #ifdef DEBUG
1526 #if defined(__ppc64__) || defined(__ppc__)
1527 #define CATCH_BREAK_INTO_DEBUGGER() \
1528 if( Catch::isDebuggerActive() ) { \
1529 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1530 : : : "memory","r0","r3","r4" ); \
1531 }
1532 #else
1533 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1534 #endif
1535 #endif
1536
1537#elif defined(_MSC_VER)
1538 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
1539#elif defined(__MINGW32__)
1540 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1541 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
1542#endif
1543
1544#ifndef CATCH_BREAK_INTO_DEBUGGER
1545#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
1546#endif
1547
1548// #included from: catch_interfaces_runner.h
1549#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
1550
1551namespace Catch {
1552 class TestCase;
1553
1554 struct IRunner {
1555 virtual ~IRunner();
1556 virtual bool aborting() const = 0;
1557 };
1558}
1559
1561// In the event of a failure works out if the debugger needs to be invoked
1562// and/or an exception thrown and takes appropriate action.
1563// This needs to be done as a macro so the debugger will stop in the user
1564// source code rather than in Catch library code
1565#define INTERNAL_CATCH_REACT( resultBuilder ) \
1566 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
1567 resultBuilder.react();
1568
1570#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
1571 do { \
1572 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1573 try { \
1574 ( __catchResult <= expr ).endExpression(); \
1575 } \
1576 catch( ... ) { \
1577 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
1578 } \
1579 INTERNAL_CATCH_REACT( __catchResult ) \
1580 } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
1581
1583#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
1584 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1585 if( Catch::getResultCapture().getLastResult()->succeeded() )
1586
1588#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
1589 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1590 if( !Catch::getResultCapture().getLastResult()->succeeded() )
1591
1593#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
1594 do { \
1595 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1596 try { \
1597 expr; \
1598 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1599 } \
1600 catch( ... ) { \
1601 __catchResult.useActiveException( resultDisposition ); \
1602 } \
1603 INTERNAL_CATCH_REACT( __catchResult ) \
1604 } while( Catch::alwaysFalse() )
1605
1607#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \
1608 do { \
1609 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1610 if( __catchResult.allowThrows() ) \
1611 try { \
1612 expr; \
1613 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
1614 } \
1615 catch( ... ) { \
1616 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1617 } \
1618 else \
1619 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1620 INTERNAL_CATCH_REACT( __catchResult ) \
1621 } while( Catch::alwaysFalse() )
1622
1624#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
1625 do { \
1626 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1627 if( __catchResult.allowThrows() ) \
1628 try { \
1629 expr; \
1630 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
1631 } \
1632 catch( exceptionType ) { \
1633 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1634 } \
1635 catch( ... ) { \
1636 __catchResult.useActiveException( resultDisposition ); \
1637 } \
1638 else \
1639 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1640 INTERNAL_CATCH_REACT( __catchResult ) \
1641 } while( Catch::alwaysFalse() )
1642
1644#ifdef CATCH_CONFIG_VARIADIC_MACROS
1645 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
1646 do { \
1647 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1648 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
1649 __catchResult.captureResult( messageType ); \
1650 INTERNAL_CATCH_REACT( __catchResult ) \
1651 } while( Catch::alwaysFalse() )
1652#else
1653 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
1654 do { \
1655 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1656 __catchResult << log + ::Catch::StreamEndStop(); \
1657 __catchResult.captureResult( messageType ); \
1658 INTERNAL_CATCH_REACT( __catchResult ) \
1659 } while( Catch::alwaysFalse() )
1660#endif
1661
1663#define INTERNAL_CATCH_INFO( log, macroName ) \
1664 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
1665
1667#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
1668 do { \
1669 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
1670 try { \
1671 std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
1672 __catchResult \
1673 .setLhs( Catch::toString( arg ) ) \
1674 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
1675 .setOp( "matches" ) \
1676 .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
1677 __catchResult.captureExpression(); \
1678 } catch( ... ) { \
1679 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
1680 } \
1681 INTERNAL_CATCH_REACT( __catchResult ) \
1682 } while( Catch::alwaysFalse() )
1683
1684// #included from: internal/catch_section.h
1685#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
1686
1687// #included from: catch_section_info.h
1688#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
1689
1690namespace Catch {
1691
1694 ( SourceLineInfo const& _lineInfo,
1695 std::string const& _name,
1696 std::string const& _description = std::string() );
1697
1698 std::string name;
1699 std::string description;
1701 };
1702
1703} // end namespace Catch
1704
1705// #included from: catch_totals.hpp
1706#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1707
1708#include <cstddef>
1709
1710namespace Catch {
1711
1712 struct Counts {
1713 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
1714
1715 Counts operator - ( Counts const& other ) const {
1716 Counts diff;
1717 diff.passed = passed - other.passed;
1718 diff.failed = failed - other.failed;
1719 diff.failedButOk = failedButOk - other.failedButOk;
1720 return diff;
1721 }
1722 Counts& operator += ( Counts const& other ) {
1723 passed += other.passed;
1724 failed += other.failed;
1725 failedButOk += other.failedButOk;
1726 return *this;
1727 }
1728
1729 std::size_t total() const {
1730 return passed + failed + failedButOk;
1731 }
1732 bool allPassed() const {
1733 return failed == 0 && failedButOk == 0;
1734 }
1735 bool allOk() const {
1736 return failed == 0;
1737 }
1738
1739 std::size_t passed;
1740 std::size_t failed;
1741 std::size_t failedButOk;
1742 };
1743
1744 struct Totals {
1745
1746 Totals operator - ( Totals const& other ) const {
1747 Totals diff;
1748 diff.assertions = assertions - other.assertions;
1749 diff.testCases = testCases - other.testCases;
1750 return diff;
1751 }
1752
1753 Totals delta( Totals const& prevTotals ) const {
1754 Totals diff = *this - prevTotals;
1755 if( diff.assertions.failed > 0 )
1756 ++diff.testCases.failed;
1757 else if( diff.assertions.failedButOk > 0 )
1758 ++diff.testCases.failedButOk;
1759 else
1760 ++diff.testCases.passed;
1761 return diff;
1762 }
1763
1764 Totals& operator += ( Totals const& other ) {
1765 assertions += other.assertions;
1766 testCases += other.testCases;
1767 return *this;
1768 }
1769
1772 };
1773}
1774
1775// #included from: catch_timer.h
1776#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
1777
1778#ifdef CATCH_PLATFORM_WINDOWS
1779typedef unsigned long long uint64_t;
1780#else
1781#include <stdint.h>
1782#endif
1783
1784namespace Catch {
1785
1786 class Timer {
1787 public:
1788 Timer() : m_ticks( 0 ) {}
1789 void start();
1790 unsigned int getElapsedMicroseconds() const;
1791 unsigned int getElapsedMilliseconds() const;
1792 double getElapsedSeconds() const;
1793
1794 private:
1795 uint64_t m_ticks;
1796 };
1797
1798} // namespace Catch
1799
1800#include <string>
1801
1802namespace Catch {
1803
1805 public:
1806 Section( SectionInfo const& info );
1808
1809 // This indicates whether the section should be executed or not
1810 operator bool() const;
1811
1812 private:
1814
1815 std::string m_name;
1819 };
1820
1821} // end namespace Catch
1822
1823#ifdef CATCH_CONFIG_VARIADIC_MACROS
1824 #define INTERNAL_CATCH_SECTION( ... ) \
1825 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
1826#else
1827 #define INTERNAL_CATCH_SECTION( name, desc ) \
1828 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
1829#endif
1830
1831// #included from: internal/catch_generators.hpp
1832#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1833
1834#include <iterator>
1835#include <vector>
1836#include <string>
1837#include <stdlib.h>
1838
1839namespace Catch {
1840
1841template<typename T>
1843 virtual ~IGenerator() {}
1844 virtual T getValue( std::size_t index ) const = 0;
1845 virtual std::size_t size () const = 0;
1846};
1847
1848template<typename T>
1849class BetweenGenerator : public IGenerator<T> {
1850public:
1851 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
1852
1853 virtual T getValue( std::size_t index ) const {
1854 return m_from+static_cast<int>( index );
1855 }
1856
1857 virtual std::size_t size() const {
1858 return static_cast<std::size_t>( 1+m_to-m_from );
1859 }
1860
1861private:
1862
1865};
1866
1867template<typename T>
1868class ValuesGenerator : public IGenerator<T> {
1869public:
1871
1872 void add( T value ) {
1873 m_values.push_back( value );
1874 }
1875
1876 virtual T getValue( std::size_t index ) const {
1877 return m_values[index];
1878 }
1879
1880 virtual std::size_t size() const {
1881 return m_values.size();
1882 }
1883
1884private:
1886};
1887
1888template<typename T>
1890public:
1891 CompositeGenerator() : m_totalSize( 0 ) {}
1892
1893 // *** Move semantics, similar to auto_ptr ***
1895 : m_fileInfo( other.m_fileInfo ),
1896 m_totalSize( 0 )
1897 {
1898 move( other );
1899 }
1900
1901 CompositeGenerator& setFileInfo( const char* fileInfo ) {
1902 m_fileInfo = fileInfo;
1903 return *this;
1904 }
1905
1907 deleteAll( m_composed );
1908 }
1909
1910 operator T () const {
1911 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
1912
1913 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1914 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1915 for( size_t index = 0; it != itEnd; ++it )
1916 {
1917 const IGenerator<T>* generator = *it;
1918 if( overallIndex >= index && overallIndex < index + generator->size() )
1919 {
1920 return generator->getValue( overallIndex-index );
1921 }
1922 index += generator->size();
1923 }
1924 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
1925 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
1926 }
1927
1928 void add( const IGenerator<T>* generator ) {
1929 m_totalSize += generator->size();
1930 m_composed.push_back( generator );
1931 }
1932
1934 move( other );
1935 return *this;
1936 }
1937
1939 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1940 valuesGen->add( value );
1941 add( valuesGen );
1942 return *this;
1943 }
1944
1945private:
1946
1947 void move( CompositeGenerator& other ) {
1948 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1949 m_totalSize += other.m_totalSize;
1950 other.m_composed.clear();
1951 }
1952
1954 std::string m_fileInfo;
1956};
1957
1958namespace Generators
1959{
1960 template<typename T>
1962 CompositeGenerator<T> generators;
1963 generators.add( new BetweenGenerator<T>( from, to ) );
1964 return generators;
1965 }
1966
1967 template<typename T>
1968 CompositeGenerator<T> values( T val1, T val2 ) {
1969 CompositeGenerator<T> generators;
1970 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1971 valuesGen->add( val1 );
1972 valuesGen->add( val2 );
1973 generators.add( valuesGen );
1974 return generators;
1975 }
1976
1977 template<typename T>
1978 CompositeGenerator<T> values( T val1, T val2, T val3 ){
1979 CompositeGenerator<T> generators;
1980 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1981 valuesGen->add( val1 );
1982 valuesGen->add( val2 );
1983 valuesGen->add( val3 );
1984 generators.add( valuesGen );
1985 return generators;
1986 }
1987
1988 template<typename T>
1989 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
1990 CompositeGenerator<T> generators;
1991 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1992 valuesGen->add( val1 );
1993 valuesGen->add( val2 );
1994 valuesGen->add( val3 );
1995 valuesGen->add( val4 );
1996 generators.add( valuesGen );
1997 return generators;
1998 }
1999
2000} // end namespace Generators
2001
2002using namespace Generators;
2003
2004} // end namespace Catch
2005
2006#define INTERNAL_CATCH_LINESTR2( line ) #line
2007#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2008
2009#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2010
2011// #included from: internal/catch_interfaces_exception.h
2012#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2013
2014#include <string>
2015// #included from: catch_interfaces_registry_hub.h
2016#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2017
2018#include <string>
2019
2020namespace Catch {
2021
2022 class TestCase;
2023 struct ITestCaseRegistry;
2024 struct IExceptionTranslatorRegistry;
2025 struct IExceptionTranslator;
2026 struct IReporterRegistry;
2027 struct IReporterFactory;
2028
2030 virtual ~IRegistryHub();
2031
2032 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2033 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2035 };
2036
2039 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
2040 virtual void registerTest( TestCase const& testInfo ) = 0;
2041 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2042 };
2043
2046 void cleanUp();
2048
2049}
2050
2051
2052namespace Catch {
2053
2054 typedef std::string(*exceptionTranslateFunction)();
2055
2058 virtual std::string translate() const = 0;
2059 };
2060
2063
2064 virtual std::string translateActiveException() const = 0;
2065 };
2066
2068 template<typename T>
2070 public:
2071
2072 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2073 : m_translateFunction( translateFunction )
2074 {}
2075
2076 virtual std::string translate() const {
2077 try {
2078 throw;
2079 }
2080 catch( T& ex ) {
2081 return m_translateFunction( ex );
2082 }
2083 }
2084
2085 protected:
2086 std::string(*m_translateFunction)( T& );
2087 };
2088
2089 public:
2090 template<typename T>
2091 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2093 ( new ExceptionTranslator<T>( translateFunction ) );
2094 }
2095 };
2096}
2097
2099#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2100 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2101 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2102 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2103
2104// #included from: internal/catch_approx.hpp
2105#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2106
2107#include <cmath>
2108#include <limits>
2109
2110namespace Catch {
2111namespace Detail {
2112
2113 class Approx {
2114 public:
2115 explicit Approx ( double value )
2116 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2117 m_scale( 1.0 ),
2118 m_value( value )
2119 {}
2120
2121 Approx( Approx const& other )
2122 : m_epsilon( other.m_epsilon ),
2123 m_scale( other.m_scale ),
2124 m_value( other.m_value )
2125 {}
2126
2127 static Approx custom() {
2128 return Approx( 0 );
2129 }
2130
2131 Approx operator()( double value ) {
2132 Approx approx( value );
2133 approx.epsilon( m_epsilon );
2134 approx.scale( m_scale );
2135 return approx;
2136 }
2137
2138 friend bool operator == ( double lhs, Approx const& rhs ) {
2139 // Thanks to Richard Harris for his help refining this formula
2140 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2141 }
2142
2143 friend bool operator == ( Approx const& lhs, double rhs ) {
2144 return operator==( rhs, lhs );
2145 }
2146
2147 friend bool operator != ( double lhs, Approx const& rhs ) {
2148 return !operator==( lhs, rhs );
2149 }
2150
2151 friend bool operator != ( Approx const& lhs, double rhs ) {
2152 return !operator==( rhs, lhs );
2153 }
2154
2155 Approx& epsilon( double newEpsilon ) {
2156 m_epsilon = newEpsilon;
2157 return *this;
2158 }
2159
2160 Approx& scale( double newScale ) {
2161 m_scale = newScale;
2162 return *this;
2163 }
2164
2165 std::string toString() const {
2166 std::ostringstream oss;
2167 oss << "Approx( " << Catch::toString( m_value ) << " )";
2168 return oss.str();
2169 }
2170
2171 private:
2173 double m_scale;
2174 double m_value;
2175 };
2176}
2177
2178template<>
2179inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
2180 return value.toString();
2181}
2182
2183} // end namespace Catch
2184
2185// #included from: internal/catch_matchers.hpp
2186#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2187
2188namespace Catch {
2189namespace Matchers {
2190 namespace Impl {
2191
2192 template<typename ExpressionT>
2193 struct Matcher : SharedImpl<IShared>
2194 {
2195 typedef ExpressionT ExpressionType;
2196
2197 virtual ~Matcher() {}
2198 virtual Ptr<Matcher> clone() const = 0;
2199 virtual bool match( ExpressionT const& expr ) const = 0;
2200 virtual std::string toString() const = 0;
2201 };
2202
2203 template<typename DerivedT, typename ExpressionT>
2204 struct MatcherImpl : Matcher<ExpressionT> {
2205
2207 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
2208 }
2209 };
2210
2211 namespace Generic {
2212
2213 template<typename ExpressionT>
2214 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
2215 public:
2216
2218 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
2219
2220 AllOf& add( Matcher<ExpressionT> const& matcher ) {
2221 m_matchers.push_back( matcher.clone() );
2222 return *this;
2223 }
2224 virtual bool match( ExpressionT const& expr ) const
2225 {
2226 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2227 if( !m_matchers[i]->match( expr ) )
2228 return false;
2229 return true;
2230 }
2231 virtual std::string toString() const {
2232 std::ostringstream oss;
2233 oss << "( ";
2234 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2235 if( i != 0 )
2236 oss << " and ";
2237 oss << m_matchers[i]->toString();
2238 }
2239 oss << " )";
2240 return oss.str();
2241 }
2242
2243 private:
2245 };
2246
2247 template<typename ExpressionT>
2248 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
2249 public:
2250
2252 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
2253
2254 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
2255 m_matchers.push_back( matcher.clone() );
2256 return *this;
2257 }
2258 virtual bool match( ExpressionT const& expr ) const
2259 {
2260 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2261 if( m_matchers[i]->match( expr ) )
2262 return true;
2263 return false;
2264 }
2265 virtual std::string toString() const {
2266 std::ostringstream oss;
2267 oss << "( ";
2268 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2269 if( i != 0 )
2270 oss << " or ";
2271 oss << m_matchers[i]->toString();
2272 }
2273 oss << " )";
2274 return oss.str();
2275 }
2276
2277 private:
2279 };
2280
2281 }
2282
2283 namespace StdString {
2284
2285 inline std::string makeString( std::string const& str ) { return str; }
2286 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
2287
2288 struct Equals : MatcherImpl<Equals, std::string> {
2289 Equals( std::string const& str ) : m_str( str ){}
2290 Equals( Equals const& other ) : m_str( other.m_str ){}
2291
2292 virtual ~Equals();
2293
2294 virtual bool match( std::string const& expr ) const {
2295 return m_str == expr;
2296 }
2297 virtual std::string toString() const {
2298 return "equals: \"" + m_str + "\"";
2299 }
2300
2301 std::string m_str;
2302 };
2303
2304 struct Contains : MatcherImpl<Contains, std::string> {
2305 Contains( std::string const& substr ) : m_substr( substr ){}
2306 Contains( Contains const& other ) : m_substr( other.m_substr ){}
2307
2308 virtual ~Contains();
2309
2310 virtual bool match( std::string const& expr ) const {
2311 return expr.find( m_substr ) != std::string::npos;
2312 }
2313 virtual std::string toString() const {
2314 return "contains: \"" + m_substr + "\"";
2315 }
2316
2317 std::string m_substr;
2318 };
2319
2320 struct StartsWith : MatcherImpl<StartsWith, std::string> {
2321 StartsWith( std::string const& substr ) : m_substr( substr ){}
2322 StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
2323
2324 virtual ~StartsWith();
2325
2326 virtual bool match( std::string const& expr ) const {
2327 return expr.find( m_substr ) == 0;
2328 }
2329 virtual std::string toString() const {
2330 return "starts with: \"" + m_substr + "\"";
2331 }
2332
2333 std::string m_substr;
2334 };
2335
2336 struct EndsWith : MatcherImpl<EndsWith, std::string> {
2337 EndsWith( std::string const& substr ) : m_substr( substr ){}
2338 EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
2339
2340 virtual ~EndsWith();
2341
2342 virtual bool match( std::string const& expr ) const {
2343 return expr.find( m_substr ) == expr.size() - m_substr.size();
2344 }
2345 virtual std::string toString() const {
2346 return "ends with: \"" + m_substr + "\"";
2347 }
2348
2349 std::string m_substr;
2350 };
2351 } // namespace StdString
2352 } // namespace Impl
2353
2354 // The following functions create the actual matcher objects.
2355 // This allows the types to be inferred
2356 template<typename ExpressionT>
2358 Impl::Matcher<ExpressionT> const& m2 ) {
2359 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
2360 }
2361 template<typename ExpressionT>
2364 Impl::Matcher<ExpressionT> const& m3 ) {
2365 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2366 }
2367 template<typename ExpressionT>
2369 Impl::Matcher<ExpressionT> const& m2 ) {
2370 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
2371 }
2372 template<typename ExpressionT>
2375 Impl::Matcher<ExpressionT> const& m3 ) {
2376 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2377 }
2378
2379 inline Impl::StdString::Equals Equals( std::string const& str ) {
2380 return Impl::StdString::Equals( str );
2381 }
2382 inline Impl::StdString::Equals Equals( const char* str ) {
2384 }
2385 inline Impl::StdString::Contains Contains( std::string const& substr ) {
2386 return Impl::StdString::Contains( substr );
2387 }
2388 inline Impl::StdString::Contains Contains( const char* substr ) {
2390 }
2391 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
2392 return Impl::StdString::StartsWith( substr );
2393 }
2394 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
2396 }
2397 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
2398 return Impl::StdString::EndsWith( substr );
2399 }
2400 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
2402 }
2403
2404} // namespace Matchers
2405
2406using namespace Matchers;
2407
2408} // namespace Catch
2409
2410// #included from: internal/catch_interfaces_tag_alias_registry.h
2411#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2412
2413// #included from: catch_tag_alias.h
2414#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2415
2416#include <string>
2417
2418namespace Catch {
2419
2420 struct TagAlias {
2421 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
2422
2423 std::string tag;
2425 };
2426
2428 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
2429 };
2430
2431} // end namespace Catch
2432
2433#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2434// #included from: catch_option.hpp
2435#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2436
2437namespace Catch {
2438
2439 // An optional type
2440 template<typename T>
2441 class Option {
2442 public:
2443 Option() : nullableValue( NULL ) {}
2444 Option( T const& _value )
2445 : nullableValue( new( storage ) T( _value ) )
2446 {}
2447 Option( Option const& _other )
2448 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
2449 {}
2450
2452 reset();
2453 }
2454
2455 Option& operator= ( Option const& _other ) {
2456 if( &_other != this ) {
2457 reset();
2458 if( _other )
2459 nullableValue = new( storage ) T( *_other );
2460 }
2461 return *this;
2462 }
2463 Option& operator = ( T const& _value ) {
2464 reset();
2465 nullableValue = new( storage ) T( _value );
2466 return *this;
2467 }
2468
2469 void reset() {
2470 if( nullableValue )
2471 nullableValue->~T();
2472 nullableValue = NULL;
2473 }
2474
2475 T& operator*() { return *nullableValue; }
2476 T const& operator*() const { return *nullableValue; }
2477 T* operator->() { return nullableValue; }
2478 const T* operator->() const { return nullableValue; }
2479
2480 T valueOr( T const& defaultValue ) const {
2481 return nullableValue ? *nullableValue : defaultValue;
2482 }
2483
2484 bool some() const { return nullableValue != NULL; }
2485 bool none() const { return nullableValue == NULL; }
2486
2487 bool operator !() const { return nullableValue == NULL; }
2488 operator SafeBool::type() const {
2489 return SafeBool::makeSafe( some() );
2490 }
2491
2492 private:
2494 char storage[sizeof(T)];
2495 };
2496
2497} // end namespace Catch
2498
2499namespace Catch {
2500
2503 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
2504 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
2505
2506 static ITagAliasRegistry const& get();
2507 };
2508
2509} // end namespace Catch
2510
2511// These files are included here so the single_include script doesn't put them
2512// in the conditionally compiled sections
2513// #included from: internal/catch_test_case_info.h
2514#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2515
2516#include <string>
2517#include <set>
2518
2519#ifdef __clang__
2520#pragma clang diagnostic push
2521#pragma clang diagnostic ignored "-Wpadded"
2522#endif
2523
2524namespace Catch {
2525
2526 struct ITestCase;
2527
2530 None = 0,
2531 IsHidden = 1 << 1,
2532 ShouldFail = 1 << 2,
2533 MayFail = 1 << 3,
2534 Throws = 1 << 4
2536
2537 TestCaseInfo( std::string const& _name,
2538 std::string const& _className,
2539 std::string const& _description,
2540 std::set<std::string> const& _tags,
2541 SourceLineInfo const& _lineInfo );
2542
2544
2545 bool isHidden() const;
2546 bool throws() const;
2547 bool okToFail() const;
2548 bool expectedToFail() const;
2549
2550 std::string name;
2551 std::string className;
2552 std::string description;
2553 std::set<std::string> tags;
2554 std::set<std::string> lcaseTags;
2555 std::string tagsAsString;
2558 };
2559
2560 class TestCase : public TestCaseInfo {
2561 public:
2562
2563 TestCase( ITestCase* testCase, TestCaseInfo const& info );
2564 TestCase( TestCase const& other );
2565
2566 TestCase withName( std::string const& _newName ) const;
2567
2568 void invoke() const;
2569
2571
2572 void swap( TestCase& other );
2573 bool operator == ( TestCase const& other ) const;
2574 bool operator < ( TestCase const& other ) const;
2575 TestCase& operator = ( TestCase const& other );
2576
2577 private:
2579 };
2580
2582 std::string const& className,
2583 std::string const& name,
2584 std::string const& description,
2585 SourceLineInfo const& lineInfo );
2586}
2587
2588#ifdef __clang__
2589#pragma clang diagnostic pop
2590#endif
2591
2592
2593#ifdef __OBJC__
2594// #included from: internal/catch_objc.hpp
2595#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2596
2597#import <objc/runtime.h>
2598
2599#include <string>
2600
2601// NB. Any general catch headers included here must be included
2602// in catch.hpp first to make sure they are included by the single
2603// header for non obj-usage
2604
2606// This protocol is really only here for (self) documenting purposes, since
2607// all its methods are optional.
2608@protocol OcFixture
2609
2610@optional
2611
2612-(void) setUp;
2613-(void) tearDown;
2614
2615@end
2616
2617namespace Catch {
2618
2619 class OcMethod : public SharedImpl<ITestCase> {
2620
2621 public:
2622 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2623
2624 virtual void invoke() const {
2625 id obj = [[m_cls alloc] init];
2626
2627 performOptionalSelector( obj, @selector(setUp) );
2628 performOptionalSelector( obj, m_sel );
2629 performOptionalSelector( obj, @selector(tearDown) );
2630
2631 arcSafeRelease( obj );
2632 }
2633 private:
2634 virtual ~OcMethod() {}
2635
2636 Class m_cls;
2637 SEL m_sel;
2638 };
2639
2640 namespace Detail{
2641
2642 inline std::string getAnnotation( Class cls,
2643 std::string const& annotationName,
2644 std::string const& testCaseName ) {
2645 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2646 SEL sel = NSSelectorFromString( selStr );
2647 arcSafeRelease( selStr );
2648 id value = performOptionalSelector( cls, sel );
2649 if( value )
2650 return [(NSString*)value UTF8String];
2651 return "";
2652 }
2653 }
2654
2655 inline size_t registerTestMethods() {
2656 size_t noTestMethods = 0;
2657 int noClasses = objc_getClassList( NULL, 0 );
2658
2659 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
2660 objc_getClassList( classes, noClasses );
2661
2662 for( int c = 0; c < noClasses; c++ ) {
2663 Class cls = classes[c];
2664 {
2665 u_int count;
2666 Method* methods = class_copyMethodList( cls, &count );
2667 for( u_int m = 0; m < count ; m++ ) {
2668 SEL selector = method_getName(methods[m]);
2669 std::string methodName = sel_getName(selector);
2670 if( startsWith( methodName, "Catch_TestCase_" ) ) {
2671 std::string testCaseName = methodName.substr( 15 );
2672 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2673 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
2674 const char* className = class_getName( cls );
2675
2676 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
2677 noTestMethods++;
2678 }
2679 }
2680 free(methods);
2681 }
2682 }
2683 return noTestMethods;
2684 }
2685
2686 namespace Matchers {
2687 namespace Impl {
2688 namespace NSStringMatchers {
2689
2690 template<typename MatcherT>
2691 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
2692 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2693 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
2694 StringHolder() {
2695 arcSafeRelease( m_substr );
2696 }
2697
2698 NSString* m_substr;
2699 };
2700
2701 struct Equals : StringHolder<Equals> {
2702 Equals( NSString* substr ) : StringHolder( substr ){}
2703
2704 virtual bool match( ExpressionType const& str ) const {
2705 return (str != nil || m_substr == nil ) &&
2706 [str isEqualToString:m_substr];
2707 }
2708
2709 virtual std::string toString() const {
2710 return "equals string: " + Catch::toString( m_substr );
2711 }
2712 };
2713
2714 struct Contains : StringHolder<Contains> {
2715 Contains( NSString* substr ) : StringHolder( substr ){}
2716
2717 virtual bool match( ExpressionType const& str ) const {
2718 return (str != nil || m_substr == nil ) &&
2719 [str rangeOfString:m_substr].location != NSNotFound;
2720 }
2721
2722 virtual std::string toString() const {
2723 return "contains string: " + Catch::toString( m_substr );
2724 }
2725 };
2726
2727 struct StartsWith : StringHolder<StartsWith> {
2728 StartsWith( NSString* substr ) : StringHolder( substr ){}
2729
2730 virtual bool match( ExpressionType const& str ) const {
2731 return (str != nil || m_substr == nil ) &&
2732 [str rangeOfString:m_substr].location == 0;
2733 }
2734
2735 virtual std::string toString() const {
2736 return "starts with: " + Catch::toString( m_substr );
2737 }
2738 };
2739 struct EndsWith : StringHolder<EndsWith> {
2740 EndsWith( NSString* substr ) : StringHolder( substr ){}
2741
2742 virtual bool match( ExpressionType const& str ) const {
2743 return (str != nil || m_substr == nil ) &&
2744 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2745 }
2746
2747 virtual std::string toString() const {
2748 return "ends with: " + Catch::toString( m_substr );
2749 }
2750 };
2751
2752 } // namespace NSStringMatchers
2753 } // namespace Impl
2754
2756 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2757
2759 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
2760
2762 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
2763
2765 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2766
2767 } // namespace Matchers
2768
2769 using namespace Matchers;
2770
2771} // namespace Catch
2772
2774#define OC_TEST_CASE( name, desc )\
2775+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2776{\
2777return @ name; \
2778}\
2779+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2780{ \
2781return @ desc; \
2782} \
2783-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2784
2785#endif
2786
2787#ifdef CATCH_IMPL
2788// #included from: internal/catch_impl.hpp
2789#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2790
2791// Collect all the implementation files together here
2792// These are the equivalent of what would usually be cpp files
2793
2794#ifdef __clang__
2795#pragma clang diagnostic push
2796#pragma clang diagnostic ignored "-Wweak-vtables"
2797#endif
2798
2799// #included from: ../catch_runner.hpp
2800#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2801
2802// #included from: internal/catch_commandline.hpp
2803#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2804
2805// #included from: catch_config.hpp
2806#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2807
2808// #included from: catch_test_spec_parser.hpp
2809#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
2810
2811#ifdef __clang__
2812#pragma clang diagnostic push
2813#pragma clang diagnostic ignored "-Wpadded"
2814#endif
2815
2816// #included from: catch_test_spec.hpp
2817#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
2818
2819#ifdef __clang__
2820#pragma clang diagnostic push
2821#pragma clang diagnostic ignored "-Wpadded"
2822#endif
2823
2824#include <string>
2825#include <vector>
2826
2827namespace Catch {
2828
2829 class TestSpec {
2830 struct Pattern : SharedImpl<> {
2831 virtual ~Pattern();
2832 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
2833 };
2834 class NamePattern : public Pattern {
2835 enum WildcardPosition {
2836 NoWildcard = 0,
2837 WildcardAtStart = 1,
2838 WildcardAtEnd = 2,
2839 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
2840 };
2841
2842 public:
2843 NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) {
2844 if( startsWith( m_name, "*" ) ) {
2845 m_name = m_name.substr( 1 );
2846 m_wildcard = WildcardAtStart;
2847 }
2848 if( endsWith( m_name, "*" ) ) {
2849 m_name = m_name.substr( 0, m_name.size()-1 );
2850 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
2851 }
2852 }
2853 virtual ~NamePattern();
2854 virtual bool matches( TestCaseInfo const& testCase ) const {
2855 switch( m_wildcard ) {
2856 case NoWildcard:
2857 return m_name == toLower( testCase.name );
2858 case WildcardAtStart:
2859 return endsWith( toLower( testCase.name ), m_name );
2860 case WildcardAtEnd:
2861 return startsWith( toLower( testCase.name ), m_name );
2862 case WildcardAtBothEnds:
2863 return contains( toLower( testCase.name ), m_name );
2864 }
2865
2866#ifdef __clang__
2867#pragma clang diagnostic push
2868#pragma clang diagnostic ignored "-Wunreachable-code"
2869#endif
2870 throw std::logic_error( "Unknown enum" );
2871#ifdef __clang__
2872#pragma clang diagnostic pop
2873#endif
2874 }
2875 private:
2876 std::string m_name;
2877 WildcardPosition m_wildcard;
2878 };
2879 class TagPattern : public Pattern {
2880 public:
2881 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
2882 virtual ~TagPattern();
2883 virtual bool matches( TestCaseInfo const& testCase ) const {
2884 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
2885 }
2886 private:
2887 std::string m_tag;
2888 };
2889 class ExcludedPattern : public Pattern {
2890 public:
2891 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
2892 virtual ~ExcludedPattern();
2893 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
2894 private:
2895 Ptr<Pattern> m_underlyingPattern;
2896 };
2897
2898 struct Filter {
2899 std::vector<Ptr<Pattern> > m_patterns;
2900
2901 bool matches( TestCaseInfo const& testCase ) const {
2902 // All patterns in a filter must match for the filter to be a match
2903 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
2904 if( !(*it)->matches( testCase ) )
2905 return false;
2906 return true;
2907 }
2908 };
2909
2910 public:
2911 bool hasFilters() const {
2912 return !m_filters.empty();
2913 }
2914 bool matches( TestCaseInfo const& testCase ) const {
2915 // A TestSpec matches if any filter matches
2916 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
2917 if( it->matches( testCase ) )
2918 return true;
2919 return false;
2920 }
2921
2922 private:
2923 std::vector<Filter> m_filters;
2924
2925 friend class TestSpecParser;
2926 };
2927}
2928
2929#ifdef __clang__
2930#pragma clang diagnostic pop
2931#endif
2932
2933namespace Catch {
2934
2935 class TestSpecParser {
2936 enum Mode{ None, Name, QuotedName, Tag };
2937 Mode m_mode;
2938 bool m_exclusion;
2939 std::size_t m_start, m_pos;
2940 std::string m_arg;
2941 TestSpec::Filter m_currentFilter;
2942 TestSpec m_testSpec;
2943 ITagAliasRegistry const* m_tagAliases;
2944
2945 public:
2946 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
2947
2948 TestSpecParser& parse( std::string const& arg ) {
2949 m_mode = None;
2950 m_exclusion = false;
2951 m_start = std::string::npos;
2952 m_arg = m_tagAliases->expandAliases( arg );
2953 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
2954 visitChar( m_arg[m_pos] );
2955 if( m_mode == Name )
2956 addPattern<TestSpec::NamePattern>();
2957 return *this;
2958 }
2959 TestSpec testSpec() {
2960 addFilter();
2961 return m_testSpec;
2962 }
2963 private:
2964 void visitChar( char c ) {
2965 if( m_mode == None ) {
2966 switch( c ) {
2967 case ' ': return;
2968 case '~': m_exclusion = true; return;
2969 case '[': return startNewMode( Tag, ++m_pos );
2970 case '"': return startNewMode( QuotedName, ++m_pos );
2971 default: startNewMode( Name, m_pos ); break;
2972 }
2973 }
2974 if( m_mode == Name ) {
2975 if( c == ',' ) {
2976 addPattern<TestSpec::NamePattern>();
2977 addFilter();
2978 }
2979 else if( c == '[' ) {
2980 if( subString() == "exclude:" )
2981 m_exclusion = true;
2982 else
2983 addPattern<TestSpec::NamePattern>();
2984 startNewMode( Tag, ++m_pos );
2985 }
2986 }
2987 else if( m_mode == QuotedName && c == '"' )
2988 addPattern<TestSpec::NamePattern>();
2989 else if( m_mode == Tag && c == ']' )
2990 addPattern<TestSpec::TagPattern>();
2991 }
2992 void startNewMode( Mode mode, std::size_t start ) {
2993 m_mode = mode;
2994 m_start = start;
2995 }
2996 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
2997 template<typename T>
2998 void addPattern() {
2999 std::string token = subString();
3000 if( startsWith( token, "exclude:" ) ) {
3001 m_exclusion = true;
3002 token = token.substr( 8 );
3003 }
3004 if( !token.empty() ) {
3005 Ptr<TestSpec::Pattern> pattern = new T( token );
3006 if( m_exclusion )
3007 pattern = new TestSpec::ExcludedPattern( pattern );
3008 m_currentFilter.m_patterns.push_back( pattern );
3009 }
3010 m_exclusion = false;
3011 m_mode = None;
3012 }
3013 void addFilter() {
3014 if( !m_currentFilter.m_patterns.empty() ) {
3015 m_testSpec.m_filters.push_back( m_currentFilter );
3016 m_currentFilter = TestSpec::Filter();
3017 }
3018 }
3019 };
3020 inline TestSpec parseTestSpec( std::string const& arg ) {
3021 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
3022 }
3023
3024} // namespace Catch
3025
3026#ifdef __clang__
3027#pragma clang diagnostic pop
3028#endif
3029
3030// #included from: catch_interfaces_config.h
3031#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3032
3033#include <iostream>
3034#include <string>
3035#include <vector>
3036
3037namespace Catch {
3038
3039 struct Verbosity { enum Level {
3040 NoOutput = 0,
3041 Quiet,
3042 Normal
3043 }; };
3044
3045 struct WarnAbout { enum What {
3046 Nothing = 0x00,
3047 NoAssertions = 0x01
3048 }; };
3049
3050 struct ShowDurations { enum OrNot {
3051 DefaultForReporter,
3052 Always,
3053 Never
3054 }; };
3055 struct RunTests { enum InWhatOrder {
3056 InDeclarationOrder,
3057 InLexicographicalOrder,
3058 InRandomOrder
3059 }; };
3060
3061 class TestSpec;
3062
3063 struct IConfig : IShared {
3064
3065 virtual ~IConfig();
3066
3067 virtual bool allowThrows() const = 0;
3068 virtual std::ostream& stream() const = 0;
3069 virtual std::string name() const = 0;
3070 virtual bool includeSuccessfulResults() const = 0;
3071 virtual bool shouldDebugBreak() const = 0;
3072 virtual bool warnAboutMissingAssertions() const = 0;
3073 virtual int abortAfter() const = 0;
3074 virtual bool showInvisibles() const = 0;
3075 virtual ShowDurations::OrNot showDurations() const = 0;
3076 virtual TestSpec const& testSpec() const = 0;
3077 virtual RunTests::InWhatOrder runOrder() const = 0;
3078 virtual unsigned int rngSeed() const = 0;
3079 virtual bool forceColour() const = 0;
3080 };
3081}
3082
3083// #included from: catch_stream.h
3084#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3085
3086#include <streambuf>
3087
3088#ifdef __clang__
3089#pragma clang diagnostic ignored "-Wpadded"
3090#endif
3091
3092namespace Catch {
3093
3094 class Stream {
3095 public:
3096 Stream();
3097 Stream( std::streambuf* _streamBuf, bool _isOwned );
3098 void release();
3099
3100 std::streambuf* streamBuf;
3101
3102 private:
3103 bool isOwned;
3104 };
3105
3106 std::ostream& cout();
3107 std::ostream& cerr();
3108}
3109
3110#include <memory>
3111#include <vector>
3112#include <string>
3113#include <iostream>
3114#include <ctime>
3115
3116#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3117#define CATCH_CONFIG_CONSOLE_WIDTH 80
3118#endif
3119
3120namespace Catch {
3121
3122 struct ConfigData {
3123
3124 ConfigData()
3125 : listTests( false ),
3126 listTags( false ),
3127 listReporters( false ),
3128 listTestNamesOnly( false ),
3129 showSuccessfulTests( false ),
3130 shouldDebugBreak( false ),
3131 noThrow( false ),
3132 showHelp( false ),
3133 showInvisibles( false ),
3134 forceColour( false ),
3135 abortAfter( -1 ),
3136 rngSeed( 0 ),
3137 verbosity( Verbosity::Normal ),
3138 warnings( WarnAbout::Nothing ),
3139 showDurations( ShowDurations::DefaultForReporter ),
3140 runOrder( RunTests::InDeclarationOrder )
3141 {}
3142
3143 bool listTests;
3144 bool listTags;
3145 bool listReporters;
3146 bool listTestNamesOnly;
3147
3148 bool showSuccessfulTests;
3149 bool shouldDebugBreak;
3150 bool noThrow;
3151 bool showHelp;
3152 bool showInvisibles;
3153 bool forceColour;
3154
3155 int abortAfter;
3156 unsigned int rngSeed;
3157
3158 Verbosity::Level verbosity;
3159 WarnAbout::What warnings;
3160 ShowDurations::OrNot showDurations;
3161 RunTests::InWhatOrder runOrder;
3162
3163 std::string reporterName;
3164 std::string outputFilename;
3165 std::string name;
3166 std::string processName;
3167
3168 std::vector<std::string> testsOrTags;
3169 };
3170
3171 class Config : public SharedImpl<IConfig> {
3172 private:
3173 Config( Config const& other );
3174 Config& operator = ( Config const& other );
3175 virtual void dummy();
3176 public:
3177
3178 Config()
3179 : m_os( Catch::cout().rdbuf() )
3180 {}
3181
3182 Config( ConfigData const& data )
3183 : m_data( data ),
3184 m_os( Catch::cout().rdbuf() )
3185 {
3186 if( !data.testsOrTags.empty() ) {
3187 TestSpecParser parser( ITagAliasRegistry::get() );
3188 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3189 parser.parse( data.testsOrTags[i] );
3190 m_testSpec = parser.testSpec();
3191 }
3192 }
3193
3194 virtual ~Config() {
3195 m_os.rdbuf( Catch::cout().rdbuf() );
3196 m_stream.release();
3197 }
3198
3199 void setFilename( std::string const& filename ) {
3200 m_data.outputFilename = filename;
3201 }
3202
3203 std::string const& getFilename() const {
3204 return m_data.outputFilename ;
3205 }
3206
3207 bool listTests() const { return m_data.listTests; }
3208 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
3209 bool listTags() const { return m_data.listTags; }
3210 bool listReporters() const { return m_data.listReporters; }
3211
3212 std::string getProcessName() const { return m_data.processName; }
3213
3214 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
3215
3216 void setStreamBuf( std::streambuf* buf ) {
3217 m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
3218 }
3219
3220 void useStream( std::string const& streamName ) {
3221 Stream stream = createStream( streamName );
3222 setStreamBuf( stream.streamBuf );
3223 m_stream.release();
3224 m_stream = stream;
3225 }
3226
3227 std::string getReporterName() const { return m_data.reporterName; }
3228
3229 int abortAfter() const { return m_data.abortAfter; }
3230
3231 TestSpec const& testSpec() const { return m_testSpec; }
3232
3233 bool showHelp() const { return m_data.showHelp; }
3234 bool showInvisibles() const { return m_data.showInvisibles; }
3235
3236 // IConfig interface
3237 virtual bool allowThrows() const { return !m_data.noThrow; }
3238 virtual std::ostream& stream() const { return m_os; }
3239 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
3240 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
3241 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
3242 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
3243 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
3244 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
3245 virtual bool forceColour() const { return m_data.forceColour; }
3246
3247 private:
3248 ConfigData m_data;
3249
3250 Stream m_stream;
3251 mutable std::ostream m_os;
3252 TestSpec m_testSpec;
3253 };
3254
3255} // end namespace Catch
3256
3257// #included from: catch_clara.h
3258#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3259
3260// Use Catch's value for console width (store Clara's off to the side, if present)
3261#ifdef CLARA_CONFIG_CONSOLE_WIDTH
3262#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3263#undef CLARA_CONFIG_CONSOLE_WIDTH
3264#endif
3265#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3266
3267// Declare Clara inside the Catch namespace
3268#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3269// #included from: ../external/clara.h
3270
3271// Only use header guard if we are not using an outer namespace
3272#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3273
3274#ifndef STITCH_CLARA_OPEN_NAMESPACE
3275#define TWOBLUECUBES_CLARA_H_INCLUDED
3276#define STITCH_CLARA_OPEN_NAMESPACE
3277#define STITCH_CLARA_CLOSE_NAMESPACE
3278#else
3279#define STITCH_CLARA_CLOSE_NAMESPACE }
3280#endif
3281
3282#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3283
3284// ----------- #included from tbc_text_format.h -----------
3285
3286// Only use header guard if we are not using an outer namespace
3287#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3288#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3289#define TBC_TEXT_FORMAT_H_INCLUDED
3290#endif
3291
3292#include <string>
3293#include <vector>
3294#include <sstream>
3295
3296// Use optional outer namespace
3297#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3298namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3299#endif
3300
3301namespace Tbc {
3302
3303#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3304 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3305#else
3306 const unsigned int consoleWidth = 80;
3307#endif
3308
3309 struct TextAttributes {
3310 TextAttributes()
3311 : initialIndent( std::string::npos ),
3312 indent( 0 ),
3313 width( consoleWidth-1 ),
3314 tabChar( '\t' )
3315 {}
3316
3317 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
3318 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
3319 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
3320 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
3321
3322 std::size_t initialIndent; // indent of first line, or npos
3323 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3324 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3325 char tabChar; // If this char is seen the indent is changed to current pos
3326 };
3327
3328 class Text {
3329 public:
3330 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
3331 : attr( _attr )
3332 {
3333 std::string wrappableChars = " [({.,/|\\-";
3334 std::size_t indent = _attr.initialIndent != std::string::npos
3335 ? _attr.initialIndent
3336 : _attr.indent;
3337 std::string remainder = _str;
3338
3339 while( !remainder.empty() ) {
3340 if( lines.size() >= 1000 ) {
3341 lines.push_back( "... message truncated due to excessive size" );
3342 return;
3343 }
3344 std::size_t tabPos = std::string::npos;
3345 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3346 std::size_t pos = remainder.find_first_of( '\n' );
3347 if( pos <= width ) {
3348 width = pos;
3349 }
3350 pos = remainder.find_last_of( _attr.tabChar, width );
3351 if( pos != std::string::npos ) {
3352 tabPos = pos;
3353 if( remainder[width] == '\n' )
3354 width--;
3355 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3356 }
3357
3358 if( width == remainder.size() ) {
3359 spliceLine( indent, remainder, width );
3360 }
3361 else if( remainder[width] == '\n' ) {
3362 spliceLine( indent, remainder, width );
3363 if( width <= 1 || remainder.size() != 1 )
3364 remainder = remainder.substr( 1 );
3365 indent = _attr.indent;
3366 }
3367 else {
3368 pos = remainder.find_last_of( wrappableChars, width );
3369 if( pos != std::string::npos && pos > 0 ) {
3370 spliceLine( indent, remainder, pos );
3371 if( remainder[0] == ' ' )
3372 remainder = remainder.substr( 1 );
3373 }
3374 else {
3375 spliceLine( indent, remainder, width-1 );
3376 lines.back() += "-";
3377 }
3378 if( lines.size() == 1 )
3379 indent = _attr.indent;
3380 if( tabPos != std::string::npos )
3381 indent += tabPos;
3382 }
3383 }
3384 }
3385
3386 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3387 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
3388 _remainder = _remainder.substr( _pos );
3389 }
3390
3391 typedef std::vector<std::string>::const_iterator const_iterator;
3392
3393 const_iterator begin() const { return lines.begin(); }
3394 const_iterator end() const { return lines.end(); }
3395 std::string const& last() const { return lines.back(); }
3396 std::size_t size() const { return lines.size(); }
3397 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
3398 std::string toString() const {
3399 std::ostringstream oss;
3400 oss << *this;
3401 return oss.str();
3402 }
3403
3404 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
3405 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3406 it != itEnd; ++it ) {
3407 if( it != _text.begin() )
3408 _stream << "\n";
3409 _stream << *it;
3410 }
3411 return _stream;
3412 }
3413
3414 private:
3415 std::string str;
3416 TextAttributes attr;
3418 };
3419
3420} // end namespace Tbc
3421
3422#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3423} // end outer namespace
3424#endif
3425
3426#endif // TBC_TEXT_FORMAT_H_INCLUDED
3427
3428// ----------- end of #include from tbc_text_format.h -----------
3429// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
3430
3431#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3432
3433#include <map>
3434#include <algorithm>
3435#include <stdexcept>
3436#include <memory>
3437
3438// Use optional outer namespace
3439#ifdef STITCH_CLARA_OPEN_NAMESPACE
3440STITCH_CLARA_OPEN_NAMESPACE
3441#endif
3442
3443namespace Clara {
3444
3445 struct UnpositionalTag {};
3446
3447 extern UnpositionalTag _;
3448
3449#ifdef CLARA_CONFIG_MAIN
3450 UnpositionalTag _;
3451#endif
3452
3453 namespace Detail {
3454
3455#ifdef CLARA_CONSOLE_WIDTH
3456 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3457#else
3458 const unsigned int consoleWidth = 80;
3459#endif
3460
3461 using namespace Tbc;
3462
3463 inline bool startsWith( std::string const& str, std::string const& prefix ) {
3464 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3465 }
3466
3467 template<typename T> struct RemoveConstRef{ typedef T type; };
3468 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3469 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3470 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3471
3472 template<typename T> struct IsBool { static const bool value = false; };
3473 template<> struct IsBool<bool> { static const bool value = true; };
3474
3475 template<typename T>
3476 void convertInto( std::string const& _source, T& _dest ) {
3477 std::stringstream ss;
3478 ss << _source;
3479 ss >> _dest;
3480 if( ss.fail() )
3481 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
3482 }
3483 inline void convertInto( std::string const& _source, std::string& _dest ) {
3484 _dest = _source;
3485 }
3486 inline void convertInto( std::string const& _source, bool& _dest ) {
3487 std::string sourceLC = _source;
3488 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3489 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
3490 _dest = true;
3491 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
3492 _dest = false;
3493 else
3494 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
3495 }
3496 inline void convertInto( bool _source, bool& _dest ) {
3497 _dest = _source;
3498 }
3499 template<typename T>
3500 inline void convertInto( bool, T& ) {
3501 throw std::runtime_error( "Invalid conversion" );
3502 }
3503
3504 template<typename ConfigT>
3505 struct IArgFunction {
3506 virtual ~IArgFunction() {}
3507# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
3508 IArgFunction() = default;
3509 IArgFunction( IArgFunction const& ) = default;
3510# endif
3511 virtual void set( ConfigT& config, std::string const& value ) const = 0;
3512 virtual void setFlag( ConfigT& config ) const = 0;
3513 virtual bool takesArg() const = 0;
3514 virtual IArgFunction* clone() const = 0;
3515 };
3516
3517 template<typename ConfigT>
3518 class BoundArgFunction {
3519 public:
3520 BoundArgFunction() : functionObj( NULL ) {}
3521 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
3522 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
3523 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
3524 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;
3525 delete functionObj;
3526 functionObj = newFunctionObj;
3527 return *this;
3528 }
3529 ~BoundArgFunction() { delete functionObj; }
3530
3531 void set( ConfigT& config, std::string const& value ) const {
3532 functionObj->set( config, value );
3533 }
3534 void setFlag( ConfigT& config ) const {
3535 functionObj->setFlag( config );
3536 }
3537 bool takesArg() const { return functionObj->takesArg(); }
3538
3539 bool isSet() const {
3540 return functionObj != NULL;
3541 }
3542 private:
3543 IArgFunction<ConfigT>* functionObj;
3544 };
3545
3546 template<typename C>
3547 struct NullBinder : IArgFunction<C>{
3548 virtual void set( C&, std::string const& ) const {}
3549 virtual void setFlag( C& ) const {}
3550 virtual bool takesArg() const { return true; }
3551 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
3552 };
3553
3554 template<typename C, typename M>
3555 struct BoundDataMember : IArgFunction<C>{
3556 BoundDataMember( M C::* _member ) : member( _member ) {}
3557 virtual void set( C& p, std::string const& stringValue ) const {
3558 convertInto( stringValue, p.*member );
3559 }
3560 virtual void setFlag( C& p ) const {
3561 convertInto( true, p.*member );
3562 }
3563 virtual bool takesArg() const { return !IsBool<M>::value; }
3564 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
3565 M C::* member;
3566 };
3567 template<typename C, typename M>
3568 struct BoundUnaryMethod : IArgFunction<C>{
3569 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
3570 virtual void set( C& p, std::string const& stringValue ) const {
3571 typename RemoveConstRef<M>::type value;
3572 convertInto( stringValue, value );
3573 (p.*member)( value );
3574 }
3575 virtual void setFlag( C& p ) const {
3576 typename RemoveConstRef<M>::type value;
3577 convertInto( true, value );
3578 (p.*member)( value );
3579 }
3580 virtual bool takesArg() const { return !IsBool<M>::value; }
3581 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
3582 void (C::*member)( M );
3583 };
3584 template<typename C>
3585 struct BoundNullaryMethod : IArgFunction<C>{
3586 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
3587 virtual void set( C& p, std::string const& stringValue ) const {
3588 bool value;
3589 convertInto( stringValue, value );
3590 if( value )
3591 (p.*member)();
3592 }
3593 virtual void setFlag( C& p ) const {
3594 (p.*member)();
3595 }
3596 virtual bool takesArg() const { return false; }
3597 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
3598 void (C::*member)();
3599 };
3600
3601 template<typename C>
3602 struct BoundUnaryFunction : IArgFunction<C>{
3603 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
3604 virtual void set( C& obj, std::string const& stringValue ) const {
3605 bool value;
3606 convertInto( stringValue, value );
3607 if( value )
3608 function( obj );
3609 }
3610 virtual void setFlag( C& p ) const {
3611 function( p );
3612 }
3613 virtual bool takesArg() const { return false; }
3614 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
3615 void (*function)( C& );
3616 };
3617
3618 template<typename C, typename T>
3619 struct BoundBinaryFunction : IArgFunction<C>{
3620 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
3621 virtual void set( C& obj, std::string const& stringValue ) const {
3622 typename RemoveConstRef<T>::type value;
3623 convertInto( stringValue, value );
3624 function( obj, value );
3625 }
3626 virtual void setFlag( C& obj ) const {
3627 typename RemoveConstRef<T>::type value;
3628 convertInto( true, value );
3629 function( obj, value );
3630 }
3631 virtual bool takesArg() const { return !IsBool<T>::value; }
3632 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
3633 void (*function)( C&, T );
3634 };
3635
3636 } // namespace Detail
3637
3638 struct Parser {
3639 Parser() : separators( " \t=:" ) {}
3640
3641 struct Token {
3642 enum Type { Positional, ShortOpt, LongOpt };
3643 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
3644 Type type;
3645 std::string data;
3646 };
3647
3648 void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
3649 const std::string doubleDash = "--";
3650 for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
3651 parseIntoTokens( argv[i] , tokens);
3652 }
3653 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
3654 while( !arg.empty() ) {
3655 Parser::Token token( Parser::Token::Positional, arg );
3656 arg = "";
3657 if( token.data[0] == '-' ) {
3658 if( token.data.size() > 1 && token.data[1] == '-' ) {
3659 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
3660 }
3661 else {
3662 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
3663 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
3664 arg = "-" + token.data.substr( 1 );
3665 token.data = token.data.substr( 0, 1 );
3666 }
3667 }
3668 }
3669 if( token.type != Parser::Token::Positional ) {
3670 std::size_t pos = token.data.find_first_of( separators );
3671 if( pos != std::string::npos ) {
3672 arg = token.data.substr( pos+1 );
3673 token.data = token.data.substr( 0, pos );
3674 }
3675 }
3676 tokens.push_back( token );
3677 }
3678 }
3679 std::string separators;
3680 };
3681
3682 template<typename ConfigT>
3683 struct CommonArgProperties {
3684 CommonArgProperties() {}
3685 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
3686
3687 Detail::BoundArgFunction<ConfigT> boundField;
3688 std::string description;
3689 std::string detail;
3690 std::string placeholder; // Only value if boundField takes an arg
3691
3692 bool takesArg() const {
3693 return !placeholder.empty();
3694 }
3695 void validate() const {
3696 if( !boundField.isSet() )
3697 throw std::logic_error( "option not bound" );
3698 }
3699 };
3700 struct OptionArgProperties {
3701 std::vector<std::string> shortNames;
3702 std::string longName;
3703
3704 bool hasShortName( std::string const& shortName ) const {
3705 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
3706 }
3707 bool hasLongName( std::string const& _longName ) const {
3708 return _longName == longName;
3709 }
3710 };
3711 struct PositionalArgProperties {
3712 PositionalArgProperties() : position( -1 ) {}
3713 int position; // -1 means non-positional (floating)
3714
3715 bool isFixedPositional() const {
3716 return position != -1;
3717 }
3718 };
3719
3720 template<typename ConfigT>
3721 class CommandLine {
3722
3723 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
3724 Arg() {}
3725 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
3726
3727 using CommonArgProperties<ConfigT>::placeholder; // !TBD
3728
3729 std::string dbgName() const {
3730 if( !longName.empty() )
3731 return "--" + longName;
3732 if( !shortNames.empty() )
3733 return "-" + shortNames[0];
3734 return "positional args";
3735 }
3736 std::string commands() const {
3737 std::ostringstream oss;
3738 bool first = true;
3739 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
3740 for(; it != itEnd; ++it ) {
3741 if( first )
3742 first = false;
3743 else
3744 oss << ", ";
3745 oss << "-" << *it;
3746 }
3747 if( !longName.empty() ) {
3748 if( !first )
3749 oss << ", ";
3750 oss << "--" << longName;
3751 }
3752 if( !placeholder.empty() )
3753 oss << " <" << placeholder << ">";
3754 return oss.str();
3755 }
3756 };
3757
3758 // NOTE: std::auto_ptr is deprecated in c++11/c++0x
3759#if defined(__cplusplus) && __cplusplus > 199711L
3760 typedef std::unique_ptr<Arg> ArgAutoPtr;
3761#else
3762 typedef std::auto_ptr<Arg> ArgAutoPtr;
3763#endif
3764
3765 friend void addOptName( Arg& arg, std::string const& optName )
3766 {
3767 if( optName.empty() )
3768 return;
3769 if( Detail::startsWith( optName, "--" ) ) {
3770 if( !arg.longName.empty() )
3771 throw std::logic_error( "Only one long opt may be specified. '"
3772 + arg.longName
3773 + "' already specified, now attempting to add '"
3774 + optName + "'" );
3775 arg.longName = optName.substr( 2 );
3776 }
3777 else if( Detail::startsWith( optName, "-" ) )
3778 arg.shortNames.push_back( optName.substr( 1 ) );
3779 else
3780 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
3781 }
3782 friend void setPositionalArg( Arg& arg, int position )
3783 {
3784 arg.position = position;
3785 }
3786
3787 class ArgBuilder {
3788 public:
3789 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
3790
3791 // Bind a non-boolean data member (requires placeholder string)
3792 template<typename C, typename M>
3793 void bind( M C::* field, std::string const& placeholder ) {
3794 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
3795 m_arg->placeholder = placeholder;
3796 }
3797 // Bind a boolean data member (no placeholder required)
3798 template<typename C>
3799 void bind( bool C::* field ) {
3800 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
3801 }
3802
3803 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
3804 template<typename C, typename M>
3805 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
3806 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
3807 m_arg->placeholder = placeholder;
3808 }
3809
3810 // Bind a method taking a single, boolean argument (no placeholder string required)
3811 template<typename C>
3812 void bind( void (C::* unaryMethod)( bool ) ) {
3813 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
3814 }
3815
3816 // Bind a method that takes no arguments (will be called if opt is present)
3817 template<typename C>
3818 void bind( void (C::* nullaryMethod)() ) {
3819 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
3820 }
3821
3822 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
3823 template<typename C>
3824 void bind( void (* unaryFunction)( C& ) ) {
3825 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
3826 }
3827
3828 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
3829 template<typename C, typename T>
3830 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
3831 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
3832 m_arg->placeholder = placeholder;
3833 }
3834
3835 ArgBuilder& describe( std::string const& description ) {
3836 m_arg->description = description;
3837 return *this;
3838 }
3839 ArgBuilder& detail( std::string const& detail ) {
3840 m_arg->detail = detail;
3841 return *this;
3842 }
3843
3844 protected:
3845 Arg* m_arg;
3846 };
3847
3848 class OptBuilder : public ArgBuilder {
3849 public:
3850 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
3851 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
3852
3853 OptBuilder& operator[]( std::string const& optName ) {
3854 addOptName( *ArgBuilder::m_arg, optName );
3855 return *this;
3856 }
3857 };
3858
3859 public:
3860
3861 CommandLine()
3862 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
3863 m_highestSpecifiedArgPosition( 0 ),
3864 m_throwOnUnrecognisedTokens( false )
3865 {}
3866 CommandLine( CommandLine const& other )
3867 : m_boundProcessName( other.m_boundProcessName ),
3868 m_options ( other.m_options ),
3869 m_positionalArgs( other.m_positionalArgs ),
3870 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
3871 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
3872 {
3873 if( other.m_floatingArg.get() )
3874 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
3875 }
3876
3877 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
3878 m_throwOnUnrecognisedTokens = shouldThrow;
3879 return *this;
3880 }
3881
3882 OptBuilder operator[]( std::string const& optName ) {
3883 m_options.push_back( Arg() );
3884 addOptName( m_options.back(), optName );
3885 OptBuilder builder( &m_options.back() );
3886 return builder;
3887 }
3888
3889 ArgBuilder operator[]( int position ) {
3890 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
3891 if( position > m_highestSpecifiedArgPosition )
3892 m_highestSpecifiedArgPosition = position;
3893 setPositionalArg( m_positionalArgs[position], position );
3894 ArgBuilder builder( &m_positionalArgs[position] );
3895 return builder;
3896 }
3897
3898 // Invoke this with the _ instance
3899 ArgBuilder operator[]( UnpositionalTag ) {
3900 if( m_floatingArg.get() )
3901 throw std::logic_error( "Only one unpositional argument can be added" );
3902 m_floatingArg.reset( new Arg() );
3903 ArgBuilder builder( m_floatingArg.get() );
3904 return builder;
3905 }
3906
3907 template<typename C, typename M>
3908 void bindProcessName( M C::* field ) {
3909 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
3910 }
3911 template<typename C, typename M>
3912 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
3913 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
3914 }
3915
3916 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
3917 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
3918 std::size_t maxWidth = 0;
3919 for( it = itBegin; it != itEnd; ++it )
3920 maxWidth = (std::max)( maxWidth, it->commands().size() );
3921
3922 for( it = itBegin; it != itEnd; ++it ) {
3923 Detail::Text usage( it->commands(), Detail::TextAttributes()
3924 .setWidth( maxWidth+indent )
3925 .setIndent( indent ) );
3926 Detail::Text desc( it->description, Detail::TextAttributes()
3927 .setWidth( width - maxWidth - 3 ) );
3928
3929 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
3930 std::string usageCol = i < usage.size() ? usage[i] : "";
3931 os << usageCol;
3932
3933 if( i < desc.size() && !desc[i].empty() )
3934 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
3935 << desc[i];
3936 os << "\n";
3937 }
3938 }
3939 }
3940 std::string optUsage() const {
3941 std::ostringstream oss;
3942 optUsage( oss );
3943 return oss.str();
3944 }
3945
3946 void argSynopsis( std::ostream& os ) const {
3947 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
3948 if( i > 1 )
3949 os << " ";
3950 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
3951 if( it != m_positionalArgs.end() )
3952 os << "<" << it->second.placeholder << ">";
3953 else if( m_floatingArg.get() )
3954 os << "<" << m_floatingArg->placeholder << ">";
3955 else
3956 throw std::logic_error( "non consecutive positional arguments with no floating args" );
3957 }
3958 // !TBD No indication of mandatory args
3959 if( m_floatingArg.get() ) {
3960 if( m_highestSpecifiedArgPosition > 1 )
3961 os << " ";
3962 os << "[<" << m_floatingArg->placeholder << "> ...]";
3963 }
3964 }
3965 std::string argSynopsis() const {
3966 std::ostringstream oss;
3967 argSynopsis( oss );
3968 return oss.str();
3969 }
3970
3971 void usage( std::ostream& os, std::string const& procName ) const {
3972 validate();
3973 os << "usage:\n " << procName << " ";
3974 argSynopsis( os );
3975 if( !m_options.empty() ) {
3976 os << " [options]\n\nwhere options are: \n";
3977 optUsage( os, 2 );
3978 }
3979 os << "\n";
3980 }
3981 std::string usage( std::string const& procName ) const {
3982 std::ostringstream oss;
3983 usage( oss, procName );
3984 return oss.str();
3985 }
3986
3987 ConfigT parse( int argc, char const * const * argv ) const {
3988 ConfigT config;
3989 parseInto( argc, argv, config );
3990 return config;
3991 }
3992
3993 std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
3994 std::string processName = argv[0];
3995 std::size_t lastSlash = processName.find_last_of( "/\\" );
3996 if( lastSlash != std::string::npos )
3997 processName = processName.substr( lastSlash+1 );
3998 m_boundProcessName.set( config, processName );
4000 Parser parser;
4001 parser.parseIntoTokens( argc, argv, tokens );
4002 return populate( tokens, config );
4003 }
4004
4005 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4006 validate();
4007 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4008 unusedTokens = populateFixedArgs( unusedTokens, config );
4009 unusedTokens = populateFloatingArgs( unusedTokens, config );
4010 return unusedTokens;
4011 }
4012
4013 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4014 std::vector<Parser::Token> unusedTokens;
4016 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4017 Parser::Token const& token = tokens[i];
4018 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4019 for(; it != itEnd; ++it ) {
4020 Arg const& arg = *it;
4021
4022 try {
4023 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4024 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4025 if( arg.takesArg() ) {
4026 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4027 errors.push_back( "Expected argument to option: " + token.data );
4028 else
4029 arg.boundField.set( config, tokens[++i].data );
4030 }
4031 else {
4032 arg.boundField.setFlag( config );
4033 }
4034 break;
4035 }
4036 }
4037 catch( std::exception& ex ) {
4038 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
4039 }
4040 }
4041 if( it == itEnd ) {
4042 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4043 unusedTokens.push_back( token );
4044 else if( errors.empty() && m_throwOnUnrecognisedTokens )
4045 errors.push_back( "unrecognised option: " + token.data );
4046 }
4047 }
4048 if( !errors.empty() ) {
4049 std::ostringstream oss;
4050 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4051 it != itEnd;
4052 ++it ) {
4053 if( it != errors.begin() )
4054 oss << "\n";
4055 oss << *it;
4056 }
4057 throw std::runtime_error( oss.str() );
4058 }
4059 return unusedTokens;
4060 }
4061 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4062 std::vector<Parser::Token> unusedTokens;
4063 int position = 1;
4064 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4065 Parser::Token const& token = tokens[i];
4066 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4067 if( it != m_positionalArgs.end() )
4068 it->second.boundField.set( config, token.data );
4069 else
4070 unusedTokens.push_back( token );
4071 if( token.type == Parser::Token::Positional )
4072 position++;
4073 }
4074 return unusedTokens;
4075 }
4076 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4077 if( !m_floatingArg.get() )
4078 return tokens;
4079 std::vector<Parser::Token> unusedTokens;
4080 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4081 Parser::Token const& token = tokens[i];
4082 if( token.type == Parser::Token::Positional )
4083 m_floatingArg->boundField.set( config, token.data );
4084 else
4085 unusedTokens.push_back( token );
4086 }
4087 return unusedTokens;
4088 }
4089
4090 void validate() const
4091 {
4092 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4093 throw std::logic_error( "No options or arguments specified" );
4094
4095 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
4096 itEnd = m_options.end();
4097 it != itEnd; ++it )
4098 it->validate();
4099 }
4100
4101 private:
4102 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4103 std::vector<Arg> m_options;
4104 std::map<int, Arg> m_positionalArgs;
4105 ArgAutoPtr m_floatingArg;
4106 int m_highestSpecifiedArgPosition;
4107 bool m_throwOnUnrecognisedTokens;
4108 };
4109
4110} // end namespace Clara
4111
4112STITCH_CLARA_CLOSE_NAMESPACE
4113#undef STITCH_CLARA_OPEN_NAMESPACE
4114#undef STITCH_CLARA_CLOSE_NAMESPACE
4115
4116#endif // TWOBLUECUBES_CLARA_H_INCLUDED
4117#undef STITCH_CLARA_OPEN_NAMESPACE
4118
4119// Restore Clara's value for console width, if present
4120#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4121#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4122#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4123#endif
4124
4125#include <fstream>
4126
4127namespace Catch {
4128
4129 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
4130 inline void abortAfterX( ConfigData& config, int x ) {
4131 if( x < 1 )
4132 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
4133 config.abortAfter = x;
4134 }
4135 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
4136
4137 inline void addWarning( ConfigData& config, std::string const& _warning ) {
4138 if( _warning == "NoAssertions" )
4139 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
4140 else
4141 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
4142 }
4143 inline void setOrder( ConfigData& config, std::string const& order ) {
4144 if( startsWith( "declared", order ) )
4145 config.runOrder = RunTests::InDeclarationOrder;
4146 else if( startsWith( "lexical", order ) )
4147 config.runOrder = RunTests::InLexicographicalOrder;
4148 else if( startsWith( "random", order ) )
4149 config.runOrder = RunTests::InRandomOrder;
4150 else
4151 throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
4152 }
4153 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
4154 if( seed == "time" ) {
4155 config.rngSeed = static_cast<unsigned int>( std::time(0) );
4156 }
4157 else {
4158 std::stringstream ss;
4159 ss << seed;
4160 ss >> config.rngSeed;
4161 if( ss.fail() )
4162 throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
4163 }
4164 }
4165 inline void setVerbosity( ConfigData& config, int level ) {
4166 // !TBD: accept strings?
4167 config.verbosity = static_cast<Verbosity::Level>( level );
4168 }
4169 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
4170 config.showDurations = _showDurations
4171 ? ShowDurations::Always
4172 : ShowDurations::Never;
4173 }
4174 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
4175 std::ifstream f( _filename.c_str() );
4176 if( !f.is_open() )
4177 throw std::domain_error( "Unable to load input file: " + _filename );
4178
4179 std::string line;
4180 while( std::getline( f, line ) ) {
4181 line = trim(line);
4182 if( !line.empty() && !startsWith( line, "#" ) )
4183 addTestOrTags( config, "\"" + line + "\"," );
4184 }
4185 }
4186
4187 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4188
4189 using namespace Clara;
4190 CommandLine<ConfigData> cli;
4191
4192 cli.bindProcessName( &ConfigData::processName );
4193
4194 cli["-?"]["-h"]["--help"]
4195 .describe( "display usage information" )
4196 .bind( &ConfigData::showHelp );
4197
4198 cli["-l"]["--list-tests"]
4199 .describe( "list all/matching test cases" )
4200 .bind( &ConfigData::listTests );
4201
4202 cli["-t"]["--list-tags"]
4203 .describe( "list all/matching tags" )
4204 .bind( &ConfigData::listTags );
4205
4206 cli["-s"]["--success"]
4207 .describe( "include successful tests in output" )
4208 .bind( &ConfigData::showSuccessfulTests );
4209
4210 cli["-b"]["--break"]
4211 .describe( "break into debugger on failure" )
4212 .bind( &ConfigData::shouldDebugBreak );
4213
4214 cli["-e"]["--nothrow"]
4215 .describe( "skip exception tests" )
4216 .bind( &ConfigData::noThrow );
4217
4218 cli["-i"]["--invisibles"]
4219 .describe( "show invisibles (tabs, newlines)" )
4220 .bind( &ConfigData::showInvisibles );
4221
4222 cli["-o"]["--out"]
4223 .describe( "output filename" )
4224 .bind( &ConfigData::outputFilename, "filename" );
4225
4226 cli["-r"]["--reporter"]
4227// .placeholder( "name[:filename]" )
4228 .describe( "reporter to use (defaults to console)" )
4229 .bind( &ConfigData::reporterName, "name" );
4230
4231 cli["-n"]["--name"]
4232 .describe( "suite name" )
4233 .bind( &ConfigData::name, "name" );
4234
4235 cli["-a"]["--abort"]
4236 .describe( "abort at first failure" )
4237 .bind( &abortAfterFirst );
4238
4239 cli["-x"]["--abortx"]
4240 .describe( "abort after x failures" )
4241 .bind( &abortAfterX, "no. failures" );
4242
4243 cli["-w"]["--warn"]
4244 .describe( "enable warnings" )
4245 .bind( &addWarning, "warning name" );
4246
4247// - needs updating if reinstated
4248// cli.into( &setVerbosity )
4249// .describe( "level of verbosity (0=no output)" )
4250// .shortOpt( "v")
4251// .longOpt( "verbosity" )
4252// .placeholder( "level" );
4253
4254 cli[_]
4255 .describe( "which test or tests to use" )
4256 .bind( &addTestOrTags, "test name, pattern or tags" );
4257
4258 cli["-d"]["--durations"]
4259 .describe( "show test durations" )
4260 .bind( &setShowDurations, "yes/no" );
4261
4262 cli["-f"]["--input-file"]
4263 .describe( "load test names to run from a file" )
4264 .bind( &loadTestNamesFromFile, "filename" );
4265
4266 // Less common commands which don't have a short form
4267 cli["--list-test-names-only"]
4268 .describe( "list all/matching test cases names only" )
4269 .bind( &ConfigData::listTestNamesOnly );
4270
4271 cli["--list-reporters"]
4272 .describe( "list all reporters" )
4273 .bind( &ConfigData::listReporters );
4274
4275 cli["--order"]
4276 .describe( "test case order (defaults to decl)" )
4277 .bind( &setOrder, "decl|lex|rand" );
4278
4279 cli["--rng-seed"]
4280 .describe( "set a specific seed for random numbers" )
4281 .bind( &setRngSeed, "'time'|number" );
4282
4283 cli["--force-colour"]
4284 .describe( "force colourised output" )
4285 .bind( &ConfigData::forceColour );
4286
4287 return cli;
4288 }
4289
4290} // end namespace Catch
4291
4292// #included from: internal/catch_list.hpp
4293#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4294
4295// #included from: catch_text.h
4296#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4297
4298#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4299
4300#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4301// #included from: ../external/tbc_text_format.h
4302// Only use header guard if we are not using an outer namespace
4303#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4304# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4305# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4306# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4307# endif
4308# else
4309# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4310# endif
4311#endif
4312#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4313#include <string>
4314#include <vector>
4315#include <sstream>
4316
4317// Use optional outer namespace
4318#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4319namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4320#endif
4321
4322namespace Tbc {
4323
4324#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4325 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4326#else
4327 const unsigned int consoleWidth = 80;
4328#endif
4329
4330 struct TextAttributes {
4331 TextAttributes()
4332 : initialIndent( std::string::npos ),
4333 indent( 0 ),
4334 width( consoleWidth-1 ),
4335 tabChar( '\t' )
4336 {}
4337
4338 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
4339 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
4340 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
4341 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4342
4343 std::size_t initialIndent; // indent of first line, or npos
4344 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4345 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4346 char tabChar; // If this char is seen the indent is changed to current pos
4347 };
4348
4349 class Text {
4350 public:
4351 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4352 : attr( _attr )
4353 {
4354 std::string wrappableChars = " [({.,/|\\-";
4355 std::size_t indent = _attr.initialIndent != std::string::npos
4356 ? _attr.initialIndent
4357 : _attr.indent;
4358 std::string remainder = _str;
4359
4360 while( !remainder.empty() ) {
4361 if( lines.size() >= 1000 ) {
4362 lines.push_back( "... message truncated due to excessive size" );
4363 return;
4364 }
4365 std::size_t tabPos = std::string::npos;
4366 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4367 std::size_t pos = remainder.find_first_of( '\n' );
4368 if( pos <= width ) {
4369 width = pos;
4370 }
4371 pos = remainder.find_last_of( _attr.tabChar, width );
4372 if( pos != std::string::npos ) {
4373 tabPos = pos;
4374 if( remainder[width] == '\n' )
4375 width--;
4376 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4377 }
4378
4379 if( width == remainder.size() ) {
4380 spliceLine( indent, remainder, width );
4381 }
4382 else if( remainder[width] == '\n' ) {
4383 spliceLine( indent, remainder, width );
4384 if( width <= 1 || remainder.size() != 1 )
4385 remainder = remainder.substr( 1 );
4386 indent = _attr.indent;
4387 }
4388 else {
4389 pos = remainder.find_last_of( wrappableChars, width );
4390 if( pos != std::string::npos && pos > 0 ) {
4391 spliceLine( indent, remainder, pos );
4392 if( remainder[0] == ' ' )
4393 remainder = remainder.substr( 1 );
4394 }
4395 else {
4396 spliceLine( indent, remainder, width-1 );
4397 lines.back() += "-";
4398 }
4399 if( lines.size() == 1 )
4400 indent = _attr.indent;
4401 if( tabPos != std::string::npos )
4402 indent += tabPos;
4403 }
4404 }
4405 }
4406
4407 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4408 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4409 _remainder = _remainder.substr( _pos );
4410 }
4411
4412 typedef std::vector<std::string>::const_iterator const_iterator;
4413
4414 const_iterator begin() const { return lines.begin(); }
4415 const_iterator end() const { return lines.end(); }
4416 std::string const& last() const { return lines.back(); }
4417 std::size_t size() const { return lines.size(); }
4418 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
4419 std::string toString() const {
4420 std::ostringstream oss;
4421 oss << *this;
4422 return oss.str();
4423 }
4424
4425 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4426 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4427 it != itEnd; ++it ) {
4428 if( it != _text.begin() )
4429 _stream << "\n";
4430 _stream << *it;
4431 }
4432 return _stream;
4433 }
4434
4435 private:
4436 std::string str;
4437 TextAttributes attr;
4439 };
4440
4441} // end namespace Tbc
4442
4443#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4444} // end outer namespace
4445#endif
4446
4447#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4448#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4449
4450namespace Catch {
4451 using Tbc::Text;
4452 using Tbc::TextAttributes;
4453}
4454
4455// #included from: catch_console_colour.hpp
4456#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4457
4458namespace Catch {
4459
4460 struct Colour {
4461 enum Code {
4462 None = 0,
4463
4464 White,
4465 Red,
4466 Green,
4467 Blue,
4468 Cyan,
4469 Yellow,
4470 Grey,
4471
4472 Bright = 0x10,
4473
4474 BrightRed = Bright | Red,
4475 BrightGreen = Bright | Green,
4476 LightGrey = Bright | Grey,
4477 BrightWhite = Bright | White,
4478
4479 // By intention
4480 FileName = LightGrey,
4481 Warning = Yellow,
4482 ResultError = BrightRed,
4483 ResultSuccess = BrightGreen,
4484 ResultExpectedFailure = Warning,
4485
4486 Error = BrightRed,
4487 Success = Green,
4488
4489 OriginalExpression = Cyan,
4490 ReconstructedExpression = Yellow,
4491
4492 SecondaryText = LightGrey,
4493 Headers = White
4494 };
4495
4496 // Use constructed object for RAII guard
4497 Colour( Code _colourCode );
4498 Colour( Colour const& other );
4499 ~Colour();
4500
4501 // Use static method for one-shot changes
4502 static void use( Code _colourCode );
4503
4504 private:
4505 bool m_moved;
4506 };
4507
4508 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
4509
4510} // end namespace Catch
4511
4512// #included from: catch_interfaces_reporter.h
4513#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
4514
4515#include <string>
4516#include <ostream>
4517#include <map>
4518#include <assert.h>
4519
4520namespace Catch
4521{
4522 struct ReporterConfig {
4523 explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
4524 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
4525
4526 ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
4527 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
4528
4529 std::ostream& stream() const { return *m_stream; }
4530 Ptr<IConfig> fullConfig() const { return m_fullConfig; }
4531
4532 private:
4533 std::ostream* m_stream;
4534 Ptr<IConfig> m_fullConfig;
4535 };
4536
4537 struct ReporterPreferences {
4538 ReporterPreferences()
4539 : shouldRedirectStdOut( false )
4540 {}
4541
4542 bool shouldRedirectStdOut;
4543 };
4544
4545 template<typename T>
4546 struct LazyStat : Option<T> {
4547 LazyStat() : used( false ) {}
4548 LazyStat& operator=( T const& _value ) {
4549 Option<T>::operator=( _value );
4550 used = false;
4551 return *this;
4552 }
4553 void reset() {
4554 Option<T>::reset();
4555 used = false;
4556 }
4557 bool used;
4558 };
4559
4560 struct TestRunInfo {
4561 TestRunInfo( std::string const& _name ) : name( _name ) {}
4562 std::string name;
4563 };
4564 struct GroupInfo {
4565 GroupInfo( std::string const& _name,
4566 std::size_t _groupIndex,
4567 std::size_t _groupsCount )
4568 : name( _name ),
4569 groupIndex( _groupIndex ),
4570 groupsCounts( _groupsCount )
4571 {}
4572
4573 std::string name;
4574 std::size_t groupIndex;
4575 std::size_t groupsCounts;
4576 };
4577
4578 struct AssertionStats {
4579 AssertionStats( AssertionResult const& _assertionResult,
4580 std::vector<MessageInfo> const& _infoMessages,
4581 Totals const& _totals )
4582 : assertionResult( _assertionResult ),
4583 infoMessages( _infoMessages ),
4584 totals( _totals )
4585 {
4586 if( assertionResult.hasMessage() ) {
4587 // Copy message into messages list.
4588 // !TBD This should have been done earlier, somewhere
4589 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
4590 builder << assertionResult.getMessage();
4591 builder.m_info.message = builder.m_stream.str();
4592
4593 infoMessages.push_back( builder.m_info );
4594 }
4595 }
4596 virtual ~AssertionStats();
4597
4598# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4599 AssertionStats( AssertionStats const& ) = default;
4600 AssertionStats( AssertionStats && ) = default;
4601 AssertionStats& operator = ( AssertionStats const& ) = default;
4602 AssertionStats& operator = ( AssertionStats && ) = default;
4603# endif
4604
4605 AssertionResult assertionResult;
4606 std::vector<MessageInfo> infoMessages;
4607 Totals totals;
4608 };
4609
4610 struct SectionStats {
4611 SectionStats( SectionInfo const& _sectionInfo,
4612 Counts const& _assertions,
4613 double _durationInSeconds,
4614 bool _missingAssertions )
4615 : sectionInfo( _sectionInfo ),
4616 assertions( _assertions ),
4617 durationInSeconds( _durationInSeconds ),
4618 missingAssertions( _missingAssertions )
4619 {}
4620 virtual ~SectionStats();
4621# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4622 SectionStats( SectionStats const& ) = default;
4623 SectionStats( SectionStats && ) = default;
4624 SectionStats& operator = ( SectionStats const& ) = default;
4625 SectionStats& operator = ( SectionStats && ) = default;
4626# endif
4627
4628 SectionInfo sectionInfo;
4629 Counts assertions;
4630 double durationInSeconds;
4631 bool missingAssertions;
4632 };
4633
4634 struct TestCaseStats {
4635 TestCaseStats( TestCaseInfo const& _testInfo,
4636 Totals const& _totals,
4637 std::string const& _stdOut,
4638 std::string const& _stdErr,
4639 bool _aborting )
4640 : testInfo( _testInfo ),
4641 totals( _totals ),
4642 stdOut( _stdOut ),
4643 stdErr( _stdErr ),
4644 aborting( _aborting )
4645 {}
4646 virtual ~TestCaseStats();
4647
4648# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4649 TestCaseStats( TestCaseStats const& ) = default;
4650 TestCaseStats( TestCaseStats && ) = default;
4651 TestCaseStats& operator = ( TestCaseStats const& ) = default;
4652 TestCaseStats& operator = ( TestCaseStats && ) = default;
4653# endif
4654
4655 TestCaseInfo testInfo;
4656 Totals totals;
4657 std::string stdOut;
4658 std::string stdErr;
4659 bool aborting;
4660 };
4661
4662 struct TestGroupStats {
4663 TestGroupStats( GroupInfo const& _groupInfo,
4664 Totals const& _totals,
4665 bool _aborting )
4666 : groupInfo( _groupInfo ),
4667 totals( _totals ),
4668 aborting( _aborting )
4669 {}
4670 TestGroupStats( GroupInfo const& _groupInfo )
4671 : groupInfo( _groupInfo ),
4672 aborting( false )
4673 {}
4674 virtual ~TestGroupStats();
4675
4676# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4677 TestGroupStats( TestGroupStats const& ) = default;
4678 TestGroupStats( TestGroupStats && ) = default;
4679 TestGroupStats& operator = ( TestGroupStats const& ) = default;
4680 TestGroupStats& operator = ( TestGroupStats && ) = default;
4681# endif
4682
4683 GroupInfo groupInfo;
4684 Totals totals;
4685 bool aborting;
4686 };
4687
4688 struct TestRunStats {
4689 TestRunStats( TestRunInfo const& _runInfo,
4690 Totals const& _totals,
4691 bool _aborting )
4692 : runInfo( _runInfo ),
4693 totals( _totals ),
4694 aborting( _aborting )
4695 {}
4696 virtual ~TestRunStats();
4697
4698# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
4699 TestRunStats( TestRunStats const& _other )
4700 : runInfo( _other.runInfo ),
4701 totals( _other.totals ),
4702 aborting( _other.aborting )
4703 {}
4704# else
4705 TestRunStats( TestRunStats const& ) = default;
4706 TestRunStats( TestRunStats && ) = default;
4707 TestRunStats& operator = ( TestRunStats const& ) = default;
4708 TestRunStats& operator = ( TestRunStats && ) = default;
4709# endif
4710
4711 TestRunInfo runInfo;
4712 Totals totals;
4713 bool aborting;
4714 };
4715
4716 struct IStreamingReporter : IShared {
4717 virtual ~IStreamingReporter();
4718
4719 // Implementing class must also provide the following static method:
4720 // static std::string getDescription();
4721
4722 virtual ReporterPreferences getPreferences() const = 0;
4723
4724 virtual void noMatchingTestCases( std::string const& spec ) = 0;
4725
4726 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
4727 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
4728
4729 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
4730 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
4731
4732 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
4733
4734 // The return value indicates if the messages buffer should be cleared:
4735 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
4736 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
4737 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
4738 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
4739 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
4740
4741 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
4742 };
4743
4744 struct IReporterFactory {
4745 virtual ~IReporterFactory();
4746 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
4747 virtual std::string getDescription() const = 0;
4748 };
4749
4750 struct IReporterRegistry {
4751 typedef std::map<std::string, IReporterFactory*> FactoryMap;
4752
4753 virtual ~IReporterRegistry();
4754 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
4755 virtual FactoryMap const& getFactories() const = 0;
4756 };
4757
4758}
4759
4760#include <limits>
4761#include <algorithm>
4762
4763namespace Catch {
4764
4765 inline std::size_t listTests( Config const& config ) {
4766
4767 TestSpec testSpec = config.testSpec();
4768 if( config.testSpec().hasFilters() )
4769 Catch::cout() << "Matching test cases:\n";
4770 else {
4771 Catch::cout() << "All available test cases:\n";
4772 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
4773 }
4774
4775 std::size_t matchedTests = 0;
4776 TextAttributes nameAttr, tagsAttr;
4777 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
4778 tagsAttr.setIndent( 6 );
4779
4780 std::vector<TestCase> matchedTestCases;
4781 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
4782 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
4783 it != itEnd;
4784 ++it ) {
4785 matchedTests++;
4786 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
4787 Colour::Code colour = testCaseInfo.isHidden()
4788 ? Colour::SecondaryText
4789 : Colour::None;
4790 Colour colourGuard( colour );
4791
4792 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
4793 if( !testCaseInfo.tags.empty() )
4794 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
4795 }
4796
4797 if( !config.testSpec().hasFilters() )
4798 Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
4799 else
4800 Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
4801 return matchedTests;
4802 }
4803
4804 inline std::size_t listTestsNamesOnly( Config const& config ) {
4805 TestSpec testSpec = config.testSpec();
4806 if( !config.testSpec().hasFilters() )
4807 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
4808 std::size_t matchedTests = 0;
4809 std::vector<TestCase> matchedTestCases;
4810 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
4811 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
4812 it != itEnd;
4813 ++it ) {
4814 matchedTests++;
4815 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
4816 Catch::cout() << testCaseInfo.name << std::endl;
4817 }
4818 return matchedTests;
4819 }
4820
4821 struct TagInfo {
4822 TagInfo() : count ( 0 ) {}
4823 void add( std::string const& spelling ) {
4824 ++count;
4825 spellings.insert( spelling );
4826 }
4827 std::string all() const {
4828 std::string out;
4829 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
4830 it != itEnd;
4831 ++it )
4832 out += "[" + *it + "]";
4833 return out;
4834 }
4835 std::set<std::string> spellings;
4836 std::size_t count;
4837 };
4838
4839 inline std::size_t listTags( Config const& config ) {
4840 TestSpec testSpec = config.testSpec();
4841 if( config.testSpec().hasFilters() )
4842 Catch::cout() << "Tags for matching test cases:\n";
4843 else {
4844 Catch::cout() << "All available tags:\n";
4845 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
4846 }
4847
4848 std::map<std::string, TagInfo> tagCounts;
4849
4850 std::vector<TestCase> matchedTestCases;
4851 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
4852 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
4853 it != itEnd;
4854 ++it ) {
4855 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4856 tagItEnd = it->getTestCaseInfo().tags.end();
4857 tagIt != tagItEnd;
4858 ++tagIt ) {
4859 std::string tagName = *tagIt;
4860 std::string lcaseTagName = toLower( tagName );
4861 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
4862 if( countIt == tagCounts.end() )
4863 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
4864 countIt->second.add( tagName );
4865 }
4866 }
4867
4868 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
4869 countItEnd = tagCounts.end();
4870 countIt != countItEnd;
4871 ++countIt ) {
4872 std::ostringstream oss;
4873 oss << " " << std::setw(2) << countIt->second.count << " ";
4874 Text wrapper( countIt->second.all(), TextAttributes()
4875 .setInitialIndent( 0 )
4876 .setIndent( oss.str().size() )
4877 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
4878 Catch::cout() << oss.str() << wrapper << "\n";
4879 }
4880 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
4881 return tagCounts.size();
4882 }
4883
4884 inline std::size_t listReporters( Config const& /*config*/ ) {
4885 Catch::cout() << "Available reporters:\n";
4886 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
4887 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
4888 std::size_t maxNameLen = 0;
4889 for(it = itBegin; it != itEnd; ++it )
4890 maxNameLen = (std::max)( maxNameLen, it->first.size() );
4891
4892 for(it = itBegin; it != itEnd; ++it ) {
4893 Text wrapper( it->second->getDescription(), TextAttributes()
4894 .setInitialIndent( 0 )
4895 .setIndent( 7+maxNameLen )
4896 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
4897 Catch::cout() << " "
4898 << it->first
4899 << ":"
4900 << std::string( maxNameLen - it->first.size() + 2, ' ' )
4901 << wrapper << "\n";
4902 }
4904 return factories.size();
4905 }
4906
4907 inline Option<std::size_t> list( Config const& config ) {
4908 Option<std::size_t> listedCount;
4909 if( config.listTests() )
4910 listedCount = listedCount.valueOr(0) + listTests( config );
4911 if( config.listTestNamesOnly() )
4912 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
4913 if( config.listTags() )
4914 listedCount = listedCount.valueOr(0) + listTags( config );
4915 if( config.listReporters() )
4916 listedCount = listedCount.valueOr(0) + listReporters( config );
4917 return listedCount;
4918 }
4919
4920} // end namespace Catch
4921
4922// #included from: internal/catch_runner_impl.hpp
4923#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
4924
4925// #included from: catch_test_case_tracker.hpp
4926#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
4927
4928#include <map>
4929#include <string>
4930#include <assert.h>
4931
4932namespace Catch {
4933namespace SectionTracking {
4934
4935 class TrackedSection {
4936
4937 typedef std::map<std::string, TrackedSection> TrackedSections;
4938
4939 public:
4940 enum RunState {
4941 NotStarted,
4942 Executing,
4943 ExecutingChildren,
4944 Completed
4945 };
4946
4947 TrackedSection( std::string const& name, TrackedSection* parent )
4948 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
4949 {}
4950
4951 RunState runState() const { return m_runState; }
4952
4953 TrackedSection* findChild( std::string const& childName );
4954 TrackedSection* acquireChild( std::string const& childName );
4955
4956 void enter() {
4957 if( m_runState == NotStarted )
4958 m_runState = Executing;
4959 }
4960 void leave();
4961
4962 TrackedSection* getParent() {
4963 return m_parent;
4964 }
4965 bool hasChildren() const {
4966 return !m_children.empty();
4967 }
4968
4969 private:
4970 std::string m_name;
4971 RunState m_runState;
4972 TrackedSections m_children;
4973 TrackedSection* m_parent;
4974 };
4975
4976 inline TrackedSection* TrackedSection::findChild( std::string const& childName ) {
4977 TrackedSections::iterator it = m_children.find( childName );
4978 return it != m_children.end()
4979 ? &it->second
4980 : NULL;
4981 }
4982 inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) {
4983 if( TrackedSection* child = findChild( childName ) )
4984 return child;
4985 m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
4986 return findChild( childName );
4987 }
4988 inline void TrackedSection::leave() {
4989 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
4990 it != itEnd;
4991 ++it )
4992 if( it->second.runState() != Completed ) {
4993 m_runState = ExecutingChildren;
4994 return;
4995 }
4996 m_runState = Completed;
4997 }
4998
4999 class TestCaseTracker {
5000 public:
5001 TestCaseTracker( std::string const& testCaseName )
5002 : m_testCase( testCaseName, NULL ),
5003 m_currentSection( &m_testCase ),
5004 m_completedASectionThisRun( false )
5005 {}
5006
5007 bool enterSection( std::string const& name ) {
5008 TrackedSection* child = m_currentSection->acquireChild( name );
5009 if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
5010 return false;
5011
5012 m_currentSection = child;
5013 m_currentSection->enter();
5014 return true;
5015 }
5016 void leaveSection() {
5017 m_currentSection->leave();
5018 m_currentSection = m_currentSection->getParent();
5019 assert( m_currentSection != NULL );
5020 m_completedASectionThisRun = true;
5021 }
5022
5023 bool currentSectionHasChildren() const {
5024 return m_currentSection->hasChildren();
5025 }
5026 bool isCompleted() const {
5027 return m_testCase.runState() == TrackedSection::Completed;
5028 }
5029
5030 class Guard {
5031 public:
5032 Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
5033 m_tracker.enterTestCase();
5034 }
5035 ~Guard() {
5036 m_tracker.leaveTestCase();
5037 }
5038 private:
5039 Guard( Guard const& );
5040 void operator = ( Guard const& );
5041 TestCaseTracker& m_tracker;
5042 };
5043
5044 private:
5045 void enterTestCase() {
5046 m_currentSection = &m_testCase;
5047 m_completedASectionThisRun = false;
5048 m_testCase.enter();
5049 }
5050 void leaveTestCase() {
5051 m_testCase.leave();
5052 }
5053
5054 TrackedSection m_testCase;
5055 TrackedSection* m_currentSection;
5056 bool m_completedASectionThisRun;
5057 };
5058
5059} // namespace SectionTracking
5060
5061using SectionTracking::TestCaseTracker;
5062
5063} // namespace Catch
5064
5065// #included from: catch_fatal_condition.hpp
5066#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
5067
5068namespace Catch {
5069
5070 // Report the error condition then exit the process
5071 inline void fatal( std::string const& message, int exitCode ) {
5072 IContext& context = Catch::getCurrentContext();
5073 IResultCapture* resultCapture = context.getResultCapture();
5074 resultCapture->handleFatalErrorCondition( message );
5075
5076 if( Catch::alwaysTrue() ) // avoids "no return" warnings
5077 exit( exitCode );
5078 }
5079
5080} // namespace Catch
5081
5082#if defined ( CATCH_PLATFORM_WINDOWS )
5083
5084namespace Catch {
5085
5086 struct FatalConditionHandler {
5087 void reset() {}
5088 };
5089
5090} // namespace Catch
5091
5092#else // Not Windows - assumed to be POSIX compatible //////////////////////////
5093
5094#include <signal.h>
5095
5096namespace Catch {
5097
5098 struct SignalDefs { int id; const char* name; };
5099 extern SignalDefs signalDefs[];
5100 SignalDefs signalDefs[] = {
5101 { SIGINT, "SIGINT - Terminal interrupt signal" },
5102 { SIGILL, "SIGILL - Illegal instruction signal" },
5103 { SIGFPE, "SIGFPE - Floating point error signal" },
5104 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
5105 { SIGTERM, "SIGTERM - Termination request signal" },
5106 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
5107 };
5108
5109 struct FatalConditionHandler {
5110
5111 static void handleSignal( int sig ) {
5112 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5113 if( sig == signalDefs[i].id )
5114 fatal( signalDefs[i].name, -sig );
5115 fatal( "<unknown signal>", -sig );
5116 }
5117
5118 FatalConditionHandler() : m_isSet( true ) {
5119 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5120 signal( signalDefs[i].id, handleSignal );
5121 }
5122 ~FatalConditionHandler() {
5123 reset();
5124 }
5125 void reset() {
5126 if( m_isSet ) {
5127 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5128 signal( signalDefs[i].id, SIG_DFL );
5129 m_isSet = false;
5130 }
5131 }
5132
5133 bool m_isSet;
5134 };
5135
5136} // namespace Catch
5137
5138#endif // not Windows
5139
5140#include <set>
5141#include <string>
5142
5143namespace Catch {
5144
5145 class StreamRedirect {
5146
5147 public:
5148 StreamRedirect( std::ostream& stream, std::string& targetString )
5149 : m_stream( stream ),
5150 m_prevBuf( stream.rdbuf() ),
5151 m_targetString( targetString )
5152 {
5153 stream.rdbuf( m_oss.rdbuf() );
5154 }
5155
5156 ~StreamRedirect() {
5157 m_targetString += m_oss.str();
5158 m_stream.rdbuf( m_prevBuf );
5159 }
5160
5161 private:
5162 std::ostream& m_stream;
5163 std::streambuf* m_prevBuf;
5164 std::ostringstream m_oss;
5165 std::string& m_targetString;
5166 };
5167
5169
5170 class RunContext : public IResultCapture, public IRunner {
5171
5172 RunContext( RunContext const& );
5173 void operator =( RunContext const& );
5174
5175 public:
5176
5177 explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter )
5178 : m_runInfo( config->name() ),
5179 m_context( getCurrentMutableContext() ),
5180 m_activeTestCase( NULL ),
5181 m_config( config ),
5182 m_reporter( reporter ),
5183 m_prevRunner( m_context.getRunner() ),
5184 m_prevResultCapture( m_context.getResultCapture() ),
5185 m_prevConfig( m_context.getConfig() )
5186 {
5187 m_context.setRunner( this );
5188 m_context.setConfig( m_config );
5189 m_context.setResultCapture( this );
5190 m_reporter->testRunStarting( m_runInfo );
5191 }
5192
5193 virtual ~RunContext() {
5194 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
5195 m_context.setRunner( m_prevRunner );
5196 m_context.setConfig( NULL );
5197 m_context.setResultCapture( m_prevResultCapture );
5198 m_context.setConfig( m_prevConfig );
5199 }
5200
5201 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
5202 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
5203 }
5204 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
5205 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
5206 }
5207
5208 Totals runTest( TestCase const& testCase ) {
5209 Totals prevTotals = m_totals;
5210
5211 std::string redirectedCout;
5212 std::string redirectedCerr;
5213
5214 TestCaseInfo testInfo = testCase.getTestCaseInfo();
5215
5216 m_reporter->testCaseStarting( testInfo );
5217
5218 m_activeTestCase = &testCase;
5219 m_testCaseTracker = TestCaseTracker( testInfo.name );
5220
5221 do {
5222 do {
5223 runCurrentTest( redirectedCout, redirectedCerr );
5224 }
5225 while( !m_testCaseTracker->isCompleted() && !aborting() );
5226 }
5227 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
5228
5229 Totals deltaTotals = m_totals.delta( prevTotals );
5230 m_totals.testCases += deltaTotals.testCases;
5231 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5232 deltaTotals,
5233 redirectedCout,
5234 redirectedCerr,
5235 aborting() ) );
5236
5237 m_activeTestCase = NULL;
5238 m_testCaseTracker.reset();
5239
5240 return deltaTotals;
5241 }
5242
5243 Ptr<IConfig const> config() const {
5244 return m_config;
5245 }
5246
5247 private: // IResultCapture
5248
5249 virtual void assertionEnded( AssertionResult const& result ) {
5250 if( result.getResultType() == ResultWas::Ok ) {
5251 m_totals.assertions.passed++;
5252 }
5253 else if( !result.isOk() ) {
5254 m_totals.assertions.failed++;
5255 }
5256
5257 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5258 m_messages.clear();
5259
5260 // Reset working state
5261 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
5262 m_lastResult = result;
5263 }
5264
5265 virtual bool sectionStarted (
5266 SectionInfo const& sectionInfo,
5267 Counts& assertions
5268 )
5269 {
5270 std::ostringstream oss;
5271 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
5272
5273 if( !m_testCaseTracker->enterSection( oss.str() ) )
5274 return false;
5275
5276 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
5277
5278 m_reporter->sectionStarting( sectionInfo );
5279
5280 assertions = m_totals.assertions;
5281
5282 return true;
5283 }
5284 bool testForMissingAssertions( Counts& assertions ) {
5285 if( assertions.total() != 0 ||
5286 !m_config->warnAboutMissingAssertions() ||
5287 m_testCaseTracker->currentSectionHasChildren() )
5288 return false;
5289 m_totals.assertions.failed++;
5290 assertions.failed++;
5291 return true;
5292 }
5293
5294 virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
5295 if( std::uncaught_exception() ) {
5296 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
5297 return;
5298 }
5299
5300 Counts assertions = m_totals.assertions - prevAssertions;
5301 bool missingAssertions = testForMissingAssertions( assertions );
5302
5303 m_testCaseTracker->leaveSection();
5304
5305 m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
5306 m_messages.clear();
5307 }
5308
5309 virtual void pushScopedMessage( MessageInfo const& message ) {
5310 m_messages.push_back( message );
5311 }
5312
5313 virtual void popScopedMessage( MessageInfo const& message ) {
5314 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
5315 }
5316
5317 virtual std::string getCurrentTestName() const {
5318 return m_activeTestCase
5319 ? m_activeTestCase->getTestCaseInfo().name
5320 : "";
5321 }
5322
5323 virtual const AssertionResult* getLastResult() const {
5324 return &m_lastResult;
5325 }
5326
5327 virtual void handleFatalErrorCondition( std::string const& message ) {
5328 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
5329 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
5330 resultBuilder << message;
5331 resultBuilder.captureExpression();
5332
5333 handleUnfinishedSections();
5334
5335 // Recreate section for test case (as we will lose the one that was in scope)
5336 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5337 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5338
5339 Counts assertions;
5340 assertions.failed = 1;
5341 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
5342 m_reporter->sectionEnded( testCaseSectionStats );
5343
5344 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
5345
5346 Totals deltaTotals;
5347 deltaTotals.testCases.failed = 1;
5348 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5349 deltaTotals,
5350 "",
5351 "",
5352 false ) );
5353 m_totals.testCases.failed++;
5354 testGroupEnded( "", m_totals, 1, 1 );
5355 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
5356 }
5357
5358 public:
5359 // !TBD We need to do this another way!
5360 bool aborting() const {
5361 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
5362 }
5363
5364 private:
5365
5366 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
5367 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5368 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5369 m_reporter->sectionStarting( testCaseSection );
5370 Counts prevAssertions = m_totals.assertions;
5371 double duration = 0;
5372 try {
5373 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
5374 TestCaseTracker::Guard guard( *m_testCaseTracker );
5375
5376 Timer timer;
5377 timer.start();
5378 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
5379 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
5380 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
5381 invokeActiveTestCase();
5382 }
5383 else {
5384 invokeActiveTestCase();
5385 }
5386 duration = timer.getElapsedSeconds();
5387 }
5388 catch( TestFailureException& ) {
5389 // This just means the test was aborted due to failure
5390 }
5391 catch(...) {
5392 makeUnexpectedResultBuilder().useActiveException();
5393 }
5394 handleUnfinishedSections();
5395 m_messages.clear();
5396
5397 Counts assertions = m_totals.assertions - prevAssertions;
5398 bool missingAssertions = testForMissingAssertions( assertions );
5399
5400 if( testCaseInfo.okToFail() ) {
5401 std::swap( assertions.failedButOk, assertions.failed );
5402 m_totals.assertions.failed -= assertions.failedButOk;
5403 m_totals.assertions.failedButOk += assertions.failedButOk;
5404 }
5405
5406 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
5407 m_reporter->sectionEnded( testCaseSectionStats );
5408 }
5409
5410 void invokeActiveTestCase() {
5411 FatalConditionHandler fatalConditionHandler; // Handle signals
5412 m_activeTestCase->invoke();
5413 fatalConditionHandler.reset();
5414 }
5415
5416 private:
5417
5418 ResultBuilder makeUnexpectedResultBuilder() const {
5419 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
5420 m_lastAssertionInfo.lineInfo,
5421 m_lastAssertionInfo.capturedExpression.c_str(),
5422 m_lastAssertionInfo.resultDisposition );
5423 }
5424
5425 void handleUnfinishedSections() {
5426 // If sections ended prematurely due to an exception we stored their
5427 // infos here so we can tear them down outside the unwind process.
5428 for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
5429 itEnd = m_unfinishedSections.rend();
5430 it != itEnd;
5431 ++it )
5432 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
5433 m_unfinishedSections.clear();
5434 }
5435
5436 struct UnfinishedSections {
5437 UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
5438 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
5439 {}
5440
5441 SectionInfo info;
5442 Counts prevAssertions;
5443 double durationInSeconds;
5444 };
5445
5446 TestRunInfo m_runInfo;
5447 IMutableContext& m_context;
5448 TestCase const* m_activeTestCase;
5449 Option<TestCaseTracker> m_testCaseTracker;
5450 AssertionResult m_lastResult;
5451
5452 Ptr<IConfig const> m_config;
5453 Totals m_totals;
5454 Ptr<IStreamingReporter> m_reporter;
5455 std::vector<MessageInfo> m_messages;
5456 IRunner* m_prevRunner;
5457 IResultCapture* m_prevResultCapture;
5458 Ptr<IConfig const> m_prevConfig;
5459 AssertionInfo m_lastAssertionInfo;
5460 std::vector<UnfinishedSections> m_unfinishedSections;
5461 };
5462
5463 IResultCapture& getResultCapture() {
5464 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
5465 return *capture;
5466 else
5467 throw std::logic_error( "No result capture instance" );
5468 }
5469
5470} // end namespace Catch
5471
5472// #included from: internal/catch_version.h
5473#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
5474
5475namespace Catch {
5476
5477 // Versioning information
5478 struct Version {
5479 Version( unsigned int _majorVersion,
5480 unsigned int _minorVersion,
5481 unsigned int _patchNumber,
5482 std::string const& _branchName,
5483 unsigned int _buildNumber );
5484
5485 unsigned int const majorVersion;
5486 unsigned int const minorVersion;
5487 unsigned int const patchNumber;
5488
5489 // buildNumber is only used if branchName is not null
5490 std::string const branchName;
5491 unsigned int const buildNumber;
5492
5493 friend std::ostream& operator << ( std::ostream& os, Version const& version );
5494
5495 private:
5496 void operator=( Version const& );
5497 };
5498
5499 extern Version libraryVersion;
5500}
5501
5502#include <fstream>
5503#include <stdlib.h>
5504#include <limits>
5505
5506namespace Catch {
5507
5508 class Runner {
5509
5510 public:
5511 Runner( Ptr<Config> const& config )
5512 : m_config( config )
5513 {
5514 openStream();
5515 makeReporter();
5516 }
5517
5518 Totals runTests() {
5519
5520 RunContext context( m_config.get(), m_reporter );
5521
5522 Totals totals;
5523
5524 context.testGroupStarting( "all tests", 1, 1 ); // deprecated?
5525
5526 TestSpec testSpec = m_config->testSpec();
5527 if( !testSpec.hasFilters() )
5528 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
5529
5530 std::vector<TestCase> testCases;
5531 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
5532
5533 int testsRunForGroup = 0;
5534 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
5535 it != itEnd;
5536 ++it ) {
5537 testsRunForGroup++;
5538 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
5539
5540 if( context.aborting() )
5541 break;
5542
5543 totals += context.runTest( *it );
5544 m_testsAlreadyRun.insert( *it );
5545 }
5546 }
5547 std::vector<TestCase> skippedTestCases;
5548 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true );
5549
5550 for( std::vector<TestCase>::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end();
5551 it != itEnd;
5552 ++it )
5553 m_reporter->skipTest( *it );
5554
5555 context.testGroupEnded( "all tests", totals, 1, 1 );
5556 return totals;
5557 }
5558
5559 private:
5560 void openStream() {
5561 // Open output file, if specified
5562 if( !m_config->getFilename().empty() ) {
5563 m_ofs.open( m_config->getFilename().c_str() );
5564 if( m_ofs.fail() ) {
5565 std::ostringstream oss;
5566 oss << "Unable to open file: '" << m_config->getFilename() << "'";
5567 throw std::domain_error( oss.str() );
5568 }
5569 m_config->setStreamBuf( m_ofs.rdbuf() );
5570 }
5571 }
5572 void makeReporter() {
5573 std::string reporterName = m_config->getReporterName().empty()
5574 ? "console"
5575 : m_config->getReporterName();
5576
5577 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
5578 if( !m_reporter ) {
5579 std::ostringstream oss;
5580 oss << "No reporter registered with name: '" << reporterName << "'";
5581 throw std::domain_error( oss.str() );
5582 }
5583 }
5584
5585 private:
5586 Ptr<Config> m_config;
5587 std::ofstream m_ofs;
5588 Ptr<IStreamingReporter> m_reporter;
5589 std::set<TestCase> m_testsAlreadyRun;
5590 };
5591
5592 class Session : NonCopyable {
5593 static bool alreadyInstantiated;
5594
5595 public:
5596
5597 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
5598
5599 Session()
5600 : m_cli( makeCommandLineParser() ) {
5601 if( alreadyInstantiated ) {
5602 std::string msg = "Only one instance of Catch::Session can ever be used";
5603 Catch::cerr() << msg << std::endl;
5604 throw std::logic_error( msg );
5605 }
5606 alreadyInstantiated = true;
5607 }
5608 ~Session() {
5610 }
5611
5612 void showHelp( std::string const& processName ) {
5613 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
5614
5615 m_cli.usage( Catch::cout(), processName );
5616 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
5617 }
5618
5619 int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
5620 try {
5621 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
5622 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
5623 if( m_configData.showHelp )
5624 showHelp( m_configData.processName );
5625 m_config.reset();
5626 }
5627 catch( std::exception& ex ) {
5628 {
5629 Colour colourGuard( Colour::Red );
5630 Catch::cerr()
5631 << "\nError(s) in input:\n"
5632 << Text( ex.what(), TextAttributes().setIndent(2) )
5633 << "\n\n";
5634 }
5635 m_cli.usage( Catch::cout(), m_configData.processName );
5636 return (std::numeric_limits<int>::max)();
5637 }
5638 return 0;
5639 }
5640
5641 void useConfigData( ConfigData const& _configData ) {
5642 m_configData = _configData;
5643 m_config.reset();
5644 }
5645
5646 int run( int argc, char* const argv[] ) {
5647
5648 int returnCode = applyCommandLine( argc, argv );
5649 if( returnCode == 0 )
5650 returnCode = run();
5651 return returnCode;
5652 }
5653
5654 int run() {
5655 if( m_configData.showHelp )
5656 return 0;
5657
5658 try
5659 {
5660 config(); // Force config to be constructed
5661
5662 std::srand( m_configData.rngSeed );
5663
5664 Runner runner( m_config );
5665
5666 // Handle list request
5667 if( Option<std::size_t> listed = list( config() ) )
5668 return static_cast<int>( *listed );
5669
5670 return static_cast<int>( runner.runTests().assertions.failed );
5671 }
5672 catch( std::exception& ex ) {
5673 Catch::cerr() << ex.what() << std::endl;
5674 return (std::numeric_limits<int>::max)();
5675 }
5676 }
5677
5678 Clara::CommandLine<ConfigData> const& cli() const {
5679 return m_cli;
5680 }
5681 std::vector<Clara::Parser::Token> const& unusedTokens() const {
5682 return m_unusedTokens;
5683 }
5684 ConfigData& configData() {
5685 return m_configData;
5686 }
5687 Config& config() {
5688 if( !m_config )
5689 m_config = new Config( m_configData );
5690 return *m_config;
5691 }
5692
5693 private:
5694 Clara::CommandLine<ConfigData> m_cli;
5695 std::vector<Clara::Parser::Token> m_unusedTokens;
5696 ConfigData m_configData;
5697 Ptr<Config> m_config;
5698 };
5699
5700 bool Session::alreadyInstantiated = false;
5701
5702} // end namespace Catch
5703
5704// #included from: catch_registry_hub.hpp
5705#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
5706
5707// #included from: catch_test_case_registry_impl.hpp
5708#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
5709
5710#include <vector>
5711#include <set>
5712#include <sstream>
5713#include <iostream>
5714#include <algorithm>
5715
5716namespace Catch {
5717
5718 class TestRegistry : public ITestCaseRegistry {
5719 struct LexSort {
5720 bool operator() (TestCase i,TestCase j) const { return (i<j);}
5721 };
5722 struct RandomNumberGenerator {
5723 int operator()( int n ) const { return std::rand() % n; }
5724 };
5725
5726 public:
5727 TestRegistry() : m_unnamedCount( 0 ) {}
5728 virtual ~TestRegistry();
5729
5730 virtual void registerTest( TestCase const& testCase ) {
5731 std::string name = testCase.getTestCaseInfo().name;
5732 if( name == "" ) {
5733 std::ostringstream oss;
5734 oss << "Anonymous test case " << ++m_unnamedCount;
5735 return registerTest( testCase.withName( oss.str() ) );
5736 }
5737
5738 if( m_functions.find( testCase ) == m_functions.end() ) {
5739 m_functions.insert( testCase );
5740 m_functionsInOrder.push_back( testCase );
5741 if( !testCase.isHidden() )
5742 m_nonHiddenFunctions.push_back( testCase );
5743 }
5744 else {
5745 TestCase const& prev = *m_functions.find( testCase );
5746 {
5747 Colour colourGuard( Colour::Red );
5748 Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
5749 << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
5750 << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
5751 }
5752 exit(1);
5753 }
5754 }
5755
5756 virtual std::vector<TestCase> const& getAllTests() const {
5757 return m_functionsInOrder;
5758 }
5759
5760 virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
5761 return m_nonHiddenFunctions;
5762 }
5763
5764 virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const {
5765
5766 for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
5767 itEnd = m_functionsInOrder.end();
5768 it != itEnd;
5769 ++it ) {
5770 bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
5771 if( includeTest != negated )
5772 matchingTestCases.push_back( *it );
5773 }
5774 sortTests( config, matchingTestCases );
5775 }
5776
5777 private:
5778
5779 static void sortTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) {
5780
5781 switch( config.runOrder() ) {
5782 case RunTests::InLexicographicalOrder:
5783 std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() );
5784 break;
5785 case RunTests::InRandomOrder:
5786 {
5787 RandomNumberGenerator rng;
5788 std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng );
5789 }
5790 break;
5791 case RunTests::InDeclarationOrder:
5792 // already in declaration order
5793 break;
5794 }
5795 }
5796 std::set<TestCase> m_functions;
5797 std::vector<TestCase> m_functionsInOrder;
5798 std::vector<TestCase> m_nonHiddenFunctions;
5799 size_t m_unnamedCount;
5800 };
5801
5803
5804 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
5805 public:
5806
5807 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
5808
5809 virtual void invoke() const {
5810 m_fun();
5811 }
5812
5813 private:
5814 virtual ~FreeFunctionTestCase();
5815
5816 TestFunction m_fun;
5817 };
5818
5819 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
5820 std::string className = classOrQualifiedMethodName;
5821 if( startsWith( className, "&" ) )
5822 {
5823 std::size_t lastColons = className.rfind( "::" );
5824 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
5825 if( penultimateColons == std::string::npos )
5826 penultimateColons = 1;
5827 className = className.substr( penultimateColons, lastColons-penultimateColons );
5828 }
5829 return className;
5830 }
5831
5833
5835 SourceLineInfo const& lineInfo,
5836 NameAndDesc const& nameAndDesc ) {
5837 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
5838 }
5839
5841
5842 void AutoReg::registerTestCase( ITestCase* testCase,
5843 char const* classOrQualifiedMethodName,
5844 NameAndDesc const& nameAndDesc,
5845 SourceLineInfo const& lineInfo ) {
5846
5848 ( makeTestCase( testCase,
5849 extractClassName( classOrQualifiedMethodName ),
5850 nameAndDesc.name,
5851 nameAndDesc.description,
5852 lineInfo ) );
5853 }
5854
5855} // end namespace Catch
5856
5857// #included from: catch_reporter_registry.hpp
5858#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
5859
5860#include <map>
5861
5862namespace Catch {
5863
5864 class ReporterRegistry : public IReporterRegistry {
5865
5866 public:
5867
5868 virtual ~ReporterRegistry() {
5869 deleteAllValues( m_factories );
5870 }
5871
5872 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
5873 FactoryMap::const_iterator it = m_factories.find( name );
5874 if( it == m_factories.end() )
5875 return NULL;
5876 return it->second->create( ReporterConfig( config ) );
5877 }
5878
5879 void registerReporter( std::string const& name, IReporterFactory* factory ) {
5880 m_factories.insert( std::make_pair( name, factory ) );
5881 }
5882
5883 FactoryMap const& getFactories() const {
5884 return m_factories;
5885 }
5886
5887 private:
5888 FactoryMap m_factories;
5889 };
5890}
5891
5892// #included from: catch_exception_translator_registry.hpp
5893#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
5894
5895#ifdef __OBJC__
5896#import "Foundation/Foundation.h"
5897#endif
5898
5899namespace Catch {
5900
5901 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
5902 public:
5903 ~ExceptionTranslatorRegistry() {
5904 deleteAll( m_translators );
5905 }
5906
5907 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5908 m_translators.push_back( translator );
5909 }
5910
5911 virtual std::string translateActiveException() const {
5912 try {
5913#ifdef __OBJC__
5914 // In Objective-C try objective-c exceptions first
5915 @try {
5916 throw;
5917 }
5918 @catch (NSException *exception) {
5919 return Catch::toString( [exception description] );
5920 }
5921#else
5922 throw;
5923#endif
5924 }
5925 catch( TestFailureException& ) {
5926 throw;
5927 }
5928 catch( std::exception& ex ) {
5929 return ex.what();
5930 }
5931 catch( std::string& msg ) {
5932 return msg;
5933 }
5934 catch( const char* msg ) {
5935 return msg;
5936 }
5937 catch(...) {
5938 return tryTranslators( m_translators.begin() );
5939 }
5940 }
5941
5942 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
5943 if( it == m_translators.end() )
5944 return "Unknown exception";
5945
5946 try {
5947 return (*it)->translate();
5948 }
5949 catch(...) {
5950 return tryTranslators( it+1 );
5951 }
5952 }
5953
5954 private:
5956 };
5957}
5958
5959namespace Catch {
5960
5961 namespace {
5962
5963 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
5964
5965 RegistryHub( RegistryHub const& );
5966 void operator=( RegistryHub const& );
5967
5968 public: // IRegistryHub
5969 RegistryHub() {
5970 }
5971 virtual IReporterRegistry const& getReporterRegistry() const {
5972 return m_reporterRegistry;
5973 }
5974 virtual ITestCaseRegistry const& getTestCaseRegistry() const {
5975 return m_testCaseRegistry;
5976 }
5977 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
5978 return m_exceptionTranslatorRegistry;
5979 }
5980
5981 public: // IMutableRegistryHub
5982 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
5983 m_reporterRegistry.registerReporter( name, factory );
5984 }
5985 virtual void registerTest( TestCase const& testInfo ) {
5986 m_testCaseRegistry.registerTest( testInfo );
5987 }
5988 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5989 m_exceptionTranslatorRegistry.registerTranslator( translator );
5990 }
5991
5992 private:
5993 TestRegistry m_testCaseRegistry;
5994 ReporterRegistry m_reporterRegistry;
5995 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5996 };
5997
5998 // Single, global, instance
5999 inline RegistryHub*& getTheRegistryHub() {
6000 static RegistryHub* theRegistryHub = NULL;
6001 if( !theRegistryHub )
6002 theRegistryHub = new RegistryHub();
6003 return theRegistryHub;
6004 }
6005 }
6006
6007 IRegistryHub& getRegistryHub() {
6008 return *getTheRegistryHub();
6009 }
6010 IMutableRegistryHub& getMutableRegistryHub() {
6011 return *getTheRegistryHub();
6012 }
6013 void cleanUp() {
6014 delete getTheRegistryHub();
6015 getTheRegistryHub() = NULL;
6017 }
6018 std::string translateActiveException() {
6020 }
6021
6022} // end namespace Catch
6023
6024// #included from: catch_notimplemented_exception.hpp
6025#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6026
6027#include <ostream>
6028
6029namespace Catch {
6030
6031 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
6032 : m_lineInfo( lineInfo ) {
6033 std::ostringstream oss;
6034 oss << lineInfo << ": function ";
6035 oss << "not implemented";
6036 m_what = oss.str();
6037 }
6038
6039 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
6040 return m_what.c_str();
6041 }
6042
6043} // end namespace Catch
6044
6045// #included from: catch_context_impl.hpp
6046#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
6047
6048// #included from: catch_stream.hpp
6049#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6050
6051// #included from: catch_streambuf.h
6052#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
6053
6054#include <streambuf>
6055
6056namespace Catch {
6057
6058 class StreamBufBase : public std::streambuf {
6059 public:
6060 virtual ~StreamBufBase() CATCH_NOEXCEPT;
6061 };
6062}
6063
6064#include <stdexcept>
6065#include <cstdio>
6066#include <iostream>
6067
6068namespace Catch {
6069
6070 template<typename WriterF, size_t bufferSize=256>
6071 class StreamBufImpl : public StreamBufBase {
6072 char data[bufferSize];
6073 WriterF m_writer;
6074
6075 public:
6076 StreamBufImpl() {
6077 setp( data, data + sizeof(data) );
6078 }
6079
6080 ~StreamBufImpl() CATCH_NOEXCEPT {
6081 sync();
6082 }
6083
6084 private:
6085 int overflow( int c ) {
6086 sync();
6087
6088 if( c != EOF ) {
6089 if( pbase() == epptr() )
6090 m_writer( std::string( 1, static_cast<char>( c ) ) );
6091 else
6092 sputc( static_cast<char>( c ) );
6093 }
6094 return 0;
6095 }
6096
6097 int sync() {
6098 if( pbase() != pptr() ) {
6099 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
6100 setp( pbase(), epptr() );
6101 }
6102 return 0;
6103 }
6104 };
6105
6107
6108 struct OutputDebugWriter {
6109
6110 void operator()( std::string const&str ) {
6111 writeToDebugConsole( str );
6112 }
6113 };
6114
6115 Stream::Stream()
6116 : streamBuf( NULL ), isOwned( false )
6117 {}
6118
6119 Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
6120 : streamBuf( _streamBuf ), isOwned( _isOwned )
6121 {}
6122
6123 void Stream::release() {
6124 if( isOwned ) {
6125 delete streamBuf;
6126 streamBuf = NULL;
6127 isOwned = false;
6128 }
6129 }
6130
6131#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
6132 std::ostream& cout() {
6133 return std::cout;
6134 }
6135 std::ostream& cerr() {
6136 return std::cerr;
6137 }
6138#endif
6139}
6140
6141namespace Catch {
6142
6143 class Context : public IMutableContext {
6144
6145 Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
6146 Context( Context const& );
6147 void operator=( Context const& );
6148
6149 public: // IContext
6150 virtual IResultCapture* getResultCapture() {
6151 return m_resultCapture;
6152 }
6153 virtual IRunner* getRunner() {
6154 return m_runner;
6155 }
6156 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
6157 return getGeneratorsForCurrentTest()
6158 .getGeneratorInfo( fileInfo, totalSize )
6159 .getCurrentIndex();
6160 }
6161 virtual bool advanceGeneratorsForCurrentTest() {
6162 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6163 return generators && generators->moveNext();
6164 }
6165
6166 virtual Ptr<IConfig const> getConfig() const {
6167 return m_config;
6168 }
6169
6170 public: // IMutableContext
6171 virtual void setResultCapture( IResultCapture* resultCapture ) {
6172 m_resultCapture = resultCapture;
6173 }
6174 virtual void setRunner( IRunner* runner ) {
6175 m_runner = runner;
6176 }
6177 virtual void setConfig( Ptr<IConfig const> const& config ) {
6178 m_config = config;
6179 }
6180
6181 friend IMutableContext& getCurrentMutableContext();
6182
6183 private:
6184 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6185 std::string testName = getResultCapture()->getCurrentTestName();
6186
6187 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6188 m_generatorsByTestName.find( testName );
6189 return it != m_generatorsByTestName.end()
6190 ? it->second
6191 : NULL;
6192 }
6193
6194 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6195 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6196 if( !generators ) {
6197 std::string testName = getResultCapture()->getCurrentTestName();
6198 generators = createGeneratorsForTest();
6199 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6200 }
6201 return *generators;
6202 }
6203
6204 private:
6205 Ptr<IConfig const> m_config;
6206 IRunner* m_runner;
6207 IResultCapture* m_resultCapture;
6208 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6209 };
6210
6211 namespace {
6212 Context* currentContext = NULL;
6213 }
6214 IMutableContext& getCurrentMutableContext() {
6215 if( !currentContext )
6216 currentContext = new Context();
6217 return *currentContext;
6218 }
6219 IContext& getCurrentContext() {
6220 return getCurrentMutableContext();
6221 }
6222
6223 Stream createStream( std::string const& streamName ) {
6224 if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false );
6225 if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false );
6226 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
6227
6228 throw std::domain_error( "Unknown stream: " + streamName );
6229 }
6230
6231 void cleanUpContext() {
6232 delete currentContext;
6233 currentContext = NULL;
6234 }
6235}
6236
6237// #included from: catch_console_colour_impl.hpp
6238#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
6239
6240namespace Catch {
6241 namespace {
6242
6243 struct IColourImpl {
6244 virtual ~IColourImpl() {}
6245 virtual void use( Colour::Code _colourCode ) = 0;
6246 };
6247
6248 struct NoColourImpl : IColourImpl {
6249 void use( Colour::Code ) {}
6250
6251 static IColourImpl* instance() {
6252 static NoColourImpl s_instance;
6253 return &s_instance;
6254 }
6255 };
6256
6257 } // anon namespace
6258} // namespace Catch
6259
6260#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6261# ifdef CATCH_PLATFORM_WINDOWS
6262# define CATCH_CONFIG_COLOUR_WINDOWS
6263# else
6264# define CATCH_CONFIG_COLOUR_ANSI
6265# endif
6266#endif
6267
6268#if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
6269
6270#ifndef NOMINMAX
6271#define NOMINMAX
6272#endif
6273
6274#ifdef __AFXDLL
6275#include <AfxWin.h>
6276#else
6277#include <windows.h>
6278#endif
6279
6280namespace Catch {
6281namespace {
6282
6283 class Win32ColourImpl : public IColourImpl {
6284 public:
6285 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6286 {
6287 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6288 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6289 originalAttributes = csbiInfo.wAttributes;
6290 }
6291
6292 virtual void use( Colour::Code _colourCode ) {
6293 switch( _colourCode ) {
6294 case Colour::None: return setTextAttribute( originalAttributes );
6295 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6296 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
6297 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
6298 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
6299 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6300 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6301 case Colour::Grey: return setTextAttribute( 0 );
6302
6303 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
6304 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6305 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6306 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6307
6308 case Colour::Bright: throw std::logic_error( "not a colour" );
6309 }
6310 }
6311
6312 private:
6313 void setTextAttribute( WORD _textAttribute ) {
6314 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
6315 }
6316 HANDLE stdoutHandle;
6317 WORD originalAttributes;
6318 };
6319
6320 IColourImpl* platformColourInstance() {
6321 static Win32ColourImpl s_instance;
6322 return &s_instance;
6323 }
6324
6325} // end anon namespace
6326} // end namespace Catch
6327
6328#elif defined( CATCH_CONFIG_COLOUR_ANSI )
6329
6330#include <unistd.h>
6331
6332namespace Catch {
6333namespace {
6334
6335 // use POSIX/ ANSI console terminal codes
6336 // Thanks to Adam Strzelecki for original contribution
6337 // (http://github.com/nanoant)
6338 // https://github.com/philsquared/Catch/pull/131
6339 class PosixColourImpl : public IColourImpl {
6340 public:
6341 virtual void use( Colour::Code _colourCode ) {
6342 switch( _colourCode ) {
6343 case Colour::None:
6344 case Colour::White: return setColour( "[0m" );
6345 case Colour::Red: return setColour( "[0;31m" );
6346 case Colour::Green: return setColour( "[0;32m" );
6347 case Colour::Blue: return setColour( "[0:34m" );
6348 case Colour::Cyan: return setColour( "[0;36m" );
6349 case Colour::Yellow: return setColour( "[0;33m" );
6350 case Colour::Grey: return setColour( "[1;30m" );
6351
6352 case Colour::LightGrey: return setColour( "[0;37m" );
6353 case Colour::BrightRed: return setColour( "[1;31m" );
6354 case Colour::BrightGreen: return setColour( "[1;32m" );
6355 case Colour::BrightWhite: return setColour( "[1;37m" );
6356
6357 case Colour::Bright: throw std::logic_error( "not a colour" );
6358 }
6359 }
6360 static IColourImpl* instance() {
6361 static PosixColourImpl s_instance;
6362 return &s_instance;
6363 }
6364
6365 private:
6366 void setColour( const char* _escapeCode ) {
6367 Catch::cout() << '\033' << _escapeCode;
6368 }
6369 };
6370
6371 IColourImpl* platformColourInstance() {
6372 Ptr<IConfig const> config = getCurrentContext().getConfig();
6373 return (config && config->forceColour()) || isatty(STDOUT_FILENO)
6374 ? PosixColourImpl::instance()
6375 : NoColourImpl::instance();
6376 }
6377
6378} // end anon namespace
6379} // end namespace Catch
6380
6381#else // not Windows or ANSI ///////////////////////////////////////////////
6382
6383namespace Catch {
6384
6385 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
6386
6387} // end namespace Catch
6388
6389#endif // Windows/ ANSI/ None
6390
6391namespace Catch {
6392
6393 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
6394 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
6395 Colour::~Colour(){ if( !m_moved ) use( None ); }
6396
6397 void Colour::use( Code _colourCode ) {
6398 static IColourImpl* impl = isDebuggerActive()
6399 ? NoColourImpl::instance()
6400 : platformColourInstance();
6401 impl->use( _colourCode );
6402 }
6403
6404} // end namespace Catch
6405
6406// #included from: catch_generators_impl.hpp
6407#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
6408
6409#include <vector>
6410#include <string>
6411#include <map>
6412
6413namespace Catch {
6414
6415 struct GeneratorInfo : IGeneratorInfo {
6416
6417 GeneratorInfo( std::size_t size )
6418 : m_size( size ),
6419 m_currentIndex( 0 )
6420 {}
6421
6422 bool moveNext() {
6423 if( ++m_currentIndex == m_size ) {
6424 m_currentIndex = 0;
6425 return false;
6426 }
6427 return true;
6428 }
6429
6430 std::size_t getCurrentIndex() const {
6431 return m_currentIndex;
6432 }
6433
6434 std::size_t m_size;
6435 std::size_t m_currentIndex;
6436 };
6437
6439
6440 class GeneratorsForTest : public IGeneratorsForTest {
6441
6442 public:
6443 ~GeneratorsForTest() {
6444 deleteAll( m_generatorsInOrder );
6445 }
6446
6447 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
6448 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
6449 if( it == m_generatorsByName.end() ) {
6450 IGeneratorInfo* info = new GeneratorInfo( size );
6451 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
6452 m_generatorsInOrder.push_back( info );
6453 return *info;
6454 }
6455 return *it->second;
6456 }
6457
6458 bool moveNext() {
6459 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
6460 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
6461 for(; it != itEnd; ++it ) {
6462 if( (*it)->moveNext() )
6463 return true;
6464 }
6465 return false;
6466 }
6467
6468 private:
6469 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
6470 std::vector<IGeneratorInfo*> m_generatorsInOrder;
6471 };
6472
6473 IGeneratorsForTest* createGeneratorsForTest()
6474 {
6475 return new GeneratorsForTest();
6476 }
6477
6478} // end namespace Catch
6479
6480// #included from: catch_assertionresult.hpp
6481#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
6482
6483namespace Catch {
6484
6485 AssertionInfo::AssertionInfo( std::string const& _macroName,
6486 SourceLineInfo const& _lineInfo,
6487 std::string const& _capturedExpression,
6488 ResultDisposition::Flags _resultDisposition )
6489 : macroName( _macroName ),
6490 lineInfo( _lineInfo ),
6491 capturedExpression( _capturedExpression ),
6492 resultDisposition( _resultDisposition )
6493 {}
6494
6495 AssertionResult::AssertionResult() {}
6496
6497 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
6498 : m_info( info ),
6499 m_resultData( data )
6500 {}
6501
6502 AssertionResult::~AssertionResult() {}
6503
6504 // Result was a success
6505 bool AssertionResult::succeeded() const {
6506 return Catch::isOk( m_resultData.resultType );
6507 }
6508
6509 // Result was a success, or failure is suppressed
6510 bool AssertionResult::isOk() const {
6511 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
6512 }
6513
6514 ResultWas::OfType AssertionResult::getResultType() const {
6515 return m_resultData.resultType;
6516 }
6517
6518 bool AssertionResult::hasExpression() const {
6519 return !m_info.capturedExpression.empty();
6520 }
6521
6522 bool AssertionResult::hasMessage() const {
6523 return !m_resultData.message.empty();
6524 }
6525
6526 std::string AssertionResult::getExpression() const {
6527 if( isFalseTest( m_info.resultDisposition ) )
6528 return "!" + m_info.capturedExpression;
6529 else
6530 return m_info.capturedExpression;
6531 }
6532 std::string AssertionResult::getExpressionInMacro() const {
6533 if( m_info.macroName.empty() )
6534 return m_info.capturedExpression;
6535 else
6536 return m_info.macroName + "( " + m_info.capturedExpression + " )";
6537 }
6538
6539 bool AssertionResult::hasExpandedExpression() const {
6540 return hasExpression() && getExpandedExpression() != getExpression();
6541 }
6542
6543 std::string AssertionResult::getExpandedExpression() const {
6544 return m_resultData.reconstructedExpression;
6545 }
6546
6547 std::string AssertionResult::getMessage() const {
6548 return m_resultData.message;
6549 }
6550 SourceLineInfo AssertionResult::getSourceInfo() const {
6551 return m_info.lineInfo;
6552 }
6553
6554 std::string AssertionResult::getTestMacroName() const {
6555 return m_info.macroName;
6556 }
6557
6558} // end namespace Catch
6559
6560// #included from: catch_test_case_info.hpp
6561#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
6562
6563namespace Catch {
6564
6565 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
6566 if( startsWith( tag, "." ) ||
6567 tag == "hide" ||
6568 tag == "!hide" )
6570 else if( tag == "!throws" )
6571 return TestCaseInfo::Throws;
6572 else if( tag == "!shouldfail" )
6574 else if( tag == "!mayfail" )
6575 return TestCaseInfo::MayFail;
6576 else
6577 return TestCaseInfo::None;
6578 }
6579 inline bool isReservedTag( std::string const& tag ) {
6580 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
6581 }
6582 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
6583 if( isReservedTag( tag ) ) {
6584 {
6585 Colour colourGuard( Colour::Red );
6586 Catch::cerr()
6587 << "Tag name [" << tag << "] not allowed.\n"
6588 << "Tag names starting with non alpha-numeric characters are reserved\n";
6589 }
6590 {
6591 Colour colourGuard( Colour::FileName );
6592 Catch::cerr() << _lineInfo << std::endl;
6593 }
6594 exit(1);
6595 }
6596 }
6597
6598 TestCase makeTestCase( ITestCase* _testCase,
6599 std::string const& _className,
6600 std::string const& _name,
6601 std::string const& _descOrTags,
6602 SourceLineInfo const& _lineInfo )
6603 {
6604 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
6605
6606 // Parse out tags
6607 std::set<std::string> tags;
6608 std::string desc, tag;
6609 bool inTag = false;
6610 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
6611 char c = _descOrTags[i];
6612 if( !inTag ) {
6613 if( c == '[' )
6614 inTag = true;
6615 else
6616 desc += c;
6617 }
6618 else {
6619 if( c == ']' ) {
6620 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
6621 if( prop == TestCaseInfo::IsHidden )
6622 isHidden = true;
6623 else if( prop == TestCaseInfo::None )
6624 enforceNotReservedTag( tag, _lineInfo );
6625
6626 tags.insert( tag );
6627 tag.clear();
6628 inTag = false;
6629 }
6630 else
6631 tag += c;
6632 }
6633 }
6634 if( isHidden ) {
6635 tags.insert( "hide" );
6636 tags.insert( "." );
6637 }
6638
6639 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
6640 return TestCase( _testCase, info );
6641 }
6642
6643 TestCaseInfo::TestCaseInfo( std::string const& _name,
6644 std::string const& _className,
6645 std::string const& _description,
6646 std::set<std::string> const& _tags,
6647 SourceLineInfo const& _lineInfo )
6648 : name( _name ),
6649 className( _className ),
6650 description( _description ),
6651 tags( _tags ),
6652 lineInfo( _lineInfo ),
6653 properties( None )
6654 {
6655 std::ostringstream oss;
6656 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
6657 oss << "[" << *it << "]";
6658 std::string lcaseTag = toLower( *it );
6659 properties = static_cast<SpecialProperties>( properties | parseSpecialTag( lcaseTag ) );
6660 lcaseTags.insert( lcaseTag );
6661 }
6662 tagsAsString = oss.str();
6663 }
6664
6665 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
6666 : name( other.name ),
6667 className( other.className ),
6668 description( other.description ),
6669 tags( other.tags ),
6670 lcaseTags( other.lcaseTags ),
6671 tagsAsString( other.tagsAsString ),
6672 lineInfo( other.lineInfo ),
6673 properties( other.properties )
6674 {}
6675
6676 bool TestCaseInfo::isHidden() const {
6677 return ( properties & IsHidden ) != 0;
6678 }
6679 bool TestCaseInfo::throws() const {
6680 return ( properties & Throws ) != 0;
6681 }
6682 bool TestCaseInfo::okToFail() const {
6683 return ( properties & (ShouldFail | MayFail ) ) != 0;
6684 }
6685 bool TestCaseInfo::expectedToFail() const {
6686 return ( properties & (ShouldFail ) ) != 0;
6687 }
6688
6689 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
6690
6691 TestCase::TestCase( TestCase const& other )
6692 : TestCaseInfo( other ),
6693 test( other.test )
6694 {}
6695
6696 TestCase TestCase::withName( std::string const& _newName ) const {
6697 TestCase other( *this );
6698 other.name = _newName;
6699 return other;
6700 }
6701
6702 void TestCase::swap( TestCase& other ) {
6703 test.swap( other.test );
6704 name.swap( other.name );
6705 className.swap( other.className );
6706 description.swap( other.description );
6707 tags.swap( other.tags );
6708 lcaseTags.swap( other.lcaseTags );
6709 tagsAsString.swap( other.tagsAsString );
6710 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
6711 std::swap( lineInfo, other.lineInfo );
6712 }
6713
6714 void TestCase::invoke() const {
6715 test->invoke();
6716 }
6717
6718 bool TestCase::operator == ( TestCase const& other ) const {
6719 return test.get() == other.test.get() &&
6720 name == other.name &&
6721 className == other.className;
6722 }
6723
6724 bool TestCase::operator < ( TestCase const& other ) const {
6725 return name < other.name;
6726 }
6727 TestCase& TestCase::operator = ( TestCase const& other ) {
6728 TestCase temp( other );
6729 swap( temp );
6730 return *this;
6731 }
6732
6733 TestCaseInfo const& TestCase::getTestCaseInfo() const
6734 {
6735 return *this;
6736 }
6737
6738} // end namespace Catch
6739
6740// #included from: catch_version.hpp
6741#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
6742
6743namespace Catch {
6744
6745 Version::Version
6746 ( unsigned int _majorVersion,
6747 unsigned int _minorVersion,
6748 unsigned int _patchNumber,
6749 std::string const& _branchName,
6750 unsigned int _buildNumber )
6751 : majorVersion( _majorVersion ),
6752 minorVersion( _minorVersion ),
6753 patchNumber( _patchNumber ),
6754 branchName( _branchName ),
6755 buildNumber( _buildNumber )
6756 {}
6757
6758 std::ostream& operator << ( std::ostream& os, Version const& version ) {
6759 os << version.majorVersion << "."
6760 << version.minorVersion << "."
6761 << version.patchNumber;
6762
6763 if( !version.branchName.empty() ) {
6764 os << "-" << version.branchName
6765 << "." << version.buildNumber;
6766 }
6767 return os;
6768 }
6769
6770 Version libraryVersion( 1, 2, 1, "", 0 );
6771
6772}
6773
6774// #included from: catch_message.hpp
6775#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
6776
6777namespace Catch {
6778
6779 MessageInfo::MessageInfo( std::string const& _macroName,
6780 SourceLineInfo const& _lineInfo,
6781 ResultWas::OfType _type )
6782 : macroName( _macroName ),
6783 lineInfo( _lineInfo ),
6784 type( _type ),
6785 sequence( ++globalCount )
6786 {}
6787
6788 // This may need protecting if threading support is added
6789 unsigned int MessageInfo::globalCount = 0;
6790
6792
6793 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
6794 : m_info( builder.m_info )
6795 {
6796 m_info.message = builder.m_stream.str();
6798 }
6799 ScopedMessage::ScopedMessage( ScopedMessage const& other )
6800 : m_info( other.m_info )
6801 {}
6802
6803 ScopedMessage::~ScopedMessage() {
6805 }
6806
6807} // end namespace Catch
6808
6809// #included from: catch_legacy_reporter_adapter.hpp
6810#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
6811
6812// #included from: catch_legacy_reporter_adapter.h
6813#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
6814
6815namespace Catch
6816{
6817 // Deprecated
6818 struct IReporter : IShared {
6819 virtual ~IReporter();
6820
6821 virtual bool shouldRedirectStdout() const = 0;
6822
6823 virtual void StartTesting() = 0;
6824 virtual void EndTesting( Totals const& totals ) = 0;
6825 virtual void StartGroup( std::string const& groupName ) = 0;
6826 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
6827 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
6828 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
6829 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
6830 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
6831 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
6832 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
6833 virtual void Aborted() = 0;
6834 virtual void Result( AssertionResult const& result ) = 0;
6835 };
6836
6837 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
6838 {
6839 public:
6840 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
6841 virtual ~LegacyReporterAdapter();
6842
6843 virtual ReporterPreferences getPreferences() const;
6844 virtual void noMatchingTestCases( std::string const& );
6845 virtual void testRunStarting( TestRunInfo const& );
6846 virtual void testGroupStarting( GroupInfo const& groupInfo );
6847 virtual void testCaseStarting( TestCaseInfo const& testInfo );
6848 virtual void sectionStarting( SectionInfo const& sectionInfo );
6849 virtual void assertionStarting( AssertionInfo const& );
6850 virtual bool assertionEnded( AssertionStats const& assertionStats );
6851 virtual void sectionEnded( SectionStats const& sectionStats );
6852 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
6853 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
6854 virtual void testRunEnded( TestRunStats const& testRunStats );
6855 virtual void skipTest( TestCaseInfo const& );
6856
6857 private:
6858 Ptr<IReporter> m_legacyReporter;
6859 };
6860}
6861
6862namespace Catch
6863{
6864 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
6865 : m_legacyReporter( legacyReporter )
6866 {}
6867 LegacyReporterAdapter::~LegacyReporterAdapter() {}
6868
6869 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
6870 ReporterPreferences prefs;
6871 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
6872 return prefs;
6873 }
6874
6875 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
6876 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
6877 m_legacyReporter->StartTesting();
6878 }
6879 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
6880 m_legacyReporter->StartGroup( groupInfo.name );
6881 }
6882 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
6883 m_legacyReporter->StartTestCase( testInfo );
6884 }
6885 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
6886 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
6887 }
6888 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
6889 // Not on legacy interface
6890 }
6891
6892 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
6893 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
6894 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
6895 it != itEnd;
6896 ++it ) {
6897 if( it->type == ResultWas::Info ) {
6898 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
6899 rb << it->message;
6900 rb.setResultType( ResultWas::Info );
6901 AssertionResult result = rb.build();
6902 m_legacyReporter->Result( result );
6903 }
6904 }
6905 }
6906 m_legacyReporter->Result( assertionStats.assertionResult );
6907 return true;
6908 }
6909 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
6910 if( sectionStats.missingAssertions )
6911 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
6912 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
6913 }
6914 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
6915 m_legacyReporter->EndTestCase
6916 ( testCaseStats.testInfo,
6917 testCaseStats.totals,
6918 testCaseStats.stdOut,
6919 testCaseStats.stdErr );
6920 }
6921 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
6922 if( testGroupStats.aborting )
6923 m_legacyReporter->Aborted();
6924 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
6925 }
6926 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
6927 m_legacyReporter->EndTesting( testRunStats.totals );
6928 }
6929 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
6930 }
6931}
6932
6933// #included from: catch_timer.hpp
6934
6935#ifdef __clang__
6936#pragma clang diagnostic push
6937#pragma clang diagnostic ignored "-Wc++11-long-long"
6938#endif
6939
6940#ifdef CATCH_PLATFORM_WINDOWS
6941#include <windows.h>
6942#else
6943#include <sys/time.h>
6944#endif
6945
6946namespace Catch {
6947
6948 namespace {
6949#ifdef CATCH_PLATFORM_WINDOWS
6950 uint64_t getCurrentTicks() {
6951 static uint64_t hz=0, hzo=0;
6952 if (!hz) {
6953 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
6954 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
6955 }
6956 uint64_t t;
6957 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
6958 return ((t-hzo)*1000000)/hz;
6959 }
6960#else
6961 uint64_t getCurrentTicks() {
6962 timeval t;
6963 gettimeofday(&t,NULL);
6964 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
6965 }
6966#endif
6967 }
6968
6969 void Timer::start() {
6970 m_ticks = getCurrentTicks();
6971 }
6972 unsigned int Timer::getElapsedMicroseconds() const {
6973 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
6974 }
6975 unsigned int Timer::getElapsedMilliseconds() const {
6976 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
6977 }
6978 double Timer::getElapsedSeconds() const {
6979 return getElapsedMicroseconds()/1000000.0;
6980 }
6981
6982} // namespace Catch
6983
6984#ifdef __clang__
6985#pragma clang diagnostic pop
6986#endif
6987// #included from: catch_common.hpp
6988#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
6989
6990namespace Catch {
6991
6992 bool startsWith( std::string const& s, std::string const& prefix ) {
6993 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
6994 }
6995 bool endsWith( std::string const& s, std::string const& suffix ) {
6996 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
6997 }
6998 bool contains( std::string const& s, std::string const& infix ) {
6999 return s.find( infix ) != std::string::npos;
7000 }
7001 void toLowerInPlace( std::string& s ) {
7002 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
7003 }
7004 std::string toLower( std::string const& s ) {
7005 std::string lc = s;
7006 toLowerInPlace( lc );
7007 return lc;
7008 }
7009 std::string trim( std::string const& str ) {
7010 static char const* whitespaceChars = "\n\r\t ";
7011 std::string::size_type start = str.find_first_not_of( whitespaceChars );
7012 std::string::size_type end = str.find_last_not_of( whitespaceChars );
7013
7014 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
7015 }
7016
7017 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
7018 bool replaced = false;
7019 std::size_t i = str.find( replaceThis );
7020 while( i != std::string::npos ) {
7021 replaced = true;
7022 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
7023 if( i < str.size()-withThis.size() )
7024 i = str.find( replaceThis, i+withThis.size() );
7025 else
7026 i = std::string::npos;
7027 }
7028 return replaced;
7029 }
7030
7031 pluralise::pluralise( std::size_t count, std::string const& label )
7032 : m_count( count ),
7033 m_label( label )
7034 {}
7035
7036 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
7037 os << pluraliser.m_count << " " << pluraliser.m_label;
7038 if( pluraliser.m_count != 1 )
7039 os << "s";
7040 return os;
7041 }
7042
7043 SourceLineInfo::SourceLineInfo() : line( 0 ){}
7044 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
7045 : file( _file ),
7046 line( _line )
7047 {}
7048 SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
7049 : file( other.file ),
7050 line( other.line )
7051 {}
7052 bool SourceLineInfo::empty() const {
7053 return file.empty();
7054 }
7055 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
7056 return line == other.line && file == other.file;
7057 }
7058 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
7059 return line < other.line || ( line == other.line && file < other.file );
7060 }
7061
7062 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
7063#ifndef __GNUG__
7064 os << info.file << "(" << info.line << ")";
7065#else
7066 os << info.file << ":" << info.line;
7067#endif
7068 return os;
7069 }
7070
7071 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
7072 std::ostringstream oss;
7073 oss << locationInfo << ": Internal Catch error: '" << message << "'";
7074 if( alwaysTrue() )
7075 throw std::logic_error( oss.str() );
7076 }
7077}
7078
7079// #included from: catch_section.hpp
7080#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
7081
7082namespace Catch {
7083
7085 ( SourceLineInfo const& _lineInfo,
7086 std::string const& _name,
7087 std::string const& _description )
7088 : name( _name ),
7089 description( _description ),
7090 lineInfo( _lineInfo )
7091 {}
7092
7093 Section::Section( SectionInfo const& info )
7094 : m_info( info ),
7095 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
7096 {
7097 m_timer.start();
7098 }
7099
7100 Section::~Section() {
7101 if( m_sectionIncluded )
7102 getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
7103 }
7104
7105 // This indicates whether the section should be executed or not
7106 Section::operator bool() const {
7107 return m_sectionIncluded;
7108 }
7109
7110} // end namespace Catch
7111
7112// #included from: catch_debugger.hpp
7113#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
7114
7115#include <iostream>
7116
7117#ifdef CATCH_PLATFORM_MAC
7118
7119 #include <assert.h>
7120 #include <stdbool.h>
7121 #include <sys/types.h>
7122 #include <unistd.h>
7123 #include <sys/sysctl.h>
7124
7125 namespace Catch{
7126
7127 // The following function is taken directly from the following technical note:
7128 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
7129
7130 // Returns true if the current process is being debugged (either
7131 // running under the debugger or has a debugger attached post facto).
7132 bool isDebuggerActive(){
7133
7134 int mib[4];
7135 struct kinfo_proc info;
7136 size_t size;
7137
7138 // Initialize the flags so that, if sysctl fails for some bizarre
7139 // reason, we get a predictable result.
7140
7141 info.kp_proc.p_flag = 0;
7142
7143 // Initialize mib, which tells sysctl the info we want, in this case
7144 // we're looking for information about a specific process ID.
7145
7146 mib[0] = CTL_KERN;
7147 mib[1] = KERN_PROC;
7148 mib[2] = KERN_PROC_PID;
7149 mib[3] = getpid();
7150
7151 // Call sysctl.
7152
7153 size = sizeof(info);
7154 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
7155 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7156 return false;
7157 }
7158
7159 // We're being debugged if the P_TRACED flag is set.
7160
7161 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7162 }
7163 } // namespace Catch
7164
7165#elif defined(_MSC_VER)
7166 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7167 namespace Catch {
7168 bool isDebuggerActive() {
7169 return IsDebuggerPresent() != 0;
7170 }
7171 }
7172#elif defined(__MINGW32__)
7173 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7174 namespace Catch {
7175 bool isDebuggerActive() {
7176 return IsDebuggerPresent() != 0;
7177 }
7178 }
7179#else
7180 namespace Catch {
7181 inline bool isDebuggerActive() { return false; }
7182 }
7183#endif // Platform
7184
7185#ifdef CATCH_PLATFORM_WINDOWS
7186 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
7187 namespace Catch {
7188 void writeToDebugConsole( std::string const& text ) {
7189 ::OutputDebugStringA( text.c_str() );
7190 }
7191 }
7192#else
7193 namespace Catch {
7194 void writeToDebugConsole( std::string const& text ) {
7195 // !TBD: Need a version for Mac/ XCode and other IDEs
7196 Catch::cout() << text;
7197 }
7198 }
7199#endif // Platform
7200
7201// #included from: catch_tostring.hpp
7202#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
7203
7204namespace Catch {
7205
7206namespace Detail {
7207
7208 std::string unprintableString = "{?}";
7209
7210 namespace {
7211 struct Endianness {
7212 enum Arch { Big, Little };
7213
7214 static Arch which() {
7215 union _{
7216 int asInt;
7217 char asChar[sizeof (int)];
7218 } u;
7219
7220 u.asInt = 1;
7221 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
7222 }
7223 };
7224 }
7225
7226 std::string rawMemoryToString( const void *object, std::size_t size )
7227 {
7228 // Reverse order for little endian architectures
7229 int i = 0, end = static_cast<int>( size ), inc = 1;
7230 if( Endianness::which() == Endianness::Little ) {
7231 i = end-1;
7232 end = inc = -1;
7233 }
7234
7235 unsigned char const *bytes = static_cast<unsigned char const *>(object);
7236 std::ostringstream os;
7237 os << "0x" << std::setfill('0') << std::hex;
7238 for( ; i != end; i += inc )
7239 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
7240 return os.str();
7241 }
7242}
7243
7244std::string toString( std::string const& value ) {
7245 std::string s = value;
7246 if( getCurrentContext().getConfig()->showInvisibles() ) {
7247 for(size_t i = 0; i < s.size(); ++i ) {
7248 std::string subs;
7249 switch( s[i] ) {
7250 case '\n': subs = "\\n"; break;
7251 case '\t': subs = "\\t"; break;
7252 default: break;
7253 }
7254 if( !subs.empty() ) {
7255 s = s.substr( 0, i ) + subs + s.substr( i+1 );
7256 ++i;
7257 }
7258 }
7259 }
7260 return "\"" + s + "\"";
7261}
7262std::string toString( std::wstring const& value ) {
7263
7264 std::string s;
7265 s.reserve( value.size() );
7266 for(size_t i = 0; i < value.size(); ++i )
7267 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
7268 return Catch::toString( s );
7269}
7270
7271std::string toString( const char* const value ) {
7272 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
7273}
7274
7275std::string toString( char* const value ) {
7276 return Catch::toString( static_cast<const char*>( value ) );
7277}
7278
7279std::string toString( const wchar_t* const value )
7280{
7281 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
7282}
7283
7284std::string toString( wchar_t* const value )
7285{
7286 return Catch::toString( static_cast<const wchar_t*>( value ) );
7287}
7288
7289std::string toString( int value ) {
7290 std::ostringstream oss;
7291 oss << value;
7292 if( value >= 255 )
7293 oss << " (0x" << std::hex << value << ")";
7294 return oss.str();
7295}
7296
7297std::string toString( unsigned long value ) {
7298 std::ostringstream oss;
7299 oss << value;
7300 if( value >= 255 )
7301 oss << " (0x" << std::hex << value << ")";
7302 return oss.str();
7303}
7304
7305std::string toString( unsigned int value ) {
7306 return Catch::toString( static_cast<unsigned long>( value ) );
7307}
7308
7309template<typename T>
7310std::string fpToString( T value, int precision ) {
7311 std::ostringstream oss;
7312 oss << std::setprecision( precision )
7313 << std::fixed
7314 << value;
7315 std::string d = oss.str();
7316 std::size_t i = d.find_last_not_of( '0' );
7317 if( i != std::string::npos && i != d.size()-1 ) {
7318 if( d[i] == '.' )
7319 i++;
7320 d = d.substr( 0, i+1 );
7321 }
7322 return d;
7323}
7324
7325std::string toString( const double value ) {
7326 return fpToString( value, 10 );
7327}
7328std::string toString( const float value ) {
7329 return fpToString( value, 5 ) + "f";
7330}
7331
7332std::string toString( bool value ) {
7333 return value ? "true" : "false";
7334}
7335
7336std::string toString( char value ) {
7337 return value < ' '
7338 ? toString( static_cast<unsigned int>( value ) )
7339 : Detail::makeString( value );
7340}
7341
7342std::string toString( signed char value ) {
7343 return toString( static_cast<char>( value ) );
7344}
7345
7346std::string toString( unsigned char value ) {
7347 return toString( static_cast<char>( value ) );
7348}
7349
7350#ifdef CATCH_CONFIG_CPP11_NULLPTR
7351std::string toString( std::nullptr_t ) {
7352 return "nullptr";
7353}
7354#endif
7355
7356#ifdef __OBJC__
7357 std::string toString( NSString const * const& nsstring ) {
7358 if( !nsstring )
7359 return "nil";
7360 return "@" + toString([nsstring UTF8String]);
7361 }
7362 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
7363 if( !nsstring )
7364 return "nil";
7365 return "@" + toString([nsstring UTF8String]);
7366 }
7367 std::string toString( NSObject* const& nsObject ) {
7368 return toString( [nsObject description] );
7369 }
7370#endif
7371
7372} // end namespace Catch
7373
7374// #included from: catch_result_builder.hpp
7375#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
7376
7377namespace Catch {
7378
7379 ResultBuilder::ResultBuilder( char const* macroName,
7380 SourceLineInfo const& lineInfo,
7381 char const* capturedExpression,
7382 ResultDisposition::Flags resultDisposition )
7383 : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ),
7384 m_shouldDebugBreak( false ),
7385 m_shouldThrow( false )
7386 {}
7387
7388 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
7389 m_data.resultType = result;
7390 return *this;
7391 }
7392 ResultBuilder& ResultBuilder::setResultType( bool result ) {
7393 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
7394 return *this;
7395 }
7396 ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) {
7397 m_exprComponents.lhs = lhs;
7398 return *this;
7399 }
7400 ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) {
7401 m_exprComponents.rhs = rhs;
7402 return *this;
7403 }
7404 ResultBuilder& ResultBuilder::setOp( std::string const& op ) {
7405 m_exprComponents.op = op;
7406 return *this;
7407 }
7408
7409 void ResultBuilder::endExpression() {
7410 m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition );
7411 captureExpression();
7412 }
7413
7414 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
7415 m_assertionInfo.resultDisposition = resultDisposition;
7416 m_stream.oss << Catch::translateActiveException();
7417 captureResult( ResultWas::ThrewException );
7418 }
7419
7420 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
7421 setResultType( resultType );
7422 captureExpression();
7423 }
7424
7425 void ResultBuilder::captureExpression() {
7426 AssertionResult result = build();
7427 getResultCapture().assertionEnded( result );
7428
7429 if( !result.isOk() ) {
7430 if( getCurrentContext().getConfig()->shouldDebugBreak() )
7431 m_shouldDebugBreak = true;
7432 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
7433 m_shouldThrow = true;
7434 }
7435 }
7436 void ResultBuilder::react() {
7437 if( m_shouldThrow )
7439 }
7440
7441 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
7442 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
7443
7444 AssertionResult ResultBuilder::build() const
7445 {
7446 assert( m_data.resultType != ResultWas::Unknown );
7447
7448 AssertionResultData data = m_data;
7449
7450 // Flip bool results if testFalse is set
7451 if( m_exprComponents.testFalse ) {
7452 if( data.resultType == ResultWas::Ok )
7453 data.resultType = ResultWas::ExpressionFailed;
7454 else if( data.resultType == ResultWas::ExpressionFailed )
7455 data.resultType = ResultWas::Ok;
7456 }
7457
7458 data.message = m_stream.oss.str();
7459 data.reconstructedExpression = reconstructExpression();
7460 if( m_exprComponents.testFalse ) {
7461 if( m_exprComponents.op == "" )
7462 data.reconstructedExpression = "!" + data.reconstructedExpression;
7463 else
7464 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
7465 }
7466 return AssertionResult( m_assertionInfo, data );
7467 }
7468 std::string ResultBuilder::reconstructExpression() const {
7469 if( m_exprComponents.op == "" )
7470 return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
7471 else if( m_exprComponents.op == "matches" )
7472 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
7473 else if( m_exprComponents.op != "!" ) {
7474 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
7475 m_exprComponents.lhs.find("\n") == std::string::npos &&
7476 m_exprComponents.rhs.find("\n") == std::string::npos )
7477 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
7478 else
7479 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
7480 }
7481 else
7482 return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
7483 }
7484
7485} // end namespace Catch
7486
7487// #included from: catch_tag_alias_registry.hpp
7488#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
7489
7490// #included from: catch_tag_alias_registry.h
7491#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
7492
7493#include <map>
7494
7495namespace Catch {
7496
7497 class TagAliasRegistry : public ITagAliasRegistry {
7498 public:
7499 virtual ~TagAliasRegistry();
7500 virtual Option<TagAlias> find( std::string const& alias ) const;
7501 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
7502 void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
7503 static TagAliasRegistry& get();
7504
7505 private:
7506 std::map<std::string, TagAlias> m_registry;
7507 };
7508
7509} // end namespace Catch
7510
7511#include <map>
7512#include <iostream>
7513
7514namespace Catch {
7515
7516 TagAliasRegistry::~TagAliasRegistry() {}
7517
7518 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
7519 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
7520 if( it != m_registry.end() )
7521 return it->second;
7522 else
7523 return Option<TagAlias>();
7524 }
7525
7526 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
7527 std::string expandedTestSpec = unexpandedTestSpec;
7528 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
7529 it != itEnd;
7530 ++it ) {
7531 std::size_t pos = expandedTestSpec.find( it->first );
7532 if( pos != std::string::npos ) {
7533 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
7534 it->second.tag +
7535 expandedTestSpec.substr( pos + it->first.size() );
7536 }
7537 }
7538 return expandedTestSpec;
7539 }
7540
7541 void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
7542
7543 if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) {
7544 std::ostringstream oss;
7545 oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
7546 throw std::domain_error( oss.str().c_str() );
7547 }
7548 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
7549 std::ostringstream oss;
7550 oss << "error: tag alias, \"" << alias << "\" already registered.\n"
7551 << "\tFirst seen at " << find(alias)->lineInfo << "\n"
7552 << "\tRedefined at " << lineInfo;
7553 throw std::domain_error( oss.str().c_str() );
7554 }
7555 }
7556
7557 TagAliasRegistry& TagAliasRegistry::get() {
7558 static TagAliasRegistry instance;
7559 return instance;
7560
7561 }
7562
7564 ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
7565
7566 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
7567 try {
7568 TagAliasRegistry::get().add( alias, tag, lineInfo );
7569 }
7570 catch( std::exception& ex ) {
7571 Colour colourGuard( Colour::Red );
7572 Catch::cerr() << ex.what() << std::endl;
7573 exit(1);
7574 }
7575 }
7576
7577} // end namespace Catch
7578
7579// #included from: ../reporters/catch_reporter_xml.hpp
7580#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
7581
7582// #included from: catch_reporter_bases.hpp
7583#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
7584
7585#include <cstring>
7586
7587namespace Catch {
7588
7589 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
7590
7591 StreamingReporterBase( ReporterConfig const& _config )
7592 : m_config( _config.fullConfig() ),
7593 stream( _config.stream() )
7594 {}
7595
7596 virtual ~StreamingReporterBase();
7597
7598 virtual void noMatchingTestCases( std::string const& ) {}
7599
7600 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
7601 currentTestRunInfo = _testRunInfo;
7602 }
7603 virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
7604 currentGroupInfo = _groupInfo;
7605 }
7606
7607 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
7608 currentTestCaseInfo = _testInfo;
7609 }
7610 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
7611 m_sectionStack.push_back( _sectionInfo );
7612 }
7613
7614 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
7615 m_sectionStack.pop_back();
7616 }
7617 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
7618 currentTestCaseInfo.reset();
7619 }
7620 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
7621 currentGroupInfo.reset();
7622 }
7623 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
7624 currentTestCaseInfo.reset();
7625 currentGroupInfo.reset();
7626 currentTestRunInfo.reset();
7627 }
7628
7629 virtual void skipTest( TestCaseInfo const& ) {
7630 // Don't do anything with this by default.
7631 // It can optionally be overridden in the derived class.
7632 }
7633
7634 Ptr<IConfig> m_config;
7635 std::ostream& stream;
7636
7637 LazyStat<TestRunInfo> currentTestRunInfo;
7638 LazyStat<GroupInfo> currentGroupInfo;
7639 LazyStat<TestCaseInfo> currentTestCaseInfo;
7640
7641 std::vector<SectionInfo> m_sectionStack;
7642 };
7643
7644 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
7645 template<typename T, typename ChildNodeT>
7646 struct Node : SharedImpl<> {
7647 explicit Node( T const& _value ) : value( _value ) {}
7648 virtual ~Node() {}
7649
7650 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
7651 T value;
7652 ChildNodes children;
7653 };
7654 struct SectionNode : SharedImpl<> {
7655 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
7656 virtual ~SectionNode();
7657
7658 bool operator == ( SectionNode const& other ) const {
7659 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
7660 }
7661 bool operator == ( Ptr<SectionNode> const& other ) const {
7662 return operator==( *other );
7663 }
7664
7665 SectionStats stats;
7666 typedef std::vector<Ptr<SectionNode> > ChildSections;
7667 typedef std::vector<AssertionStats> Assertions;
7668 ChildSections childSections;
7669 Assertions assertions;
7670 std::string stdOut;
7671 std::string stdErr;
7672 };
7673
7674 struct BySectionInfo {
7675 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
7676 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
7677 bool operator() ( Ptr<SectionNode> const& node ) const {
7678 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
7679 }
7680 private:
7681 void operator=( BySectionInfo const& );
7682 SectionInfo const& m_other;
7683 };
7684
7685 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
7686 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
7687 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
7688
7689 CumulativeReporterBase( ReporterConfig const& _config )
7690 : m_config( _config.fullConfig() ),
7691 stream( _config.stream() )
7692 {}
7693 ~CumulativeReporterBase();
7694
7695 virtual void testRunStarting( TestRunInfo const& ) {}
7696 virtual void testGroupStarting( GroupInfo const& ) {}
7697
7698 virtual void testCaseStarting( TestCaseInfo const& ) {}
7699
7700 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
7701 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
7702 Ptr<SectionNode> node;
7703 if( m_sectionStack.empty() ) {
7704 if( !m_rootSection )
7705 m_rootSection = new SectionNode( incompleteStats );
7706 node = m_rootSection;
7707 }
7708 else {
7709 SectionNode& parentNode = *m_sectionStack.back();
7710 SectionNode::ChildSections::const_iterator it =
7711 std::find_if( parentNode.childSections.begin(),
7712 parentNode.childSections.end(),
7713 BySectionInfo( sectionInfo ) );
7714 if( it == parentNode.childSections.end() ) {
7715 node = new SectionNode( incompleteStats );
7716 parentNode.childSections.push_back( node );
7717 }
7718 else
7719 node = *it;
7720 }
7721 m_sectionStack.push_back( node );
7722 m_deepestSection = node;
7723 }
7724
7725 virtual void assertionStarting( AssertionInfo const& ) {}
7726
7727 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
7728 assert( !m_sectionStack.empty() );
7729 SectionNode& sectionNode = *m_sectionStack.back();
7730 sectionNode.assertions.push_back( assertionStats );
7731 return true;
7732 }
7733 virtual void sectionEnded( SectionStats const& sectionStats ) {
7734 assert( !m_sectionStack.empty() );
7735 SectionNode& node = *m_sectionStack.back();
7736 node.stats = sectionStats;
7737 m_sectionStack.pop_back();
7738 }
7739 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
7740 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
7741 assert( m_sectionStack.size() == 0 );
7742 node->children.push_back( m_rootSection );
7743 m_testCases.push_back( node );
7744 m_rootSection.reset();
7745
7746 assert( m_deepestSection );
7747 m_deepestSection->stdOut = testCaseStats.stdOut;
7748 m_deepestSection->stdErr = testCaseStats.stdErr;
7749 }
7750 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
7751 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
7752 node->children.swap( m_testCases );
7753 m_testGroups.push_back( node );
7754 }
7755 virtual void testRunEnded( TestRunStats const& testRunStats ) {
7756 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
7757 node->children.swap( m_testGroups );
7758 m_testRuns.push_back( node );
7759 testRunEndedCumulative();
7760 }
7761 virtual void testRunEndedCumulative() = 0;
7762
7763 virtual void skipTest( TestCaseInfo const& ) {}
7764
7765 Ptr<IConfig> m_config;
7766 std::ostream& stream;
7767 std::vector<AssertionStats> m_assertions;
7769 std::vector<Ptr<TestCaseNode> > m_testCases;
7770 std::vector<Ptr<TestGroupNode> > m_testGroups;
7771
7772 std::vector<Ptr<TestRunNode> > m_testRuns;
7773
7774 Ptr<SectionNode> m_rootSection;
7775 Ptr<SectionNode> m_deepestSection;
7776 std::vector<Ptr<SectionNode> > m_sectionStack;
7777
7778 };
7779
7780 template<char C>
7781 char const* getLineOfChars() {
7782 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
7783 if( !*line ) {
7784 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
7785 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
7786 }
7787 return line;
7788 }
7789
7790} // end namespace Catch
7791
7792// #included from: ../internal/catch_reporter_registrars.hpp
7793#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
7794
7795namespace Catch {
7796
7797 template<typename T>
7798 class LegacyReporterRegistrar {
7799
7800 class ReporterFactory : public IReporterFactory {
7801 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
7802 return new LegacyReporterAdapter( new T( config ) );
7803 }
7804
7805 virtual std::string getDescription() const {
7806 return T::getDescription();
7807 }
7808 };
7809
7810 public:
7811
7812 LegacyReporterRegistrar( std::string const& name ) {
7813 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
7814 }
7815 };
7816
7817 template<typename T>
7818 class ReporterRegistrar {
7819
7820 class ReporterFactory : public IReporterFactory {
7821
7822 // *** Please Note ***:
7823 // - If you end up here looking at a compiler error because it's trying to register
7824 // your custom reporter class be aware that the native reporter interface has changed
7825 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
7826 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
7827 // However please consider updating to the new interface as the old one is now
7828 // deprecated and will probably be removed quite soon!
7829 // Please contact me via github if you have any questions at all about this.
7830 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
7831 // no idea who is actually using custom reporters at all (possibly no-one!).
7832 // The new interface is designed to minimise exposure to interface changes in the future.
7833 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
7834 return new T( config );
7835 }
7836
7837 virtual std::string getDescription() const {
7838 return T::getDescription();
7839 }
7840 };
7841
7842 public:
7843
7844 ReporterRegistrar( std::string const& name ) {
7845 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
7846 }
7847 };
7848}
7849
7850#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
7851 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
7852#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
7853 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
7854
7855// #included from: ../internal/catch_xmlwriter.hpp
7856#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
7857
7858#include <sstream>
7859#include <string>
7860#include <vector>
7861
7862namespace Catch {
7863
7864 class XmlWriter {
7865 public:
7866
7867 class ScopedElement {
7868 public:
7869 ScopedElement( XmlWriter* writer )
7870 : m_writer( writer )
7871 {}
7872
7873 ScopedElement( ScopedElement const& other )
7874 : m_writer( other.m_writer ){
7875 other.m_writer = NULL;
7876 }
7877
7878 ~ScopedElement() {
7879 if( m_writer )
7880 m_writer->endElement();
7881 }
7882
7883 ScopedElement& writeText( std::string const& text, bool indent = true ) {
7884 m_writer->writeText( text, indent );
7885 return *this;
7886 }
7887
7888 template<typename T>
7889 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
7890 m_writer->writeAttribute( name, attribute );
7891 return *this;
7892 }
7893
7894 private:
7895 mutable XmlWriter* m_writer;
7896 };
7897
7898 XmlWriter()
7899 : m_tagIsOpen( false ),
7900 m_needsNewline( false ),
7901 m_os( &Catch::cout() )
7902 {}
7903
7904 XmlWriter( std::ostream& os )
7905 : m_tagIsOpen( false ),
7906 m_needsNewline( false ),
7907 m_os( &os )
7908 {}
7909
7910 ~XmlWriter() {
7911 while( !m_tags.empty() )
7912 endElement();
7913 }
7914
7915 XmlWriter& startElement( std::string const& name ) {
7916 ensureTagClosed();
7917 newlineIfNecessary();
7918 stream() << m_indent << "<" << name;
7919 m_tags.push_back( name );
7920 m_indent += " ";
7921 m_tagIsOpen = true;
7922 return *this;
7923 }
7924
7925 ScopedElement scopedElement( std::string const& name ) {
7926 ScopedElement scoped( this );
7927 startElement( name );
7928 return scoped;
7929 }
7930
7931 XmlWriter& endElement() {
7932 newlineIfNecessary();
7933 m_indent = m_indent.substr( 0, m_indent.size()-2 );
7934 if( m_tagIsOpen ) {
7935 stream() << "/>\n";
7936 m_tagIsOpen = false;
7937 }
7938 else {
7939 stream() << m_indent << "</" << m_tags.back() << ">\n";
7940 }
7941 m_tags.pop_back();
7942 return *this;
7943 }
7944
7945 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
7946 if( !name.empty() && !attribute.empty() ) {
7947 stream() << " " << name << "=\"";
7948 writeEncodedText( attribute );
7949 stream() << "\"";
7950 }
7951 return *this;
7952 }
7953
7954 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
7955 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
7956 return *this;
7957 }
7958
7959 template<typename T>
7960 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
7961 if( !name.empty() )
7962 stream() << " " << name << "=\"" << attribute << "\"";
7963 return *this;
7964 }
7965
7966 XmlWriter& writeText( std::string const& text, bool indent = true ) {
7967 if( !text.empty() ){
7968 bool tagWasOpen = m_tagIsOpen;
7969 ensureTagClosed();
7970 if( tagWasOpen && indent )
7971 stream() << m_indent;
7972 writeEncodedText( text );
7973 m_needsNewline = true;
7974 }
7975 return *this;
7976 }
7977
7978 XmlWriter& writeComment( std::string const& text ) {
7979 ensureTagClosed();
7980 stream() << m_indent << "<!--" << text << "-->";
7981 m_needsNewline = true;
7982 return *this;
7983 }
7984
7985 XmlWriter& writeBlankLine() {
7986 ensureTagClosed();
7987 stream() << "\n";
7988 return *this;
7989 }
7990
7991 void setStream( std::ostream& os ) {
7992 m_os = &os;
7993 }
7994
7995 private:
7996 XmlWriter( XmlWriter const& );
7997 void operator=( XmlWriter const& );
7998
7999 std::ostream& stream() {
8000 return *m_os;
8001 }
8002
8003 void ensureTagClosed() {
8004 if( m_tagIsOpen ) {
8005 stream() << ">\n";
8006 m_tagIsOpen = false;
8007 }
8008 }
8009
8010 void newlineIfNecessary() {
8011 if( m_needsNewline ) {
8012 stream() << "\n";
8013 m_needsNewline = false;
8014 }
8015 }
8016
8017 void writeEncodedText( std::string const& text ) {
8018 static const char* charsToEncode = "<&\"";
8019 std::string mtext = text;
8020 std::string::size_type pos = mtext.find_first_of( charsToEncode );
8021 while( pos != std::string::npos ) {
8022 stream() << mtext.substr( 0, pos );
8023
8024 switch( mtext[pos] ) {
8025 case '<':
8026 stream() << "&lt;";
8027 break;
8028 case '&':
8029 stream() << "&amp;";
8030 break;
8031 case '\"':
8032 stream() << "&quot;";
8033 break;
8034 }
8035 mtext = mtext.substr( pos+1 );
8036 pos = mtext.find_first_of( charsToEncode );
8037 }
8038 stream() << mtext;
8039 }
8040
8041 bool m_tagIsOpen;
8042 bool m_needsNewline;
8044 std::string m_indent;
8045 std::ostream* m_os;
8046 };
8047
8048}
8049namespace Catch {
8050 class XmlReporter : public StreamingReporterBase {
8051 public:
8052 XmlReporter( ReporterConfig const& _config )
8053 : StreamingReporterBase( _config ),
8054 m_sectionDepth( 0 )
8055 {}
8056
8057 virtual ~XmlReporter();
8058
8059 static std::string getDescription() {
8060 return "Reports test results as an XML document";
8061 }
8062
8063 public: // StreamingReporterBase
8064 virtual ReporterPreferences getPreferences() const {
8065 ReporterPreferences prefs;
8066 prefs.shouldRedirectStdOut = true;
8067 return prefs;
8068 }
8069
8070 virtual void noMatchingTestCases( std::string const& s ) {
8071 StreamingReporterBase::noMatchingTestCases( s );
8072 }
8073
8074 virtual void testRunStarting( TestRunInfo const& testInfo ) {
8075 StreamingReporterBase::testRunStarting( testInfo );
8076 m_xml.setStream( stream );
8077 m_xml.startElement( "Catch" );
8078 if( !m_config->name().empty() )
8079 m_xml.writeAttribute( "name", m_config->name() );
8080 }
8081
8082 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
8083 StreamingReporterBase::testGroupStarting( groupInfo );
8084 m_xml.startElement( "Group" )
8085 .writeAttribute( "name", groupInfo.name );
8086 }
8087
8088 virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
8089 StreamingReporterBase::testCaseStarting(testInfo);
8090 m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
8091
8092 if ( m_config->showDurations() == ShowDurations::Always )
8093 m_testCaseTimer.start();
8094 }
8095
8096 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
8097 StreamingReporterBase::sectionStarting( sectionInfo );
8098 if( m_sectionDepth++ > 0 ) {
8099 m_xml.startElement( "Section" )
8100 .writeAttribute( "name", trim( sectionInfo.name ) )
8101 .writeAttribute( "description", sectionInfo.description );
8102 }
8103 }
8104
8105 virtual void assertionStarting( AssertionInfo const& ) { }
8106
8107 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
8108 const AssertionResult& assertionResult = assertionStats.assertionResult;
8109
8110 // Print any info messages in <Info> tags.
8111 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8112 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8113 it != itEnd;
8114 ++it ) {
8115 if( it->type == ResultWas::Info ) {
8116 m_xml.scopedElement( "Info" )
8117 .writeText( it->message );
8118 } else if ( it->type == ResultWas::Warning ) {
8119 m_xml.scopedElement( "Warning" )
8120 .writeText( it->message );
8121 }
8122 }
8123 }
8124
8125 // Drop out if result was successful but we're not printing them.
8126 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
8127 return true;
8128
8129 // Print the expression if there is one.
8130 if( assertionResult.hasExpression() ) {
8131 m_xml.startElement( "Expression" )
8132 .writeAttribute( "success", assertionResult.succeeded() )
8133 .writeAttribute( "type", assertionResult.getTestMacroName() )
8134 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
8135 .writeAttribute( "line", assertionResult.getSourceInfo().line );
8136
8137 m_xml.scopedElement( "Original" )
8138 .writeText( assertionResult.getExpression() );
8139 m_xml.scopedElement( "Expanded" )
8140 .writeText( assertionResult.getExpandedExpression() );
8141 }
8142
8143 // And... Print a result applicable to each result type.
8144 switch( assertionResult.getResultType() ) {
8146 m_xml.scopedElement( "Exception" )
8147 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
8148 .writeAttribute( "line", assertionResult.getSourceInfo().line )
8149 .writeText( assertionResult.getMessage() );
8150 break;
8152 m_xml.scopedElement( "Fatal Error Condition" )
8153 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
8154 .writeAttribute( "line", assertionResult.getSourceInfo().line )
8155 .writeText( assertionResult.getMessage() );
8156 break;
8157 case ResultWas::Info:
8158 m_xml.scopedElement( "Info" )
8159 .writeText( assertionResult.getMessage() );
8160 break;
8161 case ResultWas::Warning:
8162 // Warning will already have been written
8163 break;
8165 m_xml.scopedElement( "Failure" )
8166 .writeText( assertionResult.getMessage() );
8167 break;
8168 default:
8169 break;
8170 }
8171
8172 if( assertionResult.hasExpression() )
8173 m_xml.endElement();
8174
8175 return true;
8176 }
8177
8178 virtual void sectionEnded( SectionStats const& sectionStats ) {
8179 StreamingReporterBase::sectionEnded( sectionStats );
8180 if( --m_sectionDepth > 0 ) {
8181 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
8182 e.writeAttribute( "successes", sectionStats.assertions.passed );
8183 e.writeAttribute( "failures", sectionStats.assertions.failed );
8184 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
8185
8186 if ( m_config->showDurations() == ShowDurations::Always )
8187 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
8188
8189 m_xml.endElement();
8190 }
8191 }
8192
8193 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
8194 StreamingReporterBase::testCaseEnded( testCaseStats );
8195 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
8196 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
8197
8198 if ( m_config->showDurations() == ShowDurations::Always )
8199 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
8200
8201 m_xml.endElement();
8202 }
8203
8204 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
8205 StreamingReporterBase::testGroupEnded( testGroupStats );
8206 // TODO: Check testGroupStats.aborting and act accordingly.
8207 m_xml.scopedElement( "OverallResults" )
8208 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
8209 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
8210 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
8211 m_xml.endElement();
8212 }
8213
8214 virtual void testRunEnded( TestRunStats const& testRunStats ) {
8215 StreamingReporterBase::testRunEnded( testRunStats );
8216 m_xml.scopedElement( "OverallResults" )
8217 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
8218 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
8219 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
8220 m_xml.endElement();
8221 }
8222
8223 private:
8224 Timer m_testCaseTimer;
8225 XmlWriter m_xml;
8226 int m_sectionDepth;
8227 };
8228
8229 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
8230
8231} // end namespace Catch
8232
8233// #included from: ../reporters/catch_reporter_junit.hpp
8234#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
8235
8236#include <assert.h>
8237
8238namespace Catch {
8239
8240 class JunitReporter : public CumulativeReporterBase {
8241 public:
8242 JunitReporter( ReporterConfig const& _config )
8243 : CumulativeReporterBase( _config ),
8244 xml( _config.stream() )
8245 {}
8246
8247 ~JunitReporter();
8248
8249 static std::string getDescription() {
8250 return "Reports test results in an XML format that looks like Ant's junitreport target";
8251 }
8252
8253 virtual void noMatchingTestCases( std::string const& /*spec*/ ) {}
8254
8255 virtual ReporterPreferences getPreferences() const {
8256 ReporterPreferences prefs;
8257 prefs.shouldRedirectStdOut = true;
8258 return prefs;
8259 }
8260
8261 virtual void testRunStarting( TestRunInfo const& runInfo ) {
8262 CumulativeReporterBase::testRunStarting( runInfo );
8263 xml.startElement( "testsuites" );
8264 }
8265
8266 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
8267 suiteTimer.start();
8268 stdOutForSuite.str("");
8269 stdErrForSuite.str("");
8270 unexpectedExceptions = 0;
8271 CumulativeReporterBase::testGroupStarting( groupInfo );
8272 }
8273
8274 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
8275 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
8276 unexpectedExceptions++;
8277 return CumulativeReporterBase::assertionEnded( assertionStats );
8278 }
8279
8280 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
8281 stdOutForSuite << testCaseStats.stdOut;
8282 stdErrForSuite << testCaseStats.stdErr;
8283 CumulativeReporterBase::testCaseEnded( testCaseStats );
8284 }
8285
8286 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
8287 double suiteTime = suiteTimer.getElapsedSeconds();
8288 CumulativeReporterBase::testGroupEnded( testGroupStats );
8289 writeGroup( *m_testGroups.back(), suiteTime );
8290 }
8291
8292 virtual void testRunEndedCumulative() {
8293 xml.endElement();
8294 }
8295
8296 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
8297 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
8298 TestGroupStats const& stats = groupNode.value;
8299 xml.writeAttribute( "name", stats.groupInfo.name );
8300 xml.writeAttribute( "errors", unexpectedExceptions );
8301 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
8302 xml.writeAttribute( "tests", stats.totals.assertions.total() );
8303 xml.writeAttribute( "hostname", "tbd" ); // !TBD
8304 if( m_config->showDurations() == ShowDurations::Never )
8305 xml.writeAttribute( "time", "" );
8306 else
8307 xml.writeAttribute( "time", suiteTime );
8308 xml.writeAttribute( "timestamp", "tbd" ); // !TBD
8309
8310 // Write test cases
8311 for( TestGroupNode::ChildNodes::const_iterator
8312 it = groupNode.children.begin(), itEnd = groupNode.children.end();
8313 it != itEnd;
8314 ++it )
8315 writeTestCase( **it );
8316
8317 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
8318 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
8319 }
8320
8321 void writeTestCase( TestCaseNode const& testCaseNode ) {
8322 TestCaseStats const& stats = testCaseNode.value;
8323
8324 // All test cases have exactly one section - which represents the
8325 // test case itself. That section may have 0-n nested sections
8326 assert( testCaseNode.children.size() == 1 );
8327 SectionNode const& rootSection = *testCaseNode.children.front();
8328
8329 std::string className = stats.testInfo.className;
8330
8331 if( className.empty() ) {
8332 if( rootSection.childSections.empty() )
8333 className = "global";
8334 }
8335 writeSection( className, "", rootSection );
8336 }
8337
8338 void writeSection( std::string const& className,
8339 std::string const& rootName,
8340 SectionNode const& sectionNode ) {
8341 std::string name = trim( sectionNode.stats.sectionInfo.name );
8342 if( !rootName.empty() )
8343 name = rootName + "/" + name;
8344
8345 if( !sectionNode.assertions.empty() ||
8346 !sectionNode.stdOut.empty() ||
8347 !sectionNode.stdErr.empty() ) {
8348 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
8349 if( className.empty() ) {
8350 xml.writeAttribute( "classname", name );
8351 xml.writeAttribute( "name", "root" );
8352 }
8353 else {
8354 xml.writeAttribute( "classname", className );
8355 xml.writeAttribute( "name", name );
8356 }
8357 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
8358
8359 writeAssertions( sectionNode );
8360
8361 if( !sectionNode.stdOut.empty() )
8362 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
8363 if( !sectionNode.stdErr.empty() )
8364 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
8365 }
8366 for( SectionNode::ChildSections::const_iterator
8367 it = sectionNode.childSections.begin(),
8368 itEnd = sectionNode.childSections.end();
8369 it != itEnd;
8370 ++it )
8371 if( className.empty() )
8372 writeSection( name, "", **it );
8373 else
8374 writeSection( className, name, **it );
8375 }
8376
8377 void writeAssertions( SectionNode const& sectionNode ) {
8378 for( SectionNode::Assertions::const_iterator
8379 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
8380 it != itEnd;
8381 ++it )
8382 writeAssertion( *it );
8383 }
8384 void writeAssertion( AssertionStats const& stats ) {
8385 AssertionResult const& result = stats.assertionResult;
8386 if( !result.isOk() ) {
8387 std::string elementName;
8388 switch( result.getResultType() ) {
8391 elementName = "error";
8392 break;
8394 elementName = "failure";
8395 break;
8397 elementName = "failure";
8398 break;
8400 elementName = "failure";
8401 break;
8402
8403 // We should never see these here:
8404 case ResultWas::Info:
8405 case ResultWas::Warning:
8406 case ResultWas::Ok:
8407 case ResultWas::Unknown:
8410 elementName = "internalError";
8411 break;
8412 }
8413
8414 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
8415
8416 xml.writeAttribute( "message", result.getExpandedExpression() );
8417 xml.writeAttribute( "type", result.getTestMacroName() );
8418
8419 std::ostringstream oss;
8420 if( !result.getMessage().empty() )
8421 oss << result.getMessage() << "\n";
8423 it = stats.infoMessages.begin(),
8424 itEnd = stats.infoMessages.end();
8425 it != itEnd;
8426 ++it )
8427 if( it->type == ResultWas::Info )
8428 oss << it->message << "\n";
8429
8430 oss << "at " << result.getSourceInfo();
8431 xml.writeText( oss.str(), false );
8432 }
8433 }
8434
8435 XmlWriter xml;
8436 Timer suiteTimer;
8437 std::ostringstream stdOutForSuite;
8438 std::ostringstream stdErrForSuite;
8439 unsigned int unexpectedExceptions;
8440 };
8441
8442 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
8443
8444} // end namespace Catch
8445
8446// #included from: ../reporters/catch_reporter_console.hpp
8447#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
8448
8449namespace Catch {
8450
8451 struct ConsoleReporter : StreamingReporterBase {
8452 ConsoleReporter( ReporterConfig const& _config )
8453 : StreamingReporterBase( _config ),
8454 m_headerPrinted( false )
8455 {}
8456
8457 virtual ~ConsoleReporter();
8458 static std::string getDescription() {
8459 return "Reports test results as plain lines of text";
8460 }
8461 virtual ReporterPreferences getPreferences() const {
8462 ReporterPreferences prefs;
8463 prefs.shouldRedirectStdOut = false;
8464 return prefs;
8465 }
8466
8467 virtual void noMatchingTestCases( std::string const& spec ) {
8468 stream << "No test cases matched '" << spec << "'" << std::endl;
8469 }
8470
8471 virtual void assertionStarting( AssertionInfo const& ) {
8472 }
8473
8474 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
8475 AssertionResult const& result = _assertionStats.assertionResult;
8476
8477 bool printInfoMessages = true;
8478
8479 // Drop out if result was successful and we're not printing those
8480 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
8481 if( result.getResultType() != ResultWas::Warning )
8482 return false;
8483 printInfoMessages = false;
8484 }
8485
8486 lazyPrint();
8487
8488 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
8489 printer.print();
8490 stream << std::endl;
8491 return true;
8492 }
8493
8494 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
8495 m_headerPrinted = false;
8496 StreamingReporterBase::sectionStarting( _sectionInfo );
8497 }
8498 virtual void sectionEnded( SectionStats const& _sectionStats ) {
8499 if( _sectionStats.missingAssertions ) {
8500 lazyPrint();
8501 Colour colour( Colour::ResultError );
8502 if( m_sectionStack.size() > 1 )
8503 stream << "\nNo assertions in section";
8504 else
8505 stream << "\nNo assertions in test case";
8506 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
8507 }
8508 if( m_headerPrinted ) {
8509 if( m_config->showDurations() == ShowDurations::Always )
8510 stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
8511 m_headerPrinted = false;
8512 }
8513 else {
8514 if( m_config->showDurations() == ShowDurations::Always )
8515 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
8516 }
8517 StreamingReporterBase::sectionEnded( _sectionStats );
8518 }
8519
8520 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
8521 StreamingReporterBase::testCaseEnded( _testCaseStats );
8522 m_headerPrinted = false;
8523 }
8524 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
8525 if( currentGroupInfo.used ) {
8526 printSummaryDivider();
8527 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
8528 printTotals( _testGroupStats.totals );
8529 stream << "\n" << std::endl;
8530 }
8531 StreamingReporterBase::testGroupEnded( _testGroupStats );
8532 }
8533 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
8534 printTotalsDivider( _testRunStats.totals );
8535 printTotals( _testRunStats.totals );
8536 stream << std::endl;
8537 StreamingReporterBase::testRunEnded( _testRunStats );
8538 }
8539
8540 private:
8541
8542 class AssertionPrinter {
8543 void operator= ( AssertionPrinter const& );
8544 public:
8545 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
8546 : stream( _stream ),
8547 stats( _stats ),
8548 result( _stats.assertionResult ),
8549 colour( Colour::None ),
8550 message( result.getMessage() ),
8551 messages( _stats.infoMessages ),
8552 printInfoMessages( _printInfoMessages )
8553 {
8554 switch( result.getResultType() ) {
8555 case ResultWas::Ok:
8556 colour = Colour::Success;
8557 passOrFail = "PASSED";
8558 //if( result.hasMessage() )
8559 if( _stats.infoMessages.size() == 1 )
8560 messageLabel = "with message";
8561 if( _stats.infoMessages.size() > 1 )
8562 messageLabel = "with messages";
8563 break;
8565 if( result.isOk() ) {
8566 colour = Colour::Success;
8567 passOrFail = "FAILED - but was ok";
8568 }
8569 else {
8570 colour = Colour::Error;
8571 passOrFail = "FAILED";
8572 }
8573 if( _stats.infoMessages.size() == 1 )
8574 messageLabel = "with message";
8575 if( _stats.infoMessages.size() > 1 )
8576 messageLabel = "with messages";
8577 break;
8579 colour = Colour::Error;
8580 passOrFail = "FAILED";
8581 messageLabel = "due to unexpected exception with message";
8582 break;
8584 colour = Colour::Error;
8585 passOrFail = "FAILED";
8586 messageLabel = "due to a fatal error condition";
8587 break;
8589 colour = Colour::Error;
8590 passOrFail = "FAILED";
8591 messageLabel = "because no exception was thrown where one was expected";
8592 break;
8593 case ResultWas::Info:
8594 messageLabel = "info";
8595 break;
8596 case ResultWas::Warning:
8597 messageLabel = "warning";
8598 break;
8600 passOrFail = "FAILED";
8601 colour = Colour::Error;
8602 if( _stats.infoMessages.size() == 1 )
8603 messageLabel = "explicitly with message";
8604 if( _stats.infoMessages.size() > 1 )
8605 messageLabel = "explicitly with messages";
8606 break;
8607 // These cases are here to prevent compiler warnings
8608 case ResultWas::Unknown:
8611 passOrFail = "** internal error **";
8612 colour = Colour::Error;
8613 break;
8614 }
8615 }
8616
8617 void print() const {
8618 printSourceInfo();
8619 if( stats.totals.assertions.total() > 0 ) {
8620 if( result.isOk() )
8621 stream << "\n";
8622 printResultType();
8623 printOriginalExpression();
8624 printReconstructedExpression();
8625 }
8626 else {
8627 stream << "\n";
8628 }
8629 printMessage();
8630 }
8631
8632 private:
8633 void printResultType() const {
8634 if( !passOrFail.empty() ) {
8635 Colour colourGuard( colour );
8636 stream << passOrFail << ":\n";
8637 }
8638 }
8639 void printOriginalExpression() const {
8640 if( result.hasExpression() ) {
8641 Colour colourGuard( Colour::OriginalExpression );
8642 stream << " ";
8643 stream << result.getExpressionInMacro();
8644 stream << "\n";
8645 }
8646 }
8647 void printReconstructedExpression() const {
8648 if( result.hasExpandedExpression() ) {
8649 stream << "with expansion:\n";
8650 Colour colourGuard( Colour::ReconstructedExpression );
8651 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
8652 }
8653 }
8654 void printMessage() const {
8655 if( !messageLabel.empty() )
8656 stream << messageLabel << ":" << "\n";
8657 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
8658 it != itEnd;
8659 ++it ) {
8660 // If this assertion is a warning ignore any INFO messages
8661 if( printInfoMessages || it->type != ResultWas::Info )
8662 stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
8663 }
8664 }
8665 void printSourceInfo() const {
8666 Colour colourGuard( Colour::FileName );
8667 stream << result.getSourceInfo() << ": ";
8668 }
8669
8670 std::ostream& stream;
8671 AssertionStats const& stats;
8672 AssertionResult const& result;
8673 Colour::Code colour;
8674 std::string passOrFail;
8675 std::string messageLabel;
8676 std::string message;
8677 std::vector<MessageInfo> messages;
8678 bool printInfoMessages;
8679 };
8680
8681 void lazyPrint() {
8682
8683 if( !currentTestRunInfo.used )
8684 lazyPrintRunInfo();
8685 if( !currentGroupInfo.used )
8686 lazyPrintGroupInfo();
8687
8688 if( !m_headerPrinted ) {
8689 printTestCaseAndSectionHeader();
8690 m_headerPrinted = true;
8691 }
8692 }
8693 void lazyPrintRunInfo() {
8694 stream << "\n" << getLineOfChars<'~'>() << "\n";
8695 Colour colour( Colour::SecondaryText );
8696 stream << currentTestRunInfo->name
8697 << " is a Catch v" << libraryVersion << " host application.\n"
8698 << "Run with -? for options\n\n";
8699
8700 if( m_config->rngSeed() != 0 )
8701 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
8702
8703 currentTestRunInfo.used = true;
8704 }
8705 void lazyPrintGroupInfo() {
8706 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
8707 printClosedHeader( "Group: " + currentGroupInfo->name );
8708 currentGroupInfo.used = true;
8709 }
8710 }
8711 void printTestCaseAndSectionHeader() {
8712 assert( !m_sectionStack.empty() );
8713 printOpenHeader( currentTestCaseInfo->name );
8714
8715 if( m_sectionStack.size() > 1 ) {
8716 Colour colourGuard( Colour::Headers );
8717
8719 it = m_sectionStack.begin()+1, // Skip first section (test case)
8720 itEnd = m_sectionStack.end();
8721 for( ; it != itEnd; ++it )
8722 printHeaderString( it->name, 2 );
8723 }
8724
8725 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
8726
8727 if( !lineInfo.empty() ){
8728 stream << getLineOfChars<'-'>() << "\n";
8729 Colour colourGuard( Colour::FileName );
8730 stream << lineInfo << "\n";
8731 }
8732 stream << getLineOfChars<'.'>() << "\n" << std::endl;
8733 }
8734
8735 void printClosedHeader( std::string const& _name ) {
8736 printOpenHeader( _name );
8737 stream << getLineOfChars<'.'>() << "\n";
8738 }
8739 void printOpenHeader( std::string const& _name ) {
8740 stream << getLineOfChars<'-'>() << "\n";
8741 {
8742 Colour colourGuard( Colour::Headers );
8743 printHeaderString( _name );
8744 }
8745 }
8746
8747 // if string has a : in first line will set indent to follow it on
8748 // subsequent lines
8749 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
8750 std::size_t i = _string.find( ": " );
8751 if( i != std::string::npos )
8752 i+=2;
8753 else
8754 i = 0;
8755 stream << Text( _string, TextAttributes()
8756 .setIndent( indent+i)
8757 .setInitialIndent( indent ) ) << "\n";
8758 }
8759
8760 struct SummaryColumn {
8761
8762 SummaryColumn( std::string const& _label, Colour::Code _colour )
8763 : label( _label ),
8764 colour( _colour )
8765 {}
8766 SummaryColumn addRow( std::size_t count ) {
8767 std::ostringstream oss;
8768 oss << count;
8769 std::string row = oss.str();
8770 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
8771 while( it->size() < row.size() )
8772 *it = " " + *it;
8773 while( it->size() > row.size() )
8774 row = " " + row;
8775 }
8776 rows.push_back( row );
8777 return *this;
8778 }
8779
8780 std::string label;
8781 Colour::Code colour;
8783
8784 };
8785
8786 void printTotals( Totals const& totals ) {
8787 if( totals.testCases.total() == 0 ) {
8788 stream << Colour( Colour::Warning ) << "No tests ran\n";
8789 }
8790 else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
8791 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
8792 stream << " ("
8793 << pluralise( totals.assertions.passed, "assertion" ) << " in "
8794 << pluralise( totals.testCases.passed, "test case" ) << ")"
8795 << "\n";
8796 }
8797 else {
8798
8800 columns.push_back( SummaryColumn( "", Colour::None )
8801 .addRow( totals.testCases.total() )
8802 .addRow( totals.assertions.total() ) );
8803 columns.push_back( SummaryColumn( "passed", Colour::Success )
8804 .addRow( totals.testCases.passed )
8805 .addRow( totals.assertions.passed ) );
8806 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
8807 .addRow( totals.testCases.failed )
8808 .addRow( totals.assertions.failed ) );
8809 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
8810 .addRow( totals.testCases.failedButOk )
8811 .addRow( totals.assertions.failedButOk ) );
8812
8813 printSummaryRow( "test cases", columns, 0 );
8814 printSummaryRow( "assertions", columns, 1 );
8815 }
8816 }
8817 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
8818 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
8819 std::string value = it->rows[row];
8820 if( it->label.empty() ) {
8821 stream << label << ": ";
8822 if( value != "0" )
8823 stream << value;
8824 else
8825 stream << Colour( Colour::Warning ) << "- none -";
8826 }
8827 else if( value != "0" ) {
8828 stream << Colour( Colour::LightGrey ) << " | ";
8829 stream << Colour( it->colour )
8830 << value << " " << it->label;
8831 }
8832 }
8833 stream << "\n";
8834 }
8835
8836 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
8837 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
8838 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
8839 }
8840 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
8841 if( i > j && i > k )
8842 return i;
8843 else if( j > k )
8844 return j;
8845 else
8846 return k;
8847 }
8848
8849 void printTotalsDivider( Totals const& totals ) {
8850 if( totals.testCases.total() > 0 ) {
8851 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
8852 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
8853 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
8854 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
8855 findMax( failedRatio, failedButOkRatio, passedRatio )++;
8856 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
8857 findMax( failedRatio, failedButOkRatio, passedRatio )--;
8858
8859 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
8860 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
8861 if( totals.testCases.allPassed() )
8862 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
8863 else
8864 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
8865 }
8866 else {
8867 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
8868 }
8869 stream << "\n";
8870 }
8871 void printSummaryDivider() {
8872 stream << getLineOfChars<'-'>() << "\n";
8873 }
8874
8875 private:
8876 bool m_headerPrinted;
8877 };
8878
8879 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
8880
8881} // end namespace Catch
8882
8883// #included from: ../reporters/catch_reporter_compact.hpp
8884#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
8885
8886namespace Catch {
8887
8888 struct CompactReporter : StreamingReporterBase {
8889
8890 CompactReporter( ReporterConfig const& _config )
8891 : StreamingReporterBase( _config )
8892 {}
8893
8894 virtual ~CompactReporter();
8895
8896 static std::string getDescription() {
8897 return "Reports test results on a single line, suitable for IDEs";
8898 }
8899
8900 virtual ReporterPreferences getPreferences() const {
8901 ReporterPreferences prefs;
8902 prefs.shouldRedirectStdOut = false;
8903 return prefs;
8904 }
8905
8906 virtual void noMatchingTestCases( std::string const& spec ) {
8907 stream << "No test cases matched '" << spec << "'" << std::endl;
8908 }
8909
8910 virtual void assertionStarting( AssertionInfo const& ) {
8911 }
8912
8913 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
8914 AssertionResult const& result = _assertionStats.assertionResult;
8915
8916 bool printInfoMessages = true;
8917
8918 // Drop out if result was successful and we're not printing those
8919 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
8920 if( result.getResultType() != ResultWas::Warning )
8921 return false;
8922 printInfoMessages = false;
8923 }
8924
8925 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
8926 printer.print();
8927
8928 stream << std::endl;
8929 return true;
8930 }
8931
8932 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
8933 printTotals( _testRunStats.totals );
8934 stream << "\n" << std::endl;
8935 StreamingReporterBase::testRunEnded( _testRunStats );
8936 }
8937
8938 private:
8939 class AssertionPrinter {
8940 void operator= ( AssertionPrinter const& );
8941 public:
8942 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
8943 : stream( _stream )
8944 , stats( _stats )
8945 , result( _stats.assertionResult )
8946 , messages( _stats.infoMessages )
8947 , itMessage( _stats.infoMessages.begin() )
8948 , printInfoMessages( _printInfoMessages )
8949 {}
8950
8951 void print() {
8952 printSourceInfo();
8953
8954 itMessage = messages.begin();
8955
8956 switch( result.getResultType() ) {
8957 case ResultWas::Ok:
8958 printResultType( Colour::ResultSuccess, passedString() );
8959 printOriginalExpression();
8960 printReconstructedExpression();
8961 if ( ! result.hasExpression() )
8962 printRemainingMessages( Colour::None );
8963 else
8964 printRemainingMessages();
8965 break;
8967 if( result.isOk() )
8968 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
8969 else
8970 printResultType( Colour::Error, failedString() );
8971 printOriginalExpression();
8972 printReconstructedExpression();
8973 printRemainingMessages();
8974 break;
8976 printResultType( Colour::Error, failedString() );
8977 printIssue( "unexpected exception with message:" );
8978 printMessage();
8979 printExpressionWas();
8980 printRemainingMessages();
8981 break;
8983 printResultType( Colour::Error, failedString() );
8984 printIssue( "fatal error condition with message:" );
8985 printMessage();
8986 printExpressionWas();
8987 printRemainingMessages();
8988 break;
8990 printResultType( Colour::Error, failedString() );
8991 printIssue( "expected exception, got none" );
8992 printExpressionWas();
8993 printRemainingMessages();
8994 break;
8995 case ResultWas::Info:
8996 printResultType( Colour::None, "info" );
8997 printMessage();
8998 printRemainingMessages();
8999 break;
9000 case ResultWas::Warning:
9001 printResultType( Colour::None, "warning" );
9002 printMessage();
9003 printRemainingMessages();
9004 break;
9006 printResultType( Colour::Error, failedString() );
9007 printIssue( "explicitly" );
9008 printRemainingMessages( Colour::None );
9009 break;
9010 // These cases are here to prevent compiler warnings
9011 case ResultWas::Unknown:
9014 printResultType( Colour::Error, "** internal error **" );
9015 break;
9016 }
9017 }
9018
9019 private:
9020 // Colour::LightGrey
9021
9022 static Colour::Code dimColour() { return Colour::FileName; }
9023
9024#ifdef CATCH_PLATFORM_MAC
9025 static const char* failedString() { return "FAILED"; }
9026 static const char* passedString() { return "PASSED"; }
9027#else
9028 static const char* failedString() { return "failed"; }
9029 static const char* passedString() { return "passed"; }
9030#endif
9031
9032 void printSourceInfo() const {
9033 Colour colourGuard( Colour::FileName );
9034 stream << result.getSourceInfo() << ":";
9035 }
9036
9037 void printResultType( Colour::Code colour, std::string passOrFail ) const {
9038 if( !passOrFail.empty() ) {
9039 {
9040 Colour colourGuard( colour );
9041 stream << " " << passOrFail;
9042 }
9043 stream << ":";
9044 }
9045 }
9046
9047 void printIssue( std::string issue ) const {
9048 stream << " " << issue;
9049 }
9050
9051 void printExpressionWas() {
9052 if( result.hasExpression() ) {
9053 stream << ";";
9054 {
9055 Colour colour( dimColour() );
9056 stream << " expression was:";
9057 }
9058 printOriginalExpression();
9059 }
9060 }
9061
9062 void printOriginalExpression() const {
9063 if( result.hasExpression() ) {
9064 stream << " " << result.getExpression();
9065 }
9066 }
9067
9068 void printReconstructedExpression() const {
9069 if( result.hasExpandedExpression() ) {
9070 {
9071 Colour colour( dimColour() );
9072 stream << " for: ";
9073 }
9074 stream << result.getExpandedExpression();
9075 }
9076 }
9077
9078 void printMessage() {
9079 if ( itMessage != messages.end() ) {
9080 stream << " '" << itMessage->message << "'";
9081 ++itMessage;
9082 }
9083 }
9084
9085 void printRemainingMessages( Colour::Code colour = dimColour() ) {
9086 if ( itMessage == messages.end() )
9087 return;
9088
9089 // using messages.end() directly yields compilation error:
9091 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
9092
9093 {
9094 Colour colourGuard( colour );
9095 stream << " with " << pluralise( N, "message" ) << ":";
9096 }
9097
9098 for(; itMessage != itEnd; ) {
9099 // If this assertion is a warning ignore any INFO messages
9100 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
9101 stream << " '" << itMessage->message << "'";
9102 if ( ++itMessage != itEnd ) {
9103 Colour colourGuard( dimColour() );
9104 stream << " and";
9105 }
9106 }
9107 }
9108 }
9109
9110 private:
9111 std::ostream& stream;
9112 AssertionStats const& stats;
9113 AssertionResult const& result;
9114 std::vector<MessageInfo> messages;
9116 bool printInfoMessages;
9117 };
9118
9119 // Colour, message variants:
9120 // - white: No tests ran.
9121 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
9122 // - white: Passed [both/all] N test cases (no assertions).
9123 // - red: Failed N tests cases, failed M assertions.
9124 // - green: Passed [both/all] N tests cases with M assertions.
9125
9126 std::string bothOrAll( std::size_t count ) const {
9127 return count == 1 ? "" : count == 2 ? "both " : "all " ;
9128 }
9129
9130 void printTotals( const Totals& totals ) const {
9131 if( totals.testCases.total() == 0 ) {
9132 stream << "No tests ran.";
9133 }
9134 else if( totals.testCases.failed == totals.testCases.total() ) {
9135 Colour colour( Colour::ResultError );
9136 const std::string qualify_assertions_failed =
9137 totals.assertions.failed == totals.assertions.total() ?
9138 bothOrAll( totals.assertions.failed ) : "";
9139 stream <<
9140 "Failed " << bothOrAll( totals.testCases.failed )
9141 << pluralise( totals.testCases.failed, "test case" ) << ", "
9142 "failed " << qualify_assertions_failed <<
9143 pluralise( totals.assertions.failed, "assertion" ) << ".";
9144 }
9145 else if( totals.assertions.total() == 0 ) {
9146 stream <<
9147 "Passed " << bothOrAll( totals.testCases.total() )
9148 << pluralise( totals.testCases.total(), "test case" )
9149 << " (no assertions).";
9150 }
9151 else if( totals.assertions.failed ) {
9152 Colour colour( Colour::ResultError );
9153 stream <<
9154 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
9155 "failed " << pluralise( totals.assertions.failed, "assertion" ) << ".";
9156 }
9157 else {
9158 Colour colour( Colour::ResultSuccess );
9159 stream <<
9160 "Passed " << bothOrAll( totals.testCases.passed )
9161 << pluralise( totals.testCases.passed, "test case" ) <<
9162 " with " << pluralise( totals.assertions.passed, "assertion" ) << ".";
9163 }
9164 }
9165 };
9166
9167 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
9168
9169} // end namespace Catch
9170
9171namespace Catch {
9174 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
9183 IReporter::~IReporter() {}
9184 IReporterFactory::~IReporterFactory() {}
9185 IReporterRegistry::~IReporterRegistry() {}
9186 IStreamingReporter::~IStreamingReporter() {}
9187 AssertionStats::~AssertionStats() {}
9188 SectionStats::~SectionStats() {}
9189 TestCaseStats::~TestCaseStats() {}
9190 TestGroupStats::~TestGroupStats() {}
9191 TestRunStats::~TestRunStats() {}
9192 CumulativeReporterBase::SectionNode::~SectionNode() {}
9193 CumulativeReporterBase::~CumulativeReporterBase() {}
9194
9195 StreamingReporterBase::~StreamingReporterBase() {}
9196 ConsoleReporter::~ConsoleReporter() {}
9197 CompactReporter::~CompactReporter() {}
9200 IConfig::~IConfig() {}
9201 XmlReporter::~XmlReporter() {}
9202 JunitReporter::~JunitReporter() {}
9203 TestRegistry::~TestRegistry() {}
9204 FreeFunctionTestCase::~FreeFunctionTestCase() {}
9207 TestSpec::Pattern::~Pattern() {}
9208 TestSpec::NamePattern::~NamePattern() {}
9209 TestSpec::TagPattern::~TagPattern() {}
9210 TestSpec::ExcludedPattern::~ExcludedPattern() {}
9211
9216
9217 void Config::dummy() {}
9218}
9219
9220#ifdef __clang__
9221#pragma clang diagnostic pop
9222#endif
9223
9224#endif
9225
9226#ifdef CATCH_CONFIG_MAIN
9227// #included from: internal/catch_default_main.hpp
9228#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
9229
9230#ifndef __OBJC__
9231
9232// Standard C/C++ main entry point
9233int main (int argc, char * const argv[]) {
9234 return Catch::Session().run( argc, argv );
9235}
9236
9237#else // __OBJC__
9238
9239// Objective-C entry point
9240int main (int argc, char * const argv[]) {
9241#if !CATCH_ARC_ENABLED
9242 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
9243#endif
9244
9245 Catch::registerTestMethods();
9246 int result = Catch::Session().run( argc, (char* const*)argv );
9247
9248#if !CATCH_ARC_ENABLED
9249 [pool drain];
9250#endif
9251
9252 return result;
9253}
9254
9255#endif // __OBJC__
9256
9257#endif
9258
9259#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
9260# undef CLARA_CONFIG_MAIN
9261#endif
9262
9264
9265// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
9266#ifdef CATCH_CONFIG_PREFIX_ALL
9267
9268#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
9269#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
9270
9271#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
9272#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
9273#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
9274
9275#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
9276#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
9277#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
9278#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
9279#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
9280
9281#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
9282#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
9283#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
9284
9285#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
9286#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
9287
9288#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
9289#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
9290#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
9291#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
9292#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
9293
9294#ifdef CATCH_CONFIG_VARIADIC_MACROS
9295 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
9296 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
9297 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
9298 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
9299 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
9300 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
9301#else
9302 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
9303 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
9304 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
9305 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
9306 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
9307 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
9308#endif
9309#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
9310
9311#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
9312#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
9313
9314#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
9315
9316// "BDD-style" convenience wrappers
9317#ifdef CATCH_CONFIG_VARIADIC_MACROS
9318#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
9319#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
9320#else
9321#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
9322#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
9323#endif
9324#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
9325#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
9326#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
9327#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
9328#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
9329
9330// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
9331#else
9332
9333#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
9334#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
9335
9336#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
9337#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
9338#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
9339
9340#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
9341#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
9342#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
9343#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
9344#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
9345
9346#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
9347#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
9348#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
9349
9350#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
9351#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
9352
9353#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
9354#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
9355#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
9356#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
9357#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
9358
9359#ifdef CATCH_CONFIG_VARIADIC_MACROS
9360 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
9361 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
9362 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
9363 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
9364 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
9365 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
9366#else
9367 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
9368 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
9369 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
9370 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
9371 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
9372 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
9373#endif
9374#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
9375
9376#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
9377#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
9378
9379#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
9380
9381#endif
9382
9383#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
9384
9385// "BDD-style" convenience wrappers
9386#ifdef CATCH_CONFIG_VARIADIC_MACROS
9387#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
9388#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
9389#else
9390#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
9391#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
9392#endif
9393#define GIVEN( desc ) SECTION( " Given: " desc, "" )
9394#define WHEN( desc ) SECTION( " When: " desc, "" )
9395#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
9396#define THEN( desc ) SECTION( " Then: " desc, "" )
9397#define AND_THEN( desc ) SECTION( " And: " desc, "" )
9398
9400
9401// #included from: internal/catch_reenable_warnings.h
9402
9403#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
9404
9405#ifdef __clang__
9406# ifdef __ICC // icpc defines the __clang__ macro
9407# pragma warning(pop)
9408# else
9409# pragma clang diagnostic pop
9410# endif
9411#elif defined __GNUC__
9412# pragma GCC diagnostic pop
9413#endif
9414
9415#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
9416
MecaCell::Vec pos
Definition: CellBody.hpp:34
#define CATCH_NOEXCEPT
Definition: catch.hpp:223
#define CATCH_INTERNAL_ERROR(msg)
Definition: catch.hpp:331
#define INTERNAL_CATCH_STRINGIFY(expr)
Definition: catch.hpp:70
std::string getExpression() const
AssertionInfo m_info
Definition: catch.hpp:755
bool hasExpandedExpression() const
SourceLineInfo getSourceInfo() const
std::string getExpandedExpression() const
std::string getExpressionInMacro() const
bool hasMessage() const
std::string getTestMacroName() const
AssertionResult(AssertionInfo const &info, AssertionResultData const &data)
bool hasExpression() const
bool succeeded() const
ResultWas::OfType getResultType() const
AssertionResultData m_resultData
Definition: catch.hpp:756
std::string getMessage() const
BetweenGenerator(T from, T to)
Definition: catch.hpp:1851
virtual T getValue(std::size_t index) const
Definition: catch.hpp:1853
virtual std::size_t size() const
Definition: catch.hpp:1857
CompositeGenerator(CompositeGenerator &other)
Definition: catch.hpp:1894
CompositeGenerator & then(T value)
Definition: catch.hpp:1938
CompositeGenerator & setFileInfo(const char *fileInfo)
Definition: catch.hpp:1901
std::vector< const IGenerator< T > * > m_composed
Definition: catch.hpp:1953
std::string m_fileInfo
Definition: catch.hpp:1954
CompositeGenerator & then(CompositeGenerator &other)
Definition: catch.hpp:1933
void add(const IGenerator< T > *generator)
Definition: catch.hpp:1928
void move(CompositeGenerator &other)
Definition: catch.hpp:1947
Approx(double value)
Definition: catch.hpp:2115
Approx & scale(double newScale)
Definition: catch.hpp:2160
Approx operator()(double value)
Definition: catch.hpp:2131
Approx(Approx const &other)
Definition: catch.hpp:2121
std::string toString() const
Definition: catch.hpp:2165
static Approx custom()
Definition: catch.hpp:2127
Approx & epsilon(double newEpsilon)
Definition: catch.hpp:2155
ExceptionTranslator(std::string(*translateFunction)(T &))
Definition: catch.hpp:2072
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
Definition: catch.hpp:2091
ResultBuilder & captureExpression(RhsT const &rhs)
Definition: catch.hpp:1379
ResultBuilder & m_rb
Definition: catch.hpp:1388
ExpressionLhs(ResultBuilder &rb, T lhs)
Definition: catch.hpp:1316
AllOf & add(Matcher< ExpressionT > const &matcher)
Definition: catch.hpp:2220
virtual std::string toString() const
Definition: catch.hpp:2231
virtual bool match(ExpressionT const &expr) const
Definition: catch.hpp:2224
std::vector< Ptr< Matcher< ExpressionT > > > m_matchers
Definition: catch.hpp:2244
AnyOf & add(Matcher< ExpressionT > const &matcher)
Definition: catch.hpp:2254
virtual std::string toString() const
Definition: catch.hpp:2265
std::vector< Ptr< Matcher< ExpressionT > > > m_matchers
Definition: catch.hpp:2278
virtual bool match(ExpressionT const &expr) const
Definition: catch.hpp:2258
virtual void invoke() const
Definition: catch.hpp:544
virtual ~MethodTestCase()
Definition: catch.hpp:550
MethodTestCase(void(C::*method)())
Definition: catch.hpp:542
NonCopyable(NonCopyable const &info)
NonCopyable & operator=(NonCopyable const &)
virtual ~NonCopyable()
NotImplementedException(NotImplementedException const &)
Definition: catch.hpp:341
virtual ~NotImplementedException() CATCH_NOEXCEPT
Definition: catch.hpp:343
virtual const char * what() const CATCH_NOEXCEPT
SourceLineInfo m_lineInfo
Definition: catch.hpp:349
NotImplementedException(SourceLineInfo const &lineInfo)
T * operator->()
Definition: catch.hpp:2477
void reset()
Definition: catch.hpp:2469
Option(T const &_value)
Definition: catch.hpp:2444
bool none() const
Definition: catch.hpp:2485
T const & operator*() const
Definition: catch.hpp:2476
T valueOr(T const &defaultValue) const
Definition: catch.hpp:2480
bool some() const
Definition: catch.hpp:2484
T * nullableValue
Definition: catch.hpp:2493
T & operator*()
Definition: catch.hpp:2475
const T * operator->() const
Definition: catch.hpp:2478
Option(Option const &_other)
Definition: catch.hpp:2447
void swap(Ptr &other)
Definition: catch.hpp:428
T * get()
Definition: catch.hpp:429
const T * get() const
Definition: catch.hpp:430
Ptr(T *p)
Definition: catch.hpp:401
Ptr(Ptr const &other)
Definition: catch.hpp:405
T * m_p
Definition: catch.hpp:437
T * operator->() const
Definition: catch.hpp:432
void reset()
Definition: catch.hpp:413
T & operator*() const
Definition: catch.hpp:431
bool allowThrows() const
void captureResult(ResultWas::OfType resultType)
ExpressionLhs< T const & > operator<=(T const &operand)
Definition: catch.hpp:1398
ResultBuilder(char const *macroName, SourceLineInfo const &lineInfo, char const *capturedExpression, ResultDisposition::Flags resultDisposition)
ResultBuilder & setResultType(bool result)
AssertionResult build() const
void useActiveException(ResultDisposition::Flags resultDisposition=ResultDisposition::Normal)
AssertionResultData m_data
Definition: catch.hpp:822
AssertionInfo m_assertionInfo
Definition: catch.hpp:821
bool shouldDebugBreak() const
ResultBuilder & setOp(std::string const &op)
ResultBuilder & setLhs(std::string const &lhs)
ResultBuilder & setRhs(std::string const &rhs)
CopyableStream m_stream
Definition: catch.hpp:828
ResultBuilder & setResultType(ResultWas::OfType result)
std::string reconstructExpression() const
void trueValue() const
Definition: catch.hpp:253
void(SafeBool::* type)() const
Definition: catch.hpp:247
static type makeSafe(bool value)
Definition: catch.hpp:249
ScopedMessage(MessageBuilder const &builder)
ScopedMessage(ScopedMessage const &other)
MessageInfo m_info
Definition: catch.hpp:1459
bool m_sectionIncluded
Definition: catch.hpp:1817
Timer m_timer
Definition: catch.hpp:1818
SectionInfo m_info
Definition: catch.hpp:1813
std::string m_name
Definition: catch.hpp:1815
Section(SectionInfo const &info)
Counts m_assertions
Definition: catch.hpp:1816
TestCase(ITestCase *testCase, TestCaseInfo const &info)
TestCase withName(std::string const &_newName) const
void invoke() const
Ptr< ITestCase > test
Definition: catch.hpp:2578
TestCaseInfo const & getTestCaseInfo() const
TestCase(TestCase const &other)
void swap(TestCase &other)
unsigned int getElapsedMilliseconds() const
uint64_t m_ticks
Definition: catch.hpp:1795
double getElapsedSeconds() const
unsigned int getElapsedMicroseconds() const
std::vector< T > m_values
Definition: catch.hpp:1885
void add(T value)
Definition: catch.hpp:1872
virtual T getValue(std::size_t index) const
Definition: catch.hpp:1876
virtual std::size_t size() const
Definition: catch.hpp:1880
A simple vector class template.
Definition: std.hpp:290
T & front()
Returns a reference to the first element.
Definition: std.hpp:329
void push_back(const T &value)
Adds an element to the end of the vector.
Definition: std.hpp:304
iterator begin()
Returns an iterator to the first element.
Definition: std.hpp:409
iterator end()
Returns an iterator to the last element.
Definition: std.hpp:418
size_t size() const
Returns the number of elements in the vector.
Definition: std.hpp:320
bool empty() const
Checks if the vector is empty.
Definition: std.hpp:347
std::string rawMemoryToString(const T &object)
Definition: catch.hpp:1178
std::string rangeToString(InputIterator first, InputIterator last)
Definition: catch.hpp:1289
FalseType testStreamable(FalseType)
std::string rawMemoryToString(const void *object, std::size_t size)
FalseType operator<<(std::ostream const &, BorgType const &)
std::string unprintableString
CompositeGenerator< T > between(T from, T to)
Definition: catch.hpp:1961
CompositeGenerator< T > values(T val1, T val2, T val3, T val4)
Definition: catch.hpp:1989
bool applyEvaluator(T1 const &lhs, T2 const &rhs)
Definition: catch.hpp:921
bool compare(T *lhs, int rhs)
Definition: catch.hpp:990
T & opCast(T const &t)
Definition: catch.hpp:871
@ IsLessThanOrEqualTo
Definition: catch.hpp:858
@ IsGreaterThanOrEqualTo
Definition: catch.hpp:859
std::string makeString(const char *str)
Definition: catch.hpp:2286
Impl::StdString::StartsWith StartsWith(const char *substr)
Definition: catch.hpp:2394
Impl::StdString::EndsWith EndsWith(std::string const &substr)
Definition: catch.hpp:2397
Impl::Generic::AnyOf< ExpressionT > AnyOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
Definition: catch.hpp:2373
Impl::StdString::Contains Contains(const char *substr)
Definition: catch.hpp:2388
Impl::StdString::StartsWith StartsWith(std::string const &substr)
Definition: catch.hpp:2391
Impl::StdString::Equals Equals(std::string const &str)
Definition: catch.hpp:2379
Impl::Generic::AllOf< ExpressionT > AllOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
Definition: catch.hpp:2362
Impl::StdString::Contains Contains(std::string const &substr)
Definition: catch.hpp:2385
Impl::StdString::EndsWith EndsWith(const char *substr)
Definition: catch.hpp:2400
Impl::StdString::Equals Equals(const char *str)
Definition: catch.hpp:2382
Definition: catch.hpp:227
T const & operator+(T const &value, StreamEndStop)
Definition: catch.hpp:325
void toLowerInPlace(std::string &s)
std::string trim(std::string const &str)
void cleanUp()
bool alwaysTrue()
Definition: catch.hpp:310
std::string(* exceptionTranslateFunction)()
Definition: catch.hpp:2054
IContext & getCurrentContext()
void(* TestFunction)()
Definition: catch.hpp:555
std::string toString(std::vector< T, Allocator > const &v)
Definition: catch.hpp:1222
TestCase makeTestCase(ITestCase *testCase, std::string const &className, std::string const &name, std::string const &description, SourceLineInfo const &lineInfo)
bool isOk(ResultWas::OfType resultType)
Definition: catch.hpp:673
bool isJustInfo(int flags)
Definition: catch.hpp:676
IMutableRegistryHub & getMutableRegistryHub()
bool startsWith(std::string const &s, std::string const &prefix)
void throwLogicError(std::string const &message, SourceLineInfo const &locationInfo)
IMutableContext & getCurrentMutableContext()
IRegistryHub & getRegistryHub()
IGeneratorsForTest * createGeneratorsForTest()
bool shouldContinueOnFailure(int flags)
Definition: catch.hpp:693
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
bool isFalseTest(int flags)
Definition: catch.hpp:694
bool contains(std::string const &s, std::string const &infix)
void writeToDebugConsole(std::string const &text)
void deleteAll(ContainerT &container)
Definition: catch.hpp:257
bool isDebuggerActive()
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
Definition: catch.hpp:689
bool shouldSuppressFailure(int flags)
Definition: catch.hpp:695
std::string toLower(std::string const &s)
bool alwaysFalse()
Definition: catch.hpp:311
Stream createStream(std::string const &streamName)
bool endsWith(std::string const &s, std::string const &suffix)
std::string translateActiveException()
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1283
bool isTrue(bool value)
Definition: catch.hpp:309
void cleanUpContext()
void deleteAllValues(AssociativeContainerT &container)
Definition: catch.hpp:264
IResultCapture & getResultCapture()
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
Vector3D operator*(const Vector3D &v1, const Vector3D &v2)
Definition: vector3D.h:561
Vector3D operator/(const Vector3D &v, const double f)
Definition: vector3D.h:584
bool operator!=(const Vector3D &v1, const Vector3D &v2)
Definition: vector3D.h:541
Vector3D operator-(const Vector3D &v1, const Vector3D &v2)
Definition: vector3D.h:557
bool operator==(const Vector3D &v1, const Vector3D &v2)
Definition: vector3D.h:537
auto invoke(F &&f, Args &&... args) -> decltype(InvokeResult< F, Args... >::invoke(std::forward< F >(f), std::forward< Args >(args)...))
Definition: mingw.thread.h:122
void swap(shared_lock< Mutex > &lhs, shared_lock< Mutex > &rhs) noexcept
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition: json.hpp:1277
@ object
object (unordered set of name/value pairs)
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:1787
Provides common mathematical functions and vector operations.
Definition: std.hpp:4
iostream cout
Standard output stream.
Definition: std.hpp:267
iostream cerr
Standard error stream.
Definition: std.hpp:281
iostream endl
End-of-line manipulator.
Definition: std.hpp:274
double fabs(double x)
Computes the absolute value of a floating-point number.
Definition: std.hpp:93
int main(int argc, char *argv[])
Definition: main.cpp:19
SourceLineInfo lineInfo
Definition: catch.hpp:715
ResultDisposition::Flags resultDisposition
Definition: catch.hpp:717
AssertionInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, std::string const &_capturedExpression, ResultDisposition::Flags _resultDisposition)
std::string macroName
Definition: catch.hpp:714
std::string capturedExpression
Definition: catch.hpp:716
ResultWas::OfType resultType
Definition: catch.hpp:726
std::string reconstructedExpression
Definition: catch.hpp:724
AutoReg(void(C::*method)(), char const *className, NameAndDesc const &nameAndDesc, SourceLineInfo const &lineInfo)
Definition: catch.hpp:573
void registerTestCase(ITestCase *testCase, char const *className, NameAndDesc const &nameAndDesc, SourceLineInfo const &lineInfo)
AutoReg(AutoReg const &)
AutoReg(TestFunction function, SourceLineInfo const &lineInfo, NameAndDesc const &nameAndDesc)
CopyableStream(CopyableStream const &other)
Definition: catch.hpp:771
CopyableStream & operator=(CopyableStream const &other)
Definition: catch.hpp:774
std::ostringstream oss
Definition: catch.hpp:779
std::size_t failed
Definition: catch.hpp:1740
bool allOk() const
Definition: catch.hpp:1735
bool allPassed() const
Definition: catch.hpp:1732
std::size_t total() const
Definition: catch.hpp:1729
std::size_t failedButOk
Definition: catch.hpp:1741
std::size_t passed
Definition: catch.hpp:1739
static std::ostream & s
Definition: catch.hpp:1126
static std::string convert(T const &_value)
Definition: catch.hpp:1168
static std::string convert(T const &)
Definition: catch.hpp:1161
virtual size_t getGeneratorIndex(std::string const &fileInfo, size_t totalSize)=0
virtual bool advanceGeneratorsForCurrentTest()=0
virtual IResultCapture * getResultCapture()=0
virtual Ptr< IConfig const > getConfig() const =0
virtual IRunner * getRunner()=0
virtual ~IContext()
virtual std::string translate() const =0
virtual std::string translateActiveException() const =0
virtual ~IGenerator()
Definition: catch.hpp:1843
virtual std::size_t size() const =0
virtual T getValue(std::size_t index) const =0
virtual bool moveNext()=0
virtual std::size_t getCurrentIndex() const =0
virtual IGeneratorInfo & getGeneratorInfo(std::string const &fileInfo, std::size_t size)=0
virtual bool moveNext()=0
virtual void setConfig(Ptr< IConfig const > const &config)=0
virtual void setResultCapture(IResultCapture *resultCapture)=0
virtual void setRunner(IRunner *runner)=0
virtual void registerTest(TestCase const &testInfo)=0
virtual void registerReporter(std::string const &name, IReporterFactory *factory)=0
virtual void registerTranslator(const IExceptionTranslator *translator)=0
virtual ~IRegistryHub()
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry()=0
virtual IReporterRegistry const & getReporterRegistry() const =0
virtual void sectionEnded(SectionInfo const &name, Counts const &assertions, double _durationInSeconds)=0
virtual const AssertionResult * getLastResult() const =0
virtual void popScopedMessage(MessageInfo const &message)=0
virtual bool sectionStarted(SectionInfo const &sectionInfo, Counts &assertions)=0
virtual void handleFatalErrorCondition(std::string const &message)=0
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual void assertionEnded(AssertionResult const &result)=0
virtual std::string getCurrentTestName() const =0
virtual bool aborting() const =0
virtual ~IRunner()
virtual void release() const =0
virtual ~IShared()
virtual void addRef() const =0
static ITagAliasRegistry const & get()
virtual Option< TagAlias > find(std::string const &alias) const =0
virtual std::string expandAliases(std::string const &unexpandedTestSpec) const =0
virtual void invoke() const =0
virtual ~ITestCase()
virtual std::vector< TestCase > const & getAllTests() const =0
virtual void getFilteredTests(TestSpec const &testSpec, IConfig const &config, std::vector< TestCase > &matchingTestCases, bool negated=false) const =0
static bool evaluate(T1 const &lhs, T2 const &rhs)
Definition: catch.hpp:885
static bool evaluate(T1 const &lhs, T2 const &rhs)
Definition: catch.hpp:903
static bool evaluate(T1 const &lhs, T2 const &rhs)
Definition: catch.hpp:909
static bool evaluate(T1 const &lhs, T2 const &rhs)
Definition: catch.hpp:897
static bool evaluate(T1 const &lhs, T2 const &rhs)
Definition: catch.hpp:915
static bool evaluate(T1 const &lhs, T2 const &rhs)
Definition: catch.hpp:891
static const char * getName()
Definition: catch.hpp:862
virtual std::string toString() const =0
virtual Ptr< Matcher > clone() const =0
virtual bool match(ExpressionT const &expr) const =0
virtual Ptr< Matcher< ExpressionT > > clone() const
Definition: catch.hpp:2206
virtual bool match(std::string const &expr) const
Definition: catch.hpp:2310
Contains(std::string const &substr)
Definition: catch.hpp:2305
virtual std::string toString() const
Definition: catch.hpp:2313
virtual std::string toString() const
Definition: catch.hpp:2345
EndsWith(std::string const &substr)
Definition: catch.hpp:2337
virtual bool match(std::string const &expr) const
Definition: catch.hpp:2342
Equals(std::string const &str)
Definition: catch.hpp:2289
virtual std::string toString() const
Definition: catch.hpp:2297
virtual bool match(std::string const &expr) const
Definition: catch.hpp:2294
StartsWith(std::string const &substr)
Definition: catch.hpp:2321
StartsWith(StartsWith const &other)
Definition: catch.hpp:2322
virtual std::string toString() const
Definition: catch.hpp:2329
virtual bool match(std::string const &expr) const
Definition: catch.hpp:2326
std::ostringstream m_stream
Definition: catch.hpp:1450
MessageInfo m_info
Definition: catch.hpp:1449
MessageBuilder(std::string const &macroName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
Definition: catch.hpp:1437
std::string macroName
Definition: catch.hpp:1420
static unsigned int globalCount
Definition: catch.hpp:1433
MessageInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
unsigned int sequence
Definition: catch.hpp:1424
SourceLineInfo lineInfo
Definition: catch.hpp:1421
std::string message
Definition: catch.hpp:1423
ResultWas::OfType type
Definition: catch.hpp:1422
NameAndDesc(const char *_name="", const char *_description="")
Definition: catch.hpp:558
const char * description
Definition: catch.hpp:563
const char * name
Definition: catch.hpp:562
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
std::string description
Definition: catch.hpp:1699
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &_description=std::string())
std::string name
Definition: catch.hpp:1698
SourceLineInfo lineInfo
Definition: catch.hpp:1700
virtual void addRef() const
Definition: catch.hpp:451
unsigned int m_rc
Definition: catch.hpp:459
virtual void release() const
Definition: catch.hpp:454
SourceLineInfo(SourceLineInfo const &other)
SourceLineInfo(char const *_file, std::size_t _line)
bool operator==(SourceLineInfo const &other) const
std::size_t line
Definition: catch.hpp:303
bool operator<(SourceLineInfo const &other) const
std::string file
Definition: catch.hpp:302
std::string operator+()
Definition: catch.hpp:320
static std::string convert(R C::*p)
Definition: catch.hpp:1201
static std::string convert(U *p)
Definition: catch.hpp:1191
SourceLineInfo lineInfo
Definition: catch.hpp:2424
std::string tag
Definition: catch.hpp:2423
TagAlias(std::string _tag, SourceLineInfo _lineInfo)
Definition: catch.hpp:2421
std::set< std::string > tags
Definition: catch.hpp:2553
std::set< std::string > lcaseTags
Definition: catch.hpp:2554
std::string className
Definition: catch.hpp:2551
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::set< std::string > const &_tags, SourceLineInfo const &_lineInfo)
std::string description
Definition: catch.hpp:2552
std::string name
Definition: catch.hpp:2550
bool okToFail() const
bool isHidden() const
SourceLineInfo lineInfo
Definition: catch.hpp:2556
bool expectedToFail() const
TestCaseInfo(TestCaseInfo const &other)
std::string tagsAsString
Definition: catch.hpp:2555
SpecialProperties properties
Definition: catch.hpp:2557
Totals delta(Totals const &prevTotals) const
Definition: catch.hpp:1753
Counts assertions
Definition: catch.hpp:1770
Counts testCases
Definition: catch.hpp:1771
std::size_t m_count
Definition: catch.hpp:284
pluralise(std::size_t count, std::string const &label)
std::string m_label
Definition: catch.hpp:285
friend std::ostream & operator<<(std::ostream &os, pluralise const &pluraliser)
#define private
Definition: test.cpp:3