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