1 /*
2 * Catch v1.3.1
3 * Generated: 2015-12-09 18:10:29.846134
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 #ifdef __clang__
25 # ifdef __ICC // icpc defines the __clang__ macro
26 # pragma warning(push)
27 # pragma warning(disable: 161 1682)
28 # else // __ICC
29 # pragma clang diagnostic ignored "-Wglobal-constructors"
30 # pragma clang diagnostic ignored "-Wvariadic-macros"
31 # pragma clang diagnostic ignored "-Wc99-extensions"
32 # pragma clang diagnostic ignored "-Wunused-variable"
33 # pragma clang diagnostic push
34 # pragma clang diagnostic ignored "-Wpadded"
35 # pragma clang diagnostic ignored "-Wc++98-compat"
36 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
37 # pragma clang diagnostic ignored "-Wswitch-enum"
38 # pragma clang diagnostic ignored "-Wcovered-switch-default"
39 # endif
40 #elif defined __GNUC__
41 # pragma GCC diagnostic ignored "-Wvariadic-macros"
42 # pragma GCC diagnostic ignored "-Wunused-variable"
43 # pragma GCC diagnostic push
44 # pragma GCC diagnostic ignored "-Wpadded"
45 #endif
46 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
47 # define CATCH_IMPL
48 #endif
49
50 #ifdef CATCH_IMPL
51 # ifndef CLARA_CONFIG_MAIN
52 # define CLARA_CONFIG_MAIN_NOT_DEFINED
53 # define CLARA_CONFIG_MAIN
54 # endif
55 #endif
56
57 // #included from: internal/catch_notimplemented_exception.h
58 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
59
60 // #included from: catch_common.h
61 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
62
63 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
64 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
65 #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
66
67 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
68 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
69
70 #include <sstream>
71 #include <stdexcept>
72 #include <algorithm>
73
74 // #included from: catch_compiler_capabilities.h
75 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
76
77 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
78 // The following features are defined:
79 //
80 // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
81 // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
82 // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
83 // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
84 // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
85 // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
86 // CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
87 // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
88
89 // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
90
91 // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
92
93 // ****************
94 // Note to maintainers: if new toggles are added please document them
95 // in configuration.md, too
96 // ****************
97
98 // In general each macro has a _NO_<feature name> form
99 // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
100 // Many features, at point of detection, define an _INTERNAL_ macro, so they
101 // can be combined, en-mass, with the _NO_ forms later.
102
103 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
104
105 #ifdef __clang__
106
107 # if __has_feature(cxx_nullptr)
108 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
109 # endif
110
111 # if __has_feature(cxx_noexcept)
112 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
113 # endif
114
115 #endif // __clang__
116
117 ////////////////////////////////////////////////////////////////////////////////
118 // Borland
119 #ifdef __BORLANDC__
120
121 #endif // __BORLANDC__
122
123 ////////////////////////////////////////////////////////////////////////////////
124 // EDG
125 #ifdef __EDG_VERSION__
126
127 #endif // __EDG_VERSION__
128
129 ////////////////////////////////////////////////////////////////////////////////
130 // Digital Mars
131 #ifdef __DMC__
132
133 #endif // __DMC__
134
135 ////////////////////////////////////////////////////////////////////////////////
136 // GCC
137 #ifdef __GNUC__
138
139 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
140 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
141 #endif
142
143 // - otherwise more recent versions define __cplusplus >= 201103L
144 // and will get picked up below
145
146 #endif // __GNUC__
147
148 ////////////////////////////////////////////////////////////////////////////////
149 // Visual C++
150 #ifdef _MSC_VER
151
152 #if (_MSC_VER >= 1600)
153 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
154 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
155 #endif
156
157 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
158 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
159 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
160 #endif
161
162 #endif // _MSC_VER
163
164 ////////////////////////////////////////////////////////////////////////////////
165
166 // Use variadic macros if the compiler supports them
167 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
168 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
169 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
170 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
171
172 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
173
174 #endif
175
176 ////////////////////////////////////////////////////////////////////////////////
177 // C++ language feature support
178
179 // catch all support for C++11
180 #if defined(__cplusplus) && __cplusplus >= 201103L
181
182 # define CATCH_CPP11_OR_GREATER
183
184 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
185 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
186 # endif
187
188 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
189 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
190 # endif
191
192 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
193 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
194 # endif
195
196 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
197 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
198 # endif
199
200 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
201 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
202 # endif
203
204 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
205 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
206 # endif
207
208 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
209 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
210 # endif
211
212 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
213 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
214 # endif
215 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
216 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
217 # endif
218
219 #endif // __cplusplus >= 201103L
220
221 // Now set the actual defines based on the above + anything the user has configured
222 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
223 # define CATCH_CONFIG_CPP11_NULLPTR
224 #endif
225 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
226 # define CATCH_CONFIG_CPP11_NOEXCEPT
227 #endif
228 #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)
229 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
230 #endif
231 #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)
232 # define CATCH_CONFIG_CPP11_IS_ENUM
233 #endif
234 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
235 # define CATCH_CONFIG_CPP11_TUPLE
236 #endif
237 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
238 # define CATCH_CONFIG_VARIADIC_MACROS
239 #endif
240 #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
241 # define CATCH_CONFIG_CPP11_LONG_LONG
242 #endif
243 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
244 # define CATCH_CONFIG_CPP11_OVERRIDE
245 #endif
246 #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
247 # define CATCH_CONFIG_CPP11_UNIQUE_PTR
248 #endif
249
250 // noexcept support:
251 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
252 # define CATCH_NOEXCEPT noexcept
253 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
254 #else
255 # define CATCH_NOEXCEPT throw()
256 # define CATCH_NOEXCEPT_IS(x)
257 #endif
258
259 // nullptr support
260 #ifdef CATCH_CONFIG_CPP11_NULLPTR
261 # define CATCH_NULL nullptr
262 #else
263 # define CATCH_NULL NULL
264 #endif
265
266 // override support
267 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
268 # define CATCH_OVERRIDE override
269 #else
270 # define CATCH_OVERRIDE
271 #endif
272
273 // unique_ptr support
274 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
275 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
276 #else
277 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
278 #endif
279
280 namespace Catch {
281
282 struct IConfig;
283
284 struct CaseSensitive { enum Choice {
285 Yes,
286 No
287 }; };
288
289 class NonCopyable {
290 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
291 NonCopyable( NonCopyable const& ) = delete;
292 NonCopyable( NonCopyable && ) = delete;
293 NonCopyable& operator = ( NonCopyable const& ) = delete;
294 NonCopyable& operator = ( NonCopyable && ) = delete;
295 #else
296 NonCopyable( NonCopyable const& info );
297 NonCopyable& operator = ( NonCopyable const& );
298 #endif
299
300 protected:
NonCopyable()301 NonCopyable() {}
302 virtual ~NonCopyable();
303 };
304
305 class SafeBool {
306 public:
307 typedef void (SafeBool::*type)() const;
308
makeSafe(bool value)309 static type makeSafe( bool value ) {
310 return value ? &SafeBool::trueValue : 0;
311 }
312 private:
trueValue() const313 void trueValue() const {}
314 };
315
316 template<typename ContainerT>
deleteAll(ContainerT & container)317 inline void deleteAll( ContainerT& container ) {
318 typename ContainerT::const_iterator it = container.begin();
319 typename ContainerT::const_iterator itEnd = container.end();
320 for(; it != itEnd; ++it )
321 delete *it;
322 }
323 template<typename AssociativeContainerT>
deleteAllValues(AssociativeContainerT & container)324 inline void deleteAllValues( AssociativeContainerT& container ) {
325 typename AssociativeContainerT::const_iterator it = container.begin();
326 typename AssociativeContainerT::const_iterator itEnd = container.end();
327 for(; it != itEnd; ++it )
328 delete it->second;
329 }
330
331 bool startsWith( std::string const& s, std::string const& prefix );
332 bool endsWith( std::string const& s, std::string const& suffix );
333 bool contains( std::string const& s, std::string const& infix );
334 void toLowerInPlace( std::string& s );
335 std::string toLower( std::string const& s );
336 std::string trim( std::string const& str );
337 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
338
339 struct pluralise {
340 pluralise( std::size_t count, std::string const& label );
341
342 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
343
344 std::size_t m_count;
345 std::string m_label;
346 };
347
348 struct SourceLineInfo {
349
350 SourceLineInfo();
351 SourceLineInfo( char const* _file, std::size_t _line );
352 SourceLineInfo( SourceLineInfo const& other );
353 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
354 SourceLineInfo( SourceLineInfo && ) = default;
355 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
356 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
357 # endif
358 bool empty() const;
359 bool operator == ( SourceLineInfo const& other ) const;
360 bool operator < ( SourceLineInfo const& other ) const;
361
362 std::string file;
363 std::size_t line;
364 };
365
366 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
367
368 // This is just here to avoid compiler warnings with macro constants and boolean literals
isTrue(bool value)369 inline bool isTrue( bool value ){ return value; }
alwaysTrue()370 inline bool alwaysTrue() { return true; }
alwaysFalse()371 inline bool alwaysFalse() { return false; }
372
373 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
374
375 void seedRng( IConfig const& config );
376 unsigned int rngSeed();
377
378 // Use this in variadic streaming macros to allow
379 // >> +StreamEndStop
380 // as well as
381 // >> stuff +StreamEndStop
382 struct StreamEndStop {
operator +Catch::StreamEndStop383 std::string operator+() {
384 return std::string();
385 }
386 };
387 template<typename T>
operator +(T const & value,StreamEndStop)388 T const& operator + ( T const& value, StreamEndStop ) {
389 return value;
390 }
391 }
392
393 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
394 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
395
396 #include <ostream>
397
398 namespace Catch {
399
400 class NotImplementedException : public std::exception
401 {
402 public:
403 NotImplementedException( SourceLineInfo const& lineInfo );
NotImplementedException(NotImplementedException const &)404 NotImplementedException( NotImplementedException const& ) {}
405
~NotImplementedException()406 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
407
408 virtual const char* what() const CATCH_NOEXCEPT;
409
410 private:
411 std::string m_what;
412 SourceLineInfo m_lineInfo;
413 };
414
415 } // end namespace Catch
416
417 ///////////////////////////////////////////////////////////////////////////////
418 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
419
420 // #included from: internal/catch_context.h
421 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
422
423 // #included from: catch_interfaces_generators.h
424 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
425
426 #include <string>
427
428 namespace Catch {
429
430 struct IGeneratorInfo {
431 virtual ~IGeneratorInfo();
432 virtual bool moveNext() = 0;
433 virtual std::size_t getCurrentIndex() const = 0;
434 };
435
436 struct IGeneratorsForTest {
437 virtual ~IGeneratorsForTest();
438
439 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
440 virtual bool moveNext() = 0;
441 };
442
443 IGeneratorsForTest* createGeneratorsForTest();
444
445 } // end namespace Catch
446
447 // #included from: catch_ptr.hpp
448 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
449
450 #ifdef __clang__
451 #pragma clang diagnostic push
452 #pragma clang diagnostic ignored "-Wpadded"
453 #endif
454
455 namespace Catch {
456
457 // An intrusive reference counting smart pointer.
458 // T must implement addRef() and release() methods
459 // typically implementing the IShared interface
460 template<typename T>
461 class Ptr {
462 public:
Ptr()463 Ptr() : m_p( CATCH_NULL ){}
Ptr(T * p)464 Ptr( T* p ) : m_p( p ){
465 if( m_p )
466 m_p->addRef();
467 }
Ptr(Ptr const & other)468 Ptr( Ptr const& other ) : m_p( other.m_p ){
469 if( m_p )
470 m_p->addRef();
471 }
~Ptr()472 ~Ptr(){
473 if( m_p )
474 m_p->release();
475 }
reset()476 void reset() {
477 if( m_p )
478 m_p->release();
479 m_p = CATCH_NULL;
480 }
operator =(T * p)481 Ptr& operator = ( T* p ){
482 Ptr temp( p );
483 swap( temp );
484 return *this;
485 }
operator =(Ptr const & other)486 Ptr& operator = ( Ptr const& other ){
487 Ptr temp( other );
488 swap( temp );
489 return *this;
490 }
swap(Ptr & other)491 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
get() const492 T* get() const{ return m_p; }
operator *() const493 T& operator*() const { return *m_p; }
operator ->() const494 T* operator->() const { return m_p; }
operator !() const495 bool operator !() const { return m_p == CATCH_NULL; }
operator SafeBool::type() const496 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
497
498 private:
499 T* m_p;
500 };
501
502 struct IShared : NonCopyable {
503 virtual ~IShared();
504 virtual void addRef() const = 0;
505 virtual void release() const = 0;
506 };
507
508 template<typename T = IShared>
509 struct SharedImpl : T {
510
SharedImplCatch::SharedImpl511 SharedImpl() : m_rc( 0 ){}
512
addRefCatch::SharedImpl513 virtual void addRef() const {
514 ++m_rc;
515 }
releaseCatch::SharedImpl516 virtual void release() const {
517 if( --m_rc == 0 )
518 delete this;
519 }
520
521 mutable unsigned int m_rc;
522 };
523
524 } // end namespace Catch
525
526 #ifdef __clang__
527 #pragma clang diagnostic pop
528 #endif
529
530 #include <memory>
531 #include <vector>
532 #include <stdlib.h>
533
534 namespace Catch {
535
536 class TestCase;
537 class Stream;
538 struct IResultCapture;
539 struct IRunner;
540 struct IGeneratorsForTest;
541 struct IConfig;
542
543 struct IContext
544 {
545 virtual ~IContext();
546
547 virtual IResultCapture* getResultCapture() = 0;
548 virtual IRunner* getRunner() = 0;
549 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
550 virtual bool advanceGeneratorsForCurrentTest() = 0;
551 virtual Ptr<IConfig const> getConfig() const = 0;
552 };
553
554 struct IMutableContext : IContext
555 {
556 virtual ~IMutableContext();
557 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
558 virtual void setRunner( IRunner* runner ) = 0;
559 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
560 };
561
562 IContext& getCurrentContext();
563 IMutableContext& getCurrentMutableContext();
564 void cleanUpContext();
565 Stream createStream( std::string const& streamName );
566
567 }
568
569 // #included from: internal/catch_test_registry.hpp
570 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
571
572 // #included from: catch_interfaces_testcase.h
573 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
574
575 #include <vector>
576
577 namespace Catch {
578
579 class TestSpec;
580
581 struct ITestCase : IShared {
582 virtual void invoke () const = 0;
583 protected:
584 virtual ~ITestCase();
585 };
586
587 class TestCase;
588 struct IConfig;
589
590 struct ITestCaseRegistry {
591 virtual ~ITestCaseRegistry();
592 virtual std::vector<TestCase> const& getAllTests() const = 0;
593 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
594 };
595
596 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
597 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
598 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
599
600 }
601
602 namespace Catch {
603
604 template<typename C>
605 class MethodTestCase : public SharedImpl<ITestCase> {
606
607 public:
MethodTestCase(void (C::* method)())608 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
609
invoke() const610 virtual void invoke() const {
611 C obj;
612 (obj.*m_method)();
613 }
614
615 private:
~MethodTestCase()616 virtual ~MethodTestCase() {}
617
618 void (C::*m_method)();
619 };
620
621 typedef void(*TestFunction)();
622
623 struct NameAndDesc {
NameAndDescCatch::NameAndDesc624 NameAndDesc( const char* _name = "", const char* _description= "" )
625 : name( _name ), description( _description )
626 {}
627
628 const char* name;
629 const char* description;
630 };
631
632 void registerTestCase
633 ( ITestCase* testCase,
634 char const* className,
635 NameAndDesc const& nameAndDesc,
636 SourceLineInfo const& lineInfo );
637
638 struct AutoReg {
639
640 AutoReg
641 ( TestFunction function,
642 SourceLineInfo const& lineInfo,
643 NameAndDesc const& nameAndDesc );
644
645 template<typename C>
AutoRegCatch::AutoReg646 AutoReg
647 ( void (C::*method)(),
648 char const* className,
649 NameAndDesc const& nameAndDesc,
650 SourceLineInfo const& lineInfo ) {
651
652 registerTestCase
653 ( new MethodTestCase<C>( method ),
654 className,
655 nameAndDesc,
656 lineInfo );
657 }
658
659 ~AutoReg();
660
661 private:
662 AutoReg( AutoReg const& );
663 void operator= ( AutoReg const& );
664 };
665
666 void registerTestCaseFunction
667 ( TestFunction function,
668 SourceLineInfo const& lineInfo,
669 NameAndDesc const& nameAndDesc );
670
671 } // end namespace Catch
672
673 #ifdef CATCH_CONFIG_VARIADIC_MACROS
674 ///////////////////////////////////////////////////////////////////////////////
675 #define INTERNAL_CATCH_TESTCASE( ... ) \
676 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
677 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__ ) ); }\
678 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
679
680 ///////////////////////////////////////////////////////////////////////////////
681 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
682 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
683
684 ///////////////////////////////////////////////////////////////////////////////
685 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
686 namespace{ \
687 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
688 void test(); \
689 }; \
690 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 ); \
691 } \
692 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
693
694 ///////////////////////////////////////////////////////////////////////////////
695 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
696 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
697
698 #else
699 ///////////////////////////////////////////////////////////////////////////////
700 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
701 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
702 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 ) ); }\
703 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
704
705 ///////////////////////////////////////////////////////////////////////////////
706 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
707 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
708
709 ///////////////////////////////////////////////////////////////////////////////
710 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
711 namespace{ \
712 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
713 void test(); \
714 }; \
715 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 ); \
716 } \
717 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
718
719 ///////////////////////////////////////////////////////////////////////////////
720 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
721 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
722 #endif
723
724 // #included from: internal/catch_capture.hpp
725 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
726
727 // #included from: catch_result_builder.h
728 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
729
730 // #included from: catch_result_type.h
731 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
732
733 namespace Catch {
734
735 // ResultWas::OfType enum
736 struct ResultWas { enum OfType {
737 Unknown = -1,
738 Ok = 0,
739 Info = 1,
740 Warning = 2,
741
742 FailureBit = 0x10,
743
744 ExpressionFailed = FailureBit | 1,
745 ExplicitFailure = FailureBit | 2,
746
747 Exception = 0x100 | FailureBit,
748
749 ThrewException = Exception | 1,
750 DidntThrowException = Exception | 2,
751
752 FatalErrorCondition = 0x200 | FailureBit
753
754 }; };
755
isOk(ResultWas::OfType resultType)756 inline bool isOk( ResultWas::OfType resultType ) {
757 return ( resultType & ResultWas::FailureBit ) == 0;
758 }
isJustInfo(int flags)759 inline bool isJustInfo( int flags ) {
760 return flags == ResultWas::Info;
761 }
762
763 // ResultDisposition::Flags enum
764 struct ResultDisposition { enum Flags {
765 Normal = 0x01,
766
767 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
768 FalseTest = 0x04, // Prefix expression with !
769 SuppressFail = 0x08 // Failures are reported but do not fail the test
770 }; };
771
operator |(ResultDisposition::Flags lhs,ResultDisposition::Flags rhs)772 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
773 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
774 }
775
shouldContinueOnFailure(int flags)776 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
isFalseTest(int flags)777 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
shouldSuppressFailure(int flags)778 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
779
780 } // end namespace Catch
781
782 // #included from: catch_assertionresult.h
783 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
784
785 #include <string>
786
787 namespace Catch {
788
789 struct AssertionInfo
790 {
AssertionInfoCatch::AssertionInfo791 AssertionInfo() {}
792 AssertionInfo( std::string const& _macroName,
793 SourceLineInfo const& _lineInfo,
794 std::string const& _capturedExpression,
795 ResultDisposition::Flags _resultDisposition );
796
797 std::string macroName;
798 SourceLineInfo lineInfo;
799 std::string capturedExpression;
800 ResultDisposition::Flags resultDisposition;
801 };
802
803 struct AssertionResultData
804 {
AssertionResultDataCatch::AssertionResultData805 AssertionResultData() : resultType( ResultWas::Unknown ) {}
806
807 std::string reconstructedExpression;
808 std::string message;
809 ResultWas::OfType resultType;
810 };
811
812 class AssertionResult {
813 public:
814 AssertionResult();
815 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
816 ~AssertionResult();
817 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
818 AssertionResult( AssertionResult const& ) = default;
819 AssertionResult( AssertionResult && ) = default;
820 AssertionResult& operator = ( AssertionResult const& ) = default;
821 AssertionResult& operator = ( AssertionResult && ) = default;
822 # endif
823
824 bool isOk() const;
825 bool succeeded() const;
826 ResultWas::OfType getResultType() const;
827 bool hasExpression() const;
828 bool hasMessage() const;
829 std::string getExpression() const;
830 std::string getExpressionInMacro() const;
831 bool hasExpandedExpression() const;
832 std::string getExpandedExpression() const;
833 std::string getMessage() const;
834 SourceLineInfo getSourceInfo() const;
835 std::string getTestMacroName() const;
836
837 protected:
838 AssertionInfo m_info;
839 AssertionResultData m_resultData;
840 };
841
842 } // end namespace Catch
843
844 // #included from: catch_matchers.hpp
845 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
846
847 namespace Catch {
848 namespace Matchers {
849 namespace Impl {
850
851 namespace Generic {
852 template<typename ExpressionT> class AllOf;
853 template<typename ExpressionT> class AnyOf;
854 template<typename ExpressionT> class Not;
855 }
856
857 template<typename ExpressionT>
858 struct Matcher : SharedImpl<IShared>
859 {
860 typedef ExpressionT ExpressionType;
861
~MatcherCatch::Matchers::Impl::Matcher862 virtual ~Matcher() {}
863 virtual Ptr<Matcher> clone() const = 0;
864 virtual bool match( ExpressionT const& expr ) const = 0;
865 virtual std::string toString() const = 0;
866
867 Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
868 Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
869 Generic::Not<ExpressionT> operator ! () const;
870 };
871
872 template<typename DerivedT, typename ExpressionT>
873 struct MatcherImpl : Matcher<ExpressionT> {
874
cloneCatch::Matchers::Impl::MatcherImpl875 virtual Ptr<Matcher<ExpressionT> > clone() const {
876 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
877 }
878 };
879
880 namespace Generic {
881 template<typename ExpressionT>
882 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
883 public:
Not(Matcher<ExpressionT> const & matcher)884 explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
Not(Not const & other)885 Not( Not const& other ) : m_matcher( other.m_matcher ) {}
886
match(ExpressionT const & expr) const887 virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
888 return !m_matcher->match( expr );
889 }
890
toString() const891 virtual std::string toString() const CATCH_OVERRIDE {
892 return "not " + m_matcher->toString();
893 }
894 private:
895 Ptr< Matcher<ExpressionT> > m_matcher;
896 };
897
898 template<typename ExpressionT>
899 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
900 public:
901
AllOf()902 AllOf() {}
AllOf(AllOf const & other)903 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
904
add(Matcher<ExpressionT> const & matcher)905 AllOf& add( Matcher<ExpressionT> const& matcher ) {
906 m_matchers.push_back( matcher.clone() );
907 return *this;
908 }
match(ExpressionT const & expr) const909 virtual bool match( ExpressionT const& expr ) const
910 {
911 for( std::size_t i = 0; i < m_matchers.size(); ++i )
912 if( !m_matchers[i]->match( expr ) )
913 return false;
914 return true;
915 }
toString() const916 virtual std::string toString() const {
917 std::ostringstream oss;
918 oss << "( ";
919 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
920 if( i != 0 )
921 oss << " and ";
922 oss << m_matchers[i]->toString();
923 }
924 oss << " )";
925 return oss.str();
926 }
927
operator &&(Matcher<ExpressionT> const & other) const928 AllOf operator && ( Matcher<ExpressionT> const& other ) const {
929 AllOf allOfExpr( *this );
930 allOfExpr.add( other );
931 return allOfExpr;
932 }
933
934 private:
935 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
936 };
937
938 template<typename ExpressionT>
939 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
940 public:
941
AnyOf()942 AnyOf() {}
AnyOf(AnyOf const & other)943 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
944
add(Matcher<ExpressionT> const & matcher)945 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
946 m_matchers.push_back( matcher.clone() );
947 return *this;
948 }
match(ExpressionT const & expr) const949 virtual bool match( ExpressionT const& expr ) const
950 {
951 for( std::size_t i = 0; i < m_matchers.size(); ++i )
952 if( m_matchers[i]->match( expr ) )
953 return true;
954 return false;
955 }
toString() const956 virtual std::string toString() const {
957 std::ostringstream oss;
958 oss << "( ";
959 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
960 if( i != 0 )
961 oss << " or ";
962 oss << m_matchers[i]->toString();
963 }
964 oss << " )";
965 return oss.str();
966 }
967
operator ||(Matcher<ExpressionT> const & other) const968 AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
969 AnyOf anyOfExpr( *this );
970 anyOfExpr.add( other );
971 return anyOfExpr;
972 }
973
974 private:
975 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
976 };
977
978 } // namespace Generic
979
980 template<typename ExpressionT>
operator &&(Matcher<ExpressionT> const & other) const981 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
982 Generic::AllOf<ExpressionT> allOfExpr;
983 allOfExpr.add( *this );
984 allOfExpr.add( other );
985 return allOfExpr;
986 }
987
988 template<typename ExpressionT>
operator ||(Matcher<ExpressionT> const & other) const989 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
990 Generic::AnyOf<ExpressionT> anyOfExpr;
991 anyOfExpr.add( *this );
992 anyOfExpr.add( other );
993 return anyOfExpr;
994 }
995
996 template<typename ExpressionT>
operator !() const997 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
998 return Generic::Not<ExpressionT>( *this );
999 }
1000
1001 namespace StdString {
1002
makeString(std::string const & str)1003 inline std::string makeString( std::string const& str ) { return str; }
makeString(const char * str)1004 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
1005
1006 struct CasedString
1007 {
CasedStringCatch::Matchers::Impl::StdString::CasedString1008 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
1009 : m_caseSensitivity( caseSensitivity ),
1010 m_str( adjustString( str ) )
1011 {}
adjustStringCatch::Matchers::Impl::StdString::CasedString1012 std::string adjustString( std::string const& str ) const {
1013 return m_caseSensitivity == CaseSensitive::No
1014 ? toLower( str )
1015 : str;
1016
1017 }
toStringSuffixCatch::Matchers::Impl::StdString::CasedString1018 std::string toStringSuffix() const
1019 {
1020 return m_caseSensitivity == CaseSensitive::No
1021 ? " (case insensitive)"
1022 : "";
1023 }
1024 CaseSensitive::Choice m_caseSensitivity;
1025 std::string m_str;
1026 };
1027
1028 struct Equals : MatcherImpl<Equals, std::string> {
EqualsCatch::Matchers::Impl::StdString::Equals1029 Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1030 : m_data( str, caseSensitivity )
1031 {}
EqualsCatch::Matchers::Impl::StdString::Equals1032 Equals( Equals const& other ) : m_data( other.m_data ){}
1033
1034 virtual ~Equals();
1035
matchCatch::Matchers::Impl::StdString::Equals1036 virtual bool match( std::string const& expr ) const {
1037 return m_data.m_str == m_data.adjustString( expr );;
1038 }
toStringCatch::Matchers::Impl::StdString::Equals1039 virtual std::string toString() const {
1040 return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1041 }
1042
1043 CasedString m_data;
1044 };
1045
1046 struct Contains : MatcherImpl<Contains, std::string> {
ContainsCatch::Matchers::Impl::StdString::Contains1047 Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1048 : m_data( substr, caseSensitivity ){}
ContainsCatch::Matchers::Impl::StdString::Contains1049 Contains( Contains const& other ) : m_data( other.m_data ){}
1050
1051 virtual ~Contains();
1052
matchCatch::Matchers::Impl::StdString::Contains1053 virtual bool match( std::string const& expr ) const {
1054 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
1055 }
toStringCatch::Matchers::Impl::StdString::Contains1056 virtual std::string toString() const {
1057 return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1058 }
1059
1060 CasedString m_data;
1061 };
1062
1063 struct StartsWith : MatcherImpl<StartsWith, std::string> {
StartsWithCatch::Matchers::Impl::StdString::StartsWith1064 StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1065 : m_data( substr, caseSensitivity ){}
1066
StartsWithCatch::Matchers::Impl::StdString::StartsWith1067 StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
1068
1069 virtual ~StartsWith();
1070
matchCatch::Matchers::Impl::StdString::StartsWith1071 virtual bool match( std::string const& expr ) const {
1072 return m_data.adjustString( expr ).find( m_data.m_str ) == 0;
1073 }
toStringCatch::Matchers::Impl::StdString::StartsWith1074 virtual std::string toString() const {
1075 return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1076 }
1077
1078 CasedString m_data;
1079 };
1080
1081 struct EndsWith : MatcherImpl<EndsWith, std::string> {
EndsWithCatch::Matchers::Impl::StdString::EndsWith1082 EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1083 : m_data( substr, caseSensitivity ){}
EndsWithCatch::Matchers::Impl::StdString::EndsWith1084 EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
1085
1086 virtual ~EndsWith();
1087
matchCatch::Matchers::Impl::StdString::EndsWith1088 virtual bool match( std::string const& expr ) const {
1089 return m_data.adjustString( expr ).find( m_data.m_str ) == expr.size() - m_data.m_str.size();
1090 }
toStringCatch::Matchers::Impl::StdString::EndsWith1091 virtual std::string toString() const {
1092 return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1093 }
1094
1095 CasedString m_data;
1096 };
1097 } // namespace StdString
1098 } // namespace Impl
1099
1100 // The following functions create the actual matcher objects.
1101 // This allows the types to be inferred
1102 template<typename ExpressionT>
Not(Impl::Matcher<ExpressionT> const & m)1103 inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
1104 return Impl::Generic::Not<ExpressionT>( m );
1105 }
1106
1107 template<typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)1108 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1109 Impl::Matcher<ExpressionT> const& m2 ) {
1110 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
1111 }
1112 template<typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)1113 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1114 Impl::Matcher<ExpressionT> const& m2,
1115 Impl::Matcher<ExpressionT> const& m3 ) {
1116 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1117 }
1118 template<typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)1119 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1120 Impl::Matcher<ExpressionT> const& m2 ) {
1121 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
1122 }
1123 template<typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)1124 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1125 Impl::Matcher<ExpressionT> const& m2,
1126 Impl::Matcher<ExpressionT> const& m3 ) {
1127 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1128 }
1129
Equals(std::string const & str,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1130 inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1131 return Impl::StdString::Equals( str, caseSensitivity );
1132 }
Equals(const char * str,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1133 inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1134 return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
1135 }
Contains(std::string const & substr,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1136 inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1137 return Impl::StdString::Contains( substr, caseSensitivity );
1138 }
Contains(const char * substr,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1139 inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1140 return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
1141 }
StartsWith(std::string const & substr)1142 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
1143 return Impl::StdString::StartsWith( substr );
1144 }
StartsWith(const char * substr)1145 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
1146 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
1147 }
EndsWith(std::string const & substr)1148 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
1149 return Impl::StdString::EndsWith( substr );
1150 }
EndsWith(const char * substr)1151 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
1152 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
1153 }
1154
1155 } // namespace Matchers
1156
1157 using namespace Matchers;
1158
1159 } // namespace Catch
1160
1161 namespace Catch {
1162
1163 struct TestFailureException{};
1164
1165 template<typename T> class ExpressionLhs;
1166
1167 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1168
1169 struct CopyableStream {
CopyableStreamCatch::CopyableStream1170 CopyableStream() {}
CopyableStreamCatch::CopyableStream1171 CopyableStream( CopyableStream const& other ) {
1172 oss << other.oss.str();
1173 }
operator =Catch::CopyableStream1174 CopyableStream& operator=( CopyableStream const& other ) {
1175 oss.str("");
1176 oss << other.oss.str();
1177 return *this;
1178 }
1179 std::ostringstream oss;
1180 };
1181
1182 class ResultBuilder {
1183 public:
1184 ResultBuilder( char const* macroName,
1185 SourceLineInfo const& lineInfo,
1186 char const* capturedExpression,
1187 ResultDisposition::Flags resultDisposition,
1188 char const* secondArg = "" );
1189
1190 template<typename T>
1191 ExpressionLhs<T const&> operator <= ( T const& operand );
1192 ExpressionLhs<bool> operator <= ( bool value );
1193
1194 template<typename T>
operator <<(T const & value)1195 ResultBuilder& operator << ( T const& value ) {
1196 m_stream.oss << value;
1197 return *this;
1198 }
1199
1200 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1201 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1202
1203 ResultBuilder& setResultType( ResultWas::OfType result );
1204 ResultBuilder& setResultType( bool result );
1205 ResultBuilder& setLhs( std::string const& lhs );
1206 ResultBuilder& setRhs( std::string const& rhs );
1207 ResultBuilder& setOp( std::string const& op );
1208
1209 void endExpression();
1210
1211 std::string reconstructExpression() const;
1212 AssertionResult build() const;
1213
1214 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1215 void captureResult( ResultWas::OfType resultType );
1216 void captureExpression();
1217 void captureExpectedException( std::string const& expectedMessage );
1218 void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
1219 void handleResult( AssertionResult const& result );
1220 void react();
1221 bool shouldDebugBreak() const;
1222 bool allowThrows() const;
1223
1224 private:
1225 AssertionInfo m_assertionInfo;
1226 AssertionResultData m_data;
1227 struct ExprComponents {
ExprComponentsCatch::ResultBuilder::ExprComponents1228 ExprComponents() : testFalse( false ) {}
1229 bool testFalse;
1230 std::string lhs, rhs, op;
1231 } m_exprComponents;
1232 CopyableStream m_stream;
1233
1234 bool m_shouldDebugBreak;
1235 bool m_shouldThrow;
1236 };
1237
1238 } // namespace Catch
1239
1240 // Include after due to circular dependency:
1241 // #included from: catch_expression_lhs.hpp
1242 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1243
1244 // #included from: catch_evaluate.hpp
1245 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1246
1247 #ifdef _MSC_VER
1248 #pragma warning(push)
1249 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1250 #endif
1251
1252 #include <cstddef>
1253
1254 namespace Catch {
1255 namespace Internal {
1256
1257 enum Operator {
1258 IsEqualTo,
1259 IsNotEqualTo,
1260 IsLessThan,
1261 IsGreaterThan,
1262 IsLessThanOrEqualTo,
1263 IsGreaterThanOrEqualTo
1264 };
1265
getNameCatch::Internal::OperatorTraits1266 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
getNameCatch::Internal::OperatorTraits1267 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
getNameCatch::Internal::OperatorTraits1268 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
getNameCatch::Internal::OperatorTraits1269 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
getNameCatch::Internal::OperatorTraits1270 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
getNameCatch::Internal::OperatorTraits1271 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
getNameCatch::Internal::OperatorTraits1272 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1273
1274 template<typename T>
opCast(T const & t)1275 inline T& opCast(T const& t) { return const_cast<T&>(t); }
1276
1277 // nullptr_t support based on pull request #154 from Konstantin Baumann
1278 #ifdef CATCH_CONFIG_CPP11_NULLPTR
opCast(std::nullptr_t)1279 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1280 #endif // CATCH_CONFIG_CPP11_NULLPTR
1281
1282 // So the compare overloads can be operator agnostic we convey the operator as a template
1283 // enum, which is used to specialise an Evaluator for doing the comparison.
1284 template<typename T1, typename T2, Operator Op>
1285 class Evaluator{};
1286
1287 template<typename T1, typename T2>
1288 struct Evaluator<T1, T2, IsEqualTo> {
evaluateCatch::Internal::Evaluator1289 static bool evaluate( T1 const& lhs, T2 const& rhs) {
1290 return opCast( lhs ) == opCast( rhs );
1291 }
1292 };
1293 template<typename T1, typename T2>
1294 struct Evaluator<T1, T2, IsNotEqualTo> {
evaluateCatch::Internal::Evaluator1295 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1296 return opCast( lhs ) != opCast( rhs );
1297 }
1298 };
1299 template<typename T1, typename T2>
1300 struct Evaluator<T1, T2, IsLessThan> {
evaluateCatch::Internal::Evaluator1301 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1302 return opCast( lhs ) < opCast( rhs );
1303 }
1304 };
1305 template<typename T1, typename T2>
1306 struct Evaluator<T1, T2, IsGreaterThan> {
evaluateCatch::Internal::Evaluator1307 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1308 return opCast( lhs ) > opCast( rhs );
1309 }
1310 };
1311 template<typename T1, typename T2>
1312 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1313 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1314 return opCast( lhs ) >= opCast( rhs );
1315 }
1316 };
1317 template<typename T1, typename T2>
1318 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1319 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1320 return opCast( lhs ) <= opCast( rhs );
1321 }
1322 };
1323
1324 template<Operator Op, typename T1, typename T2>
applyEvaluator(T1 const & lhs,T2 const & rhs)1325 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
1326 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1327 }
1328
1329 // This level of indirection allows us to specialise for integer types
1330 // to avoid signed/ unsigned warnings
1331
1332 // "base" overload
1333 template<Operator Op, typename T1, typename T2>
compare(T1 const & lhs,T2 const & rhs)1334 bool compare( T1 const& lhs, T2 const& rhs ) {
1335 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1336 }
1337
1338 // unsigned X to int
compare(unsigned int lhs,int rhs)1339 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
1340 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1341 }
compare(unsigned long lhs,int rhs)1342 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
1343 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1344 }
compare(unsigned char lhs,int rhs)1345 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
1346 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1347 }
1348
1349 // unsigned X to long
compare(unsigned int lhs,long rhs)1350 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
1351 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1352 }
compare(unsigned long lhs,long rhs)1353 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
1354 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1355 }
compare(unsigned char lhs,long rhs)1356 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
1357 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1358 }
1359
1360 // int to unsigned X
compare(int lhs,unsigned int rhs)1361 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
1362 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1363 }
compare(int lhs,unsigned long rhs)1364 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
1365 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1366 }
compare(int lhs,unsigned char rhs)1367 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
1368 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1369 }
1370
1371 // long to unsigned X
compare(long lhs,unsigned int rhs)1372 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
1373 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1374 }
compare(long lhs,unsigned long rhs)1375 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
1376 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1377 }
compare(long lhs,unsigned char rhs)1378 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
1379 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1380 }
1381
1382 // pointer to long (when comparing against NULL)
compare(long lhs,T * rhs)1383 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
1384 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1385 }
compare(T * lhs,long rhs)1386 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
1387 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1388 }
1389
1390 // pointer to int (when comparing against NULL)
compare(int lhs,T * rhs)1391 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
1392 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1393 }
compare(T * lhs,int rhs)1394 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
1395 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1396 }
1397
1398 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1399 // long long to unsigned X
compare(long long lhs,unsigned int rhs)1400 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1401 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1402 }
compare(long long lhs,unsigned long rhs)1403 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1404 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1405 }
compare(long long lhs,unsigned long long rhs)1406 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1407 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1408 }
compare(long long lhs,unsigned char rhs)1409 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1410 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1411 }
1412
1413 // unsigned long long to X
compare(unsigned long long lhs,int rhs)1414 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1415 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1416 }
compare(unsigned long long lhs,long rhs)1417 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1418 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1419 }
compare(unsigned long long lhs,long long rhs)1420 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1421 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1422 }
compare(unsigned long long lhs,char rhs)1423 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1424 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1425 }
1426
1427 // pointer to long long (when comparing against NULL)
compare(long long lhs,T * rhs)1428 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1429 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1430 }
compare(T * lhs,long long rhs)1431 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1432 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1433 }
1434 #endif // CATCH_CONFIG_CPP11_LONG_LONG
1435
1436 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1437 // pointer to nullptr_t (when comparing against nullptr)
compare(std::nullptr_t,T * rhs)1438 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1439 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
1440 }
compare(T * lhs,std::nullptr_t)1441 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1442 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
1443 }
1444 #endif // CATCH_CONFIG_CPP11_NULLPTR
1445
1446 } // end of namespace Internal
1447 } // end of namespace Catch
1448
1449 #ifdef _MSC_VER
1450 #pragma warning(pop)
1451 #endif
1452
1453 // #included from: catch_tostring.h
1454 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1455
1456 #include <sstream>
1457 #include <iomanip>
1458 #include <limits>
1459 #include <vector>
1460 #include <cstddef>
1461
1462 #ifdef __OBJC__
1463 // #included from: catch_objc_arc.hpp
1464 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1465
1466 #import <Foundation/Foundation.h>
1467
1468 #ifdef __has_feature
1469 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1470 #else
1471 #define CATCH_ARC_ENABLED 0
1472 #endif
1473
1474 void arcSafeRelease( NSObject* obj );
1475 id performOptionalSelector( id obj, SEL sel );
1476
1477 #if !CATCH_ARC_ENABLED
arcSafeRelease(NSObject * obj)1478 inline void arcSafeRelease( NSObject* obj ) {
1479 [obj release];
1480 }
performOptionalSelector(id obj,SEL sel)1481 inline id performOptionalSelector( id obj, SEL sel ) {
1482 if( [obj respondsToSelector: sel] )
1483 return [obj performSelector: sel];
1484 return nil;
1485 }
1486 #define CATCH_UNSAFE_UNRETAINED
1487 #define CATCH_ARC_STRONG
1488 #else
arcSafeRelease(NSObject *)1489 inline void arcSafeRelease( NSObject* ){}
performOptionalSelector(id obj,SEL sel)1490 inline id performOptionalSelector( id obj, SEL sel ) {
1491 #ifdef __clang__
1492 #pragma clang diagnostic push
1493 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1494 #endif
1495 if( [obj respondsToSelector: sel] )
1496 return [obj performSelector: sel];
1497 #ifdef __clang__
1498 #pragma clang diagnostic pop
1499 #endif
1500 return nil;
1501 }
1502 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1503 #define CATCH_ARC_STRONG __strong
1504 #endif
1505
1506 #endif
1507
1508 #ifdef CATCH_CONFIG_CPP11_TUPLE
1509 #include <tuple>
1510 #endif
1511
1512 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1513 #include <type_traits>
1514 #endif
1515
1516 namespace Catch {
1517
1518 // Why we're here.
1519 template<typename T>
1520 std::string toString( T const& value );
1521
1522 // Built in overloads
1523
1524 std::string toString( std::string const& value );
1525 std::string toString( std::wstring const& value );
1526 std::string toString( const char* const value );
1527 std::string toString( char* const value );
1528 std::string toString( const wchar_t* const value );
1529 std::string toString( wchar_t* const value );
1530 std::string toString( int value );
1531 std::string toString( unsigned long value );
1532 std::string toString( unsigned int value );
1533 std::string toString( const double value );
1534 std::string toString( const float value );
1535 std::string toString( bool value );
1536 std::string toString( char value );
1537 std::string toString( signed char value );
1538 std::string toString( unsigned char value );
1539
1540 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1541 std::string toString( long long value );
1542 std::string toString( unsigned long long value );
1543 #endif
1544
1545 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1546 std::string toString( std::nullptr_t );
1547 #endif
1548
1549 #ifdef __OBJC__
1550 std::string toString( NSString const * const& nsstring );
1551 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1552 std::string toString( NSObject* const& nsObject );
1553 #endif
1554
1555 namespace Detail {
1556
1557 extern const std::string unprintableString;
1558
1559 struct BorgType {
1560 template<typename T> BorgType( T const& );
1561 };
1562
1563 struct TrueType { char sizer[1]; };
1564 struct FalseType { char sizer[2]; };
1565
1566 TrueType& testStreamable( std::ostream& );
1567 FalseType testStreamable( FalseType );
1568
1569 FalseType operator<<( std::ostream const&, BorgType const& );
1570
1571 template<typename T>
1572 struct IsStreamInsertable {
1573 static std::ostream &s;
1574 static T const&t;
1575 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1576 };
1577
1578 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1579 template<typename T,
1580 bool IsEnum = std::is_enum<T>::value
1581 >
1582 struct EnumStringMaker
1583 {
convertCatch::Detail::EnumStringMaker1584 static std::string convert( T const& ) { return unprintableString; }
1585 };
1586
1587 template<typename T>
1588 struct EnumStringMaker<T,true>
1589 {
convertCatch::Detail::EnumStringMaker1590 static std::string convert( T const& v )
1591 {
1592 return ::Catch::toString(
1593 static_cast<typename std::underlying_type<T>::type>(v)
1594 );
1595 }
1596 };
1597 #endif
1598 template<bool C>
1599 struct StringMakerBase {
1600 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1601 template<typename T>
convertCatch::Detail::StringMakerBase1602 static std::string convert( T const& v )
1603 {
1604 return EnumStringMaker<T>::convert( v );
1605 }
1606 #else
1607 template<typename T>
1608 static std::string convert( T const& ) { return unprintableString; }
1609 #endif
1610 };
1611
1612 template<>
1613 struct StringMakerBase<true> {
1614 template<typename T>
convertCatch::Detail::StringMakerBase1615 static std::string convert( T const& _value ) {
1616 std::ostringstream oss;
1617 oss << _value;
1618 return oss.str();
1619 }
1620 };
1621
1622 std::string rawMemoryToString( const void *object, std::size_t size );
1623
1624 template<typename T>
rawMemoryToString(const T & object)1625 inline std::string rawMemoryToString( const T& object ) {
1626 return rawMemoryToString( &object, sizeof(object) );
1627 }
1628
1629 } // end namespace Detail
1630
1631 template<typename T>
1632 struct StringMaker :
1633 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1634
1635 template<typename T>
1636 struct StringMaker<T*> {
1637 template<typename U>
convertCatch::StringMaker1638 static std::string convert( U* p ) {
1639 if( !p )
1640 return "NULL";
1641 else
1642 return Detail::rawMemoryToString( p );
1643 }
1644 };
1645
1646 template<typename R, typename C>
1647 struct StringMaker<R C::*> {
convertCatch::StringMaker1648 static std::string convert( R C::* p ) {
1649 if( !p )
1650 return "NULL";
1651 else
1652 return Detail::rawMemoryToString( p );
1653 }
1654 };
1655
1656 namespace Detail {
1657 template<typename InputIterator>
1658 std::string rangeToString( InputIterator first, InputIterator last );
1659 }
1660
1661 //template<typename T, typename Allocator>
1662 //struct StringMaker<std::vector<T, Allocator> > {
1663 // static std::string convert( std::vector<T,Allocator> const& v ) {
1664 // return Detail::rangeToString( v.begin(), v.end() );
1665 // }
1666 //};
1667
1668 template<typename T, typename Allocator>
toString(std::vector<T,Allocator> const & v)1669 std::string toString( std::vector<T,Allocator> const& v ) {
1670 return Detail::rangeToString( v.begin(), v.end() );
1671 }
1672
1673 #ifdef CATCH_CONFIG_CPP11_TUPLE
1674
1675 // toString for tuples
1676 namespace TupleDetail {
1677 template<
1678 typename Tuple,
1679 std::size_t N = 0,
1680 bool = (N < std::tuple_size<Tuple>::value)
1681 >
1682 struct ElementPrinter {
printCatch::TupleDetail::ElementPrinter1683 static void print( const Tuple& tuple, std::ostream& os )
1684 {
1685 os << ( N ? ", " : " " )
1686 << Catch::toString(std::get<N>(tuple));
1687 ElementPrinter<Tuple,N+1>::print(tuple,os);
1688 }
1689 };
1690
1691 template<
1692 typename Tuple,
1693 std::size_t N
1694 >
1695 struct ElementPrinter<Tuple,N,false> {
printCatch::TupleDetail::ElementPrinter1696 static void print( const Tuple&, std::ostream& ) {}
1697 };
1698
1699 }
1700
1701 template<typename ...Types>
1702 struct StringMaker<std::tuple<Types...>> {
1703
convertCatch::StringMaker1704 static std::string convert( const std::tuple<Types...>& tuple )
1705 {
1706 std::ostringstream os;
1707 os << '{';
1708 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1709 os << " }";
1710 return os.str();
1711 }
1712 };
1713 #endif // CATCH_CONFIG_CPP11_TUPLE
1714
1715 namespace Detail {
1716 template<typename T>
makeString(T const & value)1717 std::string makeString( T const& value ) {
1718 return StringMaker<T>::convert( value );
1719 }
1720 } // end namespace Detail
1721
1722 /// \brief converts any type to a string
1723 ///
1724 /// The default template forwards on to ostringstream - except when an
1725 /// ostringstream overload does not exist - in which case it attempts to detect
1726 /// that and writes {?}.
1727 /// Overload (not specialise) this template for custom typs that you don't want
1728 /// to provide an ostream overload for.
1729 template<typename T>
toString(T const & value)1730 std::string toString( T const& value ) {
1731 return StringMaker<T>::convert( value );
1732 }
1733
1734 namespace Detail {
1735 template<typename InputIterator>
rangeToString(InputIterator first,InputIterator last)1736 std::string rangeToString( InputIterator first, InputIterator last ) {
1737 std::ostringstream oss;
1738 oss << "{ ";
1739 if( first != last ) {
1740 oss << Catch::toString( *first );
1741 for( ++first ; first != last ; ++first )
1742 oss << ", " << Catch::toString( *first );
1743 }
1744 oss << " }";
1745 return oss.str();
1746 }
1747 }
1748
1749 } // end namespace Catch
1750
1751 namespace Catch {
1752
1753 // Wraps the LHS of an expression and captures the operator and RHS (if any) -
1754 // wrapping them all in a ResultBuilder object
1755 template<typename T>
1756 class ExpressionLhs {
1757 ExpressionLhs& operator = ( ExpressionLhs const& );
1758 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1759 ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
1760 # endif
1761
1762 public:
ExpressionLhs(ResultBuilder & rb,T lhs)1763 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
1764 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1765 ExpressionLhs( ExpressionLhs const& ) = default;
1766 ExpressionLhs( ExpressionLhs && ) = default;
1767 # endif
1768
1769 template<typename RhsT>
operator ==(RhsT const & rhs)1770 ResultBuilder& operator == ( RhsT const& rhs ) {
1771 return captureExpression<Internal::IsEqualTo>( rhs );
1772 }
1773
1774 template<typename RhsT>
operator !=(RhsT const & rhs)1775 ResultBuilder& operator != ( RhsT const& rhs ) {
1776 return captureExpression<Internal::IsNotEqualTo>( rhs );
1777 }
1778
1779 template<typename RhsT>
operator <(RhsT const & rhs)1780 ResultBuilder& operator < ( RhsT const& rhs ) {
1781 return captureExpression<Internal::IsLessThan>( rhs );
1782 }
1783
1784 template<typename RhsT>
operator >(RhsT const & rhs)1785 ResultBuilder& operator > ( RhsT const& rhs ) {
1786 return captureExpression<Internal::IsGreaterThan>( rhs );
1787 }
1788
1789 template<typename RhsT>
operator <=(RhsT const & rhs)1790 ResultBuilder& operator <= ( RhsT const& rhs ) {
1791 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1792 }
1793
1794 template<typename RhsT>
operator >=(RhsT const & rhs)1795 ResultBuilder& operator >= ( RhsT const& rhs ) {
1796 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1797 }
1798
operator ==(bool rhs)1799 ResultBuilder& operator == ( bool rhs ) {
1800 return captureExpression<Internal::IsEqualTo>( rhs );
1801 }
1802
operator !=(bool rhs)1803 ResultBuilder& operator != ( bool rhs ) {
1804 return captureExpression<Internal::IsNotEqualTo>( rhs );
1805 }
1806
endExpression()1807 void endExpression() {
1808 bool value = m_lhs ? true : false;
1809 m_rb
1810 .setLhs( Catch::toString( value ) )
1811 .setResultType( value )
1812 .endExpression();
1813 }
1814
1815 // Only simple binary expressions are allowed on the LHS.
1816 // If more complex compositions are required then place the sub expression in parentheses
1817 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1818 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1819 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1820 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
1821 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1822 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1823
1824 private:
1825 template<Internal::Operator Op, typename RhsT>
captureExpression(RhsT const & rhs)1826 ResultBuilder& captureExpression( RhsT const& rhs ) {
1827 return m_rb
1828 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1829 .setLhs( Catch::toString( m_lhs ) )
1830 .setRhs( Catch::toString( rhs ) )
1831 .setOp( Internal::OperatorTraits<Op>::getName() );
1832 }
1833
1834 private:
1835 ResultBuilder& m_rb;
1836 T m_lhs;
1837 };
1838
1839 } // end namespace Catch
1840
1841
1842 namespace Catch {
1843
1844 template<typename T>
operator <=(T const & operand)1845 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
1846 return ExpressionLhs<T const&>( *this, operand );
1847 }
1848
operator <=(bool value)1849 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
1850 return ExpressionLhs<bool>( *this, value );
1851 }
1852
1853 } // namespace Catch
1854
1855 // #included from: catch_message.h
1856 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1857
1858 #include <string>
1859
1860 namespace Catch {
1861
1862 struct MessageInfo {
1863 MessageInfo( std::string const& _macroName,
1864 SourceLineInfo const& _lineInfo,
1865 ResultWas::OfType _type );
1866
1867 std::string macroName;
1868 SourceLineInfo lineInfo;
1869 ResultWas::OfType type;
1870 std::string message;
1871 unsigned int sequence;
1872
operator ==Catch::MessageInfo1873 bool operator == ( MessageInfo const& other ) const {
1874 return sequence == other.sequence;
1875 }
operator <Catch::MessageInfo1876 bool operator < ( MessageInfo const& other ) const {
1877 return sequence < other.sequence;
1878 }
1879 private:
1880 static unsigned int globalCount;
1881 };
1882
1883 struct MessageBuilder {
MessageBuilderCatch::MessageBuilder1884 MessageBuilder( std::string const& macroName,
1885 SourceLineInfo const& lineInfo,
1886 ResultWas::OfType type )
1887 : m_info( macroName, lineInfo, type )
1888 {}
1889
1890 template<typename T>
operator <<Catch::MessageBuilder1891 MessageBuilder& operator << ( T const& value ) {
1892 m_stream << value;
1893 return *this;
1894 }
1895
1896 MessageInfo m_info;
1897 std::ostringstream m_stream;
1898 };
1899
1900 class ScopedMessage {
1901 public:
1902 ScopedMessage( MessageBuilder const& builder );
1903 ScopedMessage( ScopedMessage const& other );
1904 ~ScopedMessage();
1905
1906 MessageInfo m_info;
1907 };
1908
1909 } // end namespace Catch
1910
1911 // #included from: catch_interfaces_capture.h
1912 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1913
1914 #include <string>
1915
1916 namespace Catch {
1917
1918 class TestCase;
1919 class AssertionResult;
1920 struct AssertionInfo;
1921 struct SectionInfo;
1922 struct SectionEndInfo;
1923 struct MessageInfo;
1924 class ScopedMessageBuilder;
1925 struct Counts;
1926
1927 struct IResultCapture {
1928
1929 virtual ~IResultCapture();
1930
1931 virtual void assertionEnded( AssertionResult const& result ) = 0;
1932 virtual bool sectionStarted( SectionInfo const& sectionInfo,
1933 Counts& assertions ) = 0;
1934 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
1935 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
1936 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1937 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1938
1939 virtual std::string getCurrentTestName() const = 0;
1940 virtual const AssertionResult* getLastResult() const = 0;
1941
1942 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
1943 };
1944
1945 IResultCapture& getResultCapture();
1946 }
1947
1948 // #included from: catch_debugger.h
1949 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1950
1951 // #included from: catch_platform.h
1952 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1953
1954 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1955 #define CATCH_PLATFORM_MAC
1956 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1957 #define CATCH_PLATFORM_IPHONE
1958 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1959 #define CATCH_PLATFORM_WINDOWS
1960 #endif
1961
1962 #include <string>
1963
1964 namespace Catch{
1965
1966 bool isDebuggerActive();
1967 void writeToDebugConsole( std::string const& text );
1968 }
1969
1970 #ifdef CATCH_PLATFORM_MAC
1971
1972 // The following code snippet based on:
1973 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1974 #ifdef DEBUG
1975 #if defined(__ppc64__) || defined(__ppc__)
1976 #define CATCH_BREAK_INTO_DEBUGGER() \
1977 if( Catch::isDebuggerActive() ) { \
1978 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1979 : : : "memory","r0","r3","r4" ); \
1980 }
1981 #else
1982 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1983 #endif
1984 #endif
1985
1986 #elif defined(_MSC_VER)
1987 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
1988 #elif defined(__MINGW32__)
1989 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1990 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
1991 #endif
1992
1993 #ifndef CATCH_BREAK_INTO_DEBUGGER
1994 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
1995 #endif
1996
1997 // #included from: catch_interfaces_runner.h
1998 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
1999
2000 namespace Catch {
2001 class TestCase;
2002
2003 struct IRunner {
2004 virtual ~IRunner();
2005 virtual bool aborting() const = 0;
2006 };
2007 }
2008
2009 ///////////////////////////////////////////////////////////////////////////////
2010 // In the event of a failure works out if the debugger needs to be invoked
2011 // and/or an exception thrown and takes appropriate action.
2012 // This needs to be done as a macro so the debugger will stop in the user
2013 // source code rather than in Catch library code
2014 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2015 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2016 resultBuilder.react();
2017
2018 ///////////////////////////////////////////////////////////////////////////////
2019 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2020 do { \
2021 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2022 try { \
2023 ( __catchResult <= expr ).endExpression(); \
2024 } \
2025 catch( ... ) { \
2026 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
2027 } \
2028 INTERNAL_CATCH_REACT( __catchResult ) \
2029 } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2030
2031 ///////////////////////////////////////////////////////////////////////////////
2032 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2033 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2034 if( Catch::getResultCapture().getLastResult()->succeeded() )
2035
2036 ///////////////////////////////////////////////////////////////////////////////
2037 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2038 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2039 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2040
2041 ///////////////////////////////////////////////////////////////////////////////
2042 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2043 do { \
2044 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2045 try { \
2046 expr; \
2047 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2048 } \
2049 catch( ... ) { \
2050 __catchResult.useActiveException( resultDisposition ); \
2051 } \
2052 INTERNAL_CATCH_REACT( __catchResult ) \
2053 } while( Catch::alwaysFalse() )
2054
2055 ///////////////////////////////////////////////////////////////////////////////
2056 #define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2057 do { \
2058 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2059 if( __catchResult.allowThrows() ) \
2060 try { \
2061 expr; \
2062 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2063 } \
2064 catch( ... ) { \
2065 __catchResult.captureExpectedException( matcher ); \
2066 } \
2067 else \
2068 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2069 INTERNAL_CATCH_REACT( __catchResult ) \
2070 } while( Catch::alwaysFalse() )
2071
2072 ///////////////////////////////////////////////////////////////////////////////
2073 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2074 do { \
2075 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2076 if( __catchResult.allowThrows() ) \
2077 try { \
2078 expr; \
2079 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2080 } \
2081 catch( exceptionType ) { \
2082 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2083 } \
2084 catch( ... ) { \
2085 __catchResult.useActiveException( resultDisposition ); \
2086 } \
2087 else \
2088 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2089 INTERNAL_CATCH_REACT( __catchResult ) \
2090 } while( Catch::alwaysFalse() )
2091
2092 ///////////////////////////////////////////////////////////////////////////////
2093 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2094 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2095 do { \
2096 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2097 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2098 __catchResult.captureResult( messageType ); \
2099 INTERNAL_CATCH_REACT( __catchResult ) \
2100 } while( Catch::alwaysFalse() )
2101 #else
2102 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2103 do { \
2104 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2105 __catchResult << log + ::Catch::StreamEndStop(); \
2106 __catchResult.captureResult( messageType ); \
2107 INTERNAL_CATCH_REACT( __catchResult ) \
2108 } while( Catch::alwaysFalse() )
2109 #endif
2110
2111 ///////////////////////////////////////////////////////////////////////////////
2112 #define INTERNAL_CATCH_INFO( log, macroName ) \
2113 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2114
2115 ///////////////////////////////////////////////////////////////////////////////
2116 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2117 do { \
2118 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
2119 try { \
2120 std::string matcherAsString = (matcher).toString(); \
2121 __catchResult \
2122 .setLhs( Catch::toString( arg ) ) \
2123 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
2124 .setOp( "matches" ) \
2125 .setResultType( (matcher).match( arg ) ); \
2126 __catchResult.captureExpression(); \
2127 } catch( ... ) { \
2128 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2129 } \
2130 INTERNAL_CATCH_REACT( __catchResult ) \
2131 } while( Catch::alwaysFalse() )
2132
2133 // #included from: internal/catch_section.h
2134 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2135
2136 // #included from: catch_section_info.h
2137 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2138
2139 // #included from: catch_totals.hpp
2140 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2141
2142 #include <cstddef>
2143
2144 namespace Catch {
2145
2146 struct Counts {
CountsCatch::Counts2147 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2148
operator -Catch::Counts2149 Counts operator - ( Counts const& other ) const {
2150 Counts diff;
2151 diff.passed = passed - other.passed;
2152 diff.failed = failed - other.failed;
2153 diff.failedButOk = failedButOk - other.failedButOk;
2154 return diff;
2155 }
operator +=Catch::Counts2156 Counts& operator += ( Counts const& other ) {
2157 passed += other.passed;
2158 failed += other.failed;
2159 failedButOk += other.failedButOk;
2160 return *this;
2161 }
2162
totalCatch::Counts2163 std::size_t total() const {
2164 return passed + failed + failedButOk;
2165 }
allPassedCatch::Counts2166 bool allPassed() const {
2167 return failed == 0 && failedButOk == 0;
2168 }
allOkCatch::Counts2169 bool allOk() const {
2170 return failed == 0;
2171 }
2172
2173 std::size_t passed;
2174 std::size_t failed;
2175 std::size_t failedButOk;
2176 };
2177
2178 struct Totals {
2179
operator -Catch::Totals2180 Totals operator - ( Totals const& other ) const {
2181 Totals diff;
2182 diff.assertions = assertions - other.assertions;
2183 diff.testCases = testCases - other.testCases;
2184 return diff;
2185 }
2186
deltaCatch::Totals2187 Totals delta( Totals const& prevTotals ) const {
2188 Totals diff = *this - prevTotals;
2189 if( diff.assertions.failed > 0 )
2190 ++diff.testCases.failed;
2191 else if( diff.assertions.failedButOk > 0 )
2192 ++diff.testCases.failedButOk;
2193 else
2194 ++diff.testCases.passed;
2195 return diff;
2196 }
2197
operator +=Catch::Totals2198 Totals& operator += ( Totals const& other ) {
2199 assertions += other.assertions;
2200 testCases += other.testCases;
2201 return *this;
2202 }
2203
2204 Counts assertions;
2205 Counts testCases;
2206 };
2207 }
2208
2209 namespace Catch {
2210
2211 struct SectionInfo {
2212 SectionInfo
2213 ( SourceLineInfo const& _lineInfo,
2214 std::string const& _name,
2215 std::string const& _description = std::string() );
2216
2217 std::string name;
2218 std::string description;
2219 SourceLineInfo lineInfo;
2220 };
2221
2222 struct SectionEndInfo {
SectionEndInfoCatch::SectionEndInfo2223 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2224 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2225 {}
2226
2227 SectionInfo sectionInfo;
2228 Counts prevAssertions;
2229 double durationInSeconds;
2230 };
2231
2232 } // end namespace Catch
2233
2234 // #included from: catch_timer.h
2235 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2236
2237 #ifdef CATCH_PLATFORM_WINDOWS
2238 typedef unsigned long long uint64_t;
2239 #else
2240 #include <stdint.h>
2241 #endif
2242
2243 namespace Catch {
2244
2245 class Timer {
2246 public:
Timer()2247 Timer() : m_ticks( 0 ) {}
2248 void start();
2249 unsigned int getElapsedMicroseconds() const;
2250 unsigned int getElapsedMilliseconds() const;
2251 double getElapsedSeconds() const;
2252
2253 private:
2254 uint64_t m_ticks;
2255 };
2256
2257 } // namespace Catch
2258
2259 #include <string>
2260
2261 namespace Catch {
2262
2263 class Section : NonCopyable {
2264 public:
2265 Section( SectionInfo const& info );
2266 ~Section();
2267
2268 // This indicates whether the section should be executed or not
2269 operator bool() const;
2270
2271 private:
2272 SectionInfo m_info;
2273
2274 std::string m_name;
2275 Counts m_assertions;
2276 bool m_sectionIncluded;
2277 Timer m_timer;
2278 };
2279
2280 } // end namespace Catch
2281
2282 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2283 #define INTERNAL_CATCH_SECTION( ... ) \
2284 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2285 #else
2286 #define INTERNAL_CATCH_SECTION( name, desc ) \
2287 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2288 #endif
2289
2290 // #included from: internal/catch_generators.hpp
2291 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2292
2293 #include <iterator>
2294 #include <vector>
2295 #include <string>
2296 #include <stdlib.h>
2297
2298 namespace Catch {
2299
2300 template<typename T>
2301 struct IGenerator {
~IGeneratorCatch::IGenerator2302 virtual ~IGenerator() {}
2303 virtual T getValue( std::size_t index ) const = 0;
2304 virtual std::size_t size () const = 0;
2305 };
2306
2307 template<typename T>
2308 class BetweenGenerator : public IGenerator<T> {
2309 public:
BetweenGenerator(T from,T to)2310 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2311
getValue(std::size_t index) const2312 virtual T getValue( std::size_t index ) const {
2313 return m_from+static_cast<int>( index );
2314 }
2315
size() const2316 virtual std::size_t size() const {
2317 return static_cast<std::size_t>( 1+m_to-m_from );
2318 }
2319
2320 private:
2321
2322 T m_from;
2323 T m_to;
2324 };
2325
2326 template<typename T>
2327 class ValuesGenerator : public IGenerator<T> {
2328 public:
ValuesGenerator()2329 ValuesGenerator(){}
2330
add(T value)2331 void add( T value ) {
2332 m_values.push_back( value );
2333 }
2334
getValue(std::size_t index) const2335 virtual T getValue( std::size_t index ) const {
2336 return m_values[index];
2337 }
2338
size() const2339 virtual std::size_t size() const {
2340 return m_values.size();
2341 }
2342
2343 private:
2344 std::vector<T> m_values;
2345 };
2346
2347 template<typename T>
2348 class CompositeGenerator {
2349 public:
CompositeGenerator()2350 CompositeGenerator() : m_totalSize( 0 ) {}
2351
2352 // *** Move semantics, similar to auto_ptr ***
CompositeGenerator(CompositeGenerator & other)2353 CompositeGenerator( CompositeGenerator& other )
2354 : m_fileInfo( other.m_fileInfo ),
2355 m_totalSize( 0 )
2356 {
2357 move( other );
2358 }
2359
setFileInfo(const char * fileInfo)2360 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2361 m_fileInfo = fileInfo;
2362 return *this;
2363 }
2364
~CompositeGenerator()2365 ~CompositeGenerator() {
2366 deleteAll( m_composed );
2367 }
2368
operator T() const2369 operator T () const {
2370 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2371
2372 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2373 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2374 for( size_t index = 0; it != itEnd; ++it )
2375 {
2376 const IGenerator<T>* generator = *it;
2377 if( overallIndex >= index && overallIndex < index + generator->size() )
2378 {
2379 return generator->getValue( overallIndex-index );
2380 }
2381 index += generator->size();
2382 }
2383 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2384 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
2385 }
2386
add(const IGenerator<T> * generator)2387 void add( const IGenerator<T>* generator ) {
2388 m_totalSize += generator->size();
2389 m_composed.push_back( generator );
2390 }
2391
then(CompositeGenerator & other)2392 CompositeGenerator& then( CompositeGenerator& other ) {
2393 move( other );
2394 return *this;
2395 }
2396
then(T value)2397 CompositeGenerator& then( T value ) {
2398 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2399 valuesGen->add( value );
2400 add( valuesGen );
2401 return *this;
2402 }
2403
2404 private:
2405
move(CompositeGenerator & other)2406 void move( CompositeGenerator& other ) {
2407 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2408 m_totalSize += other.m_totalSize;
2409 other.m_composed.clear();
2410 }
2411
2412 std::vector<const IGenerator<T>*> m_composed;
2413 std::string m_fileInfo;
2414 size_t m_totalSize;
2415 };
2416
2417 namespace Generators
2418 {
2419 template<typename T>
between(T from,T to)2420 CompositeGenerator<T> between( T from, T to ) {
2421 CompositeGenerator<T> generators;
2422 generators.add( new BetweenGenerator<T>( from, to ) );
2423 return generators;
2424 }
2425
2426 template<typename T>
values(T val1,T val2)2427 CompositeGenerator<T> values( T val1, T val2 ) {
2428 CompositeGenerator<T> generators;
2429 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2430 valuesGen->add( val1 );
2431 valuesGen->add( val2 );
2432 generators.add( valuesGen );
2433 return generators;
2434 }
2435
2436 template<typename T>
values(T val1,T val2,T val3)2437 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2438 CompositeGenerator<T> generators;
2439 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2440 valuesGen->add( val1 );
2441 valuesGen->add( val2 );
2442 valuesGen->add( val3 );
2443 generators.add( valuesGen );
2444 return generators;
2445 }
2446
2447 template<typename T>
values(T val1,T val2,T val3,T val4)2448 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2449 CompositeGenerator<T> generators;
2450 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2451 valuesGen->add( val1 );
2452 valuesGen->add( val2 );
2453 valuesGen->add( val3 );
2454 valuesGen->add( val4 );
2455 generators.add( valuesGen );
2456 return generators;
2457 }
2458
2459 } // end namespace Generators
2460
2461 using namespace Generators;
2462
2463 } // end namespace Catch
2464
2465 #define INTERNAL_CATCH_LINESTR2( line ) #line
2466 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2467
2468 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2469
2470 // #included from: internal/catch_interfaces_exception.h
2471 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2472
2473 #include <string>
2474 #include <vector>
2475
2476 // #included from: catch_interfaces_registry_hub.h
2477 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2478
2479 #include <string>
2480
2481 namespace Catch {
2482
2483 class TestCase;
2484 struct ITestCaseRegistry;
2485 struct IExceptionTranslatorRegistry;
2486 struct IExceptionTranslator;
2487 struct IReporterRegistry;
2488 struct IReporterFactory;
2489
2490 struct IRegistryHub {
2491 virtual ~IRegistryHub();
2492
2493 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2494 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2495 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2496 };
2497
2498 struct IMutableRegistryHub {
2499 virtual ~IMutableRegistryHub();
2500 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2501 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
2502 virtual void registerTest( TestCase const& testInfo ) = 0;
2503 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2504 };
2505
2506 IRegistryHub& getRegistryHub();
2507 IMutableRegistryHub& getMutableRegistryHub();
2508 void cleanUp();
2509 std::string translateActiveException();
2510
2511 }
2512
2513 namespace Catch {
2514
2515 typedef std::string(*exceptionTranslateFunction)();
2516
2517 struct IExceptionTranslator;
2518 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2519
2520 struct IExceptionTranslator {
2521 virtual ~IExceptionTranslator();
2522 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2523 };
2524
2525 struct IExceptionTranslatorRegistry {
2526 virtual ~IExceptionTranslatorRegistry();
2527
2528 virtual std::string translateActiveException() const = 0;
2529 };
2530
2531 class ExceptionTranslatorRegistrar {
2532 template<typename T>
2533 class ExceptionTranslator : public IExceptionTranslator {
2534 public:
2535
ExceptionTranslator(std::string (* translateFunction)(T &))2536 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2537 : m_translateFunction( translateFunction )
2538 {}
2539
translate(ExceptionTranslators::const_iterator it,ExceptionTranslators::const_iterator itEnd) const2540 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
2541 try {
2542 if( it == itEnd )
2543 throw;
2544 else
2545 return (*it)->translate( it+1, itEnd );
2546 }
2547 catch( T& ex ) {
2548 return m_translateFunction( ex );
2549 }
2550 }
2551
2552 protected:
2553 std::string(*m_translateFunction)( T& );
2554 };
2555
2556 public:
2557 template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))2558 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2559 getMutableRegistryHub().registerTranslator
2560 ( new ExceptionTranslator<T>( translateFunction ) );
2561 }
2562 };
2563 }
2564
2565 ///////////////////////////////////////////////////////////////////////////////
2566 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2567 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2568 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2569 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2570
2571 // #included from: internal/catch_approx.hpp
2572 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2573
2574 #include <cmath>
2575 #include <limits>
2576
2577 namespace Catch {
2578 namespace Detail {
2579
2580 class Approx {
2581 public:
Approx(double value)2582 explicit Approx ( double value )
2583 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2584 m_scale( 1.0 ),
2585 m_value( value )
2586 {}
2587
Approx(Approx const & other)2588 Approx( Approx const& other )
2589 : m_epsilon( other.m_epsilon ),
2590 m_scale( other.m_scale ),
2591 m_value( other.m_value )
2592 {}
2593
custom()2594 static Approx custom() {
2595 return Approx( 0 );
2596 }
2597
operator ()(double value)2598 Approx operator()( double value ) {
2599 Approx approx( value );
2600 approx.epsilon( m_epsilon );
2601 approx.scale( m_scale );
2602 return approx;
2603 }
2604
operator ==(double lhs,Approx const & rhs)2605 friend bool operator == ( double lhs, Approx const& rhs ) {
2606 // Thanks to Richard Harris for his help refining this formula
2607 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2608 }
2609
operator ==(Approx const & lhs,double rhs)2610 friend bool operator == ( Approx const& lhs, double rhs ) {
2611 return operator==( rhs, lhs );
2612 }
2613
operator !=(double lhs,Approx const & rhs)2614 friend bool operator != ( double lhs, Approx const& rhs ) {
2615 return !operator==( lhs, rhs );
2616 }
2617
operator !=(Approx const & lhs,double rhs)2618 friend bool operator != ( Approx const& lhs, double rhs ) {
2619 return !operator==( rhs, lhs );
2620 }
2621
epsilon(double newEpsilon)2622 Approx& epsilon( double newEpsilon ) {
2623 m_epsilon = newEpsilon;
2624 return *this;
2625 }
2626
scale(double newScale)2627 Approx& scale( double newScale ) {
2628 m_scale = newScale;
2629 return *this;
2630 }
2631
toString() const2632 std::string toString() const {
2633 std::ostringstream oss;
2634 oss << "Approx( " << Catch::toString( m_value ) << " )";
2635 return oss.str();
2636 }
2637
2638 private:
2639 double m_epsilon;
2640 double m_scale;
2641 double m_value;
2642 };
2643 }
2644
2645 template<>
toString(Detail::Approx const & value)2646 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
2647 return value.toString();
2648 }
2649
2650 } // end namespace Catch
2651
2652 // #included from: internal/catch_interfaces_tag_alias_registry.h
2653 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2654
2655 // #included from: catch_tag_alias.h
2656 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2657
2658 #include <string>
2659
2660 namespace Catch {
2661
2662 struct TagAlias {
TagAliasCatch::TagAlias2663 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
2664
2665 std::string tag;
2666 SourceLineInfo lineInfo;
2667 };
2668
2669 struct RegistrarForTagAliases {
2670 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
2671 };
2672
2673 } // end namespace Catch
2674
2675 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2676 // #included from: catch_option.hpp
2677 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2678
2679 namespace Catch {
2680
2681 // An optional type
2682 template<typename T>
2683 class Option {
2684 public:
Option()2685 Option() : nullableValue( CATCH_NULL ) {}
Option(T const & _value)2686 Option( T const& _value )
2687 : nullableValue( new( storage ) T( _value ) )
2688 {}
Option(Option const & _other)2689 Option( Option const& _other )
2690 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
2691 {}
2692
~Option()2693 ~Option() {
2694 reset();
2695 }
2696
operator =(Option const & _other)2697 Option& operator= ( Option const& _other ) {
2698 if( &_other != this ) {
2699 reset();
2700 if( _other )
2701 nullableValue = new( storage ) T( *_other );
2702 }
2703 return *this;
2704 }
operator =(T const & _value)2705 Option& operator = ( T const& _value ) {
2706 reset();
2707 nullableValue = new( storage ) T( _value );
2708 return *this;
2709 }
2710
reset()2711 void reset() {
2712 if( nullableValue )
2713 nullableValue->~T();
2714 nullableValue = CATCH_NULL;
2715 }
2716
operator *()2717 T& operator*() { return *nullableValue; }
operator *() const2718 T const& operator*() const { return *nullableValue; }
operator ->()2719 T* operator->() { return nullableValue; }
operator ->() const2720 const T* operator->() const { return nullableValue; }
2721
valueOr(T const & defaultValue) const2722 T valueOr( T const& defaultValue ) const {
2723 return nullableValue ? *nullableValue : defaultValue;
2724 }
2725
some() const2726 bool some() const { return nullableValue != CATCH_NULL; }
none() const2727 bool none() const { return nullableValue == CATCH_NULL; }
2728
operator !() const2729 bool operator !() const { return nullableValue == CATCH_NULL; }
operator SafeBool::type() const2730 operator SafeBool::type() const {
2731 return SafeBool::makeSafe( some() );
2732 }
2733
2734 private:
2735 T* nullableValue;
2736 char storage[sizeof(T)];
2737 };
2738
2739 } // end namespace Catch
2740
2741 namespace Catch {
2742
2743 struct ITagAliasRegistry {
2744 virtual ~ITagAliasRegistry();
2745 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
2746 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
2747
2748 static ITagAliasRegistry const& get();
2749 };
2750
2751 } // end namespace Catch
2752
2753 // These files are included here so the single_include script doesn't put them
2754 // in the conditionally compiled sections
2755 // #included from: internal/catch_test_case_info.h
2756 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2757
2758 #include <string>
2759 #include <set>
2760
2761 #ifdef __clang__
2762 #pragma clang diagnostic push
2763 #pragma clang diagnostic ignored "-Wpadded"
2764 #endif
2765
2766 namespace Catch {
2767
2768 struct ITestCase;
2769
2770 struct TestCaseInfo {
2771 enum SpecialProperties{
2772 None = 0,
2773 IsHidden = 1 << 1,
2774 ShouldFail = 1 << 2,
2775 MayFail = 1 << 3,
2776 Throws = 1 << 4
2777 };
2778
2779 TestCaseInfo( std::string const& _name,
2780 std::string const& _className,
2781 std::string const& _description,
2782 std::set<std::string> const& _tags,
2783 SourceLineInfo const& _lineInfo );
2784
2785 TestCaseInfo( TestCaseInfo const& other );
2786
2787 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
2788
2789 bool isHidden() const;
2790 bool throws() const;
2791 bool okToFail() const;
2792 bool expectedToFail() const;
2793
2794 std::string name;
2795 std::string className;
2796 std::string description;
2797 std::set<std::string> tags;
2798 std::set<std::string> lcaseTags;
2799 std::string tagsAsString;
2800 SourceLineInfo lineInfo;
2801 SpecialProperties properties;
2802 };
2803
2804 class TestCase : public TestCaseInfo {
2805 public:
2806
2807 TestCase( ITestCase* testCase, TestCaseInfo const& info );
2808 TestCase( TestCase const& other );
2809
2810 TestCase withName( std::string const& _newName ) const;
2811
2812 void invoke() const;
2813
2814 TestCaseInfo const& getTestCaseInfo() const;
2815
2816 void swap( TestCase& other );
2817 bool operator == ( TestCase const& other ) const;
2818 bool operator < ( TestCase const& other ) const;
2819 TestCase& operator = ( TestCase const& other );
2820
2821 private:
2822 Ptr<ITestCase> test;
2823 };
2824
2825 TestCase makeTestCase( ITestCase* testCase,
2826 std::string const& className,
2827 std::string const& name,
2828 std::string const& description,
2829 SourceLineInfo const& lineInfo );
2830 }
2831
2832 #ifdef __clang__
2833 #pragma clang diagnostic pop
2834 #endif
2835
2836
2837 #ifdef __OBJC__
2838 // #included from: internal/catch_objc.hpp
2839 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2840
2841 #import <objc/runtime.h>
2842
2843 #include <string>
2844
2845 // NB. Any general catch headers included here must be included
2846 // in catch.hpp first to make sure they are included by the single
2847 // header for non obj-usage
2848
2849 ///////////////////////////////////////////////////////////////////////////////
2850 // This protocol is really only here for (self) documenting purposes, since
2851 // all its methods are optional.
2852 @protocol OcFixture
2853
2854 @optional
2855
2856 -(void) setUp;
2857 -(void) tearDown;
2858
2859 @end
2860
2861 namespace Catch {
2862
2863 class OcMethod : public SharedImpl<ITestCase> {
2864
2865 public:
OcMethod(Class cls,SEL sel)2866 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2867
invoke() const2868 virtual void invoke() const {
2869 id obj = [[m_cls alloc] init];
2870
2871 performOptionalSelector( obj, @selector(setUp) );
2872 performOptionalSelector( obj, m_sel );
2873 performOptionalSelector( obj, @selector(tearDown) );
2874
2875 arcSafeRelease( obj );
2876 }
2877 private:
~OcMethod()2878 virtual ~OcMethod() {}
2879
2880 Class m_cls;
2881 SEL m_sel;
2882 };
2883
2884 namespace Detail{
2885
getAnnotation(Class cls,std::string const & annotationName,std::string const & testCaseName)2886 inline std::string getAnnotation( Class cls,
2887 std::string const& annotationName,
2888 std::string const& testCaseName ) {
2889 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2890 SEL sel = NSSelectorFromString( selStr );
2891 arcSafeRelease( selStr );
2892 id value = performOptionalSelector( cls, sel );
2893 if( value )
2894 return [(NSString*)value UTF8String];
2895 return "";
2896 }
2897 }
2898
registerTestMethods()2899 inline size_t registerTestMethods() {
2900 size_t noTestMethods = 0;
2901 int noClasses = objc_getClassList( CATCH_NULL, 0 );
2902
2903 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
2904 objc_getClassList( classes, noClasses );
2905
2906 for( int c = 0; c < noClasses; c++ ) {
2907 Class cls = classes[c];
2908 {
2909 u_int count;
2910 Method* methods = class_copyMethodList( cls, &count );
2911 for( u_int m = 0; m < count ; m++ ) {
2912 SEL selector = method_getName(methods[m]);
2913 std::string methodName = sel_getName(selector);
2914 if( startsWith( methodName, "Catch_TestCase_" ) ) {
2915 std::string testCaseName = methodName.substr( 15 );
2916 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2917 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
2918 const char* className = class_getName( cls );
2919
2920 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
2921 noTestMethods++;
2922 }
2923 }
2924 free(methods);
2925 }
2926 }
2927 return noTestMethods;
2928 }
2929
2930 namespace Matchers {
2931 namespace Impl {
2932 namespace NSStringMatchers {
2933
2934 template<typename MatcherT>
2935 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2936 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2937 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2938 StringHolder() {
2939 arcSafeRelease( m_substr );
2940 }
2941
2942 NSString* m_substr;
2943 };
2944
2945 struct Equals : StringHolder<Equals> {
EqualsCatch::Matchers::Impl::NSStringMatchers::Equals2946 Equals( NSString* substr ) : StringHolder( substr ){}
2947
matchCatch::Matchers::Impl::NSStringMatchers::Equals2948 virtual bool match( ExpressionType const& str ) const {
2949 return (str != nil || m_substr == nil ) &&
2950 [str isEqualToString:m_substr];
2951 }
2952
toStringCatch::Matchers::Impl::NSStringMatchers::Equals2953 virtual std::string toString() const {
2954 return "equals string: " + Catch::toString( m_substr );
2955 }
2956 };
2957
2958 struct Contains : StringHolder<Contains> {
ContainsCatch::Matchers::Impl::NSStringMatchers::Contains2959 Contains( NSString* substr ) : StringHolder( substr ){}
2960
matchCatch::Matchers::Impl::NSStringMatchers::Contains2961 virtual bool match( ExpressionType const& str ) const {
2962 return (str != nil || m_substr == nil ) &&
2963 [str rangeOfString:m_substr].location != NSNotFound;
2964 }
2965
toStringCatch::Matchers::Impl::NSStringMatchers::Contains2966 virtual std::string toString() const {
2967 return "contains string: " + Catch::toString( m_substr );
2968 }
2969 };
2970
2971 struct StartsWith : StringHolder<StartsWith> {
StartsWithCatch::Matchers::Impl::NSStringMatchers::StartsWith2972 StartsWith( NSString* substr ) : StringHolder( substr ){}
2973
matchCatch::Matchers::Impl::NSStringMatchers::StartsWith2974 virtual bool match( ExpressionType const& str ) const {
2975 return (str != nil || m_substr == nil ) &&
2976 [str rangeOfString:m_substr].location == 0;
2977 }
2978
toStringCatch::Matchers::Impl::NSStringMatchers::StartsWith2979 virtual std::string toString() const {
2980 return "starts with: " + Catch::toString( m_substr );
2981 }
2982 };
2983 struct EndsWith : StringHolder<EndsWith> {
EndsWithCatch::Matchers::Impl::NSStringMatchers::EndsWith2984 EndsWith( NSString* substr ) : StringHolder( substr ){}
2985
matchCatch::Matchers::Impl::NSStringMatchers::EndsWith2986 virtual bool match( ExpressionType const& str ) const {
2987 return (str != nil || m_substr == nil ) &&
2988 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2989 }
2990
toStringCatch::Matchers::Impl::NSStringMatchers::EndsWith2991 virtual std::string toString() const {
2992 return "ends with: " + Catch::toString( m_substr );
2993 }
2994 };
2995
2996 } // namespace NSStringMatchers
2997 } // namespace Impl
2998
2999 inline Impl::NSStringMatchers::Equals
Equals(NSString * substr)3000 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3001
3002 inline Impl::NSStringMatchers::Contains
Contains(NSString * substr)3003 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
3004
3005 inline Impl::NSStringMatchers::StartsWith
StartsWith(NSString * substr)3006 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
3007
3008 inline Impl::NSStringMatchers::EndsWith
EndsWith(NSString * substr)3009 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3010
3011 } // namespace Matchers
3012
3013 using namespace Matchers;
3014
3015 } // namespace Catch
3016
3017 ///////////////////////////////////////////////////////////////////////////////
3018 #define OC_TEST_CASE( name, desc )\
3019 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3020 {\
3021 return @ name; \
3022 }\
3023 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3024 { \
3025 return @ desc; \
3026 } \
3027 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3028
3029 #endif
3030
3031 #ifdef CATCH_IMPL
3032 // #included from: internal/catch_impl.hpp
3033 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3034
3035 // Collect all the implementation files together here
3036 // These are the equivalent of what would usually be cpp files
3037
3038 #ifdef __clang__
3039 #pragma clang diagnostic push
3040 #pragma clang diagnostic ignored "-Wweak-vtables"
3041 #endif
3042
3043 // #included from: ../catch_session.hpp
3044 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3045
3046 // #included from: internal/catch_commandline.hpp
3047 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3048
3049 // #included from: catch_config.hpp
3050 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3051
3052 // #included from: catch_test_spec_parser.hpp
3053 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3054
3055 #ifdef __clang__
3056 #pragma clang diagnostic push
3057 #pragma clang diagnostic ignored "-Wpadded"
3058 #endif
3059
3060 // #included from: catch_test_spec.hpp
3061 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3062
3063 #ifdef __clang__
3064 #pragma clang diagnostic push
3065 #pragma clang diagnostic ignored "-Wpadded"
3066 #endif
3067
3068 // #included from: catch_wildcard_pattern.hpp
3069 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3070
3071 namespace Catch
3072 {
3073 class WildcardPattern {
3074 enum WildcardPosition {
3075 NoWildcard = 0,
3076 WildcardAtStart = 1,
3077 WildcardAtEnd = 2,
3078 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3079 };
3080
3081 public:
3082
WildcardPattern(std::string const & pattern,CaseSensitive::Choice caseSensitivity)3083 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
3084 : m_caseSensitivity( caseSensitivity ),
3085 m_wildcard( NoWildcard ),
3086 m_pattern( adjustCase( pattern ) )
3087 {
3088 if( startsWith( m_pattern, "*" ) ) {
3089 m_pattern = m_pattern.substr( 1 );
3090 m_wildcard = WildcardAtStart;
3091 }
3092 if( endsWith( m_pattern, "*" ) ) {
3093 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3094 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3095 }
3096 }
3097 virtual ~WildcardPattern();
matches(std::string const & str) const3098 virtual bool matches( std::string const& str ) const {
3099 switch( m_wildcard ) {
3100 case NoWildcard:
3101 return m_pattern == adjustCase( str );
3102 case WildcardAtStart:
3103 return endsWith( adjustCase( str ), m_pattern );
3104 case WildcardAtEnd:
3105 return startsWith( adjustCase( str ), m_pattern );
3106 case WildcardAtBothEnds:
3107 return contains( adjustCase( str ), m_pattern );
3108 }
3109
3110 #ifdef __clang__
3111 #pragma clang diagnostic push
3112 #pragma clang diagnostic ignored "-Wunreachable-code"
3113 #endif
3114 throw std::logic_error( "Unknown enum" );
3115 #ifdef __clang__
3116 #pragma clang diagnostic pop
3117 #endif
3118 }
3119 private:
adjustCase(std::string const & str) const3120 std::string adjustCase( std::string const& str ) const {
3121 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
3122 }
3123 CaseSensitive::Choice m_caseSensitivity;
3124 WildcardPosition m_wildcard;
3125 std::string m_pattern;
3126 };
3127 }
3128
3129 #include <string>
3130 #include <vector>
3131
3132 namespace Catch {
3133
3134 class TestSpec {
3135 struct Pattern : SharedImpl<> {
3136 virtual ~Pattern();
3137 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3138 };
3139 class NamePattern : public Pattern {
3140 public:
NamePattern(std::string const & name)3141 NamePattern( std::string const& name )
3142 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
3143 {}
3144 virtual ~NamePattern();
matches(TestCaseInfo const & testCase) const3145 virtual bool matches( TestCaseInfo const& testCase ) const {
3146 return m_wildcardPattern.matches( toLower( testCase.name ) );
3147 }
3148 private:
3149 WildcardPattern m_wildcardPattern;
3150 };
3151
3152 class TagPattern : public Pattern {
3153 public:
TagPattern(std::string const & tag)3154 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3155 virtual ~TagPattern();
matches(TestCaseInfo const & testCase) const3156 virtual bool matches( TestCaseInfo const& testCase ) const {
3157 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
3158 }
3159 private:
3160 std::string m_tag;
3161 };
3162
3163 class ExcludedPattern : public Pattern {
3164 public:
ExcludedPattern(Ptr<Pattern> const & underlyingPattern)3165 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3166 virtual ~ExcludedPattern();
matches(TestCaseInfo const & testCase) const3167 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3168 private:
3169 Ptr<Pattern> m_underlyingPattern;
3170 };
3171
3172 struct Filter {
3173 std::vector<Ptr<Pattern> > m_patterns;
3174
matchesCatch::TestSpec::Filter3175 bool matches( TestCaseInfo const& testCase ) const {
3176 // All patterns in a filter must match for the filter to be a match
3177 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
3178 if( !(*it)->matches( testCase ) )
3179 return false;
3180 return true;
3181 }
3182 };
3183
3184 public:
hasFilters() const3185 bool hasFilters() const {
3186 return !m_filters.empty();
3187 }
matches(TestCaseInfo const & testCase) const3188 bool matches( TestCaseInfo const& testCase ) const {
3189 // A TestSpec matches if any filter matches
3190 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3191 if( it->matches( testCase ) )
3192 return true;
3193 return false;
3194 }
3195
3196 private:
3197 std::vector<Filter> m_filters;
3198
3199 friend class TestSpecParser;
3200 };
3201 }
3202
3203 #ifdef __clang__
3204 #pragma clang diagnostic pop
3205 #endif
3206
3207 namespace Catch {
3208
3209 class TestSpecParser {
3210 enum Mode{ None, Name, QuotedName, Tag };
3211 Mode m_mode;
3212 bool m_exclusion;
3213 std::size_t m_start, m_pos;
3214 std::string m_arg;
3215 TestSpec::Filter m_currentFilter;
3216 TestSpec m_testSpec;
3217 ITagAliasRegistry const* m_tagAliases;
3218
3219 public:
TestSpecParser(ITagAliasRegistry const & tagAliases)3220 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
3221
parse(std::string const & arg)3222 TestSpecParser& parse( std::string const& arg ) {
3223 m_mode = None;
3224 m_exclusion = false;
3225 m_start = std::string::npos;
3226 m_arg = m_tagAliases->expandAliases( arg );
3227 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3228 visitChar( m_arg[m_pos] );
3229 if( m_mode == Name )
3230 addPattern<TestSpec::NamePattern>();
3231 return *this;
3232 }
testSpec()3233 TestSpec testSpec() {
3234 addFilter();
3235 return m_testSpec;
3236 }
3237 private:
visitChar(char c)3238 void visitChar( char c ) {
3239 if( m_mode == None ) {
3240 switch( c ) {
3241 case ' ': return;
3242 case '~': m_exclusion = true; return;
3243 case '[': return startNewMode( Tag, ++m_pos );
3244 case '"': return startNewMode( QuotedName, ++m_pos );
3245 default: startNewMode( Name, m_pos ); break;
3246 }
3247 }
3248 if( m_mode == Name ) {
3249 if( c == ',' ) {
3250 addPattern<TestSpec::NamePattern>();
3251 addFilter();
3252 }
3253 else if( c == '[' ) {
3254 if( subString() == "exclude:" )
3255 m_exclusion = true;
3256 else
3257 addPattern<TestSpec::NamePattern>();
3258 startNewMode( Tag, ++m_pos );
3259 }
3260 }
3261 else if( m_mode == QuotedName && c == '"' )
3262 addPattern<TestSpec::NamePattern>();
3263 else if( m_mode == Tag && c == ']' )
3264 addPattern<TestSpec::TagPattern>();
3265 }
startNewMode(Mode mode,std::size_t start)3266 void startNewMode( Mode mode, std::size_t start ) {
3267 m_mode = mode;
3268 m_start = start;
3269 }
subString() const3270 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3271 template<typename T>
addPattern()3272 void addPattern() {
3273 std::string token = subString();
3274 if( startsWith( token, "exclude:" ) ) {
3275 m_exclusion = true;
3276 token = token.substr( 8 );
3277 }
3278 if( !token.empty() ) {
3279 Ptr<TestSpec::Pattern> pattern = new T( token );
3280 if( m_exclusion )
3281 pattern = new TestSpec::ExcludedPattern( pattern );
3282 m_currentFilter.m_patterns.push_back( pattern );
3283 }
3284 m_exclusion = false;
3285 m_mode = None;
3286 }
addFilter()3287 void addFilter() {
3288 if( !m_currentFilter.m_patterns.empty() ) {
3289 m_testSpec.m_filters.push_back( m_currentFilter );
3290 m_currentFilter = TestSpec::Filter();
3291 }
3292 }
3293 };
parseTestSpec(std::string const & arg)3294 inline TestSpec parseTestSpec( std::string const& arg ) {
3295 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
3296 }
3297
3298 } // namespace Catch
3299
3300 #ifdef __clang__
3301 #pragma clang diagnostic pop
3302 #endif
3303
3304 // #included from: catch_interfaces_config.h
3305 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3306
3307 #include <iostream>
3308 #include <string>
3309 #include <vector>
3310
3311 namespace Catch {
3312
3313 struct Verbosity { enum Level {
3314 NoOutput = 0,
3315 Quiet,
3316 Normal
3317 }; };
3318
3319 struct WarnAbout { enum What {
3320 Nothing = 0x00,
3321 NoAssertions = 0x01
3322 }; };
3323
3324 struct ShowDurations { enum OrNot {
3325 DefaultForReporter,
3326 Always,
3327 Never
3328 }; };
3329 struct RunTests { enum InWhatOrder {
3330 InDeclarationOrder,
3331 InLexicographicalOrder,
3332 InRandomOrder
3333 }; };
3334
3335 class TestSpec;
3336
3337 struct IConfig : IShared {
3338
3339 virtual ~IConfig();
3340
3341 virtual bool allowThrows() const = 0;
3342 virtual std::ostream& stream() const = 0;
3343 virtual std::string name() const = 0;
3344 virtual bool includeSuccessfulResults() const = 0;
3345 virtual bool shouldDebugBreak() const = 0;
3346 virtual bool warnAboutMissingAssertions() const = 0;
3347 virtual int abortAfter() const = 0;
3348 virtual bool showInvisibles() const = 0;
3349 virtual ShowDurations::OrNot showDurations() const = 0;
3350 virtual TestSpec const& testSpec() const = 0;
3351 virtual RunTests::InWhatOrder runOrder() const = 0;
3352 virtual unsigned int rngSeed() const = 0;
3353 virtual bool forceColour() const = 0;
3354 };
3355 }
3356
3357 // #included from: catch_stream.h
3358 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3359
3360 // #included from: catch_streambuf.h
3361 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3362
3363 #include <streambuf>
3364
3365 namespace Catch {
3366
3367 class StreamBufBase : public std::streambuf {
3368 public:
3369 virtual ~StreamBufBase() CATCH_NOEXCEPT;
3370 };
3371 }
3372
3373 #include <streambuf>
3374 #include <ostream>
3375 #include <fstream>
3376
3377 namespace Catch {
3378
3379 std::ostream& cout();
3380 std::ostream& cerr();
3381
3382 struct IStream {
3383 virtual ~IStream() CATCH_NOEXCEPT;
3384 virtual std::ostream& stream() const = 0;
3385 };
3386
3387 class FileStream : public IStream {
3388 mutable std::ofstream m_ofs;
3389 public:
3390 FileStream( std::string const& filename );
3391 virtual ~FileStream() CATCH_NOEXCEPT;
3392 public: // IStream
3393 virtual std::ostream& stream() const CATCH_OVERRIDE;
3394 };
3395
3396 class CoutStream : public IStream {
3397 mutable std::ostream m_os;
3398 public:
3399 CoutStream();
3400 virtual ~CoutStream() CATCH_NOEXCEPT;
3401
3402 public: // IStream
3403 virtual std::ostream& stream() const CATCH_OVERRIDE;
3404 };
3405
3406 class DebugOutStream : public IStream {
3407 std::auto_ptr<StreamBufBase> m_streamBuf;
3408 mutable std::ostream m_os;
3409 public:
3410 DebugOutStream();
3411 virtual ~DebugOutStream() CATCH_NOEXCEPT;
3412
3413 public: // IStream
3414 virtual std::ostream& stream() const CATCH_OVERRIDE;
3415 };
3416 }
3417
3418 #include <memory>
3419 #include <vector>
3420 #include <string>
3421 #include <iostream>
3422 #include <ctime>
3423
3424 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3425 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3426 #endif
3427
3428 namespace Catch {
3429
3430 struct ConfigData {
3431
ConfigDataCatch::ConfigData3432 ConfigData()
3433 : listTests( false ),
3434 listTags( false ),
3435 listReporters( false ),
3436 listTestNamesOnly( false ),
3437 showSuccessfulTests( false ),
3438 shouldDebugBreak( false ),
3439 noThrow( false ),
3440 showHelp( false ),
3441 showInvisibles( false ),
3442 forceColour( false ),
3443 filenamesAsTags( false ),
3444 abortAfter( -1 ),
3445 rngSeed( 0 ),
3446 verbosity( Verbosity::Normal ),
3447 warnings( WarnAbout::Nothing ),
3448 showDurations( ShowDurations::DefaultForReporter ),
3449 runOrder( RunTests::InDeclarationOrder )
3450 {}
3451
3452 bool listTests;
3453 bool listTags;
3454 bool listReporters;
3455 bool listTestNamesOnly;
3456
3457 bool showSuccessfulTests;
3458 bool shouldDebugBreak;
3459 bool noThrow;
3460 bool showHelp;
3461 bool showInvisibles;
3462 bool forceColour;
3463 bool filenamesAsTags;
3464
3465 int abortAfter;
3466 unsigned int rngSeed;
3467
3468 Verbosity::Level verbosity;
3469 WarnAbout::What warnings;
3470 ShowDurations::OrNot showDurations;
3471 RunTests::InWhatOrder runOrder;
3472
3473 std::string outputFilename;
3474 std::string name;
3475 std::string processName;
3476
3477 std::vector<std::string> reporterNames;
3478 std::vector<std::string> testsOrTags;
3479 };
3480
3481 class Config : public SharedImpl<IConfig> {
3482 private:
3483 Config( Config const& other );
3484 Config& operator = ( Config const& other );
3485 virtual void dummy();
3486 public:
3487
Config()3488 Config()
3489 {}
3490
Config(ConfigData const & data)3491 Config( ConfigData const& data )
3492 : m_data( data ),
3493 m_stream( openStream() )
3494 {
3495 if( !data.testsOrTags.empty() ) {
3496 TestSpecParser parser( ITagAliasRegistry::get() );
3497 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3498 parser.parse( data.testsOrTags[i] );
3499 m_testSpec = parser.testSpec();
3500 }
3501 }
3502
~Config()3503 virtual ~Config() {
3504 }
3505
getFilename() const3506 std::string const& getFilename() const {
3507 return m_data.outputFilename ;
3508 }
3509
listTests() const3510 bool listTests() const { return m_data.listTests; }
listTestNamesOnly() const3511 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
listTags() const3512 bool listTags() const { return m_data.listTags; }
listReporters() const3513 bool listReporters() const { return m_data.listReporters; }
3514
getProcessName() const3515 std::string getProcessName() const { return m_data.processName; }
3516
shouldDebugBreak() const3517 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
3518
getReporterNames() const3519 std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
3520
abortAfter() const3521 int abortAfter() const { return m_data.abortAfter; }
3522
testSpec() const3523 TestSpec const& testSpec() const { return m_testSpec; }
3524
showHelp() const3525 bool showHelp() const { return m_data.showHelp; }
showInvisibles() const3526 bool showInvisibles() const { return m_data.showInvisibles; }
3527
3528 // IConfig interface
allowThrows() const3529 virtual bool allowThrows() const { return !m_data.noThrow; }
stream() const3530 virtual std::ostream& stream() const { return m_stream->stream(); }
name() const3531 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
includeSuccessfulResults() const3532 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
warnAboutMissingAssertions() const3533 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
showDurations() const3534 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
runOrder() const3535 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
rngSeed() const3536 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
forceColour() const3537 virtual bool forceColour() const { return m_data.forceColour; }
3538
3539 private:
3540
openStream()3541 IStream const* openStream() {
3542 if( m_data.outputFilename.empty() )
3543 return new CoutStream();
3544 else if( m_data.outputFilename[0] == '%' ) {
3545 if( m_data.outputFilename == "%debug" )
3546 return new DebugOutStream();
3547 else
3548 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
3549 }
3550 else
3551 return new FileStream( m_data.outputFilename );
3552 }
3553 ConfigData m_data;
3554
3555 std::auto_ptr<IStream const> m_stream;
3556 TestSpec m_testSpec;
3557 };
3558
3559 } // end namespace Catch
3560
3561 // #included from: catch_clara.h
3562 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3563
3564 // Use Catch's value for console width (store Clara's off to the side, if present)
3565 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
3566 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3567 #undef CLARA_CONFIG_CONSOLE_WIDTH
3568 #endif
3569 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3570
3571 // Declare Clara inside the Catch namespace
3572 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3573 // #included from: ../external/clara.h
3574
3575 // Only use header guard if we are not using an outer namespace
3576 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3577
3578 #ifndef STITCH_CLARA_OPEN_NAMESPACE
3579 #define TWOBLUECUBES_CLARA_H_INCLUDED
3580 #define STITCH_CLARA_OPEN_NAMESPACE
3581 #define STITCH_CLARA_CLOSE_NAMESPACE
3582 #else
3583 #define STITCH_CLARA_CLOSE_NAMESPACE }
3584 #endif
3585
3586 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3587
3588 // ----------- #included from tbc_text_format.h -----------
3589
3590 // Only use header guard if we are not using an outer namespace
3591 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3592 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3593 #define TBC_TEXT_FORMAT_H_INCLUDED
3594 #endif
3595
3596 #include <string>
3597 #include <vector>
3598 #include <sstream>
3599
3600 // Use optional outer namespace
3601 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3602 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3603 #endif
3604
3605 namespace Tbc {
3606
3607 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3608 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3609 #else
3610 const unsigned int consoleWidth = 80;
3611 #endif
3612
3613 struct TextAttributes {
TextAttributesSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3614 TextAttributes()
3615 : initialIndent( std::string::npos ),
3616 indent( 0 ),
3617 width( consoleWidth-1 ),
3618 tabChar( '\t' )
3619 {}
3620
setInitialIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3621 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
setIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3622 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
setWidthSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3623 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
setTabCharSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3624 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
3625
3626 std::size_t initialIndent; // indent of first line, or npos
3627 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3628 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3629 char tabChar; // If this char is seen the indent is changed to current pos
3630 };
3631
3632 class Text {
3633 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())3634 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
3635 : attr( _attr )
3636 {
3637 std::string wrappableChars = " [({.,/|\\-";
3638 std::size_t indent = _attr.initialIndent != std::string::npos
3639 ? _attr.initialIndent
3640 : _attr.indent;
3641 std::string remainder = _str;
3642
3643 while( !remainder.empty() ) {
3644 if( lines.size() >= 1000 ) {
3645 lines.push_back( "... message truncated due to excessive size" );
3646 return;
3647 }
3648 std::size_t tabPos = std::string::npos;
3649 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3650 std::size_t pos = remainder.find_first_of( '\n' );
3651 if( pos <= width ) {
3652 width = pos;
3653 }
3654 pos = remainder.find_last_of( _attr.tabChar, width );
3655 if( pos != std::string::npos ) {
3656 tabPos = pos;
3657 if( remainder[width] == '\n' )
3658 width--;
3659 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3660 }
3661
3662 if( width == remainder.size() ) {
3663 spliceLine( indent, remainder, width );
3664 }
3665 else if( remainder[width] == '\n' ) {
3666 spliceLine( indent, remainder, width );
3667 if( width <= 1 || remainder.size() != 1 )
3668 remainder = remainder.substr( 1 );
3669 indent = _attr.indent;
3670 }
3671 else {
3672 pos = remainder.find_last_of( wrappableChars, width );
3673 if( pos != std::string::npos && pos > 0 ) {
3674 spliceLine( indent, remainder, pos );
3675 if( remainder[0] == ' ' )
3676 remainder = remainder.substr( 1 );
3677 }
3678 else {
3679 spliceLine( indent, remainder, width-1 );
3680 lines.back() += "-";
3681 }
3682 if( lines.size() == 1 )
3683 indent = _attr.indent;
3684 if( tabPos != std::string::npos )
3685 indent += tabPos;
3686 }
3687 }
3688 }
3689
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)3690 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3691 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
3692 _remainder = _remainder.substr( _pos );
3693 }
3694
3695 typedef std::vector<std::string>::const_iterator const_iterator;
3696
begin() const3697 const_iterator begin() const { return lines.begin(); }
end() const3698 const_iterator end() const { return lines.end(); }
last() const3699 std::string const& last() const { return lines.back(); }
size() const3700 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const3701 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
toString() const3702 std::string toString() const {
3703 std::ostringstream oss;
3704 oss << *this;
3705 return oss.str();
3706 }
3707
operator <<(std::ostream & _stream,Text const & _text)3708 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
3709 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3710 it != itEnd; ++it ) {
3711 if( it != _text.begin() )
3712 _stream << "\n";
3713 _stream << *it;
3714 }
3715 return _stream;
3716 }
3717
3718 private:
3719 std::string str;
3720 TextAttributes attr;
3721 std::vector<std::string> lines;
3722 };
3723
3724 } // end namespace Tbc
3725
3726 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3727 } // end outer namespace
3728 #endif
3729
3730 #endif // TBC_TEXT_FORMAT_H_INCLUDED
3731
3732 // ----------- end of #include from tbc_text_format.h -----------
3733 // ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
3734
3735 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3736
3737 #include <map>
3738 #include <algorithm>
3739 #include <stdexcept>
3740 #include <memory>
3741
3742 // Use optional outer namespace
3743 #ifdef STITCH_CLARA_OPEN_NAMESPACE
3744 STITCH_CLARA_OPEN_NAMESPACE
3745 #endif
3746
3747 namespace Clara {
3748
3749 struct UnpositionalTag {};
3750
3751 extern UnpositionalTag _;
3752
3753 #ifdef CLARA_CONFIG_MAIN
3754 UnpositionalTag _;
3755 #endif
3756
3757 namespace Detail {
3758
3759 #ifdef CLARA_CONSOLE_WIDTH
3760 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3761 #else
3762 const unsigned int consoleWidth = 80;
3763 #endif
3764
3765 using namespace Tbc;
3766
startsWith(std::string const & str,std::string const & prefix)3767 inline bool startsWith( std::string const& str, std::string const& prefix ) {
3768 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3769 }
3770
3771 template<typename T> struct RemoveConstRef{ typedef T type; };
3772 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3773 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3774 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3775
3776 template<typename T> struct IsBool { static const bool value = false; };
3777 template<> struct IsBool<bool> { static const bool value = true; };
3778
3779 template<typename T>
convertInto(std::string const & _source,T & _dest)3780 void convertInto( std::string const& _source, T& _dest ) {
3781 std::stringstream ss;
3782 ss << _source;
3783 ss >> _dest;
3784 if( ss.fail() )
3785 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
3786 }
convertInto(std::string const & _source,std::string & _dest)3787 inline void convertInto( std::string const& _source, std::string& _dest ) {
3788 _dest = _source;
3789 }
convertInto(std::string const & _source,bool & _dest)3790 inline void convertInto( std::string const& _source, bool& _dest ) {
3791 std::string sourceLC = _source;
3792 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3793 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
3794 _dest = true;
3795 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
3796 _dest = false;
3797 else
3798 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
3799 }
convertInto(bool _source,bool & _dest)3800 inline void convertInto( bool _source, bool& _dest ) {
3801 _dest = _source;
3802 }
3803 template<typename T>
convertInto(bool,T &)3804 inline void convertInto( bool, T& ) {
3805 throw std::runtime_error( "Invalid conversion" );
3806 }
3807
3808 template<typename ConfigT>
3809 struct IArgFunction {
~IArgFunctionClara::Detail::IArgFunction3810 virtual ~IArgFunction() {}
3811 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
3812 IArgFunction() = default;
3813 IArgFunction( IArgFunction const& ) = default;
3814 # endif
3815 virtual void set( ConfigT& config, std::string const& value ) const = 0;
3816 virtual void setFlag( ConfigT& config ) const = 0;
3817 virtual bool takesArg() const = 0;
3818 virtual IArgFunction* clone() const = 0;
3819 };
3820
3821 template<typename ConfigT>
3822 class BoundArgFunction {
3823 public:
BoundArgFunction()3824 BoundArgFunction() : functionObj( CATCH_NULL ) {}
BoundArgFunction(IArgFunction<ConfigT> * _functionObj)3825 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
BoundArgFunction(BoundArgFunction const & other)3826 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {}
operator =(BoundArgFunction const & other)3827 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
3828 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL;
3829 delete functionObj;
3830 functionObj = newFunctionObj;
3831 return *this;
3832 }
~BoundArgFunction()3833 ~BoundArgFunction() { delete functionObj; }
3834
set(ConfigT & config,std::string const & value) const3835 void set( ConfigT& config, std::string const& value ) const {
3836 functionObj->set( config, value );
3837 }
setFlag(ConfigT & config) const3838 void setFlag( ConfigT& config ) const {
3839 functionObj->setFlag( config );
3840 }
takesArg() const3841 bool takesArg() const { return functionObj->takesArg(); }
3842
isSet() const3843 bool isSet() const {
3844 return functionObj != CATCH_NULL;
3845 }
3846 private:
3847 IArgFunction<ConfigT>* functionObj;
3848 };
3849
3850 template<typename C>
3851 struct NullBinder : IArgFunction<C>{
setClara::Detail::NullBinder3852 virtual void set( C&, std::string const& ) const {}
setFlagClara::Detail::NullBinder3853 virtual void setFlag( C& ) const {}
takesArgClara::Detail::NullBinder3854 virtual bool takesArg() const { return true; }
cloneClara::Detail::NullBinder3855 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
3856 };
3857
3858 template<typename C, typename M>
3859 struct BoundDataMember : IArgFunction<C>{
BoundDataMemberClara::Detail::BoundDataMember3860 BoundDataMember( M C::* _member ) : member( _member ) {}
setClara::Detail::BoundDataMember3861 virtual void set( C& p, std::string const& stringValue ) const {
3862 convertInto( stringValue, p.*member );
3863 }
setFlagClara::Detail::BoundDataMember3864 virtual void setFlag( C& p ) const {
3865 convertInto( true, p.*member );
3866 }
takesArgClara::Detail::BoundDataMember3867 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundDataMember3868 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
3869 M C::* member;
3870 };
3871 template<typename C, typename M>
3872 struct BoundUnaryMethod : IArgFunction<C>{
BoundUnaryMethodClara::Detail::BoundUnaryMethod3873 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
setClara::Detail::BoundUnaryMethod3874 virtual void set( C& p, std::string const& stringValue ) const {
3875 typename RemoveConstRef<M>::type value;
3876 convertInto( stringValue, value );
3877 (p.*member)( value );
3878 }
setFlagClara::Detail::BoundUnaryMethod3879 virtual void setFlag( C& p ) const {
3880 typename RemoveConstRef<M>::type value;
3881 convertInto( true, value );
3882 (p.*member)( value );
3883 }
takesArgClara::Detail::BoundUnaryMethod3884 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundUnaryMethod3885 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
3886 void (C::*member)( M );
3887 };
3888 template<typename C>
3889 struct BoundNullaryMethod : IArgFunction<C>{
BoundNullaryMethodClara::Detail::BoundNullaryMethod3890 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
setClara::Detail::BoundNullaryMethod3891 virtual void set( C& p, std::string const& stringValue ) const {
3892 bool value;
3893 convertInto( stringValue, value );
3894 if( value )
3895 (p.*member)();
3896 }
setFlagClara::Detail::BoundNullaryMethod3897 virtual void setFlag( C& p ) const {
3898 (p.*member)();
3899 }
takesArgClara::Detail::BoundNullaryMethod3900 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundNullaryMethod3901 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
3902 void (C::*member)();
3903 };
3904
3905 template<typename C>
3906 struct BoundUnaryFunction : IArgFunction<C>{
BoundUnaryFunctionClara::Detail::BoundUnaryFunction3907 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
setClara::Detail::BoundUnaryFunction3908 virtual void set( C& obj, std::string const& stringValue ) const {
3909 bool value;
3910 convertInto( stringValue, value );
3911 if( value )
3912 function( obj );
3913 }
setFlagClara::Detail::BoundUnaryFunction3914 virtual void setFlag( C& p ) const {
3915 function( p );
3916 }
takesArgClara::Detail::BoundUnaryFunction3917 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundUnaryFunction3918 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
3919 void (*function)( C& );
3920 };
3921
3922 template<typename C, typename T>
3923 struct BoundBinaryFunction : IArgFunction<C>{
BoundBinaryFunctionClara::Detail::BoundBinaryFunction3924 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
setClara::Detail::BoundBinaryFunction3925 virtual void set( C& obj, std::string const& stringValue ) const {
3926 typename RemoveConstRef<T>::type value;
3927 convertInto( stringValue, value );
3928 function( obj, value );
3929 }
setFlagClara::Detail::BoundBinaryFunction3930 virtual void setFlag( C& obj ) const {
3931 typename RemoveConstRef<T>::type value;
3932 convertInto( true, value );
3933 function( obj, value );
3934 }
takesArgClara::Detail::BoundBinaryFunction3935 virtual bool takesArg() const { return !IsBool<T>::value; }
cloneClara::Detail::BoundBinaryFunction3936 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
3937 void (*function)( C&, T );
3938 };
3939
3940 } // namespace Detail
3941
3942 struct Parser {
ParserClara::Parser3943 Parser() : separators( " \t=:" ) {}
3944
3945 struct Token {
3946 enum Type { Positional, ShortOpt, LongOpt };
TokenClara::Parser::Token3947 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
3948 Type type;
3949 std::string data;
3950 };
3951
parseIntoTokensClara::Parser3952 void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
3953 const std::string doubleDash = "--";
3954 for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
3955 parseIntoTokens( argv[i] , tokens);
3956 }
parseIntoTokensClara::Parser3957 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
3958 while( !arg.empty() ) {
3959 Parser::Token token( Parser::Token::Positional, arg );
3960 arg = "";
3961 if( token.data[0] == '-' ) {
3962 if( token.data.size() > 1 && token.data[1] == '-' ) {
3963 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
3964 }
3965 else {
3966 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
3967 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
3968 arg = "-" + token.data.substr( 1 );
3969 token.data = token.data.substr( 0, 1 );
3970 }
3971 }
3972 }
3973 if( token.type != Parser::Token::Positional ) {
3974 std::size_t pos = token.data.find_first_of( separators );
3975 if( pos != std::string::npos ) {
3976 arg = token.data.substr( pos+1 );
3977 token.data = token.data.substr( 0, pos );
3978 }
3979 }
3980 tokens.push_back( token );
3981 }
3982 }
3983 std::string separators;
3984 };
3985
3986 template<typename ConfigT>
3987 struct CommonArgProperties {
CommonArgPropertiesClara::CommonArgProperties3988 CommonArgProperties() {}
CommonArgPropertiesClara::CommonArgProperties3989 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
3990
3991 Detail::BoundArgFunction<ConfigT> boundField;
3992 std::string description;
3993 std::string detail;
3994 std::string placeholder; // Only value if boundField takes an arg
3995
takesArgClara::CommonArgProperties3996 bool takesArg() const {
3997 return !placeholder.empty();
3998 }
validateClara::CommonArgProperties3999 void validate() const {
4000 if( !boundField.isSet() )
4001 throw std::logic_error( "option not bound" );
4002 }
4003 };
4004 struct OptionArgProperties {
4005 std::vector<std::string> shortNames;
4006 std::string longName;
4007
hasShortNameClara::OptionArgProperties4008 bool hasShortName( std::string const& shortName ) const {
4009 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4010 }
hasLongNameClara::OptionArgProperties4011 bool hasLongName( std::string const& _longName ) const {
4012 return _longName == longName;
4013 }
4014 };
4015 struct PositionalArgProperties {
PositionalArgPropertiesClara::PositionalArgProperties4016 PositionalArgProperties() : position( -1 ) {}
4017 int position; // -1 means non-positional (floating)
4018
isFixedPositionalClara::PositionalArgProperties4019 bool isFixedPositional() const {
4020 return position != -1;
4021 }
4022 };
4023
4024 template<typename ConfigT>
4025 class CommandLine {
4026
4027 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
ArgClara::CommandLine::Arg4028 Arg() {}
ArgClara::CommandLine::Arg4029 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
4030
4031 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4032
dbgNameClara::CommandLine::Arg4033 std::string dbgName() const {
4034 if( !longName.empty() )
4035 return "--" + longName;
4036 if( !shortNames.empty() )
4037 return "-" + shortNames[0];
4038 return "positional args";
4039 }
commandsClara::CommandLine::Arg4040 std::string commands() const {
4041 std::ostringstream oss;
4042 bool first = true;
4043 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4044 for(; it != itEnd; ++it ) {
4045 if( first )
4046 first = false;
4047 else
4048 oss << ", ";
4049 oss << "-" << *it;
4050 }
4051 if( !longName.empty() ) {
4052 if( !first )
4053 oss << ", ";
4054 oss << "--" << longName;
4055 }
4056 if( !placeholder.empty() )
4057 oss << " <" << placeholder << ">";
4058 return oss.str();
4059 }
4060 };
4061
4062 typedef CATCH_AUTO_PTR( Arg ) ArgAutoPtr;
4063
addOptName(Arg & arg,std::string const & optName)4064 friend void addOptName( Arg& arg, std::string const& optName )
4065 {
4066 if( optName.empty() )
4067 return;
4068 if( Detail::startsWith( optName, "--" ) ) {
4069 if( !arg.longName.empty() )
4070 throw std::logic_error( "Only one long opt may be specified. '"
4071 + arg.longName
4072 + "' already specified, now attempting to add '"
4073 + optName + "'" );
4074 arg.longName = optName.substr( 2 );
4075 }
4076 else if( Detail::startsWith( optName, "-" ) )
4077 arg.shortNames.push_back( optName.substr( 1 ) );
4078 else
4079 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4080 }
setPositionalArg(Arg & arg,int position)4081 friend void setPositionalArg( Arg& arg, int position )
4082 {
4083 arg.position = position;
4084 }
4085
4086 class ArgBuilder {
4087 public:
ArgBuilder(Arg * arg)4088 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
4089
4090 // Bind a non-boolean data member (requires placeholder string)
4091 template<typename C, typename M>
bind(M C::* field,std::string const & placeholder)4092 void bind( M C::* field, std::string const& placeholder ) {
4093 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4094 m_arg->placeholder = placeholder;
4095 }
4096 // Bind a boolean data member (no placeholder required)
4097 template<typename C>
bind(bool C::* field)4098 void bind( bool C::* field ) {
4099 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
4100 }
4101
4102 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4103 template<typename C, typename M>
bind(void (C::* unaryMethod)(M),std::string const & placeholder)4104 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4105 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4106 m_arg->placeholder = placeholder;
4107 }
4108
4109 // Bind a method taking a single, boolean argument (no placeholder string required)
4110 template<typename C>
bind(void (C::* unaryMethod)(bool))4111 void bind( void (C::* unaryMethod)( bool ) ) {
4112 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
4113 }
4114
4115 // Bind a method that takes no arguments (will be called if opt is present)
4116 template<typename C>
bind(void (C::* nullaryMethod)())4117 void bind( void (C::* nullaryMethod)() ) {
4118 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
4119 }
4120
4121 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4122 template<typename C>
bind(void (* unaryFunction)(C &))4123 void bind( void (* unaryFunction)( C& ) ) {
4124 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
4125 }
4126
4127 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4128 template<typename C, typename T>
bind(void (* binaryFunction)(C &,T),std::string const & placeholder)4129 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4130 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4131 m_arg->placeholder = placeholder;
4132 }
4133
describe(std::string const & description)4134 ArgBuilder& describe( std::string const& description ) {
4135 m_arg->description = description;
4136 return *this;
4137 }
detail(std::string const & _detail)4138 ArgBuilder& detail( std::string const& _detail ) {
4139 m_arg->detail = _detail;
4140 return *this;
4141 }
4142
4143 protected:
4144 Arg* m_arg;
4145 };
4146
4147 class OptBuilder : public ArgBuilder {
4148 public:
OptBuilder(Arg * arg)4149 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
OptBuilder(OptBuilder & other)4150 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4151
operator [](std::string const & optName)4152 OptBuilder& operator[]( std::string const& optName ) {
4153 addOptName( *ArgBuilder::m_arg, optName );
4154 return *this;
4155 }
4156 };
4157
4158 public:
4159
CommandLine()4160 CommandLine()
4161 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
4162 m_highestSpecifiedArgPosition( 0 ),
4163 m_throwOnUnrecognisedTokens( false )
4164 {}
CommandLine(CommandLine const & other)4165 CommandLine( CommandLine const& other )
4166 : m_boundProcessName( other.m_boundProcessName ),
4167 m_options ( other.m_options ),
4168 m_positionalArgs( other.m_positionalArgs ),
4169 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4170 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
4171 {
4172 if( other.m_floatingArg.get() )
4173 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
4174 }
4175
setThrowOnUnrecognisedTokens(bool shouldThrow=true)4176 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4177 m_throwOnUnrecognisedTokens = shouldThrow;
4178 return *this;
4179 }
4180
operator [](std::string const & optName)4181 OptBuilder operator[]( std::string const& optName ) {
4182 m_options.push_back( Arg() );
4183 addOptName( m_options.back(), optName );
4184 OptBuilder builder( &m_options.back() );
4185 return builder;
4186 }
4187
operator [](int position)4188 ArgBuilder operator[]( int position ) {
4189 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4190 if( position > m_highestSpecifiedArgPosition )
4191 m_highestSpecifiedArgPosition = position;
4192 setPositionalArg( m_positionalArgs[position], position );
4193 ArgBuilder builder( &m_positionalArgs[position] );
4194 return builder;
4195 }
4196
4197 // Invoke this with the _ instance
operator [](UnpositionalTag)4198 ArgBuilder operator[]( UnpositionalTag ) {
4199 if( m_floatingArg.get() )
4200 throw std::logic_error( "Only one unpositional argument can be added" );
4201 m_floatingArg.reset( new Arg() );
4202 ArgBuilder builder( m_floatingArg.get() );
4203 return builder;
4204 }
4205
4206 template<typename C, typename M>
bindProcessName(M C::* field)4207 void bindProcessName( M C::* field ) {
4208 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4209 }
4210 template<typename C, typename M>
bindProcessName(void (C::* _unaryMethod)(M))4211 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4212 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
4213 }
4214
optUsage(std::ostream & os,std::size_t indent=0,std::size_t width=Detail::consoleWidth) const4215 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
4216 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4217 std::size_t maxWidth = 0;
4218 for( it = itBegin; it != itEnd; ++it )
4219 maxWidth = (std::max)( maxWidth, it->commands().size() );
4220
4221 for( it = itBegin; it != itEnd; ++it ) {
4222 Detail::Text usageText( it->commands(), Detail::TextAttributes()
4223 .setWidth( maxWidth+indent )
4224 .setIndent( indent ) );
4225 Detail::Text desc( it->description, Detail::TextAttributes()
4226 .setWidth( width - maxWidth - 3 ) );
4227
4228 for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) {
4229 std::string usageCol = i < usageText.size() ? usageText[i] : "";
4230 os << usageCol;
4231
4232 if( i < desc.size() && !desc[i].empty() )
4233 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4234 << desc[i];
4235 os << "\n";
4236 }
4237 }
4238 }
optUsage() const4239 std::string optUsage() const {
4240 std::ostringstream oss;
4241 optUsage( oss );
4242 return oss.str();
4243 }
4244
argSynopsis(std::ostream & os) const4245 void argSynopsis( std::ostream& os ) const {
4246 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4247 if( i > 1 )
4248 os << " ";
4249 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4250 if( it != m_positionalArgs.end() )
4251 os << "<" << it->second.placeholder << ">";
4252 else if( m_floatingArg.get() )
4253 os << "<" << m_floatingArg->placeholder << ">";
4254 else
4255 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4256 }
4257 // !TBD No indication of mandatory args
4258 if( m_floatingArg.get() ) {
4259 if( m_highestSpecifiedArgPosition > 1 )
4260 os << " ";
4261 os << "[<" << m_floatingArg->placeholder << "> ...]";
4262 }
4263 }
argSynopsis() const4264 std::string argSynopsis() const {
4265 std::ostringstream oss;
4266 argSynopsis( oss );
4267 return oss.str();
4268 }
4269
usage(std::ostream & os,std::string const & procName) const4270 void usage( std::ostream& os, std::string const& procName ) const {
4271 validate();
4272 os << "usage:\n " << procName << " ";
4273 argSynopsis( os );
4274 if( !m_options.empty() ) {
4275 os << " [options]\n\nwhere options are: \n";
4276 optUsage( os, 2 );
4277 }
4278 os << "\n";
4279 }
usage(std::string const & procName) const4280 std::string usage( std::string const& procName ) const {
4281 std::ostringstream oss;
4282 usage( oss, procName );
4283 return oss.str();
4284 }
4285
parse(int argc,char const * const * argv) const4286 ConfigT parse( int argc, char const * const * argv ) const {
4287 ConfigT config;
4288 parseInto( argc, argv, config );
4289 return config;
4290 }
4291
parseInto(int argc,char const * const * argv,ConfigT & config) const4292 std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
4293 std::string processName = argv[0];
4294 std::size_t lastSlash = processName.find_last_of( "/\\" );
4295 if( lastSlash != std::string::npos )
4296 processName = processName.substr( lastSlash+1 );
4297 m_boundProcessName.set( config, processName );
4298 std::vector<Parser::Token> tokens;
4299 Parser parser;
4300 parser.parseIntoTokens( argc, argv, tokens );
4301 return populate( tokens, config );
4302 }
4303
populate(std::vector<Parser::Token> const & tokens,ConfigT & config) const4304 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4305 validate();
4306 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4307 unusedTokens = populateFixedArgs( unusedTokens, config );
4308 unusedTokens = populateFloatingArgs( unusedTokens, config );
4309 return unusedTokens;
4310 }
4311
populateOptions(std::vector<Parser::Token> const & tokens,ConfigT & config) const4312 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4313 std::vector<Parser::Token> unusedTokens;
4314 std::vector<std::string> errors;
4315 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4316 Parser::Token const& token = tokens[i];
4317 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4318 for(; it != itEnd; ++it ) {
4319 Arg const& arg = *it;
4320
4321 try {
4322 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4323 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4324 if( arg.takesArg() ) {
4325 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4326 errors.push_back( "Expected argument to option: " + token.data );
4327 else
4328 arg.boundField.set( config, tokens[++i].data );
4329 }
4330 else {
4331 arg.boundField.setFlag( config );
4332 }
4333 break;
4334 }
4335 }
4336 catch( std::exception& ex ) {
4337 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
4338 }
4339 }
4340 if( it == itEnd ) {
4341 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4342 unusedTokens.push_back( token );
4343 else if( errors.empty() && m_throwOnUnrecognisedTokens )
4344 errors.push_back( "unrecognised option: " + token.data );
4345 }
4346 }
4347 if( !errors.empty() ) {
4348 std::ostringstream oss;
4349 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4350 it != itEnd;
4351 ++it ) {
4352 if( it != errors.begin() )
4353 oss << "\n";
4354 oss << *it;
4355 }
4356 throw std::runtime_error( oss.str() );
4357 }
4358 return unusedTokens;
4359 }
populateFixedArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const4360 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4361 std::vector<Parser::Token> unusedTokens;
4362 int position = 1;
4363 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4364 Parser::Token const& token = tokens[i];
4365 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4366 if( it != m_positionalArgs.end() )
4367 it->second.boundField.set( config, token.data );
4368 else
4369 unusedTokens.push_back( token );
4370 if( token.type == Parser::Token::Positional )
4371 position++;
4372 }
4373 return unusedTokens;
4374 }
populateFloatingArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const4375 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4376 if( !m_floatingArg.get() )
4377 return tokens;
4378 std::vector<Parser::Token> unusedTokens;
4379 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4380 Parser::Token const& token = tokens[i];
4381 if( token.type == Parser::Token::Positional )
4382 m_floatingArg->boundField.set( config, token.data );
4383 else
4384 unusedTokens.push_back( token );
4385 }
4386 return unusedTokens;
4387 }
4388
validate() const4389 void validate() const
4390 {
4391 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4392 throw std::logic_error( "No options or arguments specified" );
4393
4394 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
4395 itEnd = m_options.end();
4396 it != itEnd; ++it )
4397 it->validate();
4398 }
4399
4400 private:
4401 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4402 std::vector<Arg> m_options;
4403 std::map<int, Arg> m_positionalArgs;
4404 ArgAutoPtr m_floatingArg;
4405 int m_highestSpecifiedArgPosition;
4406 bool m_throwOnUnrecognisedTokens;
4407 };
4408
4409 } // end namespace Clara
4410
4411 STITCH_CLARA_CLOSE_NAMESPACE
4412 #undef STITCH_CLARA_OPEN_NAMESPACE
4413 #undef STITCH_CLARA_CLOSE_NAMESPACE
4414
4415 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
4416 #undef STITCH_CLARA_OPEN_NAMESPACE
4417
4418 // Restore Clara's value for console width, if present
4419 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4420 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4421 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4422 #endif
4423
4424 #include <fstream>
4425
4426 namespace Catch {
4427
abortAfterFirst(ConfigData & config)4428 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
abortAfterX(ConfigData & config,int x)4429 inline void abortAfterX( ConfigData& config, int x ) {
4430 if( x < 1 )
4431 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
4432 config.abortAfter = x;
4433 }
addTestOrTags(ConfigData & config,std::string const & _testSpec)4434 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
addReporterName(ConfigData & config,std::string const & _reporterName)4435 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
4436
addWarning(ConfigData & config,std::string const & _warning)4437 inline void addWarning( ConfigData& config, std::string const& _warning ) {
4438 if( _warning == "NoAssertions" )
4439 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
4440 else
4441 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
4442 }
setOrder(ConfigData & config,std::string const & order)4443 inline void setOrder( ConfigData& config, std::string const& order ) {
4444 if( startsWith( "declared", order ) )
4445 config.runOrder = RunTests::InDeclarationOrder;
4446 else if( startsWith( "lexical", order ) )
4447 config.runOrder = RunTests::InLexicographicalOrder;
4448 else if( startsWith( "random", order ) )
4449 config.runOrder = RunTests::InRandomOrder;
4450 else
4451 throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
4452 }
setRngSeed(ConfigData & config,std::string const & seed)4453 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
4454 if( seed == "time" ) {
4455 config.rngSeed = static_cast<unsigned int>( std::time(0) );
4456 }
4457 else {
4458 std::stringstream ss;
4459 ss << seed;
4460 ss >> config.rngSeed;
4461 if( ss.fail() )
4462 throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
4463 }
4464 }
setVerbosity(ConfigData & config,int level)4465 inline void setVerbosity( ConfigData& config, int level ) {
4466 // !TBD: accept strings?
4467 config.verbosity = static_cast<Verbosity::Level>( level );
4468 }
setShowDurations(ConfigData & config,bool _showDurations)4469 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
4470 config.showDurations = _showDurations
4471 ? ShowDurations::Always
4472 : ShowDurations::Never;
4473 }
loadTestNamesFromFile(ConfigData & config,std::string const & _filename)4474 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
4475 std::ifstream f( _filename.c_str() );
4476 if( !f.is_open() )
4477 throw std::domain_error( "Unable to load input file: " + _filename );
4478
4479 std::string line;
4480 while( std::getline( f, line ) ) {
4481 line = trim(line);
4482 if( !line.empty() && !startsWith( line, "#" ) )
4483 addTestOrTags( config, "\"" + line + "\"," );
4484 }
4485 }
4486
makeCommandLineParser()4487 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4488
4489 using namespace Clara;
4490 CommandLine<ConfigData> cli;
4491
4492 cli.bindProcessName( &ConfigData::processName );
4493
4494 cli["-?"]["-h"]["--help"]
4495 .describe( "display usage information" )
4496 .bind( &ConfigData::showHelp );
4497
4498 cli["-l"]["--list-tests"]
4499 .describe( "list all/matching test cases" )
4500 .bind( &ConfigData::listTests );
4501
4502 cli["-t"]["--list-tags"]
4503 .describe( "list all/matching tags" )
4504 .bind( &ConfigData::listTags );
4505
4506 cli["-s"]["--success"]
4507 .describe( "include successful tests in output" )
4508 .bind( &ConfigData::showSuccessfulTests );
4509
4510 cli["-b"]["--break"]
4511 .describe( "break into debugger on failure" )
4512 .bind( &ConfigData::shouldDebugBreak );
4513
4514 cli["-e"]["--nothrow"]
4515 .describe( "skip exception tests" )
4516 .bind( &ConfigData::noThrow );
4517
4518 cli["-i"]["--invisibles"]
4519 .describe( "show invisibles (tabs, newlines)" )
4520 .bind( &ConfigData::showInvisibles );
4521
4522 cli["-o"]["--out"]
4523 .describe( "output filename" )
4524 .bind( &ConfigData::outputFilename, "filename" );
4525
4526 cli["-r"]["--reporter"]
4527 // .placeholder( "name[:filename]" )
4528 .describe( "reporter to use (defaults to console)" )
4529 .bind( &addReporterName, "name" );
4530
4531 cli["-n"]["--name"]
4532 .describe( "suite name" )
4533 .bind( &ConfigData::name, "name" );
4534
4535 cli["-a"]["--abort"]
4536 .describe( "abort at first failure" )
4537 .bind( &abortAfterFirst );
4538
4539 cli["-x"]["--abortx"]
4540 .describe( "abort after x failures" )
4541 .bind( &abortAfterX, "no. failures" );
4542
4543 cli["-w"]["--warn"]
4544 .describe( "enable warnings" )
4545 .bind( &addWarning, "warning name" );
4546
4547 // - needs updating if reinstated
4548 // cli.into( &setVerbosity )
4549 // .describe( "level of verbosity (0=no output)" )
4550 // .shortOpt( "v")
4551 // .longOpt( "verbosity" )
4552 // .placeholder( "level" );
4553
4554 cli[_]
4555 .describe( "which test or tests to use" )
4556 .bind( &addTestOrTags, "test name, pattern or tags" );
4557
4558 cli["-d"]["--durations"]
4559 .describe( "show test durations" )
4560 .bind( &setShowDurations, "yes/no" );
4561
4562 cli["-f"]["--input-file"]
4563 .describe( "load test names to run from a file" )
4564 .bind( &loadTestNamesFromFile, "filename" );
4565
4566 cli["-#"]["--filenames-as-tags"]
4567 .describe( "adds a tag for the filename" )
4568 .bind( &ConfigData::filenamesAsTags );
4569
4570 // Less common commands which don't have a short form
4571 cli["--list-test-names-only"]
4572 .describe( "list all/matching test cases names only" )
4573 .bind( &ConfigData::listTestNamesOnly );
4574
4575 cli["--list-reporters"]
4576 .describe( "list all reporters" )
4577 .bind( &ConfigData::listReporters );
4578
4579 cli["--order"]
4580 .describe( "test case order (defaults to decl)" )
4581 .bind( &setOrder, "decl|lex|rand" );
4582
4583 cli["--rng-seed"]
4584 .describe( "set a specific seed for random numbers" )
4585 .bind( &setRngSeed, "'time'|number" );
4586
4587 cli["--force-colour"]
4588 .describe( "force colourised output" )
4589 .bind( &ConfigData::forceColour );
4590
4591 return cli;
4592 }
4593
4594 } // end namespace Catch
4595
4596 // #included from: internal/catch_list.hpp
4597 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4598
4599 // #included from: catch_text.h
4600 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4601
4602 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4603
4604 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4605 // #included from: ../external/tbc_text_format.h
4606 // Only use header guard if we are not using an outer namespace
4607 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4608 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4609 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4610 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4611 # endif
4612 # else
4613 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4614 # endif
4615 #endif
4616 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4617 #include <string>
4618 #include <vector>
4619 #include <sstream>
4620
4621 // Use optional outer namespace
4622 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4623 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4624 #endif
4625
4626 namespace Tbc {
4627
4628 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4629 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4630 #else
4631 const unsigned int consoleWidth = 80;
4632 #endif
4633
4634 struct TextAttributes {
TextAttributesCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4635 TextAttributes()
4636 : initialIndent( std::string::npos ),
4637 indent( 0 ),
4638 width( consoleWidth-1 ),
4639 tabChar( '\t' )
4640 {}
4641
setInitialIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4642 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
setIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4643 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
setWidthCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4644 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
setTabCharCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4645 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4646
4647 std::size_t initialIndent; // indent of first line, or npos
4648 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4649 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4650 char tabChar; // If this char is seen the indent is changed to current pos
4651 };
4652
4653 class Text {
4654 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())4655 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4656 : attr( _attr )
4657 {
4658 std::string wrappableChars = " [({.,/|\\-";
4659 std::size_t indent = _attr.initialIndent != std::string::npos
4660 ? _attr.initialIndent
4661 : _attr.indent;
4662 std::string remainder = _str;
4663
4664 while( !remainder.empty() ) {
4665 if( lines.size() >= 1000 ) {
4666 lines.push_back( "... message truncated due to excessive size" );
4667 return;
4668 }
4669 std::size_t tabPos = std::string::npos;
4670 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4671 std::size_t pos = remainder.find_first_of( '\n' );
4672 if( pos <= width ) {
4673 width = pos;
4674 }
4675 pos = remainder.find_last_of( _attr.tabChar, width );
4676 if( pos != std::string::npos ) {
4677 tabPos = pos;
4678 if( remainder[width] == '\n' )
4679 width--;
4680 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4681 }
4682
4683 if( width == remainder.size() ) {
4684 spliceLine( indent, remainder, width );
4685 }
4686 else if( remainder[width] == '\n' ) {
4687 spliceLine( indent, remainder, width );
4688 if( width <= 1 || remainder.size() != 1 )
4689 remainder = remainder.substr( 1 );
4690 indent = _attr.indent;
4691 }
4692 else {
4693 pos = remainder.find_last_of( wrappableChars, width );
4694 if( pos != std::string::npos && pos > 0 ) {
4695 spliceLine( indent, remainder, pos );
4696 if( remainder[0] == ' ' )
4697 remainder = remainder.substr( 1 );
4698 }
4699 else {
4700 spliceLine( indent, remainder, width-1 );
4701 lines.back() += "-";
4702 }
4703 if( lines.size() == 1 )
4704 indent = _attr.indent;
4705 if( tabPos != std::string::npos )
4706 indent += tabPos;
4707 }
4708 }
4709 }
4710
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)4711 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4712 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4713 _remainder = _remainder.substr( _pos );
4714 }
4715
4716 typedef std::vector<std::string>::const_iterator const_iterator;
4717
begin() const4718 const_iterator begin() const { return lines.begin(); }
end() const4719 const_iterator end() const { return lines.end(); }
last() const4720 std::string const& last() const { return lines.back(); }
size() const4721 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const4722 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
toString() const4723 std::string toString() const {
4724 std::ostringstream oss;
4725 oss << *this;
4726 return oss.str();
4727 }
4728
operator <<(std::ostream & _stream,Text const & _text)4729 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4730 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4731 it != itEnd; ++it ) {
4732 if( it != _text.begin() )
4733 _stream << "\n";
4734 _stream << *it;
4735 }
4736 return _stream;
4737 }
4738
4739 private:
4740 std::string str;
4741 TextAttributes attr;
4742 std::vector<std::string> lines;
4743 };
4744
4745 } // end namespace Tbc
4746
4747 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4748 } // end outer namespace
4749 #endif
4750
4751 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4752 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4753
4754 namespace Catch {
4755 using Tbc::Text;
4756 using Tbc::TextAttributes;
4757 }
4758
4759 // #included from: catch_console_colour.hpp
4760 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4761
4762 namespace Catch {
4763
4764 struct Colour {
4765 enum Code {
4766 None = 0,
4767
4768 White,
4769 Red,
4770 Green,
4771 Blue,
4772 Cyan,
4773 Yellow,
4774 Grey,
4775
4776 Bright = 0x10,
4777
4778 BrightRed = Bright | Red,
4779 BrightGreen = Bright | Green,
4780 LightGrey = Bright | Grey,
4781 BrightWhite = Bright | White,
4782
4783 // By intention
4784 FileName = LightGrey,
4785 Warning = Yellow,
4786 ResultError = BrightRed,
4787 ResultSuccess = BrightGreen,
4788 ResultExpectedFailure = Warning,
4789
4790 Error = BrightRed,
4791 Success = Green,
4792
4793 OriginalExpression = Cyan,
4794 ReconstructedExpression = Yellow,
4795
4796 SecondaryText = LightGrey,
4797 Headers = White
4798 };
4799
4800 // Use constructed object for RAII guard
4801 Colour( Code _colourCode );
4802 Colour( Colour const& other );
4803 ~Colour();
4804
4805 // Use static method for one-shot changes
4806 static void use( Code _colourCode );
4807
4808 private:
4809 bool m_moved;
4810 };
4811
operator <<(std::ostream & os,Colour const &)4812 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
4813
4814 } // end namespace Catch
4815
4816 // #included from: catch_interfaces_reporter.h
4817 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
4818
4819 #include <string>
4820 #include <ostream>
4821 #include <map>
4822 #include <assert.h>
4823
4824 namespace Catch
4825 {
4826 struct ReporterConfig {
ReporterConfigCatch::ReporterConfig4827 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
4828 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
4829
ReporterConfigCatch::ReporterConfig4830 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
4831 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
4832
streamCatch::ReporterConfig4833 std::ostream& stream() const { return *m_stream; }
fullConfigCatch::ReporterConfig4834 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
4835
4836 private:
4837 std::ostream* m_stream;
4838 Ptr<IConfig const> m_fullConfig;
4839 };
4840
4841 struct ReporterPreferences {
ReporterPreferencesCatch::ReporterPreferences4842 ReporterPreferences()
4843 : shouldRedirectStdOut( false )
4844 {}
4845
4846 bool shouldRedirectStdOut;
4847 };
4848
4849 template<typename T>
4850 struct LazyStat : Option<T> {
LazyStatCatch::LazyStat4851 LazyStat() : used( false ) {}
operator =Catch::LazyStat4852 LazyStat& operator=( T const& _value ) {
4853 Option<T>::operator=( _value );
4854 used = false;
4855 return *this;
4856 }
resetCatch::LazyStat4857 void reset() {
4858 Option<T>::reset();
4859 used = false;
4860 }
4861 bool used;
4862 };
4863
4864 struct TestRunInfo {
TestRunInfoCatch::TestRunInfo4865 TestRunInfo( std::string const& _name ) : name( _name ) {}
4866 std::string name;
4867 };
4868 struct GroupInfo {
GroupInfoCatch::GroupInfo4869 GroupInfo( std::string const& _name,
4870 std::size_t _groupIndex,
4871 std::size_t _groupsCount )
4872 : name( _name ),
4873 groupIndex( _groupIndex ),
4874 groupsCounts( _groupsCount )
4875 {}
4876
4877 std::string name;
4878 std::size_t groupIndex;
4879 std::size_t groupsCounts;
4880 };
4881
4882 struct AssertionStats {
AssertionStatsCatch::AssertionStats4883 AssertionStats( AssertionResult const& _assertionResult,
4884 std::vector<MessageInfo> const& _infoMessages,
4885 Totals const& _totals )
4886 : assertionResult( _assertionResult ),
4887 infoMessages( _infoMessages ),
4888 totals( _totals )
4889 {
4890 if( assertionResult.hasMessage() ) {
4891 // Copy message into messages list.
4892 // !TBD This should have been done earlier, somewhere
4893 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
4894 builder << assertionResult.getMessage();
4895 builder.m_info.message = builder.m_stream.str();
4896
4897 infoMessages.push_back( builder.m_info );
4898 }
4899 }
4900 virtual ~AssertionStats();
4901
4902 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4903 AssertionStats( AssertionStats const& ) = default;
4904 AssertionStats( AssertionStats && ) = default;
4905 AssertionStats& operator = ( AssertionStats const& ) = default;
4906 AssertionStats& operator = ( AssertionStats && ) = default;
4907 # endif
4908
4909 AssertionResult assertionResult;
4910 std::vector<MessageInfo> infoMessages;
4911 Totals totals;
4912 };
4913
4914 struct SectionStats {
SectionStatsCatch::SectionStats4915 SectionStats( SectionInfo const& _sectionInfo,
4916 Counts const& _assertions,
4917 double _durationInSeconds,
4918 bool _missingAssertions )
4919 : sectionInfo( _sectionInfo ),
4920 assertions( _assertions ),
4921 durationInSeconds( _durationInSeconds ),
4922 missingAssertions( _missingAssertions )
4923 {}
4924 virtual ~SectionStats();
4925 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4926 SectionStats( SectionStats const& ) = default;
4927 SectionStats( SectionStats && ) = default;
4928 SectionStats& operator = ( SectionStats const& ) = default;
4929 SectionStats& operator = ( SectionStats && ) = default;
4930 # endif
4931
4932 SectionInfo sectionInfo;
4933 Counts assertions;
4934 double durationInSeconds;
4935 bool missingAssertions;
4936 };
4937
4938 struct TestCaseStats {
TestCaseStatsCatch::TestCaseStats4939 TestCaseStats( TestCaseInfo const& _testInfo,
4940 Totals const& _totals,
4941 std::string const& _stdOut,
4942 std::string const& _stdErr,
4943 bool _aborting )
4944 : testInfo( _testInfo ),
4945 totals( _totals ),
4946 stdOut( _stdOut ),
4947 stdErr( _stdErr ),
4948 aborting( _aborting )
4949 {}
4950 virtual ~TestCaseStats();
4951
4952 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4953 TestCaseStats( TestCaseStats const& ) = default;
4954 TestCaseStats( TestCaseStats && ) = default;
4955 TestCaseStats& operator = ( TestCaseStats const& ) = default;
4956 TestCaseStats& operator = ( TestCaseStats && ) = default;
4957 # endif
4958
4959 TestCaseInfo testInfo;
4960 Totals totals;
4961 std::string stdOut;
4962 std::string stdErr;
4963 bool aborting;
4964 };
4965
4966 struct TestGroupStats {
TestGroupStatsCatch::TestGroupStats4967 TestGroupStats( GroupInfo const& _groupInfo,
4968 Totals const& _totals,
4969 bool _aborting )
4970 : groupInfo( _groupInfo ),
4971 totals( _totals ),
4972 aborting( _aborting )
4973 {}
TestGroupStatsCatch::TestGroupStats4974 TestGroupStats( GroupInfo const& _groupInfo )
4975 : groupInfo( _groupInfo ),
4976 aborting( false )
4977 {}
4978 virtual ~TestGroupStats();
4979
4980 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4981 TestGroupStats( TestGroupStats const& ) = default;
4982 TestGroupStats( TestGroupStats && ) = default;
4983 TestGroupStats& operator = ( TestGroupStats const& ) = default;
4984 TestGroupStats& operator = ( TestGroupStats && ) = default;
4985 # endif
4986
4987 GroupInfo groupInfo;
4988 Totals totals;
4989 bool aborting;
4990 };
4991
4992 struct TestRunStats {
TestRunStatsCatch::TestRunStats4993 TestRunStats( TestRunInfo const& _runInfo,
4994 Totals const& _totals,
4995 bool _aborting )
4996 : runInfo( _runInfo ),
4997 totals( _totals ),
4998 aborting( _aborting )
4999 {}
5000 virtual ~TestRunStats();
5001
5002 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestRunStatsCatch::TestRunStats5003 TestRunStats( TestRunStats const& _other )
5004 : runInfo( _other.runInfo ),
5005 totals( _other.totals ),
5006 aborting( _other.aborting )
5007 {}
5008 # else
5009 TestRunStats( TestRunStats const& ) = default;
5010 TestRunStats( TestRunStats && ) = default;
5011 TestRunStats& operator = ( TestRunStats const& ) = default;
5012 TestRunStats& operator = ( TestRunStats && ) = default;
5013 # endif
5014
5015 TestRunInfo runInfo;
5016 Totals totals;
5017 bool aborting;
5018 };
5019
5020 struct IStreamingReporter : IShared {
5021 virtual ~IStreamingReporter();
5022
5023 // Implementing class must also provide the following static method:
5024 // static std::string getDescription();
5025
5026 virtual ReporterPreferences getPreferences() const = 0;
5027
5028 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5029
5030 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5031 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5032
5033 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5034 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5035
5036 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5037
5038 // The return value indicates if the messages buffer should be cleared:
5039 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
5040
5041 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5042 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5043 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5044 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
5045
5046 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
5047 };
5048
5049 struct IReporterFactory : IShared {
5050 virtual ~IReporterFactory();
5051 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5052 virtual std::string getDescription() const = 0;
5053 };
5054
5055 struct IReporterRegistry {
5056 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5057 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5058
5059 virtual ~IReporterRegistry();
5060 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
5061 virtual FactoryMap const& getFactories() const = 0;
5062 virtual Listeners const& getListeners() const = 0;
5063 };
5064
5065 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5066
5067 }
5068
5069 #include <limits>
5070 #include <algorithm>
5071
5072 namespace Catch {
5073
listTests(Config const & config)5074 inline std::size_t listTests( Config const& config ) {
5075
5076 TestSpec testSpec = config.testSpec();
5077 if( config.testSpec().hasFilters() )
5078 Catch::cout() << "Matching test cases:\n";
5079 else {
5080 Catch::cout() << "All available test cases:\n";
5081 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5082 }
5083
5084 std::size_t matchedTests = 0;
5085 TextAttributes nameAttr, tagsAttr;
5086 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5087 tagsAttr.setIndent( 6 );
5088
5089 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5090 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5091 it != itEnd;
5092 ++it ) {
5093 matchedTests++;
5094 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5095 Colour::Code colour = testCaseInfo.isHidden()
5096 ? Colour::SecondaryText
5097 : Colour::None;
5098 Colour colourGuard( colour );
5099
5100 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
5101 if( !testCaseInfo.tags.empty() )
5102 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
5103 }
5104
5105 if( !config.testSpec().hasFilters() )
5106 Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
5107 else
5108 Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
5109 return matchedTests;
5110 }
5111
listTestsNamesOnly(Config const & config)5112 inline std::size_t listTestsNamesOnly( Config const& config ) {
5113 TestSpec testSpec = config.testSpec();
5114 if( !config.testSpec().hasFilters() )
5115 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5116 std::size_t matchedTests = 0;
5117 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5118 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5119 it != itEnd;
5120 ++it ) {
5121 matchedTests++;
5122 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5123 Catch::cout() << testCaseInfo.name << std::endl;
5124 }
5125 return matchedTests;
5126 }
5127
5128 struct TagInfo {
TagInfoCatch::TagInfo5129 TagInfo() : count ( 0 ) {}
addCatch::TagInfo5130 void add( std::string const& spelling ) {
5131 ++count;
5132 spellings.insert( spelling );
5133 }
allCatch::TagInfo5134 std::string all() const {
5135 std::string out;
5136 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5137 it != itEnd;
5138 ++it )
5139 out += "[" + *it + "]";
5140 return out;
5141 }
5142 std::set<std::string> spellings;
5143 std::size_t count;
5144 };
5145
listTags(Config const & config)5146 inline std::size_t listTags( Config const& config ) {
5147 TestSpec testSpec = config.testSpec();
5148 if( config.testSpec().hasFilters() )
5149 Catch::cout() << "Tags for matching test cases:\n";
5150 else {
5151 Catch::cout() << "All available tags:\n";
5152 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5153 }
5154
5155 std::map<std::string, TagInfo> tagCounts;
5156
5157 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5158 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5159 it != itEnd;
5160 ++it ) {
5161 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5162 tagItEnd = it->getTestCaseInfo().tags.end();
5163 tagIt != tagItEnd;
5164 ++tagIt ) {
5165 std::string tagName = *tagIt;
5166 std::string lcaseTagName = toLower( tagName );
5167 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
5168 if( countIt == tagCounts.end() )
5169 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5170 countIt->second.add( tagName );
5171 }
5172 }
5173
5174 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5175 countItEnd = tagCounts.end();
5176 countIt != countItEnd;
5177 ++countIt ) {
5178 std::ostringstream oss;
5179 oss << " " << std::setw(2) << countIt->second.count << " ";
5180 Text wrapper( countIt->second.all(), TextAttributes()
5181 .setInitialIndent( 0 )
5182 .setIndent( oss.str().size() )
5183 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
5184 Catch::cout() << oss.str() << wrapper << "\n";
5185 }
5186 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
5187 return tagCounts.size();
5188 }
5189
listReporters(Config const &)5190 inline std::size_t listReporters( Config const& /*config*/ ) {
5191 Catch::cout() << "Available reporters:\n";
5192 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
5193 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5194 std::size_t maxNameLen = 0;
5195 for(it = itBegin; it != itEnd; ++it )
5196 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5197
5198 for(it = itBegin; it != itEnd; ++it ) {
5199 Text wrapper( it->second->getDescription(), TextAttributes()
5200 .setInitialIndent( 0 )
5201 .setIndent( 7+maxNameLen )
5202 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
5203 Catch::cout() << " "
5204 << it->first
5205 << ":"
5206 << std::string( maxNameLen - it->first.size() + 2, ' ' )
5207 << wrapper << "\n";
5208 }
5209 Catch::cout() << std::endl;
5210 return factories.size();
5211 }
5212
list(Config const & config)5213 inline Option<std::size_t> list( Config const& config ) {
5214 Option<std::size_t> listedCount;
5215 if( config.listTests() )
5216 listedCount = listedCount.valueOr(0) + listTests( config );
5217 if( config.listTestNamesOnly() )
5218 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
5219 if( config.listTags() )
5220 listedCount = listedCount.valueOr(0) + listTags( config );
5221 if( config.listReporters() )
5222 listedCount = listedCount.valueOr(0) + listReporters( config );
5223 return listedCount;
5224 }
5225
5226 } // end namespace Catch
5227
5228 // #included from: internal/catch_run_context.hpp
5229 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
5230
5231 // #included from: catch_test_case_tracker.hpp
5232 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
5233
5234 #include <map>
5235 #include <string>
5236 #include <assert.h>
5237 #include <vector>
5238
5239 namespace Catch {
5240 namespace TestCaseTracking {
5241
5242 struct ITracker : SharedImpl<> {
5243 virtual ~ITracker();
5244
5245 // static queries
5246 virtual std::string name() const = 0;
5247
5248 // dynamic queries
5249 virtual bool isComplete() const = 0; // Successfully completed or failed
5250 virtual bool isSuccessfullyCompleted() const = 0;
5251 virtual bool isOpen() const = 0; // Started but not complete
5252 virtual bool hasChildren() const = 0;
5253
5254 virtual ITracker& parent() = 0;
5255
5256 // actions
5257 virtual void close() = 0; // Successfully complete
5258 virtual void fail() = 0;
5259 virtual void markAsNeedingAnotherRun() = 0;
5260
5261 virtual void addChild( Ptr<ITracker> const& child ) = 0;
5262 virtual ITracker* findChild( std::string const& name ) = 0;
5263 virtual void openChild() = 0;
5264 };
5265
5266 class TrackerContext {
5267
5268 enum RunState {
5269 NotStarted,
5270 Executing,
5271 CompletedCycle
5272 };
5273
5274 Ptr<ITracker> m_rootTracker;
5275 ITracker* m_currentTracker;
5276 RunState m_runState;
5277
5278 public:
5279
instance()5280 static TrackerContext& instance() {
5281 static TrackerContext s_instance;
5282 return s_instance;
5283 }
5284
TrackerContext()5285 TrackerContext()
5286 : m_currentTracker( CATCH_NULL ),
5287 m_runState( NotStarted )
5288 {}
5289
5290 ITracker& startRun();
5291
endRun()5292 void endRun() {
5293 m_rootTracker.reset();
5294 m_currentTracker = CATCH_NULL;
5295 m_runState = NotStarted;
5296 }
5297
startCycle()5298 void startCycle() {
5299 m_currentTracker = m_rootTracker.get();
5300 m_runState = Executing;
5301 }
completeCycle()5302 void completeCycle() {
5303 m_runState = CompletedCycle;
5304 }
5305
completedCycle() const5306 bool completedCycle() const {
5307 return m_runState == CompletedCycle;
5308 }
currentTracker()5309 ITracker& currentTracker() {
5310 return *m_currentTracker;
5311 }
setCurrentTracker(ITracker * tracker)5312 void setCurrentTracker( ITracker* tracker ) {
5313 m_currentTracker = tracker;
5314 }
5315 };
5316
5317 class TrackerBase : public ITracker {
5318 protected:
5319 enum CycleState {
5320 NotStarted,
5321 Executing,
5322 ExecutingChildren,
5323 NeedsAnotherRun,
5324 CompletedSuccessfully,
5325 Failed
5326 };
5327 class TrackerHasName {
5328 std::string m_name;
5329 public:
TrackerHasName(std::string const & name)5330 TrackerHasName( std::string const& name ) : m_name( name ) {}
operator ()(Ptr<ITracker> const & tracker)5331 bool operator ()( Ptr<ITracker> const& tracker ) {
5332 return tracker->name() == m_name;
5333 }
5334 };
5335 typedef std::vector<Ptr<ITracker> > Children;
5336 std::string m_name;
5337 TrackerContext& m_ctx;
5338 ITracker* m_parent;
5339 Children m_children;
5340 CycleState m_runState;
5341 public:
TrackerBase(std::string const & name,TrackerContext & ctx,ITracker * parent)5342 TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent )
5343 : m_name( name ),
5344 m_ctx( ctx ),
5345 m_parent( parent ),
5346 m_runState( NotStarted )
5347 {}
5348 virtual ~TrackerBase();
5349
name() const5350 virtual std::string name() const CATCH_OVERRIDE {
5351 return m_name;
5352 }
isComplete() const5353 virtual bool isComplete() const CATCH_OVERRIDE {
5354 return m_runState == CompletedSuccessfully || m_runState == Failed;
5355 }
isSuccessfullyCompleted() const5356 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
5357 return m_runState == CompletedSuccessfully;
5358 }
isOpen() const5359 virtual bool isOpen() const CATCH_OVERRIDE {
5360 return m_runState != NotStarted && !isComplete();
5361 }
hasChildren() const5362 virtual bool hasChildren() const CATCH_OVERRIDE {
5363 return !m_children.empty();
5364 }
5365
addChild(Ptr<ITracker> const & child)5366 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
5367 m_children.push_back( child );
5368 }
5369
findChild(std::string const & name)5370 virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE {
5371 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) );
5372 return( it != m_children.end() )
5373 ? it->get()
5374 : CATCH_NULL;
5375 }
parent()5376 virtual ITracker& parent() CATCH_OVERRIDE {
5377 assert( m_parent ); // Should always be non-null except for root
5378 return *m_parent;
5379 }
5380
openChild()5381 virtual void openChild() CATCH_OVERRIDE {
5382 if( m_runState != ExecutingChildren ) {
5383 m_runState = ExecutingChildren;
5384 if( m_parent )
5385 m_parent->openChild();
5386 }
5387 }
open()5388 void open() {
5389 m_runState = Executing;
5390 moveToThis();
5391 if( m_parent )
5392 m_parent->openChild();
5393 }
5394
close()5395 virtual void close() CATCH_OVERRIDE {
5396
5397 // Close any still open children (e.g. generators)
5398 while( &m_ctx.currentTracker() != this )
5399 m_ctx.currentTracker().close();
5400
5401 switch( m_runState ) {
5402 case NotStarted:
5403 case CompletedSuccessfully:
5404 case Failed:
5405 throw std::logic_error( "Illogical state" );
5406
5407 case NeedsAnotherRun:
5408 break;;
5409
5410 case Executing:
5411 m_runState = CompletedSuccessfully;
5412 break;
5413 case ExecutingChildren:
5414 if( m_children.empty() || m_children.back()->isComplete() )
5415 m_runState = CompletedSuccessfully;
5416 break;
5417
5418 default:
5419 throw std::logic_error( "Unexpected state" );
5420 }
5421 moveToParent();
5422 m_ctx.completeCycle();
5423 }
fail()5424 virtual void fail() CATCH_OVERRIDE {
5425 m_runState = Failed;
5426 if( m_parent )
5427 m_parent->markAsNeedingAnotherRun();
5428 moveToParent();
5429 m_ctx.completeCycle();
5430 }
markAsNeedingAnotherRun()5431 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
5432 m_runState = NeedsAnotherRun;
5433 }
5434 private:
moveToParent()5435 void moveToParent() {
5436 assert( m_parent );
5437 m_ctx.setCurrentTracker( m_parent );
5438 }
moveToThis()5439 void moveToThis() {
5440 m_ctx.setCurrentTracker( this );
5441 }
5442 };
5443
5444 class SectionTracker : public TrackerBase {
5445 public:
SectionTracker(std::string const & name,TrackerContext & ctx,ITracker * parent)5446 SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent )
5447 : TrackerBase( name, ctx, parent )
5448 {}
5449 virtual ~SectionTracker();
5450
acquire(TrackerContext & ctx,std::string const & name)5451 static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
5452 SectionTracker* section = CATCH_NULL;
5453
5454 ITracker& currentTracker = ctx.currentTracker();
5455 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5456 section = dynamic_cast<SectionTracker*>( childTracker );
5457 assert( section );
5458 }
5459 else {
5460 section = new SectionTracker( name, ctx, ¤tTracker );
5461 currentTracker.addChild( section );
5462 }
5463 if( !ctx.completedCycle() && !section->isComplete() ) {
5464
5465 section->open();
5466 }
5467 return *section;
5468 }
5469 };
5470
5471 class IndexTracker : public TrackerBase {
5472 int m_size;
5473 int m_index;
5474 public:
IndexTracker(std::string const & name,TrackerContext & ctx,ITracker * parent,int size)5475 IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size )
5476 : TrackerBase( name, ctx, parent ),
5477 m_size( size ),
5478 m_index( -1 )
5479 {}
5480 virtual ~IndexTracker();
5481
acquire(TrackerContext & ctx,std::string const & name,int size)5482 static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
5483 IndexTracker* tracker = CATCH_NULL;
5484
5485 ITracker& currentTracker = ctx.currentTracker();
5486 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5487 tracker = dynamic_cast<IndexTracker*>( childTracker );
5488 assert( tracker );
5489 }
5490 else {
5491 tracker = new IndexTracker( name, ctx, ¤tTracker, size );
5492 currentTracker.addChild( tracker );
5493 }
5494
5495 if( !ctx.completedCycle() && !tracker->isComplete() ) {
5496 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
5497 tracker->moveNext();
5498 tracker->open();
5499 }
5500
5501 return *tracker;
5502 }
5503
index() const5504 int index() const { return m_index; }
5505
moveNext()5506 void moveNext() {
5507 m_index++;
5508 m_children.clear();
5509 }
5510
close()5511 virtual void close() CATCH_OVERRIDE {
5512 TrackerBase::close();
5513 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
5514 m_runState = Executing;
5515 }
5516 };
5517
startRun()5518 inline ITracker& TrackerContext::startRun() {
5519 m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL );
5520 m_currentTracker = CATCH_NULL;
5521 m_runState = Executing;
5522 return *m_rootTracker;
5523 }
5524
5525 } // namespace TestCaseTracking
5526
5527 using TestCaseTracking::ITracker;
5528 using TestCaseTracking::TrackerContext;
5529 using TestCaseTracking::SectionTracker;
5530 using TestCaseTracking::IndexTracker;
5531
5532 } // namespace Catch
5533
5534 // #included from: catch_fatal_condition.hpp
5535 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
5536
5537 namespace Catch {
5538
5539 // Report the error condition then exit the process
fatal(std::string const & message,int exitCode)5540 inline void fatal( std::string const& message, int exitCode ) {
5541 IContext& context = Catch::getCurrentContext();
5542 IResultCapture* resultCapture = context.getResultCapture();
5543 resultCapture->handleFatalErrorCondition( message );
5544
5545 if( Catch::alwaysTrue() ) // avoids "no return" warnings
5546 exit( exitCode );
5547 }
5548
5549 } // namespace Catch
5550
5551 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
5552
5553 namespace Catch {
5554
5555 struct FatalConditionHandler {
resetCatch::FatalConditionHandler5556 void reset() {}
5557 };
5558
5559 } // namespace Catch
5560
5561 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
5562
5563 #include <signal.h>
5564
5565 namespace Catch {
5566
5567 struct SignalDefs { int id; const char* name; };
5568 extern SignalDefs signalDefs[];
5569 SignalDefs signalDefs[] = {
5570 { SIGINT, "SIGINT - Terminal interrupt signal" },
5571 { SIGILL, "SIGILL - Illegal instruction signal" },
5572 { SIGFPE, "SIGFPE - Floating point error signal" },
5573 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
5574 { SIGTERM, "SIGTERM - Termination request signal" },
5575 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
5576 };
5577
5578 struct FatalConditionHandler {
5579
handleSignalCatch::FatalConditionHandler5580 static void handleSignal( int sig ) {
5581 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5582 if( sig == signalDefs[i].id )
5583 fatal( signalDefs[i].name, -sig );
5584 fatal( "<unknown signal>", -sig );
5585 }
5586
FatalConditionHandlerCatch::FatalConditionHandler5587 FatalConditionHandler() : m_isSet( true ) {
5588 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5589 signal( signalDefs[i].id, handleSignal );
5590 }
~FatalConditionHandlerCatch::FatalConditionHandler5591 ~FatalConditionHandler() {
5592 reset();
5593 }
resetCatch::FatalConditionHandler5594 void reset() {
5595 if( m_isSet ) {
5596 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5597 signal( signalDefs[i].id, SIG_DFL );
5598 m_isSet = false;
5599 }
5600 }
5601
5602 bool m_isSet;
5603 };
5604
5605 } // namespace Catch
5606
5607 #endif // not Windows
5608
5609 #include <set>
5610 #include <string>
5611
5612 namespace Catch {
5613
5614 class StreamRedirect {
5615
5616 public:
StreamRedirect(std::ostream & stream,std::string & targetString)5617 StreamRedirect( std::ostream& stream, std::string& targetString )
5618 : m_stream( stream ),
5619 m_prevBuf( stream.rdbuf() ),
5620 m_targetString( targetString )
5621 {
5622 stream.rdbuf( m_oss.rdbuf() );
5623 }
5624
~StreamRedirect()5625 ~StreamRedirect() {
5626 m_targetString += m_oss.str();
5627 m_stream.rdbuf( m_prevBuf );
5628 }
5629
5630 private:
5631 std::ostream& m_stream;
5632 std::streambuf* m_prevBuf;
5633 std::ostringstream m_oss;
5634 std::string& m_targetString;
5635 };
5636
5637 ///////////////////////////////////////////////////////////////////////////
5638
5639 class RunContext : public IResultCapture, public IRunner {
5640
5641 RunContext( RunContext const& );
5642 void operator =( RunContext const& );
5643
5644 public:
5645
RunContext(Ptr<IConfig const> const & _config,Ptr<IStreamingReporter> const & reporter)5646 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
5647 : m_runInfo( _config->name() ),
5648 m_context( getCurrentMutableContext() ),
5649 m_activeTestCase( CATCH_NULL ),
5650 m_config( _config ),
5651 m_reporter( reporter )
5652 {
5653 m_context.setRunner( this );
5654 m_context.setConfig( m_config );
5655 m_context.setResultCapture( this );
5656 m_reporter->testRunStarting( m_runInfo );
5657 }
5658
~RunContext()5659 virtual ~RunContext() {
5660 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
5661 }
5662
testGroupStarting(std::string const & testSpec,std::size_t groupIndex,std::size_t groupsCount)5663 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
5664 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
5665 }
testGroupEnded(std::string const & testSpec,Totals const & totals,std::size_t groupIndex,std::size_t groupsCount)5666 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
5667 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
5668 }
5669
runTest(TestCase const & testCase)5670 Totals runTest( TestCase const& testCase ) {
5671 Totals prevTotals = m_totals;
5672
5673 std::string redirectedCout;
5674 std::string redirectedCerr;
5675
5676 TestCaseInfo testInfo = testCase.getTestCaseInfo();
5677
5678 m_reporter->testCaseStarting( testInfo );
5679
5680 m_activeTestCase = &testCase;
5681
5682 do {
5683 m_trackerContext.startRun();
5684 do {
5685 m_trackerContext.startCycle();
5686 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name );
5687 runCurrentTest( redirectedCout, redirectedCerr );
5688 }
5689 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
5690 }
5691 // !TBD: deprecated - this will be replaced by indexed trackers
5692 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
5693
5694 Totals deltaTotals = m_totals.delta( prevTotals );
5695 m_totals.testCases += deltaTotals.testCases;
5696 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5697 deltaTotals,
5698 redirectedCout,
5699 redirectedCerr,
5700 aborting() ) );
5701
5702 m_activeTestCase = CATCH_NULL;
5703 m_testCaseTracker = CATCH_NULL;
5704
5705 return deltaTotals;
5706 }
5707
config() const5708 Ptr<IConfig const> config() const {
5709 return m_config;
5710 }
5711
5712 private: // IResultCapture
5713
assertionEnded(AssertionResult const & result)5714 virtual void assertionEnded( AssertionResult const& result ) {
5715 if( result.getResultType() == ResultWas::Ok ) {
5716 m_totals.assertions.passed++;
5717 }
5718 else if( !result.isOk() ) {
5719 m_totals.assertions.failed++;
5720 }
5721
5722 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5723 m_messages.clear();
5724
5725 // Reset working state
5726 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
5727 m_lastResult = result;
5728 }
5729
sectionStarted(SectionInfo const & sectionInfo,Counts & assertions)5730 virtual bool sectionStarted (
5731 SectionInfo const& sectionInfo,
5732 Counts& assertions
5733 )
5734 {
5735 std::ostringstream oss;
5736 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
5737
5738 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() );
5739 if( !sectionTracker.isOpen() )
5740 return false;
5741 m_activeSections.push_back( §ionTracker );
5742
5743 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
5744
5745 m_reporter->sectionStarting( sectionInfo );
5746
5747 assertions = m_totals.assertions;
5748
5749 return true;
5750 }
testForMissingAssertions(Counts & assertions)5751 bool testForMissingAssertions( Counts& assertions ) {
5752 if( assertions.total() != 0 )
5753 return false;
5754 if( !m_config->warnAboutMissingAssertions() )
5755 return false;
5756 if( m_trackerContext.currentTracker().hasChildren() )
5757 return false;
5758 m_totals.assertions.failed++;
5759 assertions.failed++;
5760 return true;
5761 }
5762
sectionEnded(SectionEndInfo const & endInfo)5763 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
5764 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
5765 bool missingAssertions = testForMissingAssertions( assertions );
5766
5767 if( !m_activeSections.empty() ) {
5768 m_activeSections.back()->close();
5769 m_activeSections.pop_back();
5770 }
5771
5772 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
5773 m_messages.clear();
5774 }
5775
sectionEndedEarly(SectionEndInfo const & endInfo)5776 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
5777 if( m_unfinishedSections.empty() )
5778 m_activeSections.back()->fail();
5779 else
5780 m_activeSections.back()->close();
5781 m_activeSections.pop_back();
5782
5783 m_unfinishedSections.push_back( endInfo );
5784 }
5785
pushScopedMessage(MessageInfo const & message)5786 virtual void pushScopedMessage( MessageInfo const& message ) {
5787 m_messages.push_back( message );
5788 }
5789
popScopedMessage(MessageInfo const & message)5790 virtual void popScopedMessage( MessageInfo const& message ) {
5791 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
5792 }
5793
getCurrentTestName() const5794 virtual std::string getCurrentTestName() const {
5795 return m_activeTestCase
5796 ? m_activeTestCase->getTestCaseInfo().name
5797 : "";
5798 }
5799
getLastResult() const5800 virtual const AssertionResult* getLastResult() const {
5801 return &m_lastResult;
5802 }
5803
handleFatalErrorCondition(std::string const & message)5804 virtual void handleFatalErrorCondition( std::string const& message ) {
5805 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
5806 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
5807 resultBuilder << message;
5808 resultBuilder.captureExpression();
5809
5810 handleUnfinishedSections();
5811
5812 // Recreate section for test case (as we will lose the one that was in scope)
5813 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5814 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5815
5816 Counts assertions;
5817 assertions.failed = 1;
5818 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
5819 m_reporter->sectionEnded( testCaseSectionStats );
5820
5821 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
5822
5823 Totals deltaTotals;
5824 deltaTotals.testCases.failed = 1;
5825 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5826 deltaTotals,
5827 "",
5828 "",
5829 false ) );
5830 m_totals.testCases.failed++;
5831 testGroupEnded( "", m_totals, 1, 1 );
5832 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
5833 }
5834
5835 public:
5836 // !TBD We need to do this another way!
aborting() const5837 bool aborting() const {
5838 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
5839 }
5840
5841 private:
5842
runCurrentTest(std::string & redirectedCout,std::string & redirectedCerr)5843 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
5844 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5845 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5846 m_reporter->sectionStarting( testCaseSection );
5847 Counts prevAssertions = m_totals.assertions;
5848 double duration = 0;
5849 try {
5850 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
5851
5852 seedRng( *m_config );
5853
5854 Timer timer;
5855 timer.start();
5856 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
5857 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
5858 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
5859 invokeActiveTestCase();
5860 }
5861 else {
5862 invokeActiveTestCase();
5863 }
5864 duration = timer.getElapsedSeconds();
5865 }
5866 catch( TestFailureException& ) {
5867 // This just means the test was aborted due to failure
5868 }
5869 catch(...) {
5870 makeUnexpectedResultBuilder().useActiveException();
5871 }
5872 m_testCaseTracker->close();
5873 handleUnfinishedSections();
5874 m_messages.clear();
5875
5876 Counts assertions = m_totals.assertions - prevAssertions;
5877 bool missingAssertions = testForMissingAssertions( assertions );
5878
5879 if( testCaseInfo.okToFail() ) {
5880 std::swap( assertions.failedButOk, assertions.failed );
5881 m_totals.assertions.failed -= assertions.failedButOk;
5882 m_totals.assertions.failedButOk += assertions.failedButOk;
5883 }
5884
5885 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
5886 m_reporter->sectionEnded( testCaseSectionStats );
5887 }
5888
invokeActiveTestCase()5889 void invokeActiveTestCase() {
5890 FatalConditionHandler fatalConditionHandler; // Handle signals
5891 m_activeTestCase->invoke();
5892 fatalConditionHandler.reset();
5893 }
5894
5895 private:
5896
makeUnexpectedResultBuilder() const5897 ResultBuilder makeUnexpectedResultBuilder() const {
5898 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
5899 m_lastAssertionInfo.lineInfo,
5900 m_lastAssertionInfo.capturedExpression.c_str(),
5901 m_lastAssertionInfo.resultDisposition );
5902 }
5903
handleUnfinishedSections()5904 void handleUnfinishedSections() {
5905 // If sections ended prematurely due to an exception we stored their
5906 // infos here so we can tear them down outside the unwind process.
5907 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
5908 itEnd = m_unfinishedSections.rend();
5909 it != itEnd;
5910 ++it )
5911 sectionEnded( *it );
5912 m_unfinishedSections.clear();
5913 }
5914
5915 TestRunInfo m_runInfo;
5916 IMutableContext& m_context;
5917 TestCase const* m_activeTestCase;
5918 ITracker* m_testCaseTracker;
5919 ITracker* m_currentSectionTracker;
5920 AssertionResult m_lastResult;
5921
5922 Ptr<IConfig const> m_config;
5923 Totals m_totals;
5924 Ptr<IStreamingReporter> m_reporter;
5925 std::vector<MessageInfo> m_messages;
5926 AssertionInfo m_lastAssertionInfo;
5927 std::vector<SectionEndInfo> m_unfinishedSections;
5928 std::vector<ITracker*> m_activeSections;
5929 TrackerContext m_trackerContext;
5930 };
5931
getResultCapture()5932 IResultCapture& getResultCapture() {
5933 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
5934 return *capture;
5935 else
5936 throw std::logic_error( "No result capture instance" );
5937 }
5938
5939 } // end namespace Catch
5940
5941 // #included from: internal/catch_version.h
5942 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
5943
5944 namespace Catch {
5945
5946 // Versioning information
5947 struct Version {
5948 Version( unsigned int _majorVersion,
5949 unsigned int _minorVersion,
5950 unsigned int _patchNumber,
5951 std::string const& _branchName,
5952 unsigned int _buildNumber );
5953
5954 unsigned int const majorVersion;
5955 unsigned int const minorVersion;
5956 unsigned int const patchNumber;
5957
5958 // buildNumber is only used if branchName is not null
5959 std::string const branchName;
5960 unsigned int const buildNumber;
5961
5962 friend std::ostream& operator << ( std::ostream& os, Version const& version );
5963
5964 private:
5965 void operator=( Version const& );
5966 };
5967
5968 extern Version libraryVersion;
5969 }
5970
5971 #include <fstream>
5972 #include <stdlib.h>
5973 #include <limits>
5974
5975 namespace Catch {
5976
createReporter(std::string const & reporterName,Ptr<Config> const & config)5977 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
5978 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
5979 if( !reporter ) {
5980 std::ostringstream oss;
5981 oss << "No reporter registered with name: '" << reporterName << "'";
5982 throw std::domain_error( oss.str() );
5983 }
5984 return reporter;
5985 }
5986
makeReporter(Ptr<Config> const & config)5987 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
5988 std::vector<std::string> reporters = config->getReporterNames();
5989 if( reporters.empty() )
5990 reporters.push_back( "console" );
5991
5992 Ptr<IStreamingReporter> reporter;
5993 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
5994 it != itEnd;
5995 ++it )
5996 reporter = addReporter( reporter, createReporter( *it, config ) );
5997 return reporter;
5998 }
addListeners(Ptr<IConfig const> const & config,Ptr<IStreamingReporter> reporters)5999 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
6000 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6001 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6002 it != itEnd;
6003 ++it )
6004 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6005 return reporters;
6006 }
6007
runTests(Ptr<Config> const & config)6008 Totals runTests( Ptr<Config> const& config ) {
6009
6010 Ptr<IConfig const> iconfig = config.get();
6011
6012 Ptr<IStreamingReporter> reporter = makeReporter( config );
6013 reporter = addListeners( iconfig, reporter );
6014
6015 RunContext context( iconfig, reporter );
6016
6017 Totals totals;
6018
6019 context.testGroupStarting( config->name(), 1, 1 );
6020
6021 TestSpec testSpec = config->testSpec();
6022 if( !testSpec.hasFilters() )
6023 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6024
6025 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
6026 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6027 it != itEnd;
6028 ++it ) {
6029 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
6030 totals += context.runTest( *it );
6031 else
6032 reporter->skipTest( *it );
6033 }
6034
6035 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
6036 return totals;
6037 }
6038
applyFilenamesAsTags(IConfig const & config)6039 void applyFilenamesAsTags( IConfig const& config ) {
6040 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
6041 for(std::size_t i = 0; i < tests.size(); ++i ) {
6042 TestCase& test = const_cast<TestCase&>( tests[i] );
6043 std::set<std::string> tags = test.tags;
6044
6045 std::string filename = test.lineInfo.file;
6046 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
6047 if( lastSlash != std::string::npos )
6048 filename = filename.substr( lastSlash+1 );
6049
6050 std::string::size_type lastDot = filename.find_last_of( "." );
6051 if( lastDot != std::string::npos )
6052 filename = filename.substr( 0, lastDot );
6053
6054 tags.insert( "#" + filename );
6055 setTags( test, tags );
6056 }
6057 }
6058
6059 class Session : NonCopyable {
6060 static bool alreadyInstantiated;
6061
6062 public:
6063
6064 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
6065
Session()6066 Session()
6067 : m_cli( makeCommandLineParser() ) {
6068 if( alreadyInstantiated ) {
6069 std::string msg = "Only one instance of Catch::Session can ever be used";
6070 Catch::cerr() << msg << std::endl;
6071 throw std::logic_error( msg );
6072 }
6073 alreadyInstantiated = true;
6074 }
~Session()6075 ~Session() {
6076 Catch::cleanUp();
6077 }
6078
showHelp(std::string const & processName)6079 void showHelp( std::string const& processName ) {
6080 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
6081
6082 m_cli.usage( Catch::cout(), processName );
6083 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
6084 }
6085
applyCommandLine(int argc,char const * const argv[],OnUnusedOptions::DoWhat unusedOptionBehaviour=OnUnusedOptions::Fail)6086 int applyCommandLine( int argc, char const* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
6087 try {
6088 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
6089 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
6090 if( m_configData.showHelp )
6091 showHelp( m_configData.processName );
6092 m_config.reset();
6093 }
6094 catch( std::exception& ex ) {
6095 {
6096 Colour colourGuard( Colour::Red );
6097 Catch::cerr()
6098 << "\nError(s) in input:\n"
6099 << Text( ex.what(), TextAttributes().setIndent(2) )
6100 << "\n\n";
6101 }
6102 m_cli.usage( Catch::cout(), m_configData.processName );
6103 return (std::numeric_limits<int>::max)();
6104 }
6105 return 0;
6106 }
6107
useConfigData(ConfigData const & _configData)6108 void useConfigData( ConfigData const& _configData ) {
6109 m_configData = _configData;
6110 m_config.reset();
6111 }
6112
run(int argc,char const * const argv[])6113 int run( int argc, char const* const argv[] ) {
6114
6115 int returnCode = applyCommandLine( argc, argv );
6116 if( returnCode == 0 )
6117 returnCode = run();
6118 return returnCode;
6119 }
6120
run()6121 int run() {
6122 if( m_configData.showHelp )
6123 return 0;
6124
6125 try
6126 {
6127 config(); // Force config to be constructed
6128
6129 seedRng( *m_config );
6130
6131 if( m_configData.filenamesAsTags )
6132 applyFilenamesAsTags( *m_config );
6133
6134 // Handle list request
6135 if( Option<std::size_t> listed = list( config() ) )
6136 return static_cast<int>( *listed );
6137
6138 return static_cast<int>( runTests( m_config ).assertions.failed );
6139 }
6140 catch( std::exception& ex ) {
6141 Catch::cerr() << ex.what() << std::endl;
6142 return (std::numeric_limits<int>::max)();
6143 }
6144 }
6145
cli() const6146 Clara::CommandLine<ConfigData> const& cli() const {
6147 return m_cli;
6148 }
unusedTokens() const6149 std::vector<Clara::Parser::Token> const& unusedTokens() const {
6150 return m_unusedTokens;
6151 }
configData()6152 ConfigData& configData() {
6153 return m_configData;
6154 }
config()6155 Config& config() {
6156 if( !m_config )
6157 m_config = new Config( m_configData );
6158 return *m_config;
6159 }
6160 private:
6161 Clara::CommandLine<ConfigData> m_cli;
6162 std::vector<Clara::Parser::Token> m_unusedTokens;
6163 ConfigData m_configData;
6164 Ptr<Config> m_config;
6165 };
6166
6167 bool Session::alreadyInstantiated = false;
6168
6169 } // end namespace Catch
6170
6171 // #included from: catch_registry_hub.hpp
6172 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
6173
6174 // #included from: catch_test_case_registry_impl.hpp
6175 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
6176
6177 #include <vector>
6178 #include <set>
6179 #include <sstream>
6180 #include <iostream>
6181 #include <algorithm>
6182
6183 namespace Catch {
6184
6185 struct LexSort {
operator ()Catch::LexSort6186 bool operator() (TestCase i,TestCase j) const { return (i<j);}
6187 };
6188 struct RandomNumberGenerator {
operator ()Catch::RandomNumberGenerator6189 int operator()( int n ) const { return std::rand() % n; }
6190 };
6191
sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)6192 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
6193
6194 std::vector<TestCase> sorted = unsortedTestCases;
6195
6196 switch( config.runOrder() ) {
6197 case RunTests::InLexicographicalOrder:
6198 std::sort( sorted.begin(), sorted.end(), LexSort() );
6199 break;
6200 case RunTests::InRandomOrder:
6201 {
6202 seedRng( config );
6203
6204 RandomNumberGenerator rng;
6205 std::random_shuffle( sorted.begin(), sorted.end(), rng );
6206 }
6207 break;
6208 case RunTests::InDeclarationOrder:
6209 // already in declaration order
6210 break;
6211 }
6212 return sorted;
6213 }
matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)6214 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
6215 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
6216 }
6217
enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)6218 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
6219 std::set<TestCase> seenFunctions;
6220 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
6221 it != itEnd;
6222 ++it ) {
6223 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
6224 if( !prev.second ){
6225 Catch::cerr()
6226 << Colour( Colour::Red )
6227 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
6228 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
6229 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
6230 exit(1);
6231 }
6232 }
6233 }
6234
filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)6235 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
6236 std::vector<TestCase> filtered;
6237 filtered.reserve( testCases.size() );
6238 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
6239 it != itEnd;
6240 ++it )
6241 if( matchTest( *it, testSpec, config ) )
6242 filtered.push_back( *it );
6243 return filtered;
6244 }
getAllTestCasesSorted(IConfig const & config)6245 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
6246 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
6247 }
6248
6249 class TestRegistry : public ITestCaseRegistry {
6250 public:
TestRegistry()6251 TestRegistry()
6252 : m_currentSortOrder( RunTests::InDeclarationOrder ),
6253 m_unnamedCount( 0 )
6254 {}
6255 virtual ~TestRegistry();
6256
registerTest(TestCase const & testCase)6257 virtual void registerTest( TestCase const& testCase ) {
6258 std::string name = testCase.getTestCaseInfo().name;
6259 if( name == "" ) {
6260 std::ostringstream oss;
6261 oss << "Anonymous test case " << ++m_unnamedCount;
6262 return registerTest( testCase.withName( oss.str() ) );
6263 }
6264 m_functions.push_back( testCase );
6265 }
6266
getAllTests() const6267 virtual std::vector<TestCase> const& getAllTests() const {
6268 return m_functions;
6269 }
getAllTestsSorted(IConfig const & config) const6270 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
6271 if( m_sortedFunctions.empty() )
6272 enforceNoDuplicateTestCases( m_functions );
6273
6274 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
6275 m_sortedFunctions = sortTests( config, m_functions );
6276 m_currentSortOrder = config.runOrder();
6277 }
6278 return m_sortedFunctions;
6279 }
6280
6281 private:
6282 std::vector<TestCase> m_functions;
6283 mutable RunTests::InWhatOrder m_currentSortOrder;
6284 mutable std::vector<TestCase> m_sortedFunctions;
6285 size_t m_unnamedCount;
6286 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
6287 };
6288
6289 ///////////////////////////////////////////////////////////////////////////
6290
6291 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
6292 public:
6293
FreeFunctionTestCase(TestFunction fun)6294 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
6295
invoke() const6296 virtual void invoke() const {
6297 m_fun();
6298 }
6299
6300 private:
6301 virtual ~FreeFunctionTestCase();
6302
6303 TestFunction m_fun;
6304 };
6305
extractClassName(std::string const & classOrQualifiedMethodName)6306 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
6307 std::string className = classOrQualifiedMethodName;
6308 if( startsWith( className, "&" ) )
6309 {
6310 std::size_t lastColons = className.rfind( "::" );
6311 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
6312 if( penultimateColons == std::string::npos )
6313 penultimateColons = 1;
6314 className = className.substr( penultimateColons, lastColons-penultimateColons );
6315 }
6316 return className;
6317 }
6318
registerTestCase(ITestCase * testCase,char const * classOrQualifiedMethodName,NameAndDesc const & nameAndDesc,SourceLineInfo const & lineInfo)6319 void registerTestCase
6320 ( ITestCase* testCase,
6321 char const* classOrQualifiedMethodName,
6322 NameAndDesc const& nameAndDesc,
6323 SourceLineInfo const& lineInfo ) {
6324
6325 getMutableRegistryHub().registerTest
6326 ( makeTestCase
6327 ( testCase,
6328 extractClassName( classOrQualifiedMethodName ),
6329 nameAndDesc.name,
6330 nameAndDesc.description,
6331 lineInfo ) );
6332 }
registerTestCaseFunction(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)6333 void registerTestCaseFunction
6334 ( TestFunction function,
6335 SourceLineInfo const& lineInfo,
6336 NameAndDesc const& nameAndDesc ) {
6337 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
6338 }
6339
6340 ///////////////////////////////////////////////////////////////////////////
6341
AutoReg(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)6342 AutoReg::AutoReg
6343 ( TestFunction function,
6344 SourceLineInfo const& lineInfo,
6345 NameAndDesc const& nameAndDesc ) {
6346 registerTestCaseFunction( function, lineInfo, nameAndDesc );
6347 }
6348
~AutoReg()6349 AutoReg::~AutoReg() {}
6350
6351 } // end namespace Catch
6352
6353 // #included from: catch_reporter_registry.hpp
6354 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
6355
6356 #include <map>
6357
6358 namespace Catch {
6359
6360 class ReporterRegistry : public IReporterRegistry {
6361
6362 public:
6363
~ReporterRegistry()6364 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
6365
create(std::string const & name,Ptr<IConfig const> const & config) const6366 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
6367 FactoryMap::const_iterator it = m_factories.find( name );
6368 if( it == m_factories.end() )
6369 return CATCH_NULL;
6370 return it->second->create( ReporterConfig( config ) );
6371 }
6372
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)6373 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
6374 m_factories.insert( std::make_pair( name, factory ) );
6375 }
registerListener(Ptr<IReporterFactory> const & factory)6376 void registerListener( Ptr<IReporterFactory> const& factory ) {
6377 m_listeners.push_back( factory );
6378 }
6379
getFactories() const6380 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
6381 return m_factories;
6382 }
getListeners() const6383 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
6384 return m_listeners;
6385 }
6386
6387 private:
6388 FactoryMap m_factories;
6389 Listeners m_listeners;
6390 };
6391 }
6392
6393 // #included from: catch_exception_translator_registry.hpp
6394 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
6395
6396 #ifdef __OBJC__
6397 #import "Foundation/Foundation.h"
6398 #endif
6399
6400 namespace Catch {
6401
6402 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
6403 public:
~ExceptionTranslatorRegistry()6404 ~ExceptionTranslatorRegistry() {
6405 deleteAll( m_translators );
6406 }
6407
registerTranslator(const IExceptionTranslator * translator)6408 virtual void registerTranslator( const IExceptionTranslator* translator ) {
6409 m_translators.push_back( translator );
6410 }
6411
translateActiveException() const6412 virtual std::string translateActiveException() const {
6413 try {
6414 #ifdef __OBJC__
6415 // In Objective-C try objective-c exceptions first
6416 @try {
6417 return tryTranslators();
6418 }
6419 @catch (NSException *exception) {
6420 return Catch::toString( [exception description] );
6421 }
6422 #else
6423 return tryTranslators();
6424 #endif
6425 }
6426 catch( TestFailureException& ) {
6427 throw;
6428 }
6429 catch( std::exception& ex ) {
6430 return ex.what();
6431 }
6432 catch( std::string& msg ) {
6433 return msg;
6434 }
6435 catch( const char* msg ) {
6436 return msg;
6437 }
6438 catch(...) {
6439 return "Unknown exception";
6440 }
6441 }
6442
tryTranslators() const6443 std::string tryTranslators() const {
6444 if( m_translators.empty() )
6445 throw;
6446 else
6447 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
6448 }
6449
6450 private:
6451 std::vector<const IExceptionTranslator*> m_translators;
6452 };
6453 }
6454
6455 namespace Catch {
6456
6457 namespace {
6458
6459 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
6460
6461 RegistryHub( RegistryHub const& );
6462 void operator=( RegistryHub const& );
6463
6464 public: // IRegistryHub
RegistryHub()6465 RegistryHub() {
6466 }
getReporterRegistry() const6467 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
6468 return m_reporterRegistry;
6469 }
getTestCaseRegistry() const6470 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
6471 return m_testCaseRegistry;
6472 }
getExceptionTranslatorRegistry()6473 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
6474 return m_exceptionTranslatorRegistry;
6475 }
6476
6477 public: // IMutableRegistryHub
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)6478 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
6479 m_reporterRegistry.registerReporter( name, factory );
6480 }
registerListener(Ptr<IReporterFactory> const & factory)6481 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
6482 m_reporterRegistry.registerListener( factory );
6483 }
registerTest(TestCase const & testInfo)6484 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
6485 m_testCaseRegistry.registerTest( testInfo );
6486 }
registerTranslator(const IExceptionTranslator * translator)6487 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
6488 m_exceptionTranslatorRegistry.registerTranslator( translator );
6489 }
6490
6491 private:
6492 TestRegistry m_testCaseRegistry;
6493 ReporterRegistry m_reporterRegistry;
6494 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
6495 };
6496
6497 // Single, global, instance
getTheRegistryHub()6498 inline RegistryHub*& getTheRegistryHub() {
6499 static RegistryHub* theRegistryHub = CATCH_NULL;
6500 if( !theRegistryHub )
6501 theRegistryHub = new RegistryHub();
6502 return theRegistryHub;
6503 }
6504 }
6505
getRegistryHub()6506 IRegistryHub& getRegistryHub() {
6507 return *getTheRegistryHub();
6508 }
getMutableRegistryHub()6509 IMutableRegistryHub& getMutableRegistryHub() {
6510 return *getTheRegistryHub();
6511 }
cleanUp()6512 void cleanUp() {
6513 delete getTheRegistryHub();
6514 getTheRegistryHub() = CATCH_NULL;
6515 cleanUpContext();
6516 }
translateActiveException()6517 std::string translateActiveException() {
6518 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
6519 }
6520
6521 } // end namespace Catch
6522
6523 // #included from: catch_notimplemented_exception.hpp
6524 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6525
6526 #include <ostream>
6527
6528 namespace Catch {
6529
NotImplementedException(SourceLineInfo const & lineInfo)6530 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
6531 : m_lineInfo( lineInfo ) {
6532 std::ostringstream oss;
6533 oss << lineInfo << ": function ";
6534 oss << "not implemented";
6535 m_what = oss.str();
6536 }
6537
what() const6538 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
6539 return m_what.c_str();
6540 }
6541
6542 } // end namespace Catch
6543
6544 // #included from: catch_context_impl.hpp
6545 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
6546
6547 // #included from: catch_stream.hpp
6548 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6549
6550 #include <stdexcept>
6551 #include <cstdio>
6552 #include <iostream>
6553
6554 namespace Catch {
6555
6556 template<typename WriterF, size_t bufferSize=256>
6557 class StreamBufImpl : public StreamBufBase {
6558 char data[bufferSize];
6559 WriterF m_writer;
6560
6561 public:
StreamBufImpl()6562 StreamBufImpl() {
6563 setp( data, data + sizeof(data) );
6564 }
6565
~StreamBufImpl()6566 ~StreamBufImpl() CATCH_NOEXCEPT {
6567 sync();
6568 }
6569
6570 private:
overflow(int c)6571 int overflow( int c ) {
6572 sync();
6573
6574 if( c != EOF ) {
6575 if( pbase() == epptr() )
6576 m_writer( std::string( 1, static_cast<char>( c ) ) );
6577 else
6578 sputc( static_cast<char>( c ) );
6579 }
6580 return 0;
6581 }
6582
sync()6583 int sync() {
6584 if( pbase() != pptr() ) {
6585 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
6586 setp( pbase(), epptr() );
6587 }
6588 return 0;
6589 }
6590 };
6591
6592 ///////////////////////////////////////////////////////////////////////////
6593
FileStream(std::string const & filename)6594 FileStream::FileStream( std::string const& filename ) {
6595 m_ofs.open( filename.c_str() );
6596 if( m_ofs.fail() ) {
6597 std::ostringstream oss;
6598 oss << "Unable to open file: '" << filename << "'";
6599 throw std::domain_error( oss.str() );
6600 }
6601 }
6602
stream() const6603 std::ostream& FileStream::stream() const {
6604 return m_ofs;
6605 }
6606
6607 struct OutputDebugWriter {
6608
operator ()Catch::OutputDebugWriter6609 void operator()( std::string const&str ) {
6610 writeToDebugConsole( str );
6611 }
6612 };
6613
DebugOutStream()6614 DebugOutStream::DebugOutStream()
6615 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
6616 m_os( m_streamBuf.get() )
6617 {}
6618
stream() const6619 std::ostream& DebugOutStream::stream() const {
6620 return m_os;
6621 }
6622
6623 // Store the streambuf from cout up-front because
6624 // cout may get redirected when running tests
CoutStream()6625 CoutStream::CoutStream()
6626 : m_os( Catch::cout().rdbuf() )
6627 {}
6628
stream() const6629 std::ostream& CoutStream::stream() const {
6630 return m_os;
6631 }
6632
6633 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()6634 std::ostream& cout() {
6635 return std::cout;
6636 }
cerr()6637 std::ostream& cerr() {
6638 return std::cerr;
6639 }
6640 #endif
6641 }
6642
6643 namespace Catch {
6644
6645 class Context : public IMutableContext {
6646
Context()6647 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
6648 Context( Context const& );
6649 void operator=( Context const& );
6650
6651 public: // IContext
getResultCapture()6652 virtual IResultCapture* getResultCapture() {
6653 return m_resultCapture;
6654 }
getRunner()6655 virtual IRunner* getRunner() {
6656 return m_runner;
6657 }
getGeneratorIndex(std::string const & fileInfo,size_t totalSize)6658 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
6659 return getGeneratorsForCurrentTest()
6660 .getGeneratorInfo( fileInfo, totalSize )
6661 .getCurrentIndex();
6662 }
advanceGeneratorsForCurrentTest()6663 virtual bool advanceGeneratorsForCurrentTest() {
6664 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6665 return generators && generators->moveNext();
6666 }
6667
getConfig() const6668 virtual Ptr<IConfig const> getConfig() const {
6669 return m_config;
6670 }
6671
6672 public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)6673 virtual void setResultCapture( IResultCapture* resultCapture ) {
6674 m_resultCapture = resultCapture;
6675 }
setRunner(IRunner * runner)6676 virtual void setRunner( IRunner* runner ) {
6677 m_runner = runner;
6678 }
setConfig(Ptr<IConfig const> const & config)6679 virtual void setConfig( Ptr<IConfig const> const& config ) {
6680 m_config = config;
6681 }
6682
6683 friend IMutableContext& getCurrentMutableContext();
6684
6685 private:
findGeneratorsForCurrentTest()6686 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6687 std::string testName = getResultCapture()->getCurrentTestName();
6688
6689 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6690 m_generatorsByTestName.find( testName );
6691 return it != m_generatorsByTestName.end()
6692 ? it->second
6693 : CATCH_NULL;
6694 }
6695
getGeneratorsForCurrentTest()6696 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6697 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6698 if( !generators ) {
6699 std::string testName = getResultCapture()->getCurrentTestName();
6700 generators = createGeneratorsForTest();
6701 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6702 }
6703 return *generators;
6704 }
6705
6706 private:
6707 Ptr<IConfig const> m_config;
6708 IRunner* m_runner;
6709 IResultCapture* m_resultCapture;
6710 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6711 };
6712
6713 namespace {
6714 Context* currentContext = CATCH_NULL;
6715 }
getCurrentMutableContext()6716 IMutableContext& getCurrentMutableContext() {
6717 if( !currentContext )
6718 currentContext = new Context();
6719 return *currentContext;
6720 }
getCurrentContext()6721 IContext& getCurrentContext() {
6722 return getCurrentMutableContext();
6723 }
6724
cleanUpContext()6725 void cleanUpContext() {
6726 delete currentContext;
6727 currentContext = CATCH_NULL;
6728 }
6729 }
6730
6731 // #included from: catch_console_colour_impl.hpp
6732 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
6733
6734 namespace Catch {
6735 namespace {
6736
6737 struct IColourImpl {
~IColourImplCatch::__anon5febd4dc0411::IColourImpl6738 virtual ~IColourImpl() {}
6739 virtual void use( Colour::Code _colourCode ) = 0;
6740 };
6741
6742 struct NoColourImpl : IColourImpl {
useCatch::__anon5febd4dc0411::NoColourImpl6743 void use( Colour::Code ) {}
6744
instanceCatch::__anon5febd4dc0411::NoColourImpl6745 static IColourImpl* instance() {
6746 static NoColourImpl s_instance;
6747 return &s_instance;
6748 }
6749 };
6750
6751 } // anon namespace
6752 } // namespace Catch
6753
6754 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6755 # ifdef CATCH_PLATFORM_WINDOWS
6756 # define CATCH_CONFIG_COLOUR_WINDOWS
6757 # else
6758 # define CATCH_CONFIG_COLOUR_ANSI
6759 # endif
6760 #endif
6761
6762 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
6763
6764 #ifndef NOMINMAX
6765 #define NOMINMAX
6766 #endif
6767
6768 #ifdef __AFXDLL
6769 #include <AfxWin.h>
6770 #else
6771 #include <windows.h>
6772 #endif
6773
6774 namespace Catch {
6775 namespace {
6776
6777 class Win32ColourImpl : public IColourImpl {
6778 public:
Win32ColourImpl()6779 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6780 {
6781 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6782 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6783 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
6784 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
6785 }
6786
use(Colour::Code _colourCode)6787 virtual void use( Colour::Code _colourCode ) {
6788 switch( _colourCode ) {
6789 case Colour::None: return setTextAttribute( originalForegroundAttributes );
6790 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6791 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
6792 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
6793 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
6794 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6795 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6796 case Colour::Grey: return setTextAttribute( 0 );
6797
6798 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
6799 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6800 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6801 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6802
6803 case Colour::Bright: throw std::logic_error( "not a colour" );
6804 }
6805 }
6806
6807 private:
setTextAttribute(WORD _textAttribute)6808 void setTextAttribute( WORD _textAttribute ) {
6809 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
6810 }
6811 HANDLE stdoutHandle;
6812 WORD originalForegroundAttributes;
6813 WORD originalBackgroundAttributes;
6814 };
6815
platformColourInstance()6816 IColourImpl* platformColourInstance() {
6817 static Win32ColourImpl s_instance;
6818 return &s_instance;
6819 }
6820
6821 } // end anon namespace
6822 } // end namespace Catch
6823
6824 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
6825
6826 #include <unistd.h>
6827
6828 namespace Catch {
6829 namespace {
6830
6831 // use POSIX/ ANSI console terminal codes
6832 // Thanks to Adam Strzelecki for original contribution
6833 // (http://github.com/nanoant)
6834 // https://github.com/philsquared/Catch/pull/131
6835 class PosixColourImpl : public IColourImpl {
6836 public:
use(Colour::Code _colourCode)6837 virtual void use( Colour::Code _colourCode ) {
6838 switch( _colourCode ) {
6839 case Colour::None:
6840 case Colour::White: return setColour( "[0m" );
6841 case Colour::Red: return setColour( "[0;31m" );
6842 case Colour::Green: return setColour( "[0;32m" );
6843 case Colour::Blue: return setColour( "[0:34m" );
6844 case Colour::Cyan: return setColour( "[0;36m" );
6845 case Colour::Yellow: return setColour( "[0;33m" );
6846 case Colour::Grey: return setColour( "[1;30m" );
6847
6848 case Colour::LightGrey: return setColour( "[0;37m" );
6849 case Colour::BrightRed: return setColour( "[1;31m" );
6850 case Colour::BrightGreen: return setColour( "[1;32m" );
6851 case Colour::BrightWhite: return setColour( "[1;37m" );
6852
6853 case Colour::Bright: throw std::logic_error( "not a colour" );
6854 }
6855 }
instance()6856 static IColourImpl* instance() {
6857 static PosixColourImpl s_instance;
6858 return &s_instance;
6859 }
6860
6861 private:
setColour(const char * _escapeCode)6862 void setColour( const char* _escapeCode ) {
6863 Catch::cout() << '\033' << _escapeCode;
6864 }
6865 };
6866
platformColourInstance()6867 IColourImpl* platformColourInstance() {
6868 Ptr<IConfig const> config = getCurrentContext().getConfig();
6869 return (config && config->forceColour()) || isatty(STDOUT_FILENO)
6870 ? PosixColourImpl::instance()
6871 : NoColourImpl::instance();
6872 }
6873
6874 } // end anon namespace
6875 } // end namespace Catch
6876
6877 #else // not Windows or ANSI ///////////////////////////////////////////////
6878
6879 namespace Catch {
6880
platformColourInstance()6881 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
6882
6883 } // end namespace Catch
6884
6885 #endif // Windows/ ANSI/ None
6886
6887 namespace Catch {
6888
Colour(Code _colourCode)6889 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
Colour(Colour const & _other)6890 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
~Colour()6891 Colour::~Colour(){ if( !m_moved ) use( None ); }
6892
use(Code _colourCode)6893 void Colour::use( Code _colourCode ) {
6894 static IColourImpl* impl = isDebuggerActive()
6895 ? NoColourImpl::instance()
6896 : platformColourInstance();
6897 impl->use( _colourCode );
6898 }
6899
6900 } // end namespace Catch
6901
6902 // #included from: catch_generators_impl.hpp
6903 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
6904
6905 #include <vector>
6906 #include <string>
6907 #include <map>
6908
6909 namespace Catch {
6910
6911 struct GeneratorInfo : IGeneratorInfo {
6912
GeneratorInfoCatch::GeneratorInfo6913 GeneratorInfo( std::size_t size )
6914 : m_size( size ),
6915 m_currentIndex( 0 )
6916 {}
6917
moveNextCatch::GeneratorInfo6918 bool moveNext() {
6919 if( ++m_currentIndex == m_size ) {
6920 m_currentIndex = 0;
6921 return false;
6922 }
6923 return true;
6924 }
6925
getCurrentIndexCatch::GeneratorInfo6926 std::size_t getCurrentIndex() const {
6927 return m_currentIndex;
6928 }
6929
6930 std::size_t m_size;
6931 std::size_t m_currentIndex;
6932 };
6933
6934 ///////////////////////////////////////////////////////////////////////////
6935
6936 class GeneratorsForTest : public IGeneratorsForTest {
6937
6938 public:
~GeneratorsForTest()6939 ~GeneratorsForTest() {
6940 deleteAll( m_generatorsInOrder );
6941 }
6942
getGeneratorInfo(std::string const & fileInfo,std::size_t size)6943 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
6944 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
6945 if( it == m_generatorsByName.end() ) {
6946 IGeneratorInfo* info = new GeneratorInfo( size );
6947 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
6948 m_generatorsInOrder.push_back( info );
6949 return *info;
6950 }
6951 return *it->second;
6952 }
6953
moveNext()6954 bool moveNext() {
6955 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
6956 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
6957 for(; it != itEnd; ++it ) {
6958 if( (*it)->moveNext() )
6959 return true;
6960 }
6961 return false;
6962 }
6963
6964 private:
6965 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
6966 std::vector<IGeneratorInfo*> m_generatorsInOrder;
6967 };
6968
createGeneratorsForTest()6969 IGeneratorsForTest* createGeneratorsForTest()
6970 {
6971 return new GeneratorsForTest();
6972 }
6973
6974 } // end namespace Catch
6975
6976 // #included from: catch_assertionresult.hpp
6977 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
6978
6979 namespace Catch {
6980
AssertionInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,std::string const & _capturedExpression,ResultDisposition::Flags _resultDisposition)6981 AssertionInfo::AssertionInfo( std::string const& _macroName,
6982 SourceLineInfo const& _lineInfo,
6983 std::string const& _capturedExpression,
6984 ResultDisposition::Flags _resultDisposition )
6985 : macroName( _macroName ),
6986 lineInfo( _lineInfo ),
6987 capturedExpression( _capturedExpression ),
6988 resultDisposition( _resultDisposition )
6989 {}
6990
AssertionResult()6991 AssertionResult::AssertionResult() {}
6992
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)6993 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
6994 : m_info( info ),
6995 m_resultData( data )
6996 {}
6997
~AssertionResult()6998 AssertionResult::~AssertionResult() {}
6999
7000 // Result was a success
succeeded() const7001 bool AssertionResult::succeeded() const {
7002 return Catch::isOk( m_resultData.resultType );
7003 }
7004
7005 // Result was a success, or failure is suppressed
isOk() const7006 bool AssertionResult::isOk() const {
7007 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
7008 }
7009
getResultType() const7010 ResultWas::OfType AssertionResult::getResultType() const {
7011 return m_resultData.resultType;
7012 }
7013
hasExpression() const7014 bool AssertionResult::hasExpression() const {
7015 return !m_info.capturedExpression.empty();
7016 }
7017
hasMessage() const7018 bool AssertionResult::hasMessage() const {
7019 return !m_resultData.message.empty();
7020 }
7021
getExpression() const7022 std::string AssertionResult::getExpression() const {
7023 if( isFalseTest( m_info.resultDisposition ) )
7024 return "!" + m_info.capturedExpression;
7025 else
7026 return m_info.capturedExpression;
7027 }
getExpressionInMacro() const7028 std::string AssertionResult::getExpressionInMacro() const {
7029 if( m_info.macroName.empty() )
7030 return m_info.capturedExpression;
7031 else
7032 return m_info.macroName + "( " + m_info.capturedExpression + " )";
7033 }
7034
hasExpandedExpression() const7035 bool AssertionResult::hasExpandedExpression() const {
7036 return hasExpression() && getExpandedExpression() != getExpression();
7037 }
7038
getExpandedExpression() const7039 std::string AssertionResult::getExpandedExpression() const {
7040 return m_resultData.reconstructedExpression;
7041 }
7042
getMessage() const7043 std::string AssertionResult::getMessage() const {
7044 return m_resultData.message;
7045 }
getSourceInfo() const7046 SourceLineInfo AssertionResult::getSourceInfo() const {
7047 return m_info.lineInfo;
7048 }
7049
getTestMacroName() const7050 std::string AssertionResult::getTestMacroName() const {
7051 return m_info.macroName;
7052 }
7053
7054 } // end namespace Catch
7055
7056 // #included from: catch_test_case_info.hpp
7057 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
7058
7059 namespace Catch {
7060
parseSpecialTag(std::string const & tag)7061 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
7062 if( startsWith( tag, "." ) ||
7063 tag == "hide" ||
7064 tag == "!hide" )
7065 return TestCaseInfo::IsHidden;
7066 else if( tag == "!throws" )
7067 return TestCaseInfo::Throws;
7068 else if( tag == "!shouldfail" )
7069 return TestCaseInfo::ShouldFail;
7070 else if( tag == "!mayfail" )
7071 return TestCaseInfo::MayFail;
7072 else
7073 return TestCaseInfo::None;
7074 }
isReservedTag(std::string const & tag)7075 inline bool isReservedTag( std::string const& tag ) {
7076 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
7077 }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)7078 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
7079 if( isReservedTag( tag ) ) {
7080 {
7081 Colour colourGuard( Colour::Red );
7082 Catch::cerr()
7083 << "Tag name [" << tag << "] not allowed.\n"
7084 << "Tag names starting with non alpha-numeric characters are reserved\n";
7085 }
7086 {
7087 Colour colourGuard( Colour::FileName );
7088 Catch::cerr() << _lineInfo << std::endl;
7089 }
7090 exit(1);
7091 }
7092 }
7093
makeTestCase(ITestCase * _testCase,std::string const & _className,std::string const & _name,std::string const & _descOrTags,SourceLineInfo const & _lineInfo)7094 TestCase makeTestCase( ITestCase* _testCase,
7095 std::string const& _className,
7096 std::string const& _name,
7097 std::string const& _descOrTags,
7098 SourceLineInfo const& _lineInfo )
7099 {
7100 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
7101
7102 // Parse out tags
7103 std::set<std::string> tags;
7104 std::string desc, tag;
7105 bool inTag = false;
7106 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7107 char c = _descOrTags[i];
7108 if( !inTag ) {
7109 if( c == '[' )
7110 inTag = true;
7111 else
7112 desc += c;
7113 }
7114 else {
7115 if( c == ']' ) {
7116 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
7117 if( prop == TestCaseInfo::IsHidden )
7118 isHidden = true;
7119 else if( prop == TestCaseInfo::None )
7120 enforceNotReservedTag( tag, _lineInfo );
7121
7122 tags.insert( tag );
7123 tag.clear();
7124 inTag = false;
7125 }
7126 else
7127 tag += c;
7128 }
7129 }
7130 if( isHidden ) {
7131 tags.insert( "hide" );
7132 tags.insert( "." );
7133 }
7134
7135 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
7136 return TestCase( _testCase, info );
7137 }
7138
setTags(TestCaseInfo & testCaseInfo,std::set<std::string> const & tags)7139 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
7140 {
7141 testCaseInfo.tags = tags;
7142 testCaseInfo.lcaseTags.clear();
7143
7144 std::ostringstream oss;
7145 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
7146 oss << "[" << *it << "]";
7147 std::string lcaseTag = toLower( *it );
7148 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
7149 testCaseInfo.lcaseTags.insert( lcaseTag );
7150 }
7151 testCaseInfo.tagsAsString = oss.str();
7152 }
7153
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::set<std::string> const & _tags,SourceLineInfo const & _lineInfo)7154 TestCaseInfo::TestCaseInfo( std::string const& _name,
7155 std::string const& _className,
7156 std::string const& _description,
7157 std::set<std::string> const& _tags,
7158 SourceLineInfo const& _lineInfo )
7159 : name( _name ),
7160 className( _className ),
7161 description( _description ),
7162 lineInfo( _lineInfo ),
7163 properties( None )
7164 {
7165 setTags( *this, _tags );
7166 }
7167
TestCaseInfo(TestCaseInfo const & other)7168 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
7169 : name( other.name ),
7170 className( other.className ),
7171 description( other.description ),
7172 tags( other.tags ),
7173 lcaseTags( other.lcaseTags ),
7174 tagsAsString( other.tagsAsString ),
7175 lineInfo( other.lineInfo ),
7176 properties( other.properties )
7177 {}
7178
isHidden() const7179 bool TestCaseInfo::isHidden() const {
7180 return ( properties & IsHidden ) != 0;
7181 }
throws() const7182 bool TestCaseInfo::throws() const {
7183 return ( properties & Throws ) != 0;
7184 }
okToFail() const7185 bool TestCaseInfo::okToFail() const {
7186 return ( properties & (ShouldFail | MayFail ) ) != 0;
7187 }
expectedToFail() const7188 bool TestCaseInfo::expectedToFail() const {
7189 return ( properties & (ShouldFail ) ) != 0;
7190 }
7191
TestCase(ITestCase * testCase,TestCaseInfo const & info)7192 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
7193
TestCase(TestCase const & other)7194 TestCase::TestCase( TestCase const& other )
7195 : TestCaseInfo( other ),
7196 test( other.test )
7197 {}
7198
withName(std::string const & _newName) const7199 TestCase TestCase::withName( std::string const& _newName ) const {
7200 TestCase other( *this );
7201 other.name = _newName;
7202 return other;
7203 }
7204
swap(TestCase & other)7205 void TestCase::swap( TestCase& other ) {
7206 test.swap( other.test );
7207 name.swap( other.name );
7208 className.swap( other.className );
7209 description.swap( other.description );
7210 tags.swap( other.tags );
7211 lcaseTags.swap( other.lcaseTags );
7212 tagsAsString.swap( other.tagsAsString );
7213 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
7214 std::swap( lineInfo, other.lineInfo );
7215 }
7216
invoke() const7217 void TestCase::invoke() const {
7218 test->invoke();
7219 }
7220
operator ==(TestCase const & other) const7221 bool TestCase::operator == ( TestCase const& other ) const {
7222 return test.get() == other.test.get() &&
7223 name == other.name &&
7224 className == other.className;
7225 }
7226
operator <(TestCase const & other) const7227 bool TestCase::operator < ( TestCase const& other ) const {
7228 return name < other.name;
7229 }
operator =(TestCase const & other)7230 TestCase& TestCase::operator = ( TestCase const& other ) {
7231 TestCase temp( other );
7232 swap( temp );
7233 return *this;
7234 }
7235
getTestCaseInfo() const7236 TestCaseInfo const& TestCase::getTestCaseInfo() const
7237 {
7238 return *this;
7239 }
7240
7241 } // end namespace Catch
7242
7243 // #included from: catch_version.hpp
7244 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7245
7246 namespace Catch {
7247
Version(unsigned int _majorVersion,unsigned int _minorVersion,unsigned int _patchNumber,std::string const & _branchName,unsigned int _buildNumber)7248 Version::Version
7249 ( unsigned int _majorVersion,
7250 unsigned int _minorVersion,
7251 unsigned int _patchNumber,
7252 std::string const& _branchName,
7253 unsigned int _buildNumber )
7254 : majorVersion( _majorVersion ),
7255 minorVersion( _minorVersion ),
7256 patchNumber( _patchNumber ),
7257 branchName( _branchName ),
7258 buildNumber( _buildNumber )
7259 {}
7260
operator <<(std::ostream & os,Version const & version)7261 std::ostream& operator << ( std::ostream& os, Version const& version ) {
7262 os << version.majorVersion << "."
7263 << version.minorVersion << "."
7264 << version.patchNumber;
7265
7266 if( !version.branchName.empty() ) {
7267 os << "-" << version.branchName
7268 << "." << version.buildNumber;
7269 }
7270 return os;
7271 }
7272
7273 Version libraryVersion( 1, 3, 1, "", 0 );
7274
7275 }
7276
7277 // #included from: catch_message.hpp
7278 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
7279
7280 namespace Catch {
7281
MessageInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)7282 MessageInfo::MessageInfo( std::string const& _macroName,
7283 SourceLineInfo const& _lineInfo,
7284 ResultWas::OfType _type )
7285 : macroName( _macroName ),
7286 lineInfo( _lineInfo ),
7287 type( _type ),
7288 sequence( ++globalCount )
7289 {}
7290
7291 // This may need protecting if threading support is added
7292 unsigned int MessageInfo::globalCount = 0;
7293
7294 ////////////////////////////////////////////////////////////////////////////
7295
ScopedMessage(MessageBuilder const & builder)7296 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
7297 : m_info( builder.m_info )
7298 {
7299 m_info.message = builder.m_stream.str();
7300 getResultCapture().pushScopedMessage( m_info );
7301 }
ScopedMessage(ScopedMessage const & other)7302 ScopedMessage::ScopedMessage( ScopedMessage const& other )
7303 : m_info( other.m_info )
7304 {}
7305
~ScopedMessage()7306 ScopedMessage::~ScopedMessage() {
7307 getResultCapture().popScopedMessage( m_info );
7308 }
7309
7310 } // end namespace Catch
7311
7312 // #included from: catch_legacy_reporter_adapter.hpp
7313 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
7314
7315 // #included from: catch_legacy_reporter_adapter.h
7316 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
7317
7318 namespace Catch
7319 {
7320 // Deprecated
7321 struct IReporter : IShared {
7322 virtual ~IReporter();
7323
7324 virtual bool shouldRedirectStdout() const = 0;
7325
7326 virtual void StartTesting() = 0;
7327 virtual void EndTesting( Totals const& totals ) = 0;
7328 virtual void StartGroup( std::string const& groupName ) = 0;
7329 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
7330 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
7331 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
7332 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
7333 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
7334 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
7335 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
7336 virtual void Aborted() = 0;
7337 virtual void Result( AssertionResult const& result ) = 0;
7338 };
7339
7340 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
7341 {
7342 public:
7343 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
7344 virtual ~LegacyReporterAdapter();
7345
7346 virtual ReporterPreferences getPreferences() const;
7347 virtual void noMatchingTestCases( std::string const& );
7348 virtual void testRunStarting( TestRunInfo const& );
7349 virtual void testGroupStarting( GroupInfo const& groupInfo );
7350 virtual void testCaseStarting( TestCaseInfo const& testInfo );
7351 virtual void sectionStarting( SectionInfo const& sectionInfo );
7352 virtual void assertionStarting( AssertionInfo const& );
7353 virtual bool assertionEnded( AssertionStats const& assertionStats );
7354 virtual void sectionEnded( SectionStats const& sectionStats );
7355 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
7356 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
7357 virtual void testRunEnded( TestRunStats const& testRunStats );
7358 virtual void skipTest( TestCaseInfo const& );
7359
7360 private:
7361 Ptr<IReporter> m_legacyReporter;
7362 };
7363 }
7364
7365 namespace Catch
7366 {
LegacyReporterAdapter(Ptr<IReporter> const & legacyReporter)7367 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
7368 : m_legacyReporter( legacyReporter )
7369 {}
~LegacyReporterAdapter()7370 LegacyReporterAdapter::~LegacyReporterAdapter() {}
7371
getPreferences() const7372 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
7373 ReporterPreferences prefs;
7374 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
7375 return prefs;
7376 }
7377
noMatchingTestCases(std::string const &)7378 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
testRunStarting(TestRunInfo const &)7379 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
7380 m_legacyReporter->StartTesting();
7381 }
testGroupStarting(GroupInfo const & groupInfo)7382 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
7383 m_legacyReporter->StartGroup( groupInfo.name );
7384 }
testCaseStarting(TestCaseInfo const & testInfo)7385 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
7386 m_legacyReporter->StartTestCase( testInfo );
7387 }
sectionStarting(SectionInfo const & sectionInfo)7388 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
7389 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
7390 }
assertionStarting(AssertionInfo const &)7391 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
7392 // Not on legacy interface
7393 }
7394
assertionEnded(AssertionStats const & assertionStats)7395 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
7396 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
7397 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
7398 it != itEnd;
7399 ++it ) {
7400 if( it->type == ResultWas::Info ) {
7401 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
7402 rb << it->message;
7403 rb.setResultType( ResultWas::Info );
7404 AssertionResult result = rb.build();
7405 m_legacyReporter->Result( result );
7406 }
7407 }
7408 }
7409 m_legacyReporter->Result( assertionStats.assertionResult );
7410 return true;
7411 }
sectionEnded(SectionStats const & sectionStats)7412 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
7413 if( sectionStats.missingAssertions )
7414 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
7415 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
7416 }
testCaseEnded(TestCaseStats const & testCaseStats)7417 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
7418 m_legacyReporter->EndTestCase
7419 ( testCaseStats.testInfo,
7420 testCaseStats.totals,
7421 testCaseStats.stdOut,
7422 testCaseStats.stdErr );
7423 }
testGroupEnded(TestGroupStats const & testGroupStats)7424 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
7425 if( testGroupStats.aborting )
7426 m_legacyReporter->Aborted();
7427 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
7428 }
testRunEnded(TestRunStats const & testRunStats)7429 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
7430 m_legacyReporter->EndTesting( testRunStats.totals );
7431 }
skipTest(TestCaseInfo const &)7432 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
7433 }
7434 }
7435
7436 // #included from: catch_timer.hpp
7437
7438 #ifdef __clang__
7439 #pragma clang diagnostic push
7440 #pragma clang diagnostic ignored "-Wc++11-long-long"
7441 #endif
7442
7443 #ifdef CATCH_PLATFORM_WINDOWS
7444 #include <windows.h>
7445 #else
7446 #include <sys/time.h>
7447 #endif
7448
7449 namespace Catch {
7450
7451 namespace {
7452 #ifdef CATCH_PLATFORM_WINDOWS
getCurrentTicks()7453 uint64_t getCurrentTicks() {
7454 static uint64_t hz=0, hzo=0;
7455 if (!hz) {
7456 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
7457 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
7458 }
7459 uint64_t t;
7460 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
7461 return ((t-hzo)*1000000)/hz;
7462 }
7463 #else
7464 uint64_t getCurrentTicks() {
7465 timeval t;
7466 gettimeofday(&t,CATCH_NULL);
7467 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
7468 }
7469 #endif
7470 }
7471
start()7472 void Timer::start() {
7473 m_ticks = getCurrentTicks();
7474 }
getElapsedMicroseconds() const7475 unsigned int Timer::getElapsedMicroseconds() const {
7476 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
7477 }
getElapsedMilliseconds() const7478 unsigned int Timer::getElapsedMilliseconds() const {
7479 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
7480 }
getElapsedSeconds() const7481 double Timer::getElapsedSeconds() const {
7482 return getElapsedMicroseconds()/1000000.0;
7483 }
7484
7485 } // namespace Catch
7486
7487 #ifdef __clang__
7488 #pragma clang diagnostic pop
7489 #endif
7490 // #included from: catch_common.hpp
7491 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
7492
7493 namespace Catch {
7494
startsWith(std::string const & s,std::string const & prefix)7495 bool startsWith( std::string const& s, std::string const& prefix ) {
7496 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
7497 }
endsWith(std::string const & s,std::string const & suffix)7498