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