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