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