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