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