1 /*
2 * Catch v1.3.0
3 * Generated: 2015-12-04 10:18:17.055188
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() : m_unnamedCount( 0 ) {}
6252 virtual ~TestRegistry();
6253
registerTest(TestCase const & testCase)6254 virtual void registerTest( TestCase const& testCase ) {
6255 std::string name = testCase.getTestCaseInfo().name;
6256 if( name == "" ) {
6257 std::ostringstream oss;
6258 oss << "Anonymous test case " << ++m_unnamedCount;
6259 return registerTest( testCase.withName( oss.str() ) );
6260 }
6261 m_functions.push_back( testCase );
6262 }
6263
getAllTests() const6264 virtual std::vector<TestCase> const& getAllTests() const {
6265 return m_functions;
6266 }
getAllTestsSorted(IConfig const & config) const6267 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
6268 if( m_sortedFunctions.empty() )
6269 enforceNoDuplicateTestCases( m_functions );
6270
6271 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
6272 m_sortedFunctions = sortTests( config, m_functions );
6273 m_currentSortOrder = config.runOrder();
6274 }
6275 return m_sortedFunctions;
6276 }
6277
6278 private:
6279 std::vector<TestCase> m_functions;
6280 mutable RunTests::InWhatOrder m_currentSortOrder;
6281 mutable std::vector<TestCase> m_sortedFunctions;
6282 size_t m_unnamedCount;
6283 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
6284 };
6285
6286 ///////////////////////////////////////////////////////////////////////////
6287
6288 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
6289 public:
6290
FreeFunctionTestCase(TestFunction fun)6291 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
6292
invoke() const6293 virtual void invoke() const {
6294 m_fun();
6295 }
6296
6297 private:
6298 virtual ~FreeFunctionTestCase();
6299
6300 TestFunction m_fun;
6301 };
6302
extractClassName(std::string const & classOrQualifiedMethodName)6303 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
6304 std::string className = classOrQualifiedMethodName;
6305 if( startsWith( className, "&" ) )
6306 {
6307 std::size_t lastColons = className.rfind( "::" );
6308 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
6309 if( penultimateColons == std::string::npos )
6310 penultimateColons = 1;
6311 className = className.substr( penultimateColons, lastColons-penultimateColons );
6312 }
6313 return className;
6314 }
6315
registerTestCase(ITestCase * testCase,char const * classOrQualifiedMethodName,NameAndDesc const & nameAndDesc,SourceLineInfo const & lineInfo)6316 void registerTestCase
6317 ( ITestCase* testCase,
6318 char const* classOrQualifiedMethodName,
6319 NameAndDesc const& nameAndDesc,
6320 SourceLineInfo const& lineInfo ) {
6321
6322 getMutableRegistryHub().registerTest
6323 ( makeTestCase
6324 ( testCase,
6325 extractClassName( classOrQualifiedMethodName ),
6326 nameAndDesc.name,
6327 nameAndDesc.description,
6328 lineInfo ) );
6329 }
registerTestCaseFunction(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)6330 void registerTestCaseFunction
6331 ( TestFunction function,
6332 SourceLineInfo const& lineInfo,
6333 NameAndDesc const& nameAndDesc ) {
6334 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
6335 }
6336
6337 ///////////////////////////////////////////////////////////////////////////
6338
AutoReg(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)6339 AutoReg::AutoReg
6340 ( TestFunction function,
6341 SourceLineInfo const& lineInfo,
6342 NameAndDesc const& nameAndDesc ) {
6343 registerTestCaseFunction( function, lineInfo, nameAndDesc );
6344 }
6345
~AutoReg()6346 AutoReg::~AutoReg() {}
6347
6348 } // end namespace Catch
6349
6350 // #included from: catch_reporter_registry.hpp
6351 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
6352
6353 #include <map>
6354
6355 namespace Catch {
6356
6357 class ReporterRegistry : public IReporterRegistry {
6358
6359 public:
6360
~ReporterRegistry()6361 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
6362
create(std::string const & name,Ptr<IConfig const> const & config) const6363 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
6364 FactoryMap::const_iterator it = m_factories.find( name );
6365 if( it == m_factories.end() )
6366 return CATCH_NULL;
6367 return it->second->create( ReporterConfig( config ) );
6368 }
6369
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)6370 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
6371 m_factories.insert( std::make_pair( name, factory ) );
6372 }
registerListener(Ptr<IReporterFactory> const & factory)6373 void registerListener( Ptr<IReporterFactory> const& factory ) {
6374 m_listeners.push_back( factory );
6375 }
6376
getFactories() const6377 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
6378 return m_factories;
6379 }
getListeners() const6380 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
6381 return m_listeners;
6382 }
6383
6384 private:
6385 FactoryMap m_factories;
6386 Listeners m_listeners;
6387 };
6388 }
6389
6390 // #included from: catch_exception_translator_registry.hpp
6391 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
6392
6393 #ifdef __OBJC__
6394 #import "Foundation/Foundation.h"
6395 #endif
6396
6397 namespace Catch {
6398
6399 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
6400 public:
~ExceptionTranslatorRegistry()6401 ~ExceptionTranslatorRegistry() {
6402 deleteAll( m_translators );
6403 }
6404
registerTranslator(const IExceptionTranslator * translator)6405 virtual void registerTranslator( const IExceptionTranslator* translator ) {
6406 m_translators.push_back( translator );
6407 }
6408
translateActiveException() const6409 virtual std::string translateActiveException() const {
6410 try {
6411 #ifdef __OBJC__
6412 // In Objective-C try objective-c exceptions first
6413 @try {
6414 return tryTranslators();
6415 }
6416 @catch (NSException *exception) {
6417 return Catch::toString( [exception description] );
6418 }
6419 #else
6420 return tryTranslators();
6421 #endif
6422 }
6423 catch( TestFailureException& ) {
6424 throw;
6425 }
6426 catch( std::exception& ex ) {
6427 return ex.what();
6428 }
6429 catch( std::string& msg ) {
6430 return msg;
6431 }
6432 catch( const char* msg ) {
6433 return msg;
6434 }
6435 catch(...) {
6436 return "Unknown exception";
6437 }
6438 }
6439
tryTranslators() const6440 std::string tryTranslators() const {
6441 if( m_translators.empty() )
6442 throw;
6443 else
6444 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
6445 }
6446
6447 private:
6448 std::vector<const IExceptionTranslator*> m_translators;
6449 };
6450 }
6451
6452 namespace Catch {
6453
6454 namespace {
6455
6456 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
6457
6458 RegistryHub( RegistryHub const& );
6459 void operator=( RegistryHub const& );
6460
6461 public: // IRegistryHub
RegistryHub()6462 RegistryHub() {
6463 }
getReporterRegistry() const6464 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
6465 return m_reporterRegistry;
6466 }
getTestCaseRegistry() const6467 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
6468 return m_testCaseRegistry;
6469 }
getExceptionTranslatorRegistry()6470 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
6471 return m_exceptionTranslatorRegistry;
6472 }
6473
6474 public: // IMutableRegistryHub
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)6475 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
6476 m_reporterRegistry.registerReporter( name, factory );
6477 }
registerListener(Ptr<IReporterFactory> const & factory)6478 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
6479 m_reporterRegistry.registerListener( factory );
6480 }
registerTest(TestCase const & testInfo)6481 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
6482 m_testCaseRegistry.registerTest( testInfo );
6483 }
registerTranslator(const IExceptionTranslator * translator)6484 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
6485 m_exceptionTranslatorRegistry.registerTranslator( translator );
6486 }
6487
6488 private:
6489 TestRegistry m_testCaseRegistry;
6490 ReporterRegistry m_reporterRegistry;
6491 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
6492 };
6493
6494 // Single, global, instance
getTheRegistryHub()6495 inline RegistryHub*& getTheRegistryHub() {
6496 static RegistryHub* theRegistryHub = CATCH_NULL;
6497 if( !theRegistryHub )
6498 theRegistryHub = new RegistryHub();
6499 return theRegistryHub;
6500 }
6501 }
6502
getRegistryHub()6503 IRegistryHub& getRegistryHub() {
6504 return *getTheRegistryHub();
6505 }
getMutableRegistryHub()6506 IMutableRegistryHub& getMutableRegistryHub() {
6507 return *getTheRegistryHub();
6508 }
cleanUp()6509 void cleanUp() {
6510 delete getTheRegistryHub();
6511 getTheRegistryHub() = CATCH_NULL;
6512 cleanUpContext();
6513 }
translateActiveException()6514 std::string translateActiveException() {
6515 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
6516 }
6517
6518 } // end namespace Catch
6519
6520 // #included from: catch_notimplemented_exception.hpp
6521 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6522
6523 #include <ostream>
6524
6525 namespace Catch {
6526
NotImplementedException(SourceLineInfo const & lineInfo)6527 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
6528 : m_lineInfo( lineInfo ) {
6529 std::ostringstream oss;
6530 oss << lineInfo << ": function ";
6531 oss << "not implemented";
6532 m_what = oss.str();
6533 }
6534
what() const6535 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
6536 return m_what.c_str();
6537 }
6538
6539 } // end namespace Catch
6540
6541 // #included from: catch_context_impl.hpp
6542 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
6543
6544 // #included from: catch_stream.hpp
6545 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6546
6547 #include <stdexcept>
6548 #include <cstdio>
6549 #include <iostream>
6550
6551 namespace Catch {
6552
6553 template<typename WriterF, size_t bufferSize=256>
6554 class StreamBufImpl : public StreamBufBase {
6555 char data[bufferSize];
6556 WriterF m_writer;
6557
6558 public:
StreamBufImpl()6559 StreamBufImpl() {
6560 setp( data, data + sizeof(data) );
6561 }
6562
~StreamBufImpl()6563 ~StreamBufImpl() CATCH_NOEXCEPT {
6564 sync();
6565 }
6566
6567 private:
overflow(int c)6568 int overflow( int c ) {
6569 sync();
6570
6571 if( c != EOF ) {
6572 if( pbase() == epptr() )
6573 m_writer( std::string( 1, static_cast<char>( c ) ) );
6574 else
6575 sputc( static_cast<char>( c ) );
6576 }
6577 return 0;
6578 }
6579
sync()6580 int sync() {
6581 if( pbase() != pptr() ) {
6582 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
6583 setp( pbase(), epptr() );
6584 }
6585 return 0;
6586 }
6587 };
6588
6589 ///////////////////////////////////////////////////////////////////////////
6590
FileStream(std::string const & filename)6591 FileStream::FileStream( std::string const& filename ) {
6592 m_ofs.open( filename.c_str() );
6593 if( m_ofs.fail() ) {
6594 std::ostringstream oss;
6595 oss << "Unable to open file: '" << filename << "'";
6596 throw std::domain_error( oss.str() );
6597 }
6598 }
6599
stream() const6600 std::ostream& FileStream::stream() const {
6601 return m_ofs;
6602 }
6603
6604 struct OutputDebugWriter {
6605
operator ()Catch::OutputDebugWriter6606 void operator()( std::string const&str ) {
6607 writeToDebugConsole( str );
6608 }
6609 };
6610
DebugOutStream()6611 DebugOutStream::DebugOutStream()
6612 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
6613 m_os( m_streamBuf.get() )
6614 {}
6615
stream() const6616 std::ostream& DebugOutStream::stream() const {
6617 return m_os;
6618 }
6619
6620 // Store the streambuf from cout up-front because
6621 // cout may get redirected when running tests
CoutStream()6622 CoutStream::CoutStream()
6623 : m_os( Catch::cout().rdbuf() )
6624 {}
6625
stream() const6626 std::ostream& CoutStream::stream() const {
6627 return m_os;
6628 }
6629
6630 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()6631 std::ostream& cout() {
6632 return std::cout;
6633 }
cerr()6634 std::ostream& cerr() {
6635 return std::cerr;
6636 }
6637 #endif
6638 }
6639
6640 namespace Catch {
6641
6642 class Context : public IMutableContext {
6643
Context()6644 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
6645 Context( Context const& );
6646 void operator=( Context const& );
6647
6648 public: // IContext
getResultCapture()6649 virtual IResultCapture* getResultCapture() {
6650 return m_resultCapture;
6651 }
getRunner()6652 virtual IRunner* getRunner() {
6653 return m_runner;
6654 }
getGeneratorIndex(std::string const & fileInfo,size_t totalSize)6655 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
6656 return getGeneratorsForCurrentTest()
6657 .getGeneratorInfo( fileInfo, totalSize )
6658 .getCurrentIndex();
6659 }
advanceGeneratorsForCurrentTest()6660 virtual bool advanceGeneratorsForCurrentTest() {
6661 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6662 return generators && generators->moveNext();
6663 }
6664
getConfig() const6665 virtual Ptr<IConfig const> getConfig() const {
6666 return m_config;
6667 }
6668
6669 public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)6670 virtual void setResultCapture( IResultCapture* resultCapture ) {
6671 m_resultCapture = resultCapture;
6672 }
setRunner(IRunner * runner)6673 virtual void setRunner( IRunner* runner ) {
6674 m_runner = runner;
6675 }
setConfig(Ptr<IConfig const> const & config)6676 virtual void setConfig( Ptr<IConfig const> const& config ) {
6677 m_config = config;
6678 }
6679
6680 friend IMutableContext& getCurrentMutableContext();
6681
6682 private:
findGeneratorsForCurrentTest()6683 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6684 std::string testName = getResultCapture()->getCurrentTestName();
6685
6686 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6687 m_generatorsByTestName.find( testName );
6688 return it != m_generatorsByTestName.end()
6689 ? it->second
6690 : CATCH_NULL;
6691 }
6692
getGeneratorsForCurrentTest()6693 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6694 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6695 if( !generators ) {
6696 std::string testName = getResultCapture()->getCurrentTestName();
6697 generators = createGeneratorsForTest();
6698 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6699 }
6700 return *generators;
6701 }
6702
6703 private:
6704 Ptr<IConfig const> m_config;
6705 IRunner* m_runner;
6706 IResultCapture* m_resultCapture;
6707 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6708 };
6709
6710 namespace {
6711 Context* currentContext = CATCH_NULL;
6712 }
getCurrentMutableContext()6713 IMutableContext& getCurrentMutableContext() {
6714 if( !currentContext )
6715 currentContext = new Context();
6716 return *currentContext;
6717 }
getCurrentContext()6718 IContext& getCurrentContext() {
6719 return getCurrentMutableContext();
6720 }
6721
cleanUpContext()6722 void cleanUpContext() {
6723 delete currentContext;
6724 currentContext = CATCH_NULL;
6725 }
6726 }
6727
6728 // #included from: catch_console_colour_impl.hpp
6729 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
6730
6731 namespace Catch {
6732 namespace {
6733
6734 struct IColourImpl {
~IColourImplCatch::__anonae0470d70411::IColourImpl6735 virtual ~IColourImpl() {}
6736 virtual void use( Colour::Code _colourCode ) = 0;
6737 };
6738
6739 struct NoColourImpl : IColourImpl {
useCatch::__anonae0470d70411::NoColourImpl6740 void use( Colour::Code ) {}
6741
instanceCatch::__anonae0470d70411::NoColourImpl6742 static IColourImpl* instance() {
6743 static NoColourImpl s_instance;
6744 return &s_instance;
6745 }
6746 };
6747
6748 } // anon namespace
6749 } // namespace Catch
6750
6751 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6752 # ifdef CATCH_PLATFORM_WINDOWS
6753 # define CATCH_CONFIG_COLOUR_WINDOWS
6754 # else
6755 # define CATCH_CONFIG_COLOUR_ANSI
6756 # endif
6757 #endif
6758
6759 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
6760
6761 #ifndef NOMINMAX
6762 #define NOMINMAX
6763 #endif
6764
6765 #ifdef __AFXDLL
6766 #include <AfxWin.h>
6767 #else
6768 #include <windows.h>
6769 #endif
6770
6771 namespace Catch {
6772 namespace {
6773
6774 class Win32ColourImpl : public IColourImpl {
6775 public:
Win32ColourImpl()6776 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6777 {
6778 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6779 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6780 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
6781 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
6782 }
6783
use(Colour::Code _colourCode)6784 virtual void use( Colour::Code _colourCode ) {
6785 switch( _colourCode ) {
6786 case Colour::None: return setTextAttribute( originalForegroundAttributes );
6787 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6788 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
6789 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
6790 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
6791 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6792 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6793 case Colour::Grey: return setTextAttribute( 0 );
6794
6795 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
6796 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6797 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6798 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6799
6800 case Colour::Bright: throw std::logic_error( "not a colour" );
6801 }
6802 }
6803
6804 private:
setTextAttribute(WORD _textAttribute)6805 void setTextAttribute( WORD _textAttribute ) {
6806 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
6807 }
6808 HANDLE stdoutHandle;
6809 WORD originalForegroundAttributes;
6810 WORD originalBackgroundAttributes;
6811 };
6812
platformColourInstance()6813 IColourImpl* platformColourInstance() {
6814 static Win32ColourImpl s_instance;
6815 return &s_instance;
6816 }
6817
6818 } // end anon namespace
6819 } // end namespace Catch
6820
6821 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
6822
6823 #include <unistd.h>
6824
6825 namespace Catch {
6826 namespace {
6827
6828 // use POSIX/ ANSI console terminal codes
6829 // Thanks to Adam Strzelecki for original contribution
6830 // (http://github.com/nanoant)
6831 // https://github.com/philsquared/Catch/pull/131
6832 class PosixColourImpl : public IColourImpl {
6833 public:
use(Colour::Code _colourCode)6834 virtual void use( Colour::Code _colourCode ) {
6835 switch( _colourCode ) {
6836 case Colour::None:
6837 case Colour::White: return setColour( "[0m" );
6838 case Colour::Red: return setColour( "[0;31m" );
6839 case Colour::Green: return setColour( "[0;32m" );
6840 case Colour::Blue: return setColour( "[0:34m" );
6841 case Colour::Cyan: return setColour( "[0;36m" );
6842 case Colour::Yellow: return setColour( "[0;33m" );
6843 case Colour::Grey: return setColour( "[1;30m" );
6844
6845 case Colour::LightGrey: return setColour( "[0;37m" );
6846 case Colour::BrightRed: return setColour( "[1;31m" );
6847 case Colour::BrightGreen: return setColour( "[1;32m" );
6848 case Colour::BrightWhite: return setColour( "[1;37m" );
6849
6850 case Colour::Bright: throw std::logic_error( "not a colour" );
6851 }
6852 }
instance()6853 static IColourImpl* instance() {
6854 static PosixColourImpl s_instance;
6855 return &s_instance;
6856 }
6857
6858 private:
setColour(const char * _escapeCode)6859 void setColour( const char* _escapeCode ) {
6860 Catch::cout() << '\033' << _escapeCode;
6861 }
6862 };
6863
platformColourInstance()6864 IColourImpl* platformColourInstance() {
6865 Ptr<IConfig const> config = getCurrentContext().getConfig();
6866 return (config && config->forceColour()) || isatty(STDOUT_FILENO)
6867 ? PosixColourImpl::instance()
6868 : NoColourImpl::instance();
6869 }
6870
6871 } // end anon namespace
6872 } // end namespace Catch
6873
6874 #else // not Windows or ANSI ///////////////////////////////////////////////
6875
6876 namespace Catch {
6877
platformColourInstance()6878 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
6879
6880 } // end namespace Catch
6881
6882 #endif // Windows/ ANSI/ None
6883
6884 namespace Catch {
6885
Colour(Code _colourCode)6886 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
Colour(Colour const & _other)6887 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
~Colour()6888 Colour::~Colour(){ if( !m_moved ) use( None ); }
6889
use(Code _colourCode)6890 void Colour::use( Code _colourCode ) {
6891 static IColourImpl* impl = isDebuggerActive()
6892 ? NoColourImpl::instance()
6893 : platformColourInstance();
6894 impl->use( _colourCode );
6895 }
6896
6897 } // end namespace Catch
6898
6899 // #included from: catch_generators_impl.hpp
6900 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
6901
6902 #include <vector>
6903 #include <string>
6904 #include <map>
6905
6906 namespace Catch {
6907
6908 struct GeneratorInfo : IGeneratorInfo {
6909
GeneratorInfoCatch::GeneratorInfo6910 GeneratorInfo( std::size_t size )
6911 : m_size( size ),
6912 m_currentIndex( 0 )
6913 {}
6914
moveNextCatch::GeneratorInfo6915 bool moveNext() {
6916 if( ++m_currentIndex == m_size ) {
6917 m_currentIndex = 0;
6918 return false;
6919 }
6920 return true;
6921 }
6922
getCurrentIndexCatch::GeneratorInfo6923 std::size_t getCurrentIndex() const {
6924 return m_currentIndex;
6925 }
6926
6927 std::size_t m_size;
6928 std::size_t m_currentIndex;
6929 };
6930
6931 ///////////////////////////////////////////////////////////////////////////
6932
6933 class GeneratorsForTest : public IGeneratorsForTest {
6934
6935 public:
~GeneratorsForTest()6936 ~GeneratorsForTest() {
6937 deleteAll( m_generatorsInOrder );
6938 }
6939
getGeneratorInfo(std::string const & fileInfo,std::size_t size)6940 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
6941 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
6942 if( it == m_generatorsByName.end() ) {
6943 IGeneratorInfo* info = new GeneratorInfo( size );
6944 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
6945 m_generatorsInOrder.push_back( info );
6946 return *info;
6947 }
6948 return *it->second;
6949 }
6950
moveNext()6951 bool moveNext() {
6952 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
6953 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
6954 for(; it != itEnd; ++it ) {
6955 if( (*it)->moveNext() )
6956 return true;
6957 }
6958 return false;
6959 }
6960
6961 private:
6962 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
6963 std::vector<IGeneratorInfo*> m_generatorsInOrder;
6964 };
6965
createGeneratorsForTest()6966 IGeneratorsForTest* createGeneratorsForTest()
6967 {
6968 return new GeneratorsForTest();
6969 }
6970
6971 } // end namespace Catch
6972
6973 // #included from: catch_assertionresult.hpp
6974 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
6975
6976 namespace Catch {
6977
AssertionInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,std::string const & _capturedExpression,ResultDisposition::Flags _resultDisposition)6978 AssertionInfo::AssertionInfo( std::string const& _macroName,
6979 SourceLineInfo const& _lineInfo,
6980 std::string const& _capturedExpression,
6981 ResultDisposition::Flags _resultDisposition )
6982 : macroName( _macroName ),
6983 lineInfo( _lineInfo ),
6984 capturedExpression( _capturedExpression ),
6985 resultDisposition( _resultDisposition )
6986 {}
6987
AssertionResult()6988 AssertionResult::AssertionResult() {}
6989
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)6990 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
6991 : m_info( info ),
6992 m_resultData( data )
6993 {}
6994
~AssertionResult()6995 AssertionResult::~AssertionResult() {}
6996
6997 // Result was a success
succeeded() const6998 bool AssertionResult::succeeded() const {
6999 return Catch::isOk( m_resultData.resultType );
7000 }
7001
7002 // Result was a success, or failure is suppressed
isOk() const7003 bool AssertionResult::isOk() const {
7004 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
7005 }
7006
getResultType() const7007 ResultWas::OfType AssertionResult::getResultType() const {
7008 return m_resultData.resultType;
7009 }
7010
hasExpression() const7011 bool AssertionResult::hasExpression() const {
7012 return !m_info.capturedExpression.empty();
7013 }
7014
hasMessage() const7015 bool AssertionResult::hasMessage() const {
7016 return !m_resultData.message.empty();
7017 }
7018
getExpression() const7019 std::string AssertionResult::getExpression() const {
7020 if( isFalseTest( m_info.resultDisposition ) )
7021 return "!" + m_info.capturedExpression;
7022 else
7023 return m_info.capturedExpression;
7024 }
getExpressionInMacro() const7025 std::string AssertionResult::getExpressionInMacro() const {
7026 if( m_info.macroName.empty() )
7027 return m_info.capturedExpression;
7028 else
7029 return m_info.macroName + "( " + m_info.capturedExpression + " )";
7030 }
7031
hasExpandedExpression() const7032 bool AssertionResult::hasExpandedExpression() const {
7033 return hasExpression() && getExpandedExpression() != getExpression();
7034 }
7035
getExpandedExpression() const7036 std::string AssertionResult::getExpandedExpression() const {
7037 return m_resultData.reconstructedExpression;
7038 }
7039
getMessage() const7040 std::string AssertionResult::getMessage() const {
7041 return m_resultData.message;
7042 }
getSourceInfo() const7043 SourceLineInfo AssertionResult::getSourceInfo() const {
7044 return m_info.lineInfo;
7045 }
7046
getTestMacroName() const7047 std::string AssertionResult::getTestMacroName() const {
7048 return m_info.macroName;
7049 }
7050
7051 } // end namespace Catch
7052
7053 // #included from: catch_test_case_info.hpp
7054 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
7055
7056 namespace Catch {
7057
parseSpecialTag(std::string const & tag)7058 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
7059 if( startsWith( tag, "." ) ||
7060 tag == "hide" ||
7061 tag == "!hide" )
7062 return TestCaseInfo::IsHidden;
7063 else if( tag == "!throws" )
7064 return TestCaseInfo::Throws;
7065 else if( tag == "!shouldfail" )
7066 return TestCaseInfo::ShouldFail;
7067 else if( tag == "!mayfail" )
7068 return TestCaseInfo::MayFail;
7069 else
7070 return TestCaseInfo::None;
7071 }
isReservedTag(std::string const & tag)7072 inline bool isReservedTag( std::string const& tag ) {
7073 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
7074 }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)7075 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
7076 if( isReservedTag( tag ) ) {
7077 {
7078 Colour colourGuard( Colour::Red );
7079 Catch::cerr()
7080 << "Tag name [" << tag << "] not allowed.\n"
7081 << "Tag names starting with non alpha-numeric characters are reserved\n";
7082 }
7083 {
7084 Colour colourGuard( Colour::FileName );
7085 Catch::cerr() << _lineInfo << std::endl;
7086 }
7087 exit(1);
7088 }
7089 }
7090
makeTestCase(ITestCase * _testCase,std::string const & _className,std::string const & _name,std::string const & _descOrTags,SourceLineInfo const & _lineInfo)7091 TestCase makeTestCase( ITestCase* _testCase,
7092 std::string const& _className,
7093 std::string const& _name,
7094 std::string const& _descOrTags,
7095 SourceLineInfo const& _lineInfo )
7096 {
7097 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
7098
7099 // Parse out tags
7100 std::set<std::string> tags;
7101 std::string desc, tag;
7102 bool inTag = false;
7103 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7104 char c = _descOrTags[i];
7105 if( !inTag ) {
7106 if( c == '[' )
7107 inTag = true;
7108 else
7109 desc += c;
7110 }
7111 else {
7112 if( c == ']' ) {
7113 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
7114 if( prop == TestCaseInfo::IsHidden )
7115 isHidden = true;
7116 else if( prop == TestCaseInfo::None )
7117 enforceNotReservedTag( tag, _lineInfo );
7118
7119 tags.insert( tag );
7120 tag.clear();
7121 inTag = false;
7122 }
7123 else
7124 tag += c;
7125 }
7126 }
7127 if( isHidden ) {
7128 tags.insert( "hide" );
7129 tags.insert( "." );
7130 }
7131
7132 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
7133 return TestCase( _testCase, info );
7134 }
7135
setTags(TestCaseInfo & testCaseInfo,std::set<std::string> const & tags)7136 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
7137 {
7138 testCaseInfo.tags = tags;
7139 testCaseInfo.lcaseTags.clear();
7140
7141 std::ostringstream oss;
7142 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
7143 oss << "[" << *it << "]";
7144 std::string lcaseTag = toLower( *it );
7145 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
7146 testCaseInfo.lcaseTags.insert( lcaseTag );
7147 }
7148 testCaseInfo.tagsAsString = oss.str();
7149 }
7150
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::set<std::string> const & _tags,SourceLineInfo const & _lineInfo)7151 TestCaseInfo::TestCaseInfo( std::string const& _name,
7152 std::string const& _className,
7153 std::string const& _description,
7154 std::set<std::string> const& _tags,
7155 SourceLineInfo const& _lineInfo )
7156 : name( _name ),
7157 className( _className ),
7158 description( _description ),
7159 lineInfo( _lineInfo ),
7160 properties( None )
7161 {
7162 setTags( *this, _tags );
7163 }
7164
TestCaseInfo(TestCaseInfo const & other)7165 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
7166 : name( other.name ),
7167 className( other.className ),
7168 description( other.description ),
7169 tags( other.tags ),
7170 lcaseTags( other.lcaseTags ),
7171 tagsAsString( other.tagsAsString ),
7172 lineInfo( other.lineInfo ),
7173 properties( other.properties )
7174 {}
7175
isHidden() const7176 bool TestCaseInfo::isHidden() const {
7177 return ( properties & IsHidden ) != 0;
7178 }
throws() const7179 bool TestCaseInfo::throws() const {
7180 return ( properties & Throws ) != 0;
7181 }
okToFail() const7182 bool TestCaseInfo::okToFail() const {
7183 return ( properties & (ShouldFail | MayFail ) ) != 0;
7184 }
expectedToFail() const7185 bool TestCaseInfo::expectedToFail() const {
7186 return ( properties & (ShouldFail ) ) != 0;
7187 }
7188
TestCase(ITestCase * testCase,TestCaseInfo const & info)7189 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
7190
TestCase(TestCase const & other)7191 TestCase::TestCase( TestCase const& other )
7192 : TestCaseInfo( other ),
7193 test( other.test )
7194 {}
7195
withName(std::string const & _newName) const7196 TestCase TestCase::withName( std::string const& _newName ) const {
7197 TestCase other( *this );
7198 other.name = _newName;
7199 return other;
7200 }
7201
swap(TestCase & other)7202 void TestCase::swap( TestCase& other ) {
7203 test.swap( other.test );
7204 name.swap( other.name );
7205 className.swap( other.className );
7206 description.swap( other.description );
7207 tags.swap( other.tags );
7208 lcaseTags.swap( other.lcaseTags );
7209 tagsAsString.swap( other.tagsAsString );
7210 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
7211 std::swap( lineInfo, other.lineInfo );
7212 }
7213
invoke() const7214 void TestCase::invoke() const {
7215 test->invoke();
7216 }
7217
operator ==(TestCase const & other) const7218 bool TestCase::operator == ( TestCase const& other ) const {
7219 return test.get() == other.test.get() &&
7220 name == other.name &&
7221 className == other.className;
7222 }
7223
operator <(TestCase const & other) const7224 bool TestCase::operator < ( TestCase const& other ) const {
7225 return name < other.name;
7226 }
operator =(TestCase const & other)7227 TestCase& TestCase::operator = ( TestCase const& other ) {
7228 TestCase temp( other );
7229 swap( temp );
7230 return *this;
7231 }
7232
getTestCaseInfo() const7233 TestCaseInfo const& TestCase::getTestCaseInfo() const
7234 {
7235 return *this;
7236 }
7237
7238 } // end namespace Catch
7239
7240 // #included from: catch_version.hpp
7241 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7242
7243 namespace Catch {
7244
Version(unsigned int _majorVersion,unsigned int _minorVersion,unsigned int _patchNumber,std::string const & _branchName,unsigned int _buildNumber)7245 Version::Version
7246 ( unsigned int _majorVersion,
7247 unsigned int _minorVersion,
7248 unsigned int _patchNumber,
7249 std::string const& _branchName,
7250 unsigned int _buildNumber )
7251 : majorVersion( _majorVersion ),
7252 minorVersion( _minorVersion ),
7253 patchNumber( _patchNumber ),
7254 branchName( _branchName ),
7255 buildNumber( _buildNumber )
7256 {}
7257
operator <<(std::ostream & os,Version const & version)7258 std::ostream& operator << ( std::ostream& os, Version const& version ) {
7259 os << version.majorVersion << "."
7260 << version.minorVersion << "."
7261 << version.patchNumber;
7262
7263 if( !version.branchName.empty() ) {
7264 os << "-" << version.branchName
7265 << "." << version.buildNumber;
7266 }
7267 return os;
7268 }
7269
7270 Version libraryVersion( 1, 3, 0, "", 0 );
7271
7272 }
7273
7274 // #included from: catch_message.hpp
7275 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
7276
7277 namespace Catch {
7278
MessageInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)7279 MessageInfo::MessageInfo( std::string const& _macroName,
7280 SourceLineInfo const& _lineInfo,
7281 ResultWas::OfType _type )
7282 : macroName( _macroName ),
7283 lineInfo( _lineInfo ),
7284 type( _type ),
7285 sequence( ++globalCount )
7286 {}
7287
7288 // This may need protecting if threading support is added
7289 unsigned int MessageInfo::globalCount = 0;
7290
7291 ////////////////////////////////////////////////////////////////////////////
7292
ScopedMessage(MessageBuilder const & builder)7293 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
7294 : m_info( builder.m_info )
7295 {
7296 m_info.message = builder.m_stream.str();
7297 getResultCapture().pushScopedMessage( m_info );
7298 }
ScopedMessage(ScopedMessage const & other)7299 ScopedMessage::ScopedMessage( ScopedMessage const& other )
7300 : m_info( other.m_info )
7301 {}
7302
~ScopedMessage()7303 ScopedMessage::~ScopedMessage() {
7304 getResultCapture().popScopedMessage( m_info );
7305 }
7306
7307 } // end namespace Catch
7308
7309 // #included from: catch_legacy_reporter_adapter.hpp
7310 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
7311
7312 // #included from: catch_legacy_reporter_adapter.h
7313 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
7314
7315 namespace Catch
7316 {
7317 // Deprecated
7318 struct IReporter : IShared {
7319 virtual ~IReporter();
7320
7321 virtual bool shouldRedirectStdout() const = 0;
7322
7323 virtual void StartTesting() = 0;
7324 virtual void EndTesting( Totals const& totals ) = 0;
7325 virtual void StartGroup( std::string const& groupName ) = 0;
7326 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
7327 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
7328 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
7329 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
7330 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
7331 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
7332 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
7333 virtual void Aborted() = 0;
7334 virtual void Result( AssertionResult const& result ) = 0;
7335 };
7336
7337 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
7338 {
7339 public:
7340 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
7341 virtual ~LegacyReporterAdapter();
7342
7343 virtual ReporterPreferences getPreferences() const;
7344 virtual void noMatchingTestCases( std::string const& );
7345 virtual void testRunStarting( TestRunInfo const& );
7346 virtual void testGroupStarting( GroupInfo const& groupInfo );
7347 virtual void testCaseStarting( TestCaseInfo const& testInfo );
7348 virtual void sectionStarting( SectionInfo const& sectionInfo );
7349 virtual void assertionStarting( AssertionInfo const& );
7350 virtual bool assertionEnded( AssertionStats const& assertionStats );
7351 virtual void sectionEnded( SectionStats const& sectionStats );
7352 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
7353 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
7354 virtual void testRunEnded( TestRunStats const& testRunStats );
7355 virtual void skipTest( TestCaseInfo const& );
7356
7357 private:
7358 Ptr<IReporter> m_legacyReporter;
7359 };
7360 }
7361
7362 namespace Catch
7363 {
LegacyReporterAdapter(Ptr<IReporter> const & legacyReporter)7364 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
7365 : m_legacyReporter( legacyReporter )
7366 {}
~LegacyReporterAdapter()7367 LegacyReporterAdapter::~LegacyReporterAdapter() {}
7368
getPreferences() const7369 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
7370 ReporterPreferences prefs;
7371 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
7372 return prefs;
7373 }
7374
noMatchingTestCases(std::string const &)7375 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
testRunStarting(TestRunInfo const &)7376 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
7377 m_legacyReporter->StartTesting();
7378 }
testGroupStarting(GroupInfo const & groupInfo)7379 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
7380 m_legacyReporter->StartGroup( groupInfo.name );
7381 }
testCaseStarting(TestCaseInfo const & testInfo)7382 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
7383 m_legacyReporter->StartTestCase( testInfo );
7384 }
sectionStarting(SectionInfo const & sectionInfo)7385 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
7386 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
7387 }
assertionStarting(AssertionInfo const &)7388 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
7389 // Not on legacy interface
7390 }
7391
assertionEnded(AssertionStats const & assertionStats)7392 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
7393 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
7394 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
7395 it != itEnd;
7396 ++it ) {
7397 if( it->type == ResultWas::Info ) {
7398 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
7399 rb << it->message;
7400 rb.setResultType( ResultWas::Info );
7401 AssertionResult result = rb.build();
7402 m_legacyReporter->Result( result );
7403 }
7404 }
7405 }
7406 m_legacyReporter->Result( assertionStats.assertionResult );
7407 return true;
7408 }
sectionEnded(SectionStats const & sectionStats)7409 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
7410 if( sectionStats.missingAssertions )
7411 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
7412 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
7413 }
testCaseEnded(TestCaseStats const & testCaseStats)7414 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
7415 m_legacyReporter->EndTestCase
7416 ( testCaseStats.testInfo,
7417 testCaseStats.totals,
7418 testCaseStats.stdOut,
7419 testCaseStats.stdErr );
7420 }
testGroupEnded(TestGroupStats const & testGroupStats)7421 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
7422 if( testGroupStats.aborting )
7423 m_legacyReporter->Aborted();
7424 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
7425 }
testRunEnded(TestRunStats const & testRunStats)7426 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
7427 m_legacyReporter->EndTesting( testRunStats.totals );
7428 }
skipTest(TestCaseInfo const &)7429 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
7430 }
7431 }
7432
7433 // #included from: catch_timer.hpp
7434
7435 #ifdef __clang__
7436 #pragma clang diagnostic push
7437 #pragma clang diagnostic ignored "-Wc++11-long-long"
7438 #endif
7439
7440 #ifdef CATCH_PLATFORM_WINDOWS
7441 #include <windows.h>
7442 #else
7443 #include <sys/time.h>
7444 #endif
7445
7446 namespace Catch {
7447
7448 namespace {
7449 #ifdef CATCH_PLATFORM_WINDOWS
getCurrentTicks()7450 uint64_t getCurrentTicks() {
7451 static uint64_t hz=0, hzo=0;
7452 if (!hz) {
7453 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
7454 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
7455 }
7456 uint64_t t;
7457 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
7458 return ((t-hzo)*1000000)/hz;
7459 }
7460 #else
7461 uint64_t getCurrentTicks() {
7462 timeval t;
7463 gettimeofday(&t,CATCH_NULL);
7464 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
7465 }
7466 #endif
7467 }
7468
start()7469 void Timer::start() {
7470 m_ticks = getCurrentTicks();
7471 }
getElapsedMicroseconds() const7472 unsigned int Timer::getElapsedMicroseconds() const {
7473 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
7474 }
getElapsedMilliseconds() const7475 unsigned int Timer::getElapsedMilliseconds() const {
7476 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
7477 }
getElapsedSeconds() const7478 double Timer::getElapsedSeconds() const {
7479 return getElapsedMicroseconds()/1000000.0;
7480 }
7481
7482 } // namespace Catch
7483
7484 #ifdef __clang__
7485 #pragma clang diagnostic pop
7486 #endif
7487 // #included from: catch_common.hpp
7488 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
7489
7490 namespace Catch {
7491
startsWith(std::string const & s,std::string const & prefix)7492 bool startsWith( std::string const& s, std::string const& prefix ) {
7493 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
7494 }
endsWith(std::string const & s,std::string const & suffix)7495