1 /*
2 * Catch v1.12.1
3 * Generated: 2018-03-02 21:17:41.036711
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>
opCast(T const & t)1323 T& opCast(T const& t) { return const_cast<T&>(t); }
1324
1325 // nullptr_t support based on pull request #154 from Konstantin Baumann
1326 #ifdef CATCH_CONFIG_CPP11_NULLPTR
opCast(std::nullptr_t)1327 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1328 #endif // CATCH_CONFIG_CPP11_NULLPTR
1329
1330 // So the compare overloads can be operator agnostic we convey the operator as a template
1331 // enum, which is used to specialise an Evaluator for doing the comparison.
1332 template<typename T1, typename T2, Operator Op>
1333 struct Evaluator{};
1334
1335 template<typename T1, typename T2>
1336 struct Evaluator<T1, T2, IsEqualTo> {
evaluateCatch::Internal::Evaluator1337 static bool evaluate( T1 const& lhs, T2 const& rhs) {
1338 return bool( opCast( lhs ) == opCast( rhs ) );
1339 }
1340 };
1341 template<typename T1, typename T2>
1342 struct Evaluator<T1, T2, IsNotEqualTo> {
evaluateCatch::Internal::Evaluator1343 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1344 return bool( opCast( lhs ) != opCast( rhs ) );
1345 }
1346 };
1347 template<typename T1, typename T2>
1348 struct Evaluator<T1, T2, IsLessThan> {
evaluateCatch::Internal::Evaluator1349 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1350 return bool( opCast( lhs ) < opCast( rhs ) );
1351 }
1352 };
1353 template<typename T1, typename T2>
1354 struct Evaluator<T1, T2, IsGreaterThan> {
evaluateCatch::Internal::Evaluator1355 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1356 return bool( opCast( lhs ) > opCast( rhs ) );
1357 }
1358 };
1359 template<typename T1, typename T2>
1360 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1361 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1362 return bool( opCast( lhs ) >= opCast( rhs ) );
1363 }
1364 };
1365 template<typename T1, typename T2>
1366 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1367 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1368 return bool( opCast( lhs ) <= opCast( rhs ) );
1369 }
1370 };
1371
1372 template<Operator Op, typename T1, typename T2>
applyEvaluator(T1 const & lhs,T2 const & rhs)1373 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
1374 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1375 }
1376
1377 // This level of indirection allows us to specialise for integer types
1378 // to avoid signed/ unsigned warnings
1379
1380 // "base" overload
1381 template<Operator Op, typename T1, typename T2>
compare(T1 const & lhs,T2 const & rhs)1382 bool compare( T1 const& lhs, T2 const& rhs ) {
1383 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1384 }
1385
1386 // unsigned X to int
compare(unsigned int lhs,int rhs)1387 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
1388 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1389 }
compare(unsigned long lhs,int rhs)1390 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
1391 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1392 }
compare(unsigned char lhs,int rhs)1393 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
1394 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1395 }
1396
1397 // unsigned X to long
compare(unsigned int lhs,long rhs)1398 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
1399 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1400 }
compare(unsigned long lhs,long rhs)1401 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
1402 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1403 }
compare(unsigned char lhs,long rhs)1404 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
1405 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1406 }
1407
1408 // int to unsigned X
compare(int lhs,unsigned int rhs)1409 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
1410 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1411 }
compare(int lhs,unsigned long rhs)1412 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
1413 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1414 }
compare(int lhs,unsigned char rhs)1415 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
1416 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1417 }
1418
1419 // long to unsigned X
compare(long lhs,unsigned int rhs)1420 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
1421 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1422 }
compare(long lhs,unsigned long rhs)1423 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
1424 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1425 }
compare(long lhs,unsigned char rhs)1426 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
1427 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1428 }
1429
1430 // pointer to long (when comparing against NULL)
compare(long lhs,T * rhs)1431 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
1432 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1433 }
compare(T * lhs,long rhs)1434 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
1435 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1436 }
1437
1438 // pointer to int (when comparing against NULL)
compare(int lhs,T * rhs)1439 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
1440 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1441 }
compare(T * lhs,int rhs)1442 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
1443 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1444 }
1445
1446 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1447 // long long to unsigned X
compare(long long lhs,unsigned int rhs)1448 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1449 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1450 }
compare(long long lhs,unsigned long rhs)1451 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1452 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1453 }
compare(long long lhs,unsigned long long rhs)1454 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1455 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1456 }
compare(long long lhs,unsigned char rhs)1457 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1458 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1459 }
1460
1461 // unsigned long long to X
compare(unsigned long long lhs,int rhs)1462 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1463 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1464 }
compare(unsigned long long lhs,long rhs)1465 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1466 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1467 }
compare(unsigned long long lhs,long long rhs)1468 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1469 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1470 }
compare(unsigned long long lhs,char rhs)1471 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1472 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1473 }
1474
1475 // pointer to long long (when comparing against NULL)
compare(long long lhs,T * rhs)1476 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1477 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1478 }
compare(T * lhs,long long rhs)1479 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1480 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1481 }
1482 #endif // CATCH_CONFIG_CPP11_LONG_LONG
1483
1484 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1485 // pointer to nullptr_t (when comparing against nullptr)
compare(std::nullptr_t,T * rhs)1486 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1487 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
1488 }
compare(T * lhs,std::nullptr_t)1489 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1490 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
1491 }
1492 #endif // CATCH_CONFIG_CPP11_NULLPTR
1493
1494 } // end of namespace Internal
1495 } // end of namespace Catch
1496
1497 #ifdef _MSC_VER
1498 #pragma warning(pop)
1499 #endif
1500
1501 // #included from: catch_tostring.h
1502 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1503
1504 #include <sstream>
1505 #include <iomanip>
1506 #include <limits>
1507 #include <vector>
1508 #include <cstddef>
1509
1510 #ifdef __OBJC__
1511 // #included from: catch_objc_arc.hpp
1512 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1513
1514 #import <Foundation/Foundation.h>
1515
1516 #ifdef __has_feature
1517 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1518 #else
1519 #define CATCH_ARC_ENABLED 0
1520 #endif
1521
1522 void arcSafeRelease( NSObject* obj );
1523 id performOptionalSelector( id obj, SEL sel );
1524
1525 #if !CATCH_ARC_ENABLED
arcSafeRelease(NSObject * obj)1526 inline void arcSafeRelease( NSObject* obj ) {
1527 [obj release];
1528 }
performOptionalSelector(id obj,SEL sel)1529 inline id performOptionalSelector( id obj, SEL sel ) {
1530 if( [obj respondsToSelector: sel] )
1531 return [obj performSelector: sel];
1532 return nil;
1533 }
1534 #define CATCH_UNSAFE_UNRETAINED
1535 #define CATCH_ARC_STRONG
1536 #else
arcSafeRelease(NSObject *)1537 inline void arcSafeRelease( NSObject* ){}
performOptionalSelector(id obj,SEL sel)1538 inline id performOptionalSelector( id obj, SEL sel ) {
1539 #ifdef __clang__
1540 #pragma clang diagnostic push
1541 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1542 #endif
1543 if( [obj respondsToSelector: sel] )
1544 return [obj performSelector: sel];
1545 #ifdef __clang__
1546 #pragma clang diagnostic pop
1547 #endif
1548 return nil;
1549 }
1550 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1551 #define CATCH_ARC_STRONG __strong
1552 #endif
1553
1554 #endif
1555
1556 #ifdef CATCH_CONFIG_CPP11_TUPLE
1557 #include <tuple>
1558 #endif
1559
1560 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1561 #include <type_traits>
1562 #endif
1563
1564 namespace Catch {
1565
1566 // Why we're here.
1567 template<typename T>
1568 std::string toString( T const& value );
1569
1570 // Built in overloads
1571
1572 std::string toString( std::string const& value );
1573 std::string toString( std::wstring const& value );
1574 std::string toString( const char* const value );
1575 std::string toString( char* const value );
1576 std::string toString( const wchar_t* const value );
1577 std::string toString( wchar_t* const value );
1578 std::string toString( int value );
1579 std::string toString( unsigned long value );
1580 std::string toString( unsigned int value );
1581 std::string toString( const double value );
1582 std::string toString( const float value );
1583 std::string toString( bool value );
1584 std::string toString( char value );
1585 std::string toString( signed char value );
1586 std::string toString( unsigned char value );
1587
1588 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1589 std::string toString( long long value );
1590 std::string toString( unsigned long long value );
1591 #endif
1592
1593 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1594 std::string toString( std::nullptr_t );
1595 #endif
1596
1597 #ifdef __OBJC__
1598 std::string toString( NSString const * const& nsstring );
1599 std::string toString( NSString * CATCH_ARC_STRONG & nsstring );
1600 std::string toString( NSObject* const& nsObject );
1601 #endif
1602
1603 namespace Detail {
1604
1605 extern const std::string unprintableString;
1606
1607 #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK)
1608 struct BorgType {
1609 template<typename T> BorgType( T const& );
1610 };
1611
1612 struct TrueType { char sizer[1]; };
1613 struct FalseType { char sizer[2]; };
1614
1615 TrueType& testStreamable( std::ostream& );
1616 FalseType testStreamable( FalseType );
1617
1618 FalseType operator<<( std::ostream const&, BorgType const& );
1619
1620 template<typename T>
1621 struct IsStreamInsertable {
1622 static std::ostream &s;
1623 static T const&t;
1624 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1625 };
1626 #else
1627 template<typename T>
1628 class IsStreamInsertable {
1629 template<typename SS, typename TT>
1630 static auto test(int)
1631 -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
1632
1633 template<typename, typename>
1634 static auto test(...) -> std::false_type;
1635
1636 public:
1637 static const bool value = decltype(test<std::ostream,const T&>(0))::value;
1638 };
1639 #endif
1640
1641 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1642 template<typename T,
1643 bool IsEnum = std::is_enum<T>::value
1644 >
1645 struct EnumStringMaker
1646 {
convertCatch::Detail::EnumStringMaker1647 static std::string convert( T const& ) { return unprintableString; }
1648 };
1649
1650 template<typename T>
1651 struct EnumStringMaker<T,true>
1652 {
convertCatch::Detail::EnumStringMaker1653 static std::string convert( T const& v )
1654 {
1655 return ::Catch::toString(
1656 static_cast<typename std::underlying_type<T>::type>(v)
1657 );
1658 }
1659 };
1660 #endif
1661 template<bool C>
1662 struct StringMakerBase {
1663 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1664 template<typename T>
convertCatch::Detail::StringMakerBase1665 static std::string convert( T const& v )
1666 {
1667 return EnumStringMaker<T>::convert( v );
1668 }
1669 #else
1670 template<typename T>
1671 static std::string convert( T const& ) { return unprintableString; }
1672 #endif
1673 };
1674
1675 template<>
1676 struct StringMakerBase<true> {
1677 template<typename T>
convertCatch::Detail::StringMakerBase1678 static std::string convert( T const& _value ) {
1679 std::ostringstream oss;
1680 oss << _value;
1681 return oss.str();
1682 }
1683 };
1684
1685 std::string rawMemoryToString( const void *object, std::size_t size );
1686
1687 template<typename T>
rawMemoryToString(const T & object)1688 std::string rawMemoryToString( const T& object ) {
1689 return rawMemoryToString( &object, sizeof(object) );
1690 }
1691
1692 } // end namespace Detail
1693
1694 template<typename T>
1695 struct StringMaker :
1696 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1697
1698 template<typename T>
1699 struct StringMaker<T*> {
1700 template<typename U>
convertCatch::StringMaker1701 static std::string convert( U* p ) {
1702 if( !p )
1703 return "NULL";
1704 else
1705 return Detail::rawMemoryToString( p );
1706 }
1707 };
1708
1709 template<typename R, typename C>
1710 struct StringMaker<R C::*> {
convertCatch::StringMaker1711 static std::string convert( R C::* p ) {
1712 if( !p )
1713 return "NULL";
1714 else
1715 return Detail::rawMemoryToString( p );
1716 }
1717 };
1718
1719 namespace Detail {
1720 template<typename InputIterator>
1721 std::string rangeToString( InputIterator first, InputIterator last );
1722 }
1723
1724 //template<typename T, typename Allocator>
1725 //struct StringMaker<std::vector<T, Allocator> > {
1726 // static std::string convert( std::vector<T,Allocator> const& v ) {
1727 // return Detail::rangeToString( v.begin(), v.end() );
1728 // }
1729 //};
1730
1731 template<typename T, typename Allocator>
toString(std::vector<T,Allocator> const & v)1732 std::string toString( std::vector<T,Allocator> const& v ) {
1733 return Detail::rangeToString( v.begin(), v.end() );
1734 }
1735
1736 #ifdef CATCH_CONFIG_CPP11_TUPLE
1737
1738 // toString for tuples
1739 namespace TupleDetail {
1740 template<
1741 typename Tuple,
1742 std::size_t N = 0,
1743 bool = (N < std::tuple_size<Tuple>::value)
1744 >
1745 struct ElementPrinter {
printCatch::TupleDetail::ElementPrinter1746 static void print( const Tuple& tuple, std::ostream& os )
1747 {
1748 os << ( N ? ", " : " " )
1749 << Catch::toString(std::get<N>(tuple));
1750 ElementPrinter<Tuple,N+1>::print(tuple,os);
1751 }
1752 };
1753
1754 template<
1755 typename Tuple,
1756 std::size_t N
1757 >
1758 struct ElementPrinter<Tuple,N,false> {
printCatch::TupleDetail::ElementPrinter1759 static void print( const Tuple&, std::ostream& ) {}
1760 };
1761
1762 }
1763
1764 template<typename ...Types>
1765 struct StringMaker<std::tuple<Types...>> {
1766
convertCatch::StringMaker1767 static std::string convert( const std::tuple<Types...>& tuple )
1768 {
1769 std::ostringstream os;
1770 os << '{';
1771 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1772 os << " }";
1773 return os.str();
1774 }
1775 };
1776 #endif // CATCH_CONFIG_CPP11_TUPLE
1777
1778 namespace Detail {
1779 template<typename T>
makeString(T const & value)1780 std::string makeString( T const& value ) {
1781 return StringMaker<T>::convert( value );
1782 }
1783 } // end namespace Detail
1784
1785 /// \brief converts any type to a string
1786 ///
1787 /// The default template forwards on to ostringstream - except when an
1788 /// ostringstream overload does not exist - in which case it attempts to detect
1789 /// that and writes {?}.
1790 /// Overload (not specialise) this template for custom typs that you don't want
1791 /// to provide an ostream overload for.
1792 template<typename T>
toString(T const & value)1793 std::string toString( T const& value ) {
1794 return StringMaker<T>::convert( value );
1795 }
1796
1797 namespace Detail {
1798 template<typename InputIterator>
rangeToString(InputIterator first,InputIterator last)1799 std::string rangeToString( InputIterator first, InputIterator last ) {
1800 std::ostringstream oss;
1801 oss << "{ ";
1802 if( first != last ) {
1803 oss << Catch::toString( *first );
1804 for( ++first ; first != last ; ++first )
1805 oss << ", " << Catch::toString( *first );
1806 }
1807 oss << " }";
1808 return oss.str();
1809 }
1810 }
1811
1812 } // end namespace Catch
1813
1814 namespace Catch {
1815
1816 template<typename LhsT, Internal::Operator Op, typename RhsT>
1817 class BinaryExpression;
1818
1819 template<typename ArgT, typename MatcherT>
1820 class MatchExpression;
1821
1822 // Wraps the LHS of an expression and overloads comparison operators
1823 // for also capturing those and RHS (if any)
1824 template<typename T>
1825 class ExpressionLhs : public DecomposedExpression {
1826 public:
ExpressionLhs(ResultBuilder & rb,T lhs)1827 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
1828
1829 ExpressionLhs& operator = ( const ExpressionLhs& );
1830
1831 template<typename RhsT>
1832 BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
operator ==(RhsT const & rhs)1833 operator == ( RhsT const& rhs ) {
1834 return captureExpression<Internal::IsEqualTo>( rhs );
1835 }
1836
1837 template<typename RhsT>
1838 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
operator !=(RhsT const & rhs)1839 operator != ( RhsT const& rhs ) {
1840 return captureExpression<Internal::IsNotEqualTo>( rhs );
1841 }
1842
1843 template<typename RhsT>
1844 BinaryExpression<T, Internal::IsLessThan, RhsT const&>
operator <(RhsT const & rhs)1845 operator < ( RhsT const& rhs ) {
1846 return captureExpression<Internal::IsLessThan>( rhs );
1847 }
1848
1849 template<typename RhsT>
1850 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
operator >(RhsT const & rhs)1851 operator > ( RhsT const& rhs ) {
1852 return captureExpression<Internal::IsGreaterThan>( rhs );
1853 }
1854
1855 template<typename RhsT>
1856 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
operator <=(RhsT const & rhs)1857 operator <= ( RhsT const& rhs ) {
1858 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1859 }
1860
1861 template<typename RhsT>
1862 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
operator >=(RhsT const & rhs)1863 operator >= ( RhsT const& rhs ) {
1864 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1865 }
1866
operator ==(bool rhs)1867 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
1868 return captureExpression<Internal::IsEqualTo>( rhs );
1869 }
1870
operator !=(bool rhs)1871 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
1872 return captureExpression<Internal::IsNotEqualTo>( rhs );
1873 }
1874
endExpression()1875 void endExpression() {
1876 m_truthy = m_lhs ? true : false;
1877 m_rb
1878 .setResultType( m_truthy )
1879 .endExpression( *this );
1880 }
1881
reconstructExpression(std::string & dest) const1882 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1883 dest = Catch::toString( m_lhs );
1884 }
1885
1886 private:
1887 template<Internal::Operator Op, typename RhsT>
captureExpression(RhsT & rhs) const1888 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
1889 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
1890 }
1891
1892 template<Internal::Operator Op>
captureExpression(bool rhs) const1893 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
1894 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
1895 }
1896
1897 private:
1898 ResultBuilder& m_rb;
1899 T m_lhs;
1900 bool m_truthy;
1901 };
1902
1903 template<typename LhsT, Internal::Operator Op, typename RhsT>
1904 class BinaryExpression : public DecomposedExpression {
1905 public:
BinaryExpression(ResultBuilder & rb,LhsT lhs,RhsT rhs)1906 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
1907 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
1908
1909 BinaryExpression& operator = ( BinaryExpression& );
1910
endExpression() const1911 void endExpression() const {
1912 m_rb
1913 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
1914 .endExpression( *this );
1915 }
1916
isBinaryExpression() const1917 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1918 return true;
1919 }
1920
reconstructExpression(std::string & dest) const1921 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1922 std::string lhs = Catch::toString( m_lhs );
1923 std::string rhs = Catch::toString( m_rhs );
1924 char delim = lhs.size() + rhs.size() < 40 &&
1925 lhs.find('\n') == std::string::npos &&
1926 rhs.find('\n') == std::string::npos ? ' ' : '\n';
1927 dest.reserve( 7 + lhs.size() + rhs.size() );
1928 // 2 for spaces around operator
1929 // 2 for operator
1930 // 2 for parentheses (conditionally added later)
1931 // 1 for negation (conditionally added later)
1932 dest = lhs;
1933 dest += delim;
1934 dest += Internal::OperatorTraits<Op>::getName();
1935 dest += delim;
1936 dest += rhs;
1937 }
1938
1939 private:
1940 ResultBuilder& m_rb;
1941 LhsT m_lhs;
1942 RhsT m_rhs;
1943 };
1944
1945 template<typename ArgT, typename MatcherT>
1946 class MatchExpression : public DecomposedExpression {
1947 public:
MatchExpression(ArgT arg,MatcherT matcher,char const * matcherString)1948 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
1949 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
1950
isBinaryExpression() const1951 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1952 return true;
1953 }
1954
reconstructExpression(std::string & dest) const1955 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1956 std::string matcherAsString = m_matcher.toString();
1957 dest = Catch::toString( m_arg );
1958 dest += ' ';
1959 if( matcherAsString == Detail::unprintableString )
1960 dest += m_matcherString;
1961 else
1962 dest += matcherAsString;
1963 }
1964
1965 private:
1966 ArgT m_arg;
1967 MatcherT m_matcher;
1968 char const* m_matcherString;
1969 };
1970
1971 } // end namespace Catch
1972
1973
1974 namespace Catch {
1975
1976 template<typename T>
operator <=(T const & operand)1977 ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
1978 return ExpressionLhs<T const&>( *this, operand );
1979 }
1980
operator <=(bool value)1981 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
1982 return ExpressionLhs<bool>( *this, value );
1983 }
1984
1985 template<typename ArgT, typename MatcherT>
captureMatch(ArgT const & arg,MatcherT const & matcher,char const * matcherString)1986 void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
1987 char const* matcherString ) {
1988 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
1989 setResultType( matcher.match( arg ) );
1990 endExpression( expr );
1991 }
1992
1993 } // namespace Catch
1994
1995 // #included from: catch_message.h
1996 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1997
1998 #include <string>
1999
2000 namespace Catch {
2001
2002 struct MessageInfo {
2003 MessageInfo( std::string const& _macroName,
2004 SourceLineInfo const& _lineInfo,
2005 ResultWas::OfType _type );
2006
2007 std::string macroName;
2008 SourceLineInfo lineInfo;
2009 ResultWas::OfType type;
2010 std::string message;
2011 unsigned int sequence;
2012
operator ==Catch::MessageInfo2013 bool operator == ( MessageInfo const& other ) const {
2014 return sequence == other.sequence;
2015 }
operator <Catch::MessageInfo2016 bool operator < ( MessageInfo const& other ) const {
2017 return sequence < other.sequence;
2018 }
2019 private:
2020 static unsigned int globalCount;
2021 };
2022
2023 struct MessageBuilder {
MessageBuilderCatch::MessageBuilder2024 MessageBuilder( std::string const& macroName,
2025 SourceLineInfo const& lineInfo,
2026 ResultWas::OfType type )
2027 : m_info( macroName, lineInfo, type )
2028 {}
2029
2030 template<typename T>
operator <<Catch::MessageBuilder2031 MessageBuilder& operator << ( T const& value ) {
2032 m_stream << value;
2033 return *this;
2034 }
2035
2036 MessageInfo m_info;
2037 std::ostringstream m_stream;
2038 };
2039
2040 class ScopedMessage {
2041 public:
2042 ScopedMessage( MessageBuilder const& builder );
2043 ScopedMessage( ScopedMessage const& other );
2044 ~ScopedMessage();
2045
2046 MessageInfo m_info;
2047 };
2048
2049 } // end namespace Catch
2050
2051 // #included from: catch_interfaces_capture.h
2052 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
2053
2054 #include <string>
2055
2056 namespace Catch {
2057
2058 class TestCase;
2059 class AssertionResult;
2060 struct AssertionInfo;
2061 struct SectionInfo;
2062 struct SectionEndInfo;
2063 struct MessageInfo;
2064 class ScopedMessageBuilder;
2065 struct Counts;
2066
2067 struct IResultCapture {
2068
2069 virtual ~IResultCapture();
2070
2071 virtual void assertionEnded( AssertionResult const& result ) = 0;
2072 virtual bool sectionStarted( SectionInfo const& sectionInfo,
2073 Counts& assertions ) = 0;
2074 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2075 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
2076 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2077 virtual void popScopedMessage( MessageInfo const& message ) = 0;
2078
2079 virtual std::string getCurrentTestName() const = 0;
2080 virtual const AssertionResult* getLastResult() const = 0;
2081
2082 virtual void exceptionEarlyReported() = 0;
2083
2084 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
2085
2086 virtual bool lastAssertionPassed() = 0;
2087 virtual void assertionPassed() = 0;
2088 virtual void assertionRun() = 0;
2089 };
2090
2091 IResultCapture& getResultCapture();
2092 }
2093
2094 // #included from: catch_debugger.h
2095 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
2096
2097 // #included from: catch_platform.h
2098 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2099
2100 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
2101 # define CATCH_PLATFORM_MAC
2102 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
2103 # define CATCH_PLATFORM_IPHONE
2104 #elif defined(linux) || defined(__linux) || defined(__linux__)
2105 # define CATCH_PLATFORM_LINUX
2106 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2107 # define CATCH_PLATFORM_WINDOWS
2108 # if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
2109 # define CATCH_DEFINES_NOMINMAX
2110 # endif
2111 # if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
2112 # define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
2113 # endif
2114 #endif
2115
2116 #include <string>
2117
2118 namespace Catch{
2119
2120 bool isDebuggerActive();
2121 void writeToDebugConsole( std::string const& text );
2122 }
2123
2124 #ifdef CATCH_PLATFORM_MAC
2125
2126 // The following code snippet based on:
2127 // http://cocoawithlove.com/2008/03/break-into-debugger.html
2128 #if defined(__ppc64__) || defined(__ppc__)
2129 #define CATCH_TRAP() \
2130 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2131 : : : "memory","r0","r3","r4" ) /* NOLINT */
2132 #elif defined(__aarch64__)
2133 // Backport of https://github.com/catchorg/Catch2/commit/a25c1a24af8bffd35727a888a307ff0280cf9387
2134 #define CATCH_TRAP() __asm__(".inst 0xd4200000")
2135 #else
2136 #define CATCH_TRAP() __asm__("int $3\n" : : /* NOLINT */ )
2137 #endif
2138
2139 #elif defined(CATCH_PLATFORM_LINUX)
2140 // If we can use inline assembler, do it because this allows us to break
2141 // directly at the location of the failing check instead of breaking inside
2142 // raise() called from it, i.e. one stack frame below.
2143 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
2144 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
2145 #else // Fall back to the generic way.
2146 #include <signal.h>
2147
2148 #define CATCH_TRAP() raise(SIGTRAP)
2149 #endif
2150 #elif defined(_MSC_VER)
2151 #define CATCH_TRAP() __debugbreak()
2152 #elif defined(__MINGW32__)
2153 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
2154 #define CATCH_TRAP() DebugBreak()
2155 #endif
2156
2157 #ifdef CATCH_TRAP
2158 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
2159 #else
2160 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2161 #endif
2162
2163 // #included from: catch_interfaces_runner.h
2164 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2165
2166 namespace Catch {
2167 class TestCase;
2168
2169 struct IRunner {
2170 virtual ~IRunner();
2171 virtual bool aborting() const = 0;
2172 };
2173 }
2174
2175 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
2176 # define CATCH_INTERNAL_STRINGIFY(expr) #expr
2177 #else
2178 # define CATCH_INTERNAL_STRINGIFY(expr) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
2179 #endif
2180
2181 #if defined(CATCH_CONFIG_FAST_COMPILE)
2182 ///////////////////////////////////////////////////////////////////////////////
2183 // We can speedup compilation significantly by breaking into debugger lower in
2184 // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
2185 // macro in each assertion
2186 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2187 resultBuilder.react();
2188
2189 ///////////////////////////////////////////////////////////////////////////////
2190 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2191 // macros.
2192 // This can potentially cause false negative, if the test code catches
2193 // the exception before it propagates back up to the runner.
2194 #define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
2195 do { \
2196 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
2197 __catchResult.setExceptionGuard(); \
2198 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2199 ( __catchResult <= expr ).endExpression(); \
2200 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2201 __catchResult.unsetExceptionGuard(); \
2202 INTERNAL_CATCH_REACT( __catchResult ) \
2203 } 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
2204 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2205
2206 #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
2207 do { \
2208 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2209 __catchResult.setExceptionGuard(); \
2210 __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \
2211 __catchResult.unsetExceptionGuard(); \
2212 INTERNAL_CATCH_REACT( __catchResult ) \
2213 } while( Catch::alwaysFalse() )
2214
2215 #else
2216 ///////////////////////////////////////////////////////////////////////////////
2217 // In the event of a failure works out if the debugger needs to be invoked
2218 // and/or an exception thrown and takes appropriate action.
2219 // This needs to be done as a macro so the debugger will stop in the user
2220 // source code rather than in Catch library code
2221 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2222 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2223 resultBuilder.react();
2224 #endif
2225
2226 ///////////////////////////////////////////////////////////////////////////////
2227 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
2228 do { \
2229 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
2230 try { \
2231 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2232 ( __catchResult <= expr ).endExpression(); \
2233 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2234 } \
2235 catch( ... ) { \
2236 __catchResult.useActiveException( resultDisposition ); \
2237 } \
2238 INTERNAL_CATCH_REACT( __catchResult ) \
2239 } 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
2240 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2241
2242 ///////////////////////////////////////////////////////////////////////////////
2243 #define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \
2244 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
2245 if( Catch::getResultCapture().lastAssertionPassed() )
2246
2247 ///////////////////////////////////////////////////////////////////////////////
2248 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \
2249 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
2250 if( !Catch::getResultCapture().lastAssertionPassed() )
2251
2252 ///////////////////////////////////////////////////////////////////////////////
2253 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
2254 do { \
2255 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \
2256 try { \
2257 static_cast<void>(expr); \
2258 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2259 } \
2260 catch( ... ) { \
2261 __catchResult.useActiveException( resultDisposition ); \
2262 } \
2263 INTERNAL_CATCH_REACT( __catchResult ) \
2264 } while( Catch::alwaysFalse() )
2265
2266 ///////////////////////////////////////////////////////////////////////////////
2267 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
2268 do { \
2269 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition, CATCH_INTERNAL_STRINGIFY(matcher) ); \
2270 if( __catchResult.allowThrows() ) \
2271 try { \
2272 static_cast<void>(expr); \
2273 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2274 } \
2275 catch( ... ) { \
2276 __catchResult.captureExpectedException( matcher ); \
2277 } \
2278 else \
2279 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2280 INTERNAL_CATCH_REACT( __catchResult ) \
2281 } while( Catch::alwaysFalse() )
2282
2283 ///////////////////////////////////////////////////////////////////////////////
2284 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
2285 do { \
2286 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
2287 if( __catchResult.allowThrows() ) \
2288 try { \
2289 static_cast<void>(expr); \
2290 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2291 } \
2292 catch( exceptionType ) { \
2293 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2294 } \
2295 catch( ... ) { \
2296 __catchResult.useActiveException( resultDisposition ); \
2297 } \
2298 else \
2299 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2300 INTERNAL_CATCH_REACT( __catchResult ) \
2301 } while( Catch::alwaysFalse() )
2302
2303 ///////////////////////////////////////////////////////////////////////////////
2304 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2305 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
2306 do { \
2307 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2308 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2309 __catchResult.captureResult( messageType ); \
2310 INTERNAL_CATCH_REACT( __catchResult ) \
2311 } while( Catch::alwaysFalse() )
2312 #else
2313 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \
2314 do { \
2315 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2316 __catchResult << log + ::Catch::StreamEndStop(); \
2317 __catchResult.captureResult( messageType ); \
2318 INTERNAL_CATCH_REACT( __catchResult ) \
2319 } while( Catch::alwaysFalse() )
2320 #endif
2321
2322 ///////////////////////////////////////////////////////////////////////////////
2323 #define INTERNAL_CATCH_INFO( macroName, log ) \
2324 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2325
2326 ///////////////////////////////////////////////////////////////////////////////
2327 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
2328 do { \
2329 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2330 try { \
2331 __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \
2332 } catch( ... ) { \
2333 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2334 } \
2335 INTERNAL_CATCH_REACT( __catchResult ) \
2336 } while( Catch::alwaysFalse() )
2337
2338 // #included from: internal/catch_section.h
2339 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2340
2341 // #included from: catch_section_info.h
2342 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2343
2344 // #included from: catch_totals.hpp
2345 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2346
2347 #include <cstddef>
2348
2349 namespace Catch {
2350
2351 struct Counts {
CountsCatch::Counts2352 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2353
operator -Catch::Counts2354 Counts operator - ( Counts const& other ) const {
2355 Counts diff;
2356 diff.passed = passed - other.passed;
2357 diff.failed = failed - other.failed;
2358 diff.failedButOk = failedButOk - other.failedButOk;
2359 return diff;
2360 }
operator +=Catch::Counts2361 Counts& operator += ( Counts const& other ) {
2362 passed += other.passed;
2363 failed += other.failed;
2364 failedButOk += other.failedButOk;
2365 return *this;
2366 }
2367
totalCatch::Counts2368 std::size_t total() const {
2369 return passed + failed + failedButOk;
2370 }
allPassedCatch::Counts2371 bool allPassed() const {
2372 return failed == 0 && failedButOk == 0;
2373 }
allOkCatch::Counts2374 bool allOk() const {
2375 return failed == 0;
2376 }
2377
2378 std::size_t passed;
2379 std::size_t failed;
2380 std::size_t failedButOk;
2381 };
2382
2383 struct Totals {
2384
operator -Catch::Totals2385 Totals operator - ( Totals const& other ) const {
2386 Totals diff;
2387 diff.assertions = assertions - other.assertions;
2388 diff.testCases = testCases - other.testCases;
2389 return diff;
2390 }
2391
deltaCatch::Totals2392 Totals delta( Totals const& prevTotals ) const {
2393 Totals diff = *this - prevTotals;
2394 if( diff.assertions.failed > 0 )
2395 ++diff.testCases.failed;
2396 else if( diff.assertions.failedButOk > 0 )
2397 ++diff.testCases.failedButOk;
2398 else
2399 ++diff.testCases.passed;
2400 return diff;
2401 }
2402
operator +=Catch::Totals2403 Totals& operator += ( Totals const& other ) {
2404 assertions += other.assertions;
2405 testCases += other.testCases;
2406 return *this;
2407 }
2408
2409 Counts assertions;
2410 Counts testCases;
2411 };
2412 }
2413
2414 #include <string>
2415
2416 namespace Catch {
2417
2418 struct SectionInfo {
2419 SectionInfo
2420 ( SourceLineInfo const& _lineInfo,
2421 std::string const& _name,
2422 std::string const& _description = std::string() );
2423
2424 std::string name;
2425 std::string description;
2426 SourceLineInfo lineInfo;
2427 };
2428
2429 struct SectionEndInfo {
SectionEndInfoCatch::SectionEndInfo2430 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2431 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2432 {}
2433
2434 SectionInfo sectionInfo;
2435 Counts prevAssertions;
2436 double durationInSeconds;
2437 };
2438
2439 } // end namespace Catch
2440
2441 // #included from: catch_timer.h
2442 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2443
2444 #ifdef _MSC_VER
2445
2446 namespace Catch {
2447 typedef unsigned long long UInt64;
2448 }
2449 #else
2450 #include <stdint.h>
2451 namespace Catch {
2452 typedef uint64_t UInt64;
2453 }
2454 #endif
2455
2456 namespace Catch {
2457 class Timer {
2458 public:
Timer()2459 Timer() : m_ticks( 0 ) {}
2460 void start();
2461 unsigned int getElapsedMicroseconds() const;
2462 unsigned int getElapsedMilliseconds() const;
2463 double getElapsedSeconds() const;
2464
2465 private:
2466 UInt64 m_ticks;
2467 };
2468
2469 } // namespace Catch
2470
2471 #include <string>
2472
2473 namespace Catch {
2474
2475 class Section : NonCopyable {
2476 public:
2477 Section( SectionInfo const& info );
2478 ~Section();
2479
2480 // This indicates whether the section should be executed or not
2481 operator bool() const;
2482
2483 private:
2484 SectionInfo m_info;
2485
2486 std::string m_name;
2487 Counts m_assertions;
2488 bool m_sectionIncluded;
2489 Timer m_timer;
2490 };
2491
2492 } // end namespace Catch
2493
2494 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2495 #define INTERNAL_CATCH_SECTION( ... ) \
2496 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2497 #else
2498 #define INTERNAL_CATCH_SECTION( name, desc ) \
2499 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2500 #endif
2501
2502 // #included from: internal/catch_generators.hpp
2503 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2504
2505 #include <vector>
2506 #include <string>
2507 #include <stdlib.h>
2508
2509 namespace Catch {
2510
2511 template<typename T>
2512 struct IGenerator {
~IGeneratorCatch::IGenerator2513 virtual ~IGenerator() {}
2514 virtual T getValue( std::size_t index ) const = 0;
2515 virtual std::size_t size () const = 0;
2516 };
2517
2518 template<typename T>
2519 class BetweenGenerator : public IGenerator<T> {
2520 public:
BetweenGenerator(T from,T to)2521 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2522
getValue(std::size_t index) const2523 virtual T getValue( std::size_t index ) const {
2524 return m_from+static_cast<int>( index );
2525 }
2526
size() const2527 virtual std::size_t size() const {
2528 return static_cast<std::size_t>( 1+m_to-m_from );
2529 }
2530
2531 private:
2532
2533 T m_from;
2534 T m_to;
2535 };
2536
2537 template<typename T>
2538 class ValuesGenerator : public IGenerator<T> {
2539 public:
ValuesGenerator()2540 ValuesGenerator(){}
2541
add(T value)2542 void add( T value ) {
2543 m_values.push_back( value );
2544 }
2545
getValue(std::size_t index) const2546 virtual T getValue( std::size_t index ) const {
2547 return m_values[index];
2548 }
2549
size() const2550 virtual std::size_t size() const {
2551 return m_values.size();
2552 }
2553
2554 private:
2555 std::vector<T> m_values;
2556 };
2557
2558 template<typename T>
2559 class CompositeGenerator {
2560 public:
CompositeGenerator()2561 CompositeGenerator() : m_totalSize( 0 ) {}
2562
2563 // *** Move semantics, similar to auto_ptr ***
CompositeGenerator(CompositeGenerator & other)2564 CompositeGenerator( CompositeGenerator& other )
2565 : m_fileInfo( other.m_fileInfo ),
2566 m_totalSize( 0 )
2567 {
2568 move( other );
2569 }
2570
setFileInfo(const char * fileInfo)2571 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2572 m_fileInfo = fileInfo;
2573 return *this;
2574 }
2575
~CompositeGenerator()2576 ~CompositeGenerator() {
2577 deleteAll( m_composed );
2578 }
2579
operator T() const2580 operator T () const {
2581 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2582
2583 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2584 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2585 for( size_t index = 0; it != itEnd; ++it )
2586 {
2587 const IGenerator<T>* generator = *it;
2588 if( overallIndex >= index && overallIndex < index + generator->size() )
2589 {
2590 return generator->getValue( overallIndex-index );
2591 }
2592 index += generator->size();
2593 }
2594 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2595 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
2596 }
2597
add(const IGenerator<T> * generator)2598 void add( const IGenerator<T>* generator ) {
2599 m_totalSize += generator->size();
2600 m_composed.push_back( generator );
2601 }
2602
then(CompositeGenerator & other)2603 CompositeGenerator& then( CompositeGenerator& other ) {
2604 move( other );
2605 return *this;
2606 }
2607
then(T value)2608 CompositeGenerator& then( T value ) {
2609 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2610 valuesGen->add( value );
2611 add( valuesGen );
2612 return *this;
2613 }
2614
2615 private:
2616
move(CompositeGenerator & other)2617 void move( CompositeGenerator& other ) {
2618 m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() );
2619 m_totalSize += other.m_totalSize;
2620 other.m_composed.clear();
2621 }
2622
2623 std::vector<const IGenerator<T>*> m_composed;
2624 std::string m_fileInfo;
2625 size_t m_totalSize;
2626 };
2627
2628 namespace Generators
2629 {
2630 template<typename T>
between(T from,T to)2631 CompositeGenerator<T> between( T from, T to ) {
2632 CompositeGenerator<T> generators;
2633 generators.add( new BetweenGenerator<T>( from, to ) );
2634 return generators;
2635 }
2636
2637 template<typename T>
values(T val1,T val2)2638 CompositeGenerator<T> values( T val1, T val2 ) {
2639 CompositeGenerator<T> generators;
2640 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2641 valuesGen->add( val1 );
2642 valuesGen->add( val2 );
2643 generators.add( valuesGen );
2644 return generators;
2645 }
2646
2647 template<typename T>
values(T val1,T val2,T val3)2648 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2649 CompositeGenerator<T> generators;
2650 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2651 valuesGen->add( val1 );
2652 valuesGen->add( val2 );
2653 valuesGen->add( val3 );
2654 generators.add( valuesGen );
2655 return generators;
2656 }
2657
2658 template<typename T>
values(T val1,T val2,T val3,T val4)2659 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2660 CompositeGenerator<T> generators;
2661 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2662 valuesGen->add( val1 );
2663 valuesGen->add( val2 );
2664 valuesGen->add( val3 );
2665 valuesGen->add( val4 );
2666 generators.add( valuesGen );
2667 return generators;
2668 }
2669
2670 } // end namespace Generators
2671
2672 using namespace Generators;
2673
2674 } // end namespace Catch
2675
2676 #define INTERNAL_CATCH_LINESTR2( line ) #line
2677 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2678
2679 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2680
2681 // #included from: internal/catch_interfaces_exception.h
2682 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2683
2684 #include <string>
2685 #include <vector>
2686
2687 // #included from: catch_interfaces_registry_hub.h
2688 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2689
2690 #include <string>
2691
2692 namespace Catch {
2693
2694 class TestCase;
2695 struct ITestCaseRegistry;
2696 struct IExceptionTranslatorRegistry;
2697 struct IExceptionTranslator;
2698 struct IReporterRegistry;
2699 struct IReporterFactory;
2700 struct ITagAliasRegistry;
2701
2702 struct IRegistryHub {
2703 virtual ~IRegistryHub();
2704
2705 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2706 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2707 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
2708
2709 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2710 };
2711
2712 struct IMutableRegistryHub {
2713 virtual ~IMutableRegistryHub();
2714 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2715 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
2716 virtual void registerTest( TestCase const& testInfo ) = 0;
2717 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2718 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
2719 };
2720
2721 IRegistryHub& getRegistryHub();
2722 IMutableRegistryHub& getMutableRegistryHub();
2723 void cleanUp();
2724 std::string translateActiveException();
2725
2726 }
2727
2728 namespace Catch {
2729
2730 typedef std::string(*exceptionTranslateFunction)();
2731
2732 struct IExceptionTranslator;
2733 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2734
2735 struct IExceptionTranslator {
2736 virtual ~IExceptionTranslator();
2737 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2738 };
2739
2740 struct IExceptionTranslatorRegistry {
2741 virtual ~IExceptionTranslatorRegistry();
2742
2743 virtual std::string translateActiveException() const = 0;
2744 };
2745
2746 class ExceptionTranslatorRegistrar {
2747 template<typename T>
2748 class ExceptionTranslator : public IExceptionTranslator {
2749 public:
2750
ExceptionTranslator(std::string (* translateFunction)(T &))2751 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2752 : m_translateFunction( translateFunction )
2753 {}
2754
translate(ExceptionTranslators::const_iterator it,ExceptionTranslators::const_iterator itEnd) const2755 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
2756 try {
2757 if( it == itEnd )
2758 throw;
2759 else
2760 return (*it)->translate( it+1, itEnd );
2761 }
2762 catch( T& ex ) {
2763 return m_translateFunction( ex );
2764 }
2765 }
2766
2767 protected:
2768 std::string(*m_translateFunction)( T& );
2769 };
2770
2771 public:
2772 template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))2773 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2774 getMutableRegistryHub().registerTranslator
2775 ( new ExceptionTranslator<T>( translateFunction ) );
2776 }
2777 };
2778 }
2779
2780 ///////////////////////////////////////////////////////////////////////////////
2781 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2782 static std::string translatorName( signature ); \
2783 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2784 static std::string translatorName( signature )
2785
2786 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2787
2788 // #included from: internal/catch_approx.hpp
2789 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2790
2791 #include <cmath>
2792 #include <limits>
2793
2794 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2795 #include <type_traits>
2796 #endif
2797
2798 namespace Catch {
2799 namespace Detail {
2800
2801 class Approx {
2802 public:
Approx(double value)2803 explicit Approx ( double value )
2804 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2805 m_margin( 0.0 ),
2806 m_scale( 1.0 ),
2807 m_value( value )
2808 {}
2809
custom()2810 static Approx custom() {
2811 return Approx( 0 );
2812 }
2813
2814 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2815
2816 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ()(T value)2817 Approx operator()( T value ) {
2818 Approx approx( static_cast<double>(value) );
2819 approx.epsilon( m_epsilon );
2820 approx.margin( m_margin );
2821 approx.scale( m_scale );
2822 return approx;
2823 }
2824
2825 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx(T value)2826 explicit Approx( T value ): Approx(static_cast<double>(value))
2827 {}
2828
2829 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ==(const T & lhs,Approx const & rhs)2830 friend bool operator == ( const T& lhs, Approx const& rhs ) {
2831 // Thanks to Richard Harris for his help refining this formula
2832 auto lhs_v = double(lhs);
2833 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)));
2834 if (relativeOK) {
2835 return true;
2836 }
2837
2838 return std::fabs(lhs_v - rhs.m_value) <= rhs.m_margin;
2839 }
2840
2841 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ==(Approx const & lhs,const T & rhs)2842 friend bool operator == ( Approx const& lhs, const T& rhs ) {
2843 return operator==( rhs, lhs );
2844 }
2845
2846 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator !=(T lhs,Approx const & rhs)2847 friend bool operator != ( T lhs, Approx const& rhs ) {
2848 return !operator==( lhs, rhs );
2849 }
2850
2851 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator !=(Approx const & lhs,T rhs)2852 friend bool operator != ( Approx const& lhs, T rhs ) {
2853 return !operator==( rhs, lhs );
2854 }
2855
2856 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator <=(T lhs,Approx const & rhs)2857 friend bool operator <= ( T lhs, Approx const& rhs ) {
2858 return double(lhs) < rhs.m_value || lhs == rhs;
2859 }
2860
2861 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator <=(Approx const & lhs,T rhs)2862 friend bool operator <= ( Approx const& lhs, T rhs ) {
2863 return lhs.m_value < double(rhs) || lhs == rhs;
2864 }
2865
2866 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator >=(T lhs,Approx const & rhs)2867 friend bool operator >= ( T lhs, Approx const& rhs ) {
2868 return double(lhs) > rhs.m_value || lhs == rhs;
2869 }
2870
2871 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator >=(Approx const & lhs,T rhs)2872 friend bool operator >= ( Approx const& lhs, T rhs ) {
2873 return lhs.m_value > double(rhs) || lhs == rhs;
2874 }
2875
2876 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
epsilon(T newEpsilon)2877 Approx& epsilon( T newEpsilon ) {
2878 m_epsilon = double(newEpsilon);
2879 return *this;
2880 }
2881
2882 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
margin(T newMargin)2883 Approx& margin( T newMargin ) {
2884 m_margin = double(newMargin);
2885 return *this;
2886 }
2887
2888 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
scale(T newScale)2889 Approx& scale( T newScale ) {
2890 m_scale = double(newScale);
2891 return *this;
2892 }
2893
2894 #else
2895
operator ()(double value)2896 Approx operator()( double value ) {
2897 Approx approx( value );
2898 approx.epsilon( m_epsilon );
2899 approx.margin( m_margin );
2900 approx.scale( m_scale );
2901 return approx;
2902 }
2903
operator ==(double lhs,Approx const & rhs)2904 friend bool operator == ( double lhs, Approx const& rhs ) {
2905 // Thanks to Richard Harris for his help refining this formula
2906 bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
2907 if (relativeOK) {
2908 return true;
2909 }
2910 return std::fabs(lhs - rhs.m_value) <= rhs.m_margin;
2911 }
2912
operator ==(Approx const & lhs,double rhs)2913 friend bool operator == ( Approx const& lhs, double rhs ) {
2914 return operator==( rhs, lhs );
2915 }
2916
operator !=(double lhs,Approx const & rhs)2917 friend bool operator != ( double lhs, Approx const& rhs ) {
2918 return !operator==( lhs, rhs );
2919 }
2920
operator !=(Approx const & lhs,double rhs)2921 friend bool operator != ( Approx const& lhs, double rhs ) {
2922 return !operator==( rhs, lhs );
2923 }
2924
operator <=(double lhs,Approx const & rhs)2925 friend bool operator <= ( double lhs, Approx const& rhs ) {
2926 return lhs < rhs.m_value || lhs == rhs;
2927 }
2928
operator <=(Approx const & lhs,double rhs)2929 friend bool operator <= ( Approx const& lhs, double rhs ) {
2930 return lhs.m_value < rhs || lhs == rhs;
2931 }
2932
operator >=(double lhs,Approx const & rhs)2933 friend bool operator >= ( double lhs, Approx const& rhs ) {
2934 return lhs > rhs.m_value || lhs == rhs;
2935 }
2936
operator >=(Approx const & lhs,double rhs)2937 friend bool operator >= ( Approx const& lhs, double rhs ) {
2938 return lhs.m_value > rhs || lhs == rhs;
2939 }
2940
epsilon(double newEpsilon)2941 Approx& epsilon( double newEpsilon ) {
2942 m_epsilon = newEpsilon;
2943 return *this;
2944 }
2945
margin(double newMargin)2946 Approx& margin( double newMargin ) {
2947 m_margin = newMargin;
2948 return *this;
2949 }
2950
scale(double newScale)2951 Approx& scale( double newScale ) {
2952 m_scale = newScale;
2953 return *this;
2954 }
2955 #endif
2956
toString() const2957 std::string toString() const {
2958 std::ostringstream oss;
2959 oss << "Approx( " << Catch::toString( m_value ) << " )";
2960 return oss.str();
2961 }
2962
2963 private:
2964 double m_epsilon;
2965 double m_margin;
2966 double m_scale;
2967 double m_value;
2968 };
2969 }
2970
2971 template<>
toString(Detail::Approx const & value)2972 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
2973 return value.toString();
2974 }
2975
2976 } // end namespace Catch
2977
2978 // #included from: internal/catch_matchers_string.h
2979 #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
2980
2981 namespace Catch {
2982 namespace Matchers {
2983
2984 namespace StdString {
2985
2986 struct CasedString
2987 {
2988 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
2989 std::string adjustString( std::string const& str ) const;
2990 std::string caseSensitivitySuffix() const;
2991
2992 CaseSensitive::Choice m_caseSensitivity;
2993 std::string m_str;
2994 };
2995
2996 struct StringMatcherBase : MatcherBase<std::string> {
2997 StringMatcherBase( std::string const& operation, CasedString const& comparator );
2998 virtual std::string describe() const CATCH_OVERRIDE;
2999
3000 CasedString m_comparator;
3001 std::string m_operation;
3002 };
3003
3004 struct EqualsMatcher : StringMatcherBase {
3005 EqualsMatcher( CasedString const& comparator );
3006 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
3007 };
3008 struct ContainsMatcher : StringMatcherBase {
3009 ContainsMatcher( CasedString const& comparator );
3010 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
3011 };
3012 struct StartsWithMatcher : StringMatcherBase {
3013 StartsWithMatcher( CasedString const& comparator );
3014 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
3015 };
3016 struct EndsWithMatcher : StringMatcherBase {
3017 EndsWithMatcher( CasedString const& comparator );
3018 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
3019 };
3020
3021 } // namespace StdString
3022
3023 // The following functions create the actual matcher objects.
3024 // This allows the types to be inferred
3025
3026 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3027 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3028 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3029 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3030
3031 } // namespace Matchers
3032 } // namespace Catch
3033
3034 // #included from: internal/catch_matchers_vector.h
3035 #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
3036
3037 namespace Catch {
3038 namespace Matchers {
3039
3040 namespace Vector {
3041
3042 template<typename T>
3043 struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
3044
ContainsElementMatcherCatch::Matchers::Vector::ContainsElementMatcher3045 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
3046
matchCatch::Matchers::Vector::ContainsElementMatcher3047 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3048 return std::find(v.begin(), v.end(), m_comparator) != v.end();
3049 }
3050
describeCatch::Matchers::Vector::ContainsElementMatcher3051 virtual std::string describe() const CATCH_OVERRIDE {
3052 return "Contains: " + Catch::toString( m_comparator );
3053 }
3054
3055 T const& m_comparator;
3056 };
3057
3058 template<typename T>
3059 struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3060
ContainsMatcherCatch::Matchers::Vector::ContainsMatcher3061 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3062
matchCatch::Matchers::Vector::ContainsMatcher3063 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3064 // !TBD: see note in EqualsMatcher
3065 if (m_comparator.size() > v.size())
3066 return false;
3067 for (size_t i = 0; i < m_comparator.size(); ++i)
3068 if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
3069 return false;
3070 return true;
3071 }
describeCatch::Matchers::Vector::ContainsMatcher3072 virtual std::string describe() const CATCH_OVERRIDE {
3073 return "Contains: " + Catch::toString( m_comparator );
3074 }
3075
3076 std::vector<T> const& m_comparator;
3077 };
3078
3079 template<typename T>
3080 struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3081
EqualsMatcherCatch::Matchers::Vector::EqualsMatcher3082 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3083
matchCatch::Matchers::Vector::EqualsMatcher3084 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3085 // !TBD: This currently works if all elements can be compared using !=
3086 // - a more general approach would be via a compare template that defaults
3087 // to using !=. but could be specialised for, e.g. std::vector<T> etc
3088 // - then just call that directly
3089 if (m_comparator.size() != v.size())
3090 return false;
3091 for (size_t i = 0; i < v.size(); ++i)
3092 if (m_comparator[i] != v[i])
3093 return false;
3094 return true;
3095 }
describeCatch::Matchers::Vector::EqualsMatcher3096 virtual std::string describe() const CATCH_OVERRIDE {
3097 return "Equals: " + Catch::toString( m_comparator );
3098 }
3099 std::vector<T> const& m_comparator;
3100 };
3101
3102 } // namespace Vector
3103
3104 // The following functions create the actual matcher objects.
3105 // This allows the types to be inferred
3106
3107 template<typename T>
Contains(std::vector<T> const & comparator)3108 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
3109 return Vector::ContainsMatcher<T>( comparator );
3110 }
3111
3112 template<typename T>
VectorContains(T const & comparator)3113 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
3114 return Vector::ContainsElementMatcher<T>( comparator );
3115 }
3116
3117 template<typename T>
Equals(std::vector<T> const & comparator)3118 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
3119 return Vector::EqualsMatcher<T>( comparator );
3120 }
3121
3122 } // namespace Matchers
3123 } // namespace Catch
3124
3125 // #included from: internal/catch_interfaces_tag_alias_registry.h
3126 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
3127
3128 // #included from: catch_tag_alias.h
3129 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
3130
3131 #include <string>
3132
3133 namespace Catch {
3134
3135 struct TagAlias {
TagAliasCatch::TagAlias3136 TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
3137
3138 std::string tag;
3139 SourceLineInfo lineInfo;
3140 };
3141
3142 struct RegistrarForTagAliases {
3143 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
3144 };
3145
3146 } // end namespace Catch
3147
3148 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
3149 // #included from: catch_option.hpp
3150 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3151
3152 namespace Catch {
3153
3154 // An optional type
3155 template<typename T>
3156 class Option {
3157 public:
Option()3158 Option() : nullableValue( CATCH_NULL ) {}
Option(T const & _value)3159 Option( T const& _value )
3160 : nullableValue( new( storage ) T( _value ) )
3161 {}
Option(Option const & _other)3162 Option( Option const& _other )
3163 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
3164 {}
3165
~Option()3166 ~Option() {
3167 reset();
3168 }
3169
operator =(Option const & _other)3170 Option& operator= ( Option const& _other ) {
3171 if( &_other != this ) {
3172 reset();
3173 if( _other )
3174 nullableValue = new( storage ) T( *_other );
3175 }
3176 return *this;
3177 }
operator =(T const & _value)3178 Option& operator = ( T const& _value ) {
3179 reset();
3180 nullableValue = new( storage ) T( _value );
3181 return *this;
3182 }
3183
reset()3184 void reset() {
3185 if( nullableValue )
3186 nullableValue->~T();
3187 nullableValue = CATCH_NULL;
3188 }
3189
operator *()3190 T& operator*() { return *nullableValue; }
operator *() const3191 T const& operator*() const { return *nullableValue; }
operator ->()3192 T* operator->() { return nullableValue; }
operator ->() const3193 const T* operator->() const { return nullableValue; }
3194
valueOr(T const & defaultValue) const3195 T valueOr( T const& defaultValue ) const {
3196 return nullableValue ? *nullableValue : defaultValue;
3197 }
3198
some() const3199 bool some() const { return nullableValue != CATCH_NULL; }
none() const3200 bool none() const { return nullableValue == CATCH_NULL; }
3201
operator !() const3202 bool operator !() const { return nullableValue == CATCH_NULL; }
operator SafeBool::type() const3203 operator SafeBool::type() const {
3204 return SafeBool::makeSafe( some() );
3205 }
3206
3207 private:
3208 T *nullableValue;
3209 union {
3210 char storage[sizeof(T)];
3211
3212 // These are here to force alignment for the storage
3213 long double dummy1;
3214 void (*dummy2)();
3215 long double dummy3;
3216 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
3217 long long dummy4;
3218 #endif
3219 };
3220 };
3221
3222 } // end namespace Catch
3223
3224 namespace Catch {
3225
3226 struct ITagAliasRegistry {
3227 virtual ~ITagAliasRegistry();
3228 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
3229 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
3230
3231 static ITagAliasRegistry const& get();
3232 };
3233
3234 } // end namespace Catch
3235
3236 // These files are included here so the single_include script doesn't put them
3237 // in the conditionally compiled sections
3238 // #included from: internal/catch_test_case_info.h
3239 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
3240
3241 #include <string>
3242 #include <set>
3243
3244 #ifdef __clang__
3245 #pragma clang diagnostic push
3246 #pragma clang diagnostic ignored "-Wpadded"
3247 #endif
3248
3249 namespace Catch {
3250
3251 struct ITestCase;
3252
3253 struct TestCaseInfo {
3254 enum SpecialProperties{
3255 None = 0,
3256 IsHidden = 1 << 1,
3257 ShouldFail = 1 << 2,
3258 MayFail = 1 << 3,
3259 Throws = 1 << 4,
3260 NonPortable = 1 << 5
3261 };
3262
3263 TestCaseInfo( std::string const& _name,
3264 std::string const& _className,
3265 std::string const& _description,
3266 std::set<std::string> const& _tags,
3267 SourceLineInfo const& _lineInfo );
3268
3269 TestCaseInfo( TestCaseInfo const& other );
3270
3271 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
3272
3273 bool isHidden() const;
3274 bool throws() const;
3275 bool okToFail() const;
3276 bool expectedToFail() const;
3277
3278 std::string name;
3279 std::string className;
3280 std::string description;
3281 std::set<std::string> tags;
3282 std::set<std::string> lcaseTags;
3283 std::string tagsAsString;
3284 SourceLineInfo lineInfo;
3285 SpecialProperties properties;
3286 };
3287
3288 class TestCase : public TestCaseInfo {
3289 public:
3290
3291 TestCase( ITestCase* testCase, TestCaseInfo const& info );
3292 TestCase( TestCase const& other );
3293
3294 TestCase withName( std::string const& _newName ) const;
3295
3296 void invoke() const;
3297
3298 TestCaseInfo const& getTestCaseInfo() const;
3299
3300 void swap( TestCase& other );
3301 bool operator == ( TestCase const& other ) const;
3302 bool operator < ( TestCase const& other ) const;
3303 TestCase& operator = ( TestCase const& other );
3304
3305 private:
3306 Ptr<ITestCase> test;
3307 };
3308
3309 TestCase makeTestCase( ITestCase* testCase,
3310 std::string const& className,
3311 std::string const& name,
3312 std::string const& description,
3313 SourceLineInfo const& lineInfo );
3314 }
3315
3316 #ifdef __clang__
3317 #pragma clang diagnostic pop
3318 #endif
3319
3320
3321 #ifdef __OBJC__
3322 // #included from: internal/catch_objc.hpp
3323 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
3324
3325 #import <objc/runtime.h>
3326
3327 #include <string>
3328
3329 // NB. Any general catch headers included here must be included
3330 // in catch.hpp first to make sure they are included by the single
3331 // header for non obj-usage
3332
3333 ///////////////////////////////////////////////////////////////////////////////
3334 // This protocol is really only here for (self) documenting purposes, since
3335 // all its methods are optional.
3336 @protocol OcFixture
3337
3338 @optional
3339
3340 -(void) setUp;
3341 -(void) tearDown;
3342
3343 @end
3344
3345 namespace Catch {
3346
3347 class OcMethod : public SharedImpl<ITestCase> {
3348
3349 public:
OcMethod(Class cls,SEL sel)3350 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3351
invoke() const3352 virtual void invoke() const {
3353 id obj = [[m_cls alloc] init];
3354
3355 performOptionalSelector( obj, @selector(setUp) );
3356 performOptionalSelector( obj, m_sel );
3357 performOptionalSelector( obj, @selector(tearDown) );
3358
3359 arcSafeRelease( obj );
3360 }
3361 private:
~OcMethod()3362 virtual ~OcMethod() {}
3363
3364 Class m_cls;
3365 SEL m_sel;
3366 };
3367
3368 namespace Detail{
3369
getAnnotation(Class cls,std::string const & annotationName,std::string const & testCaseName)3370 inline std::string getAnnotation( Class cls,
3371 std::string const& annotationName,
3372 std::string const& testCaseName ) {
3373 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3374 SEL sel = NSSelectorFromString( selStr );
3375 arcSafeRelease( selStr );
3376 id value = performOptionalSelector( cls, sel );
3377 if( value )
3378 return [(NSString*)value UTF8String];
3379 return "";
3380 }
3381 }
3382
registerTestMethods()3383 inline size_t registerTestMethods() {
3384 size_t noTestMethods = 0;
3385 int noClasses = objc_getClassList( CATCH_NULL, 0 );
3386
3387 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
3388 objc_getClassList( classes, noClasses );
3389
3390 for( int c = 0; c < noClasses; c++ ) {
3391 Class cls = classes[c];
3392 {
3393 u_int count;
3394 Method* methods = class_copyMethodList( cls, &count );
3395 for( u_int m = 0; m < count ; m++ ) {
3396 SEL selector = method_getName(methods[m]);
3397 std::string methodName = sel_getName(selector);
3398 if( startsWith( methodName, "Catch_TestCase_" ) ) {
3399 std::string testCaseName = methodName.substr( 15 );
3400 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3401 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
3402 const char* className = class_getName( cls );
3403
3404 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
3405 noTestMethods++;
3406 }
3407 }
3408 free(methods);
3409 }
3410 }
3411 return noTestMethods;
3412 }
3413
3414 namespace Matchers {
3415 namespace Impl {
3416 namespace NSStringMatchers {
3417
3418 struct StringHolder : MatcherBase<NSString*>{
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder3419 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder3420 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder3421 StringHolder() {
3422 arcSafeRelease( m_substr );
3423 }
3424
matchCatch::Matchers::Impl::NSStringMatchers::StringHolder3425 virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
3426 return false;
3427 }
3428
3429 NSString* m_substr;
3430 };
3431
3432 struct Equals : StringHolder {
EqualsCatch::Matchers::Impl::NSStringMatchers::Equals3433 Equals( NSString* substr ) : StringHolder( substr ){}
3434
matchCatch::Matchers::Impl::NSStringMatchers::Equals3435 virtual bool match( NSString* str ) const CATCH_OVERRIDE {
3436 return (str != nil || m_substr == nil ) &&
3437 [str isEqualToString:m_substr];
3438 }
3439
describeCatch::Matchers::Impl::NSStringMatchers::Equals3440 virtual std::string describe() const CATCH_OVERRIDE {
3441 return "equals string: " + Catch::toString( m_substr );
3442 }
3443 };
3444
3445 struct Contains : StringHolder {
ContainsCatch::Matchers::Impl::NSStringMatchers::Contains3446 Contains( NSString* substr ) : StringHolder( substr ){}
3447
matchCatch::Matchers::Impl::NSStringMatchers::Contains3448 virtual bool match( NSString* str ) const {
3449 return (str != nil || m_substr == nil ) &&
3450 [str rangeOfString:m_substr].location != NSNotFound;
3451 }
3452
describeCatch::Matchers::Impl::NSStringMatchers::Contains3453 virtual std::string describe() const CATCH_OVERRIDE {
3454 return "contains string: " + Catch::toString( m_substr );
3455 }
3456 };
3457
3458 struct StartsWith : StringHolder {
StartsWithCatch::Matchers::Impl::NSStringMatchers::StartsWith3459 StartsWith( NSString* substr ) : StringHolder( substr ){}
3460
matchCatch::Matchers::Impl::NSStringMatchers::StartsWith3461 virtual bool match( NSString* str ) const {
3462 return (str != nil || m_substr == nil ) &&
3463 [str rangeOfString:m_substr].location == 0;
3464 }
3465
describeCatch::Matchers::Impl::NSStringMatchers::StartsWith3466 virtual std::string describe() const CATCH_OVERRIDE {
3467 return "starts with: " + Catch::toString( m_substr );
3468 }
3469 };
3470 struct EndsWith : StringHolder {
EndsWithCatch::Matchers::Impl::NSStringMatchers::EndsWith3471 EndsWith( NSString* substr ) : StringHolder( substr ){}
3472
matchCatch::Matchers::Impl::NSStringMatchers::EndsWith3473 virtual bool match( NSString* str ) const {
3474 return (str != nil || m_substr == nil ) &&
3475 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3476 }
3477
describeCatch::Matchers::Impl::NSStringMatchers::EndsWith3478 virtual std::string describe() const CATCH_OVERRIDE {
3479 return "ends with: " + Catch::toString( m_substr );
3480 }
3481 };
3482
3483 } // namespace NSStringMatchers
3484 } // namespace Impl
3485
3486 inline Impl::NSStringMatchers::Equals
Equals(NSString * substr)3487 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3488
3489 inline Impl::NSStringMatchers::Contains
Contains(NSString * substr)3490 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
3491
3492 inline Impl::NSStringMatchers::StartsWith
StartsWith(NSString * substr)3493 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
3494
3495 inline Impl::NSStringMatchers::EndsWith
EndsWith(NSString * substr)3496 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3497
3498 } // namespace Matchers
3499
3500 using namespace Matchers;
3501
3502 } // namespace Catch
3503
3504 ///////////////////////////////////////////////////////////////////////////////
3505 #define OC_TEST_CASE( name, desc )\
3506 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3507 {\
3508 return @ name; \
3509 }\
3510 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3511 { \
3512 return @ desc; \
3513 } \
3514 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3515
3516 #endif
3517
3518 #ifdef CATCH_IMPL
3519
3520 // !TBD: Move the leak detector code into a separate header
3521 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
3522 #include <crtdbg.h>
3523 class LeakDetector {
3524 public:
LeakDetector()3525 LeakDetector() {
3526 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
3527 flag |= _CRTDBG_LEAK_CHECK_DF;
3528 flag |= _CRTDBG_ALLOC_MEM_DF;
3529 _CrtSetDbgFlag(flag);
3530 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3531 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3532 // Change this to leaking allocation's number to break there
3533 _CrtSetBreakAlloc(-1);
3534 }
3535 };
3536 #else
3537 class LeakDetector {};
3538 #endif
3539
3540 LeakDetector leakDetector;
3541
3542 // #included from: internal/catch_impl.hpp
3543 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3544
3545 // Collect all the implementation files together here
3546 // These are the equivalent of what would usually be cpp files
3547
3548 #ifdef __clang__
3549 #pragma clang diagnostic push
3550 #pragma clang diagnostic ignored "-Wweak-vtables"
3551 #endif
3552
3553 // #included from: ../catch_session.hpp
3554 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3555
3556 // #included from: internal/catch_commandline.hpp
3557 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3558
3559 // #included from: catch_config.hpp
3560 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3561
3562 // #included from: catch_test_spec_parser.hpp
3563 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3564
3565 #ifdef __clang__
3566 #pragma clang diagnostic push
3567 #pragma clang diagnostic ignored "-Wpadded"
3568 #endif
3569
3570 // #included from: catch_test_spec.hpp
3571 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3572
3573 #ifdef __clang__
3574 #pragma clang diagnostic push
3575 #pragma clang diagnostic ignored "-Wpadded"
3576 #endif
3577
3578 // #included from: catch_wildcard_pattern.hpp
3579 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3580
3581 #include <stdexcept>
3582
3583 namespace Catch
3584 {
3585 class WildcardPattern {
3586 enum WildcardPosition {
3587 NoWildcard = 0,
3588 WildcardAtStart = 1,
3589 WildcardAtEnd = 2,
3590 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3591 };
3592
3593 public:
3594
WildcardPattern(std::string const & pattern,CaseSensitive::Choice caseSensitivity)3595 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
3596 : m_caseSensitivity( caseSensitivity ),
3597 m_wildcard( NoWildcard ),
3598 m_pattern( adjustCase( pattern ) )
3599 {
3600 if( startsWith( m_pattern, '*' ) ) {
3601 m_pattern = m_pattern.substr( 1 );
3602 m_wildcard = WildcardAtStart;
3603 }
3604 if( endsWith( m_pattern, '*' ) ) {
3605 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3606 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3607 }
3608 }
3609 virtual ~WildcardPattern();
matches(std::string const & str) const3610 virtual bool matches( std::string const& str ) const {
3611 switch( m_wildcard ) {
3612 case NoWildcard:
3613 return m_pattern == adjustCase( str );
3614 case WildcardAtStart:
3615 return endsWith( adjustCase( str ), m_pattern );
3616 case WildcardAtEnd:
3617 return startsWith( adjustCase( str ), m_pattern );
3618 case WildcardAtBothEnds:
3619 return contains( adjustCase( str ), m_pattern );
3620 }
3621
3622 #ifdef __clang__
3623 #pragma clang diagnostic push
3624 #pragma clang diagnostic ignored "-Wunreachable-code"
3625 #endif
3626 throw std::logic_error( "Unknown enum" );
3627 #ifdef __clang__
3628 #pragma clang diagnostic pop
3629 #endif
3630 }
3631 private:
adjustCase(std::string const & str) const3632 std::string adjustCase( std::string const& str ) const {
3633 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
3634 }
3635 CaseSensitive::Choice m_caseSensitivity;
3636 WildcardPosition m_wildcard;
3637 std::string m_pattern;
3638 };
3639 }
3640
3641 #include <string>
3642 #include <vector>
3643
3644 namespace Catch {
3645
3646 class TestSpec {
3647 struct Pattern : SharedImpl<> {
3648 virtual ~Pattern();
3649 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3650 };
3651 class NamePattern : public Pattern {
3652 public:
NamePattern(std::string const & name)3653 NamePattern( std::string const& name )
3654 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
3655 {}
3656 virtual ~NamePattern();
matches(TestCaseInfo const & testCase) const3657 virtual bool matches( TestCaseInfo const& testCase ) const {
3658 return m_wildcardPattern.matches( toLower( testCase.name ) );
3659 }
3660 private:
3661 WildcardPattern m_wildcardPattern;
3662 };
3663
3664 class TagPattern : public Pattern {
3665 public:
TagPattern(std::string const & tag)3666 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3667 virtual ~TagPattern();
matches(TestCaseInfo const & testCase) const3668 virtual bool matches( TestCaseInfo const& testCase ) const {
3669 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
3670 }
3671 private:
3672 std::string m_tag;
3673 };
3674
3675 class ExcludedPattern : public Pattern {
3676 public:
ExcludedPattern(Ptr<Pattern> const & underlyingPattern)3677 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3678 virtual ~ExcludedPattern();
matches(TestCaseInfo const & testCase) const3679 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3680 private:
3681 Ptr<Pattern> m_underlyingPattern;
3682 };
3683
3684 struct Filter {
3685 std::vector<Ptr<Pattern> > m_patterns;
3686
matchesCatch::TestSpec::Filter3687 bool matches( TestCaseInfo const& testCase ) const {
3688 // All patterns in a filter must match for the filter to be a match
3689 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
3690 if( !(*it)->matches( testCase ) )
3691 return false;
3692 }
3693 return true;
3694 }
3695 };
3696
3697 public:
hasFilters() const3698 bool hasFilters() const {
3699 return !m_filters.empty();
3700 }
matches(TestCaseInfo const & testCase) const3701 bool matches( TestCaseInfo const& testCase ) const {
3702 // A TestSpec matches if any filter matches
3703 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3704 if( it->matches( testCase ) )
3705 return true;
3706 return false;
3707 }
3708
3709 private:
3710 std::vector<Filter> m_filters;
3711
3712 friend class TestSpecParser;
3713 };
3714 }
3715
3716 #ifdef __clang__
3717 #pragma clang diagnostic pop
3718 #endif
3719
3720 namespace Catch {
3721
3722 class TestSpecParser {
3723 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
3724 Mode m_mode;
3725 bool m_exclusion;
3726 std::size_t m_start, m_pos;
3727 std::string m_arg;
3728 std::vector<std::size_t> m_escapeChars;
3729 TestSpec::Filter m_currentFilter;
3730 TestSpec m_testSpec;
3731 ITagAliasRegistry const* m_tagAliases;
3732
3733 public:
TestSpecParser(ITagAliasRegistry const & tagAliases)3734 TestSpecParser( ITagAliasRegistry const& tagAliases ) :m_mode(None), m_exclusion(false), m_start(0), m_pos(0), m_tagAliases( &tagAliases ) {}
3735
parse(std::string const & arg)3736 TestSpecParser& parse( std::string const& arg ) {
3737 m_mode = None;
3738 m_exclusion = false;
3739 m_start = std::string::npos;
3740 m_arg = m_tagAliases->expandAliases( arg );
3741 m_escapeChars.clear();
3742 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3743 visitChar( m_arg[m_pos] );
3744 if( m_mode == Name )
3745 addPattern<TestSpec::NamePattern>();
3746 return *this;
3747 }
testSpec()3748 TestSpec testSpec() {
3749 addFilter();
3750 return m_testSpec;
3751 }
3752 private:
visitChar(char c)3753 void visitChar( char c ) {
3754 if( m_mode == None ) {
3755 switch( c ) {
3756 case ' ': return;
3757 case '~': m_exclusion = true; return;
3758 case '[': return startNewMode( Tag, ++m_pos );
3759 case '"': return startNewMode( QuotedName, ++m_pos );
3760 case '\\': return escape();
3761 default: startNewMode( Name, m_pos ); break;
3762 }
3763 }
3764 if( m_mode == Name ) {
3765 if( c == ',' ) {
3766 addPattern<TestSpec::NamePattern>();
3767 addFilter();
3768 }
3769 else if( c == '[' ) {
3770 if( subString() == "exclude:" )
3771 m_exclusion = true;
3772 else
3773 addPattern<TestSpec::NamePattern>();
3774 startNewMode( Tag, ++m_pos );
3775 }
3776 else if( c == '\\' )
3777 escape();
3778 }
3779 else if( m_mode == EscapedName )
3780 m_mode = Name;
3781 else if( m_mode == QuotedName && c == '"' )
3782 addPattern<TestSpec::NamePattern>();
3783 else if( m_mode == Tag && c == ']' )
3784 addPattern<TestSpec::TagPattern>();
3785 }
startNewMode(Mode mode,std::size_t start)3786 void startNewMode( Mode mode, std::size_t start ) {
3787 m_mode = mode;
3788 m_start = start;
3789 }
escape()3790 void escape() {
3791 if( m_mode == None )
3792 m_start = m_pos;
3793 m_mode = EscapedName;
3794 m_escapeChars.push_back( m_pos );
3795 }
subString() const3796 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3797 template<typename T>
addPattern()3798 void addPattern() {
3799 std::string token = subString();
3800 for( size_t i = 0; i < m_escapeChars.size(); ++i )
3801 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
3802 m_escapeChars.clear();
3803 if( startsWith( token, "exclude:" ) ) {
3804 m_exclusion = true;
3805 token = token.substr( 8 );
3806 }
3807 if( !token.empty() ) {
3808 Ptr<TestSpec::Pattern> pattern = new T( token );
3809 if( m_exclusion )
3810 pattern = new TestSpec::ExcludedPattern( pattern );
3811 m_currentFilter.m_patterns.push_back( pattern );
3812 }
3813 m_exclusion = false;
3814 m_mode = None;
3815 }
addFilter()3816 void addFilter() {
3817 if( !m_currentFilter.m_patterns.empty() ) {
3818 m_testSpec.m_filters.push_back( m_currentFilter );
3819 m_currentFilter = TestSpec::Filter();
3820 }
3821 }
3822 };
parseTestSpec(std::string const & arg)3823 inline TestSpec parseTestSpec( std::string const& arg ) {
3824 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
3825 }
3826
3827 } // namespace Catch
3828
3829 #ifdef __clang__
3830 #pragma clang diagnostic pop
3831 #endif
3832
3833 // #included from: catch_interfaces_config.h
3834 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3835
3836 #include <iosfwd>
3837 #include <string>
3838 #include <vector>
3839
3840 namespace Catch {
3841
3842 struct Verbosity { enum Level {
3843 NoOutput = 0,
3844 Quiet,
3845 Normal
3846 }; };
3847
3848 struct WarnAbout { enum What {
3849 Nothing = 0x00,
3850 NoAssertions = 0x01
3851 }; };
3852
3853 struct ShowDurations { enum OrNot {
3854 DefaultForReporter,
3855 Always,
3856 Never
3857 }; };
3858 struct RunTests { enum InWhatOrder {
3859 InDeclarationOrder,
3860 InLexicographicalOrder,
3861 InRandomOrder
3862 }; };
3863 struct UseColour { enum YesOrNo {
3864 Auto,
3865 Yes,
3866 No
3867 }; };
3868 struct WaitForKeypress { enum When {
3869 Never,
3870 BeforeStart = 1,
3871 BeforeExit = 2,
3872 BeforeStartAndExit = BeforeStart | BeforeExit
3873 }; };
3874
3875 class TestSpec;
3876
3877 struct IConfig : IShared {
3878
3879 virtual ~IConfig();
3880
3881 virtual bool allowThrows() const = 0;
3882 virtual std::ostream& stream() const = 0;
3883 virtual std::string name() const = 0;
3884 virtual bool includeSuccessfulResults() const = 0;
3885 virtual bool shouldDebugBreak() const = 0;
3886 virtual bool warnAboutMissingAssertions() const = 0;
3887 virtual int abortAfter() const = 0;
3888 virtual bool showInvisibles() const = 0;
3889 virtual ShowDurations::OrNot showDurations() const = 0;
3890 virtual TestSpec const& testSpec() const = 0;
3891 virtual RunTests::InWhatOrder runOrder() const = 0;
3892 virtual unsigned int rngSeed() const = 0;
3893 virtual UseColour::YesOrNo useColour() const = 0;
3894 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
3895
3896 };
3897 }
3898
3899 // #included from: catch_stream.h
3900 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3901
3902 // #included from: catch_streambuf.h
3903 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3904
3905 #include <streambuf>
3906
3907 namespace Catch {
3908
3909 class StreamBufBase : public std::streambuf {
3910 public:
3911 virtual ~StreamBufBase() CATCH_NOEXCEPT;
3912 };
3913 }
3914
3915 #include <streambuf>
3916 #include <ostream>
3917 #include <fstream>
3918 #include <memory>
3919
3920 namespace Catch {
3921
3922 std::ostream& cout();
3923 std::ostream& cerr();
3924 std::ostream& clog();
3925
3926 struct IStream {
3927 virtual ~IStream() CATCH_NOEXCEPT;
3928 virtual std::ostream& stream() const = 0;
3929 };
3930
3931 class FileStream : public IStream {
3932 mutable std::ofstream m_ofs;
3933 public:
3934 FileStream( std::string const& filename );
3935 virtual ~FileStream() CATCH_NOEXCEPT;
3936 public: // IStream
3937 virtual std::ostream& stream() const CATCH_OVERRIDE;
3938 };
3939
3940 class CoutStream : public IStream {
3941 mutable std::ostream m_os;
3942 public:
3943 CoutStream();
3944 virtual ~CoutStream() CATCH_NOEXCEPT;
3945
3946 public: // IStream
3947 virtual std::ostream& stream() const CATCH_OVERRIDE;
3948 };
3949
3950 class DebugOutStream : public IStream {
3951 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
3952 mutable std::ostream m_os;
3953 public:
3954 DebugOutStream();
3955 virtual ~DebugOutStream() CATCH_NOEXCEPT;
3956
3957 public: // IStream
3958 virtual std::ostream& stream() const CATCH_OVERRIDE;
3959 };
3960 }
3961
3962 #include <memory>
3963 #include <vector>
3964 #include <string>
3965 #include <stdexcept>
3966
3967 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3968 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3969 #endif
3970
3971 namespace Catch {
3972
3973 struct ConfigData {
3974
ConfigDataCatch::ConfigData3975 ConfigData()
3976 : listTests( false ),
3977 listTags( false ),
3978 listReporters( false ),
3979 listTestNamesOnly( false ),
3980 listExtraInfo( false ),
3981 showSuccessfulTests( false ),
3982 shouldDebugBreak( false ),
3983 noThrow( false ),
3984 showHelp( false ),
3985 showInvisibles( false ),
3986 filenamesAsTags( false ),
3987 libIdentify( false ),
3988 abortAfter( -1 ),
3989 rngSeed( 0 ),
3990 verbosity( Verbosity::Normal ),
3991 warnings( WarnAbout::Nothing ),
3992 showDurations( ShowDurations::DefaultForReporter ),
3993 runOrder( RunTests::InDeclarationOrder ),
3994 useColour( UseColour::Auto ),
3995 waitForKeypress( WaitForKeypress::Never )
3996 {}
3997
3998 bool listTests;
3999 bool listTags;
4000 bool listReporters;
4001 bool listTestNamesOnly;
4002 bool listExtraInfo;
4003
4004 bool showSuccessfulTests;
4005 bool shouldDebugBreak;
4006 bool noThrow;
4007 bool showHelp;
4008 bool showInvisibles;
4009 bool filenamesAsTags;
4010 bool libIdentify;
4011
4012 int abortAfter;
4013 unsigned int rngSeed;
4014
4015 Verbosity::Level verbosity;
4016 WarnAbout::What warnings;
4017 ShowDurations::OrNot showDurations;
4018 RunTests::InWhatOrder runOrder;
4019 UseColour::YesOrNo useColour;
4020 WaitForKeypress::When waitForKeypress;
4021
4022 std::string outputFilename;
4023 std::string name;
4024 std::string processName;
4025
4026 std::vector<std::string> reporterNames;
4027 std::vector<std::string> testsOrTags;
4028 std::vector<std::string> sectionsToRun;
4029 };
4030
4031 class Config : public SharedImpl<IConfig> {
4032 private:
4033 Config( Config const& other );
4034 Config& operator = ( Config const& other );
4035 virtual void dummy();
4036 public:
4037
Config()4038 Config()
4039 {}
4040
Config(ConfigData const & data)4041 Config( ConfigData const& data )
4042 : m_data( data ),
4043 m_stream( openStream() )
4044 {
4045 if( !data.testsOrTags.empty() ) {
4046 TestSpecParser parser( ITagAliasRegistry::get() );
4047 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
4048 parser.parse( data.testsOrTags[i] );
4049 m_testSpec = parser.testSpec();
4050 }
4051 }
4052
~Config()4053 virtual ~Config() {}
4054
getFilename() const4055 std::string const& getFilename() const {
4056 return m_data.outputFilename ;
4057 }
4058
listTests() const4059 bool listTests() const { return m_data.listTests; }
listTestNamesOnly() const4060 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
listTags() const4061 bool listTags() const { return m_data.listTags; }
listReporters() const4062 bool listReporters() const { return m_data.listReporters; }
listExtraInfo() const4063 bool listExtraInfo() const { return m_data.listExtraInfo; }
4064
getProcessName() const4065 std::string getProcessName() const { return m_data.processName; }
4066
getReporterNames() const4067 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
getSectionsToRun() const4068 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
4069
testSpec() const4070 virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
4071
showHelp() const4072 bool showHelp() const { return m_data.showHelp; }
4073
4074 // IConfig interface
allowThrows() const4075 virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; }
stream() const4076 virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); }
name() const4077 virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; }
includeSuccessfulResults() const4078 virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; }
warnAboutMissingAssertions() const4079 virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; }
showDurations() const4080 virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; }
runOrder() const4081 virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; }
rngSeed() const4082 virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; }
useColour() const4083 virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; }
shouldDebugBreak() const4084 virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; }
abortAfter() const4085 virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; }
showInvisibles() const4086 virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; }
4087
4088 private:
4089
openStream()4090 IStream const* openStream() {
4091 if( m_data.outputFilename.empty() )
4092 return new CoutStream();
4093 else if( m_data.outputFilename[0] == '%' ) {
4094 if( m_data.outputFilename == "%debug" )
4095 return new DebugOutStream();
4096 else
4097 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
4098 }
4099 else
4100 return new FileStream( m_data.outputFilename );
4101 }
4102 ConfigData m_data;
4103
4104 CATCH_AUTO_PTR( IStream const ) m_stream;
4105 TestSpec m_testSpec;
4106 };
4107
4108 } // end namespace Catch
4109
4110 // #included from: catch_clara.h
4111 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
4112
4113 // Use Catch's value for console width (store Clara's off to the side, if present)
4114 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
4115 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
4116 #undef CLARA_CONFIG_CONSOLE_WIDTH
4117 #endif
4118 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4119
4120 // Declare Clara inside the Catch namespace
4121 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
4122 // #included from: ../external/clara.h
4123
4124 // Version 0.0.2.4
4125
4126 // Only use header guard if we are not using an outer namespace
4127 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
4128
4129 #ifndef STITCH_CLARA_OPEN_NAMESPACE
4130 #define TWOBLUECUBES_CLARA_H_INCLUDED
4131 #define STITCH_CLARA_OPEN_NAMESPACE
4132 #define STITCH_CLARA_CLOSE_NAMESPACE
4133 #else
4134 #define STITCH_CLARA_CLOSE_NAMESPACE }
4135 #endif
4136
4137 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
4138
4139 // ----------- #included from tbc_text_format.h -----------
4140
4141 // Only use header guard if we are not using an outer namespace
4142 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
4143 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4144 #define TBC_TEXT_FORMAT_H_INCLUDED
4145 #endif
4146
4147 #include <string>
4148 #include <vector>
4149 #include <sstream>
4150 #include <algorithm>
4151 #include <cctype>
4152
4153 // Use optional outer namespace
4154 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4155 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4156 #endif
4157
4158 namespace Tbc {
4159
4160 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4161 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4162 #else
4163 const unsigned int consoleWidth = 80;
4164 #endif
4165
4166 struct TextAttributes {
TextAttributesSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4167 TextAttributes()
4168 : initialIndent( std::string::npos ),
4169 indent( 0 ),
4170 width( consoleWidth-1 ),
4171 tabChar( '\t' )
4172 {}
4173
setInitialIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4174 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
setIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4175 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
setWidthSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4176 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
setTabCharSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4177 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4178
4179 std::size_t initialIndent; // indent of first line, or npos
4180 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4181 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4182 char tabChar; // If this char is seen the indent is changed to current pos
4183 };
4184
4185 class Text {
4186 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())4187 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4188 : attr( _attr )
4189 {
4190 std::string wrappableChars = " [({.,/|\\-";
4191 std::size_t indent = _attr.initialIndent != std::string::npos
4192 ? _attr.initialIndent
4193 : _attr.indent;
4194 std::string remainder = _str;
4195
4196 while( !remainder.empty() ) {
4197 if( lines.size() >= 1000 ) {
4198 lines.push_back( "... message truncated due to excessive size" );
4199 return;
4200 }
4201 std::size_t tabPos = std::string::npos;
4202 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4203 std::size_t pos = remainder.find_first_of( '\n' );
4204 if( pos <= width ) {
4205 width = pos;
4206 }
4207 pos = remainder.find_last_of( _attr.tabChar, width );
4208 if( pos != std::string::npos ) {
4209 tabPos = pos;
4210 if( remainder[width] == '\n' )
4211 width--;
4212 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4213 }
4214
4215 if( width == remainder.size() ) {
4216 spliceLine( indent, remainder, width );
4217 }
4218 else if( remainder[width] == '\n' ) {
4219 spliceLine( indent, remainder, width );
4220 if( width <= 1 || remainder.size() != 1 )
4221 remainder = remainder.substr( 1 );
4222 indent = _attr.indent;
4223 }
4224 else {
4225 pos = remainder.find_last_of( wrappableChars, width );
4226 if( pos != std::string::npos && pos > 0 ) {
4227 spliceLine( indent, remainder, pos );
4228 if( remainder[0] == ' ' )
4229 remainder = remainder.substr( 1 );
4230 }
4231 else {
4232 spliceLine( indent, remainder, width-1 );
4233 lines.back() += "-";
4234 }
4235 if( lines.size() == 1 )
4236 indent = _attr.indent;
4237 if( tabPos != std::string::npos )
4238 indent += tabPos;
4239 }
4240 }
4241 }
4242
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)4243 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4244 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4245 _remainder = _remainder.substr( _pos );
4246 }
4247
4248 typedef std::vector<std::string>::const_iterator const_iterator;
4249
begin() const4250 const_iterator begin() const { return lines.begin(); }
end() const4251 const_iterator end() const { return lines.end(); }
last() const4252 std::string const& last() const { return lines.back(); }
size() const4253 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const4254 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
toString() const4255 std::string toString() const {
4256 std::ostringstream oss;
4257 oss << *this;
4258 return oss.str();
4259 }
4260
operator <<(std::ostream & _stream,Text const & _text)4261 friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4262 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4263 it != itEnd; ++it ) {
4264 if( it != _text.begin() )
4265 _stream << "\n";
4266 _stream << *it;
4267 }
4268 return _stream;
4269 }
4270
4271 private:
4272 std::string str;
4273 TextAttributes attr;
4274 std::vector<std::string> lines;
4275 };
4276
4277 } // end namespace Tbc
4278
4279 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4280 } // end outer namespace
4281 #endif
4282
4283 #endif // TBC_TEXT_FORMAT_H_INCLUDED
4284
4285 // ----------- end of #include from tbc_text_format.h -----------
4286 // ........... back in clara.h
4287
4288 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
4289
4290 // ----------- #included from clara_compilers.h -----------
4291
4292 #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4293 #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4294
4295 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
4296 // The following features are defined:
4297 //
4298 // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
4299 // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
4300 // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
4301 // CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
4302 // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
4303
4304 // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
4305
4306 // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
4307
4308 // In general each macro has a _NO_<feature name> form
4309 // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
4310 // Many features, at point of detection, define an _INTERNAL_ macro, so they
4311 // can be combined, en-mass, with the _NO_ forms later.
4312
4313 // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
4314
4315 #ifdef __clang__
4316
4317 #if __has_feature(cxx_nullptr)
4318 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4319 #endif
4320
4321 #if __has_feature(cxx_noexcept)
4322 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4323 #endif
4324
4325 #endif // __clang__
4326
4327 ////////////////////////////////////////////////////////////////////////////////
4328 // GCC
4329 #ifdef __GNUC__
4330
4331 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
4332 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4333 #endif
4334
4335 // - otherwise more recent versions define __cplusplus >= 201103L
4336 // and will get picked up below
4337
4338 #endif // __GNUC__
4339
4340 ////////////////////////////////////////////////////////////////////////////////
4341 // Visual C++
4342 #ifdef _MSC_VER
4343
4344 #if (_MSC_VER >= 1600)
4345 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4346 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4347 #endif
4348
4349 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
4350 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4351 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4352 #endif
4353
4354 #endif // _MSC_VER
4355
4356 ////////////////////////////////////////////////////////////////////////////////
4357 // C++ language feature support
4358
4359 // catch all support for C++11
4360 #if defined(__cplusplus) && __cplusplus >= 201103L
4361
4362 #define CLARA_CPP11_OR_GREATER
4363
4364 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
4365 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4366 #endif
4367
4368 #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4369 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4370 #endif
4371
4372 #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4373 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4374 #endif
4375
4376 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
4377 #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
4378 #endif
4379 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
4380 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4381 #endif
4382
4383 #endif // __cplusplus >= 201103L
4384
4385 // Now set the actual defines based on the above + anything the user has configured
4386 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
4387 #define CLARA_CONFIG_CPP11_NULLPTR
4388 #endif
4389 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
4390 #define CLARA_CONFIG_CPP11_NOEXCEPT
4391 #endif
4392 #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)
4393 #define CLARA_CONFIG_CPP11_GENERATED_METHODS
4394 #endif
4395 #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
4396 #define CLARA_CONFIG_CPP11_OVERRIDE
4397 #endif
4398 #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)
4399 #define CLARA_CONFIG_CPP11_UNIQUE_PTR
4400 #endif
4401
4402 // noexcept support:
4403 #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
4404 #define CLARA_NOEXCEPT noexcept
4405 # define CLARA_NOEXCEPT_IS(x) noexcept(x)
4406 #else
4407 #define CLARA_NOEXCEPT throw()
4408 # define CLARA_NOEXCEPT_IS(x)
4409 #endif
4410
4411 // nullptr support
4412 #ifdef CLARA_CONFIG_CPP11_NULLPTR
4413 #define CLARA_NULL nullptr
4414 #else
4415 #define CLARA_NULL NULL
4416 #endif
4417
4418 // override support
4419 #ifdef CLARA_CONFIG_CPP11_OVERRIDE
4420 #define CLARA_OVERRIDE override
4421 #else
4422 #define CLARA_OVERRIDE
4423 #endif
4424
4425 // unique_ptr support
4426 #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
4427 # define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
4428 #else
4429 # define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
4430 #endif
4431
4432 #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4433
4434 // ----------- end of #include from clara_compilers.h -----------
4435 // ........... back in clara.h
4436
4437 #include <map>
4438 #include <stdexcept>
4439 #include <memory>
4440
4441 #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
4442 #define CLARA_PLATFORM_WINDOWS
4443 #endif
4444
4445 // Use optional outer namespace
4446 #ifdef STITCH_CLARA_OPEN_NAMESPACE
4447 STITCH_CLARA_OPEN_NAMESPACE
4448 #endif
4449
4450 namespace Clara {
4451
4452 struct UnpositionalTag {};
4453
4454 extern UnpositionalTag _;
4455
4456 #ifdef CLARA_CONFIG_MAIN
4457 UnpositionalTag _;
4458 #endif
4459
4460 namespace Detail {
4461
4462 #ifdef CLARA_CONSOLE_WIDTH
4463 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
4464 #else
4465 const unsigned int consoleWidth = 80;
4466 #endif
4467
4468 using namespace Tbc;
4469
startsWith(std::string const & str,std::string const & prefix)4470 inline bool startsWith( std::string const& str, std::string const& prefix ) {
4471 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
4472 }
4473
4474 template<typename T> struct RemoveConstRef{ typedef T type; };
4475 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
4476 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
4477 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
4478
4479 template<typename T> struct IsBool { static const bool value = false; };
4480 template<> struct IsBool<bool> { static const bool value = true; };
4481
4482 template<typename T>
convertInto(std::string const & _source,T & _dest)4483 void convertInto( std::string const& _source, T& _dest ) {
4484 std::stringstream ss;
4485 ss << _source;
4486 ss >> _dest;
4487 if( ss.fail() )
4488 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
4489 }
convertInto(std::string const & _source,std::string & _dest)4490 inline void convertInto( std::string const& _source, std::string& _dest ) {
4491 _dest = _source;
4492 }
toLowerCh(char c)4493 char toLowerCh(char c) {
4494 return static_cast<char>( std::tolower( c ) );
4495 }
convertInto(std::string const & _source,bool & _dest)4496 inline void convertInto( std::string const& _source, bool& _dest ) {
4497 std::string sourceLC = _source;
4498 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
4499 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
4500 _dest = true;
4501 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
4502 _dest = false;
4503 else
4504 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
4505 }
4506
4507 template<typename ConfigT>
4508 struct IArgFunction {
~IArgFunctionClara::Detail::IArgFunction4509 virtual ~IArgFunction() {}
4510 #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
4511 IArgFunction() = default;
4512 IArgFunction( IArgFunction const& ) = default;
4513 #endif
4514 virtual void set( ConfigT& config, std::string const& value ) const = 0;
4515 virtual bool takesArg() const = 0;
4516 virtual IArgFunction* clone() const = 0;
4517 };
4518
4519 template<typename ConfigT>
4520 class BoundArgFunction {
4521 public:
BoundArgFunction()4522 BoundArgFunction() : functionObj( CLARA_NULL ) {}
BoundArgFunction(IArgFunction<ConfigT> * _functionObj)4523 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
BoundArgFunction(BoundArgFunction const & other)4524 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
operator =(BoundArgFunction const & other)4525 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
4526 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
4527 delete functionObj;
4528 functionObj = newFunctionObj;
4529 return *this;
4530 }
~BoundArgFunction()4531 ~BoundArgFunction() { delete functionObj; }
4532
set(ConfigT & config,std::string const & value) const4533 void set( ConfigT& config, std::string const& value ) const {
4534 functionObj->set( config, value );
4535 }
takesArg() const4536 bool takesArg() const { return functionObj->takesArg(); }
4537
isSet() const4538 bool isSet() const {
4539 return functionObj != CLARA_NULL;
4540 }
4541 private:
4542 IArgFunction<ConfigT>* functionObj;
4543 };
4544
4545 template<typename C>
4546 struct NullBinder : IArgFunction<C>{
setClara::Detail::NullBinder4547 virtual void set( C&, std::string const& ) const {}
takesArgClara::Detail::NullBinder4548 virtual bool takesArg() const { return true; }
cloneClara::Detail::NullBinder4549 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4550 };
4551
4552 template<typename C, typename M>
4553 struct BoundDataMember : IArgFunction<C>{
BoundDataMemberClara::Detail::BoundDataMember4554 BoundDataMember( M C::* _member ) : member( _member ) {}
setClara::Detail::BoundDataMember4555 virtual void set( C& p, std::string const& stringValue ) const {
4556 convertInto( stringValue, p.*member );
4557 }
takesArgClara::Detail::BoundDataMember4558 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundDataMember4559 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4560 M C::* member;
4561 };
4562 template<typename C, typename M>
4563 struct BoundUnaryMethod : IArgFunction<C>{
BoundUnaryMethodClara::Detail::BoundUnaryMethod4564 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
setClara::Detail::BoundUnaryMethod4565 virtual void set( C& p, std::string const& stringValue ) const {
4566 typename RemoveConstRef<M>::type value;
4567 convertInto( stringValue, value );
4568 (p.*member)( value );
4569 }
takesArgClara::Detail::BoundUnaryMethod4570 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundUnaryMethod4571 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4572 void (C::*member)( M );
4573 };
4574 template<typename C>
4575 struct BoundNullaryMethod : IArgFunction<C>{
BoundNullaryMethodClara::Detail::BoundNullaryMethod4576 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
setClara::Detail::BoundNullaryMethod4577 virtual void set( C& p, std::string const& stringValue ) const {
4578 bool value;
4579 convertInto( stringValue, value );
4580 if( value )
4581 (p.*member)();
4582 }
takesArgClara::Detail::BoundNullaryMethod4583 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundNullaryMethod4584 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4585 void (C::*member)();
4586 };
4587
4588 template<typename C>
4589 struct BoundUnaryFunction : IArgFunction<C>{
BoundUnaryFunctionClara::Detail::BoundUnaryFunction4590 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
setClara::Detail::BoundUnaryFunction4591 virtual void set( C& obj, std::string const& stringValue ) const {
4592 bool value;
4593 convertInto( stringValue, value );
4594 if( value )
4595 function( obj );
4596 }
takesArgClara::Detail::BoundUnaryFunction4597 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundUnaryFunction4598 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4599 void (*function)( C& );
4600 };
4601
4602 template<typename C, typename T>
4603 struct BoundBinaryFunction : IArgFunction<C>{
BoundBinaryFunctionClara::Detail::BoundBinaryFunction4604 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
setClara::Detail::BoundBinaryFunction4605 virtual void set( C& obj, std::string const& stringValue ) const {
4606 typename RemoveConstRef<T>::type value;
4607 convertInto( stringValue, value );
4608 function( obj, value );
4609 }
takesArgClara::Detail::BoundBinaryFunction4610 virtual bool takesArg() const { return !IsBool<T>::value; }
cloneClara::Detail::BoundBinaryFunction4611 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4612 void (*function)( C&, T );
4613 };
4614
4615 } // namespace Detail
4616
argsToVector(int argc,char const * const * const argv)4617 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
4618 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
4619 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4620 args[i] = argv[i];
4621
4622 return args;
4623 }
4624
4625 class Parser {
4626 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4627 Mode mode;
4628 std::size_t from;
4629 bool inQuotes;
4630 public:
4631
4632 struct Token {
4633 enum Type { Positional, ShortOpt, LongOpt };
TokenClara::Parser::Token4634 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4635 Type type;
4636 std::string data;
4637 };
4638
Parser()4639 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
4640
parseIntoTokens(std::vector<std::string> const & args,std::vector<Token> & tokens)4641 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
4642 const std::string doubleDash = "--";
4643 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4644 parseIntoTokens( args[i], tokens);
4645 }
4646
parseIntoTokens(std::string const & arg,std::vector<Token> & tokens)4647 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
4648 for( std::size_t i = 0; i < arg.size(); ++i ) {
4649 char c = arg[i];
4650 if( c == '"' )
4651 inQuotes = !inQuotes;
4652 mode = handleMode( i, c, arg, tokens );
4653 }
4654 mode = handleMode( arg.size(), '\0', arg, tokens );
4655 }
handleMode(std::size_t i,char c,std::string const & arg,std::vector<Token> & tokens)4656 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4657 switch( mode ) {
4658 case None: return handleNone( i, c );
4659 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
4660 case ShortOpt:
4661 case LongOpt:
4662 case SlashOpt: return handleOpt( i, c, arg, tokens );
4663 case Positional: return handlePositional( i, c, arg, tokens );
4664 default: throw std::logic_error( "Unknown mode" );
4665 }
4666 }
4667
handleNone(std::size_t i,char c)4668 Mode handleNone( std::size_t i, char c ) {
4669 if( inQuotes ) {
4670 from = i;
4671 return Positional;
4672 }
4673 switch( c ) {
4674 case '-': return MaybeShortOpt;
4675 #ifdef CLARA_PLATFORM_WINDOWS
4676 case '/': from = i+1; return SlashOpt;
4677 #endif
4678 default: from = i; return Positional;
4679 }
4680 }
handleMaybeShortOpt(std::size_t i,char c)4681 Mode handleMaybeShortOpt( std::size_t i, char c ) {
4682 switch( c ) {
4683 case '-': from = i+1; return LongOpt;
4684 default: from = i; return ShortOpt;
4685 }
4686 }
4687
handleOpt(std::size_t i,char c,std::string const & arg,std::vector<Token> & tokens)4688 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4689 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
4690 return mode;
4691
4692 std::string optName = arg.substr( from, i-from );
4693 if( mode == ShortOpt )
4694 for( std::size_t j = 0; j < optName.size(); ++j )
4695 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
4696 else if( mode == SlashOpt && optName.size() == 1 )
4697 tokens.push_back( Token( Token::ShortOpt, optName ) );
4698 else
4699 tokens.push_back( Token( Token::LongOpt, optName ) );
4700 return None;
4701 }
handlePositional(std::size_t i,char c,std::string const & arg,std::vector<Token> & tokens)4702 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4703 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
4704 return mode;
4705
4706 std::string data = arg.substr( from, i-from );
4707 tokens.push_back( Token( Token::Positional, data ) );
4708 return None;
4709 }
4710 };
4711
4712 template<typename ConfigT>
4713 struct CommonArgProperties {
CommonArgPropertiesClara::CommonArgProperties4714 CommonArgProperties() {}
CommonArgPropertiesClara::CommonArgProperties4715 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4716
4717 Detail::BoundArgFunction<ConfigT> boundField;
4718 std::string description;
4719 std::string detail;
4720 std::string placeholder; // Only value if boundField takes an arg
4721
takesArgClara::CommonArgProperties4722 bool takesArg() const {
4723 return !placeholder.empty();
4724 }
validateClara::CommonArgProperties4725 void validate() const {
4726 if( !boundField.isSet() )
4727 throw std::logic_error( "option not bound" );
4728 }
4729 };
4730 struct OptionArgProperties {
4731 std::vector<std::string> shortNames;
4732 std::string longName;
4733
hasShortNameClara::OptionArgProperties4734 bool hasShortName( std::string const& shortName ) const {
4735 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4736 }
hasLongNameClara::OptionArgProperties4737 bool hasLongName( std::string const& _longName ) const {
4738 return _longName == longName;
4739 }
4740 };
4741 struct PositionalArgProperties {
PositionalArgPropertiesClara::PositionalArgProperties4742 PositionalArgProperties() : position( -1 ) {}
4743 int position; // -1 means non-positional (floating)
4744
isFixedPositionalClara::PositionalArgProperties4745 bool isFixedPositional() const {
4746 return position != -1;
4747 }
4748 };
4749
4750 template<typename ConfigT>
4751 class CommandLine {
4752
4753 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
ArgClara::CommandLine::Arg4754 Arg() {}
ArgClara::CommandLine::Arg4755 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
4756
4757 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4758
dbgNameClara::CommandLine::Arg4759 std::string dbgName() const {
4760 if( !longName.empty() )
4761 return "--" + longName;
4762 if( !shortNames.empty() )
4763 return "-" + shortNames[0];
4764 return "positional args";
4765 }
commandsClara::CommandLine::Arg4766 std::string commands() const {
4767 std::ostringstream oss;
4768 bool first = true;
4769 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4770 for(; it != itEnd; ++it ) {
4771 if( first )
4772 first = false;
4773 else
4774 oss << ", ";
4775 oss << "-" << *it;
4776 }
4777 if( !longName.empty() ) {
4778 if( !first )
4779 oss << ", ";
4780 oss << "--" << longName;
4781 }
4782 if( !placeholder.empty() )
4783 oss << " <" << placeholder << ">";
4784 return oss.str();
4785 }
4786 };
4787
4788 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
4789
addOptName(Arg & arg,std::string const & optName)4790 friend void addOptName( Arg& arg, std::string const& optName )
4791 {
4792 if( optName.empty() )
4793 return;
4794 if( Detail::startsWith( optName, "--" ) ) {
4795 if( !arg.longName.empty() )
4796 throw std::logic_error( "Only one long opt may be specified. '"
4797 + arg.longName
4798 + "' already specified, now attempting to add '"
4799 + optName + "'" );
4800 arg.longName = optName.substr( 2 );
4801 }
4802 else if( Detail::startsWith( optName, "-" ) )
4803 arg.shortNames.push_back( optName.substr( 1 ) );
4804 else
4805 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4806 }
setPositionalArg(Arg & arg,int position)4807 friend void setPositionalArg( Arg& arg, int position )
4808 {
4809 arg.position = position;
4810 }
4811
4812 class ArgBuilder {
4813 public:
ArgBuilder(Arg * arg)4814 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
4815
4816 // Bind a non-boolean data member (requires placeholder string)
4817 template<typename C, typename M>
bind(M C::* field,std::string const & placeholder)4818 void bind( M C::* field, std::string const& placeholder ) {
4819 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4820 m_arg->placeholder = placeholder;
4821 }
4822 // Bind a boolean data member (no placeholder required)
4823 template<typename C>
bind(bool C::* field)4824 void bind( bool C::* field ) {
4825 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
4826 }
4827
4828 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4829 template<typename C, typename M>
bind(void (C::* unaryMethod)(M),std::string const & placeholder)4830 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4831 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4832 m_arg->placeholder = placeholder;
4833 }
4834
4835 // Bind a method taking a single, boolean argument (no placeholder string required)
4836 template<typename C>
bind(void (C::* unaryMethod)(bool))4837 void bind( void (C::* unaryMethod)( bool ) ) {
4838 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
4839 }
4840
4841 // Bind a method that takes no arguments (will be called if opt is present)
4842 template<typename C>
bind(void (C::* nullaryMethod)())4843 void bind( void (C::* nullaryMethod)() ) {
4844 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
4845 }
4846
4847 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4848 template<typename C>
bind(void (* unaryFunction)(C &))4849 void bind( void (* unaryFunction)( C& ) ) {
4850 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
4851 }
4852
4853 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4854 template<typename C, typename T>
bind(void (* binaryFunction)(C &,T),std::string const & placeholder)4855 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4856 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4857 m_arg->placeholder = placeholder;
4858 }
4859
describe(std::string const & description)4860 ArgBuilder& describe( std::string const& description ) {
4861 m_arg->description = description;
4862 return *this;
4863 }
detail(std::string const & detail)4864 ArgBuilder& detail( std::string const& detail ) {
4865 m_arg->detail = detail;
4866 return *this;
4867 }
4868
4869 protected:
4870 Arg* m_arg;
4871 };
4872
4873 class OptBuilder : public ArgBuilder {
4874 public:
OptBuilder(Arg * arg)4875 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
OptBuilder(OptBuilder & other)4876 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4877
operator [](std::string const & optName)4878 OptBuilder& operator[]( std::string const& optName ) {
4879 addOptName( *ArgBuilder::m_arg, optName );
4880 return *this;
4881 }
4882 };
4883
4884 public:
4885
CommandLine()4886 CommandLine()
4887 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
4888 m_highestSpecifiedArgPosition( 0 ),
4889 m_throwOnUnrecognisedTokens( false )
4890 {}
CommandLine(CommandLine const & other)4891 CommandLine( CommandLine const& other )
4892 : m_boundProcessName( other.m_boundProcessName ),
4893 m_options ( other.m_options ),
4894 m_positionalArgs( other.m_positionalArgs ),
4895 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4896 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
4897 {
4898 if( other.m_floatingArg.get() )
4899 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
4900 }
4901
setThrowOnUnrecognisedTokens(bool shouldThrow=true)4902 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4903 m_throwOnUnrecognisedTokens = shouldThrow;
4904 return *this;
4905 }
4906
operator [](std::string const & optName)4907 OptBuilder operator[]( std::string const& optName ) {
4908 m_options.push_back( Arg() );
4909 addOptName( m_options.back(), optName );
4910 OptBuilder builder( &m_options.back() );
4911 return builder;
4912 }
4913
operator [](int position)4914 ArgBuilder operator[]( int position ) {
4915 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4916 if( position > m_highestSpecifiedArgPosition )
4917 m_highestSpecifiedArgPosition = position;
4918 setPositionalArg( m_positionalArgs[position], position );
4919 ArgBuilder builder( &m_positionalArgs[position] );
4920 return builder;
4921 }
4922
4923 // Invoke this with the _ instance
operator [](UnpositionalTag)4924 ArgBuilder operator[]( UnpositionalTag ) {
4925 if( m_floatingArg.get() )
4926 throw std::logic_error( "Only one unpositional argument can be added" );
4927 m_floatingArg.reset( new Arg() );
4928 ArgBuilder builder( m_floatingArg.get() );
4929 return builder;
4930 }
4931
4932 template<typename C, typename M>
bindProcessName(M C::* field)4933 void bindProcessName( M C::* field ) {
4934 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4935 }
4936 template<typename C, typename M>
bindProcessName(void (C::* _unaryMethod)(M))4937 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4938 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
4939 }
4940
optUsage(std::ostream & os,std::size_t indent=0,std::size_t width=Detail::consoleWidth) const4941 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
4942 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4943 std::size_t maxWidth = 0;
4944 for( it = itBegin; it != itEnd; ++it )
4945 maxWidth = (std::max)( maxWidth, it->commands().size() );
4946
4947 for( it = itBegin; it != itEnd; ++it ) {
4948 Detail::Text usage( it->commands(), Detail::TextAttributes()
4949 .setWidth( maxWidth+indent )
4950 .setIndent( indent ) );
4951 Detail::Text desc( it->description, Detail::TextAttributes()
4952 .setWidth( width - maxWidth - 3 ) );
4953
4954 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4955 std::string usageCol = i < usage.size() ? usage[i] : "";
4956 os << usageCol;
4957
4958 if( i < desc.size() && !desc[i].empty() )
4959 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4960 << desc[i];
4961 os << "\n";
4962 }
4963 }
4964 }
optUsage() const4965 std::string optUsage() const {
4966 std::ostringstream oss;
4967 optUsage( oss );
4968 return oss.str();
4969 }
4970
argSynopsis(std::ostream & os) const4971 void argSynopsis( std::ostream& os ) const {
4972 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4973 if( i > 1 )
4974 os << " ";
4975 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4976 if( it != m_positionalArgs.end() )
4977 os << "<" << it->second.placeholder << ">";
4978 else if( m_floatingArg.get() )
4979 os << "<" << m_floatingArg->placeholder << ">";
4980 else
4981 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4982 }
4983 // !TBD No indication of mandatory args
4984 if( m_floatingArg.get() ) {
4985 if( m_highestSpecifiedArgPosition > 1 )
4986 os << " ";
4987 os << "[<" << m_floatingArg->placeholder << "> ...]";
4988 }
4989 }
argSynopsis() const4990 std::string argSynopsis() const {
4991 std::ostringstream oss;
4992 argSynopsis( oss );
4993 return oss.str();
4994 }
4995
usage(std::ostream & os,std::string const & procName) const4996 void usage( std::ostream& os, std::string const& procName ) const {
4997 validate();
4998 os << "usage:\n " << procName << " ";
4999 argSynopsis( os );
5000 if( !m_options.empty() ) {
5001 os << " [options]\n\nwhere options are: \n";
5002 optUsage( os, 2 );
5003 }
5004 os << "\n";
5005 }
usage(std::string const & procName) const5006 std::string usage( std::string const& procName ) const {
5007 std::ostringstream oss;
5008 usage( oss, procName );
5009 return oss.str();
5010 }
5011
parse(std::vector<std::string> const & args) const5012 ConfigT parse( std::vector<std::string> const& args ) const {
5013 ConfigT config;
5014 parseInto( args, config );
5015 return config;
5016 }
5017
parseInto(std::vector<std::string> const & args,ConfigT & config) const5018 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
5019 std::string processName = args.empty() ? std::string() : args[0];
5020 std::size_t lastSlash = processName.find_last_of( "/\\" );
5021 if( lastSlash != std::string::npos )
5022 processName = processName.substr( lastSlash+1 );
5023 m_boundProcessName.set( config, processName );
5024 std::vector<Parser::Token> tokens;
5025 Parser parser;
5026 parser.parseIntoTokens( args, tokens );
5027 return populate( tokens, config );
5028 }
5029
populate(std::vector<Parser::Token> const & tokens,ConfigT & config) const5030 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5031 validate();
5032 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
5033 unusedTokens = populateFixedArgs( unusedTokens, config );
5034 unusedTokens = populateFloatingArgs( unusedTokens, config );
5035 return unusedTokens;
5036 }
5037
populateOptions(std::vector<Parser::Token> const & tokens,ConfigT & config) const5038 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5039 std::vector<Parser::Token> unusedTokens;
5040 std::vector<std::string> errors;
5041 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5042 Parser::Token const& token = tokens[i];
5043 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
5044 for(; it != itEnd; ++it ) {
5045 Arg const& arg = *it;
5046
5047 try {
5048 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
5049 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
5050 if( arg.takesArg() ) {
5051 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
5052 errors.push_back( "Expected argument to option: " + token.data );
5053 else
5054 arg.boundField.set( config, tokens[++i].data );
5055 }
5056 else {
5057 arg.boundField.set( config, "true" );
5058 }
5059 break;
5060 }
5061 }
5062 catch( std::exception& ex ) {
5063 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
5064 }
5065 }
5066 if( it == itEnd ) {
5067 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
5068 unusedTokens.push_back( token );
5069 else if( errors.empty() && m_throwOnUnrecognisedTokens )
5070 errors.push_back( "unrecognised option: " + token.data );
5071 }
5072 }
5073 if( !errors.empty() ) {
5074 std::ostringstream oss;
5075 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
5076 it != itEnd;
5077 ++it ) {
5078 if( it != errors.begin() )
5079 oss << "\n";
5080 oss << *it;
5081 }
5082 throw std::runtime_error( oss.str() );
5083 }
5084 return unusedTokens;
5085 }
populateFixedArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const5086 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5087 std::vector<Parser::Token> unusedTokens;
5088 int position = 1;
5089 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5090 Parser::Token const& token = tokens[i];
5091 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
5092 if( it != m_positionalArgs.end() )
5093 it->second.boundField.set( config, token.data );
5094 else
5095 unusedTokens.push_back( token );
5096 if( token.type == Parser::Token::Positional )
5097 position++;
5098 }
5099 return unusedTokens;
5100 }
populateFloatingArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const5101 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5102 if( !m_floatingArg.get() )
5103 return tokens;
5104 std::vector<Parser::Token> unusedTokens;
5105 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5106 Parser::Token const& token = tokens[i];
5107 if( token.type == Parser::Token::Positional )
5108 m_floatingArg->boundField.set( config, token.data );
5109 else
5110 unusedTokens.push_back( token );
5111 }
5112 return unusedTokens;
5113 }
5114
validate() const5115 void validate() const
5116 {
5117 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
5118 throw std::logic_error( "No options or arguments specified" );
5119
5120 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
5121 itEnd = m_options.end();
5122 it != itEnd; ++it )
5123 it->validate();
5124 }
5125
5126 private:
5127 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
5128 std::vector<Arg> m_options;
5129 std::map<int, Arg> m_positionalArgs;
5130 ArgAutoPtr m_floatingArg;
5131 int m_highestSpecifiedArgPosition;
5132 bool m_throwOnUnrecognisedTokens;
5133 };
5134
5135 } // end namespace Clara
5136
5137 STITCH_CLARA_CLOSE_NAMESPACE
5138 #undef STITCH_CLARA_OPEN_NAMESPACE
5139 #undef STITCH_CLARA_CLOSE_NAMESPACE
5140
5141 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
5142 #undef STITCH_CLARA_OPEN_NAMESPACE
5143
5144 // Restore Clara's value for console width, if present
5145 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5146 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5147 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5148 #endif
5149
5150 #include <fstream>
5151 #include <ctime>
5152
5153 namespace Catch {
5154
abortAfterFirst(ConfigData & config)5155 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
abortAfterX(ConfigData & config,int x)5156 inline void abortAfterX( ConfigData& config, int x ) {
5157 if( x < 1 )
5158 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
5159 config.abortAfter = x;
5160 }
addTestOrTags(ConfigData & config,std::string const & _testSpec)5161 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
addSectionToRun(ConfigData & config,std::string const & sectionName)5162 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
addReporterName(ConfigData & config,std::string const & _reporterName)5163 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
5164
addWarning(ConfigData & config,std::string const & _warning)5165 inline void addWarning( ConfigData& config, std::string const& _warning ) {
5166 if( _warning == "NoAssertions" )
5167 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
5168 else
5169 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
5170 }
setOrder(ConfigData & config,std::string const & order)5171 inline void setOrder( ConfigData& config, std::string const& order ) {
5172 if( startsWith( "declared", order ) )
5173 config.runOrder = RunTests::InDeclarationOrder;
5174 else if( startsWith( "lexical", order ) )
5175 config.runOrder = RunTests::InLexicographicalOrder;
5176 else if( startsWith( "random", order ) )
5177 config.runOrder = RunTests::InRandomOrder;
5178 else
5179 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
5180 }
setRngSeed(ConfigData & config,std::string const & seed)5181 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
5182 if( seed == "time" ) {
5183 config.rngSeed = static_cast<unsigned int>( std::time(0) );
5184 }
5185 else {
5186 std::stringstream ss;
5187 ss << seed;
5188 ss >> config.rngSeed;
5189 if( ss.fail() )
5190 throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
5191 }
5192 }
setVerbosity(ConfigData & config,int level)5193 inline void setVerbosity( ConfigData& config, int level ) {
5194 // !TBD: accept strings?
5195 config.verbosity = static_cast<Verbosity::Level>( level );
5196 }
setShowDurations(ConfigData & config,bool _showDurations)5197 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
5198 config.showDurations = _showDurations
5199 ? ShowDurations::Always
5200 : ShowDurations::Never;
5201 }
setUseColour(ConfigData & config,std::string const & value)5202 inline void setUseColour( ConfigData& config, std::string const& value ) {
5203 std::string mode = toLower( value );
5204
5205 if( mode == "yes" )
5206 config.useColour = UseColour::Yes;
5207 else if( mode == "no" )
5208 config.useColour = UseColour::No;
5209 else if( mode == "auto" )
5210 config.useColour = UseColour::Auto;
5211 else
5212 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
5213 }
setWaitForKeypress(ConfigData & config,std::string const & keypress)5214 inline void setWaitForKeypress( ConfigData& config, std::string const& keypress ) {
5215 std::string keypressLc = toLower( keypress );
5216 if( keypressLc == "start" )
5217 config.waitForKeypress = WaitForKeypress::BeforeStart;
5218 else if( keypressLc == "exit" )
5219 config.waitForKeypress = WaitForKeypress::BeforeExit;
5220 else if( keypressLc == "both" )
5221 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
5222 else
5223 throw std::runtime_error( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
5224 };
5225
forceColour(ConfigData & config)5226 inline void forceColour( ConfigData& config ) {
5227 config.useColour = UseColour::Yes;
5228 }
loadTestNamesFromFile(ConfigData & config,std::string const & _filename)5229 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
5230 std::ifstream f( _filename.c_str() );
5231 if( !f.is_open() )
5232 throw std::domain_error( "Unable to load input file: " + _filename );
5233
5234 std::string line;
5235 while( std::getline( f, line ) ) {
5236 line = trim(line);
5237 if( !line.empty() && !startsWith( line, '#' ) ) {
5238 if( !startsWith( line, '"' ) )
5239 line = '"' + line + '"';
5240 addTestOrTags( config, line + ',' );
5241 }
5242 }
5243 }
5244
makeCommandLineParser()5245 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
5246
5247 using namespace Clara;
5248 CommandLine<ConfigData> cli;
5249
5250 cli.bindProcessName( &ConfigData::processName );
5251
5252 cli["-?"]["-h"]["--help"]
5253 .describe( "display usage information" )
5254 .bind( &ConfigData::showHelp );
5255
5256 cli["-l"]["--list-tests"]
5257 .describe( "list all/matching test cases" )
5258 .bind( &ConfigData::listTests );
5259
5260 cli["-t"]["--list-tags"]
5261 .describe( "list all/matching tags" )
5262 .bind( &ConfigData::listTags );
5263
5264 cli["-s"]["--success"]
5265 .describe( "include successful tests in output" )
5266 .bind( &ConfigData::showSuccessfulTests );
5267
5268 cli["-b"]["--break"]
5269 .describe( "break into debugger on failure" )
5270 .bind( &ConfigData::shouldDebugBreak );
5271
5272 cli["-e"]["--nothrow"]
5273 .describe( "skip exception tests" )
5274 .bind( &ConfigData::noThrow );
5275
5276 cli["-i"]["--invisibles"]
5277 .describe( "show invisibles (tabs, newlines)" )
5278 .bind( &ConfigData::showInvisibles );
5279
5280 cli["-o"]["--out"]
5281 .describe( "output filename" )
5282 .bind( &ConfigData::outputFilename, "filename" );
5283
5284 cli["-r"]["--reporter"]
5285 // .placeholder( "name[:filename]" )
5286 .describe( "reporter to use (defaults to console)" )
5287 .bind( &addReporterName, "name" );
5288
5289 cli["-n"]["--name"]
5290 .describe( "suite name" )
5291 .bind( &ConfigData::name, "name" );
5292
5293 cli["-a"]["--abort"]
5294 .describe( "abort at first failure" )
5295 .bind( &abortAfterFirst );
5296
5297 cli["-x"]["--abortx"]
5298 .describe( "abort after x failures" )
5299 .bind( &abortAfterX, "no. failures" );
5300
5301 cli["-w"]["--warn"]
5302 .describe( "enable warnings" )
5303 .bind( &addWarning, "warning name" );
5304
5305 // - needs updating if reinstated
5306 // cli.into( &setVerbosity )
5307 // .describe( "level of verbosity (0=no output)" )
5308 // .shortOpt( "v")
5309 // .longOpt( "verbosity" )
5310 // .placeholder( "level" );
5311
5312 cli[_]
5313 .describe( "which test or tests to use" )
5314 .bind( &addTestOrTags, "test name, pattern or tags" );
5315
5316 cli["-d"]["--durations"]
5317 .describe( "show test durations" )
5318 .bind( &setShowDurations, "yes|no" );
5319
5320 cli["-f"]["--input-file"]
5321 .describe( "load test names to run from a file" )
5322 .bind( &loadTestNamesFromFile, "filename" );
5323
5324 cli["-#"]["--filenames-as-tags"]
5325 .describe( "adds a tag for the filename" )
5326 .bind( &ConfigData::filenamesAsTags );
5327
5328 cli["-c"]["--section"]
5329 .describe( "specify section to run" )
5330 .bind( &addSectionToRun, "section name" );
5331
5332 // Less common commands which don't have a short form
5333 cli["--list-test-names-only"]
5334 .describe( "list all/matching test cases names only" )
5335 .bind( &ConfigData::listTestNamesOnly );
5336
5337 cli["--list-extra-info"]
5338 .describe( "list all/matching test cases with more info" )
5339 .bind( &ConfigData::listExtraInfo );
5340
5341 cli["--list-reporters"]
5342 .describe( "list all reporters" )
5343 .bind( &ConfigData::listReporters );
5344
5345 cli["--order"]
5346 .describe( "test case order (defaults to decl)" )
5347 .bind( &setOrder, "decl|lex|rand" );
5348
5349 cli["--rng-seed"]
5350 .describe( "set a specific seed for random numbers" )
5351 .bind( &setRngSeed, "'time'|number" );
5352
5353 cli["--force-colour"]
5354 .describe( "force colourised output (deprecated)" )
5355 .bind( &forceColour );
5356
5357 cli["--use-colour"]
5358 .describe( "should output be colourised" )
5359 .bind( &setUseColour, "yes|no" );
5360
5361 cli["--libidentify"]
5362 .describe( "report name and version according to libidentify standard" )
5363 .bind( &ConfigData::libIdentify );
5364
5365 cli["--wait-for-keypress"]
5366 .describe( "waits for a keypress before exiting" )
5367 .bind( &setWaitForKeypress, "start|exit|both" );
5368
5369 return cli;
5370 }
5371
5372 } // end namespace Catch
5373
5374 // #included from: internal/catch_list.hpp
5375 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5376
5377 // #included from: catch_text.h
5378 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
5379
5380 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
5381
5382 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
5383 // #included from: ../external/tbc_text_format.h
5384 // Only use header guard if we are not using an outer namespace
5385 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5386 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5387 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5388 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5389 # endif
5390 # else
5391 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5392 # endif
5393 #endif
5394 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5395 #include <string>
5396 #include <vector>
5397 #include <sstream>
5398
5399 // Use optional outer namespace
5400 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5401 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
5402 #endif
5403
5404 namespace Tbc {
5405
5406 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
5407 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
5408 #else
5409 const unsigned int consoleWidth = 80;
5410 #endif
5411
5412 struct TextAttributes {
TextAttributesCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5413 TextAttributes()
5414 : initialIndent( std::string::npos ),
5415 indent( 0 ),
5416 width( consoleWidth-1 )
5417 {}
5418
setInitialIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5419 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
setIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5420 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
setWidthCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5421 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
5422
5423 std::size_t initialIndent; // indent of first line, or npos
5424 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
5425 std::size_t width; // maximum width of text, including indent. Longer text will wrap
5426 };
5427
5428 class Text {
5429 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())5430 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
5431 : attr( _attr )
5432 {
5433 const std::string wrappableBeforeChars = "[({<\t";
5434 const std::string wrappableAfterChars = "])}>-,./|\\";
5435 const std::string wrappableInsteadOfChars = " \n\r";
5436 std::string indent = _attr.initialIndent != std::string::npos
5437 ? std::string( _attr.initialIndent, ' ' )
5438 : std::string( _attr.indent, ' ' );
5439
5440 typedef std::string::const_iterator iterator;
5441 iterator it = _str.begin();
5442 const iterator strEnd = _str.end();
5443
5444 while( it != strEnd ) {
5445
5446 if( lines.size() >= 1000 ) {
5447 lines.push_back( "... message truncated due to excessive size" );
5448 return;
5449 }
5450
5451 std::string suffix;
5452 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
5453 iterator itEnd = it+width;
5454 iterator itNext = _str.end();
5455
5456 iterator itNewLine = std::find( it, itEnd, '\n' );
5457 if( itNewLine != itEnd )
5458 itEnd = itNewLine;
5459
5460 if( itEnd != strEnd ) {
5461 bool foundWrapPoint = false;
5462 iterator findIt = itEnd;
5463 do {
5464 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
5465 itEnd = findIt+1;
5466 itNext = findIt+1;
5467 foundWrapPoint = true;
5468 }
5469 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
5470 itEnd = findIt;
5471 itNext = findIt;
5472 foundWrapPoint = true;
5473 }
5474 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
5475 itNext = findIt+1;
5476 itEnd = findIt;
5477 foundWrapPoint = true;
5478 }
5479 if( findIt == it )
5480 break;
5481 else
5482 --findIt;
5483 }
5484 while( !foundWrapPoint );
5485
5486 if( !foundWrapPoint ) {
5487 // No good wrap char, so we'll break mid word and add a hyphen
5488 --itEnd;
5489 itNext = itEnd;
5490 suffix = "-";
5491 }
5492 else {
5493 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
5494 --itEnd;
5495 }
5496 }
5497 lines.push_back( indent + std::string( it, itEnd ) + suffix );
5498
5499 if( indent.size() != _attr.indent )
5500 indent = std::string( _attr.indent, ' ' );
5501 it = itNext;
5502 }
5503 }
5504
5505 typedef std::vector<std::string>::const_iterator const_iterator;
5506
begin() const5507 const_iterator begin() const { return lines.begin(); }
end() const5508 const_iterator end() const { return lines.end(); }
last() const5509 std::string const& last() const { return lines.back(); }
size() const5510 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const5511 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
toString() const5512 std::string toString() const {
5513 std::ostringstream oss;
5514 oss << *this;
5515 return oss.str();
5516 }
5517
operator <<(std::ostream & _stream,Text const & _text)5518 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
5519 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
5520 it != itEnd; ++it ) {
5521 if( it != _text.begin() )
5522 _stream << "\n";
5523 _stream << *it;
5524 }
5525 return _stream;
5526 }
5527
5528 private:
5529 std::string str;
5530 TextAttributes attr;
5531 std::vector<std::string> lines;
5532 };
5533
5534 } // end namespace Tbc
5535
5536 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5537 } // end outer namespace
5538 #endif
5539
5540 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5541 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5542
5543 namespace Catch {
5544 using Tbc::Text;
5545 using Tbc::TextAttributes;
5546 }
5547
5548 // #included from: catch_console_colour.hpp
5549 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
5550
5551 namespace Catch {
5552
5553 struct Colour {
5554 enum Code {
5555 None = 0,
5556
5557 White,
5558 Red,
5559 Green,
5560 Blue,
5561 Cyan,
5562 Yellow,
5563 Grey,
5564
5565 Bright = 0x10,
5566
5567 BrightRed = Bright | Red,
5568 BrightGreen = Bright | Green,
5569 LightGrey = Bright | Grey,
5570 BrightWhite = Bright | White,
5571
5572 // By intention
5573 FileName = LightGrey,
5574 Warning = Yellow,
5575 ResultError = BrightRed,
5576 ResultSuccess = BrightGreen,
5577 ResultExpectedFailure = Warning,
5578
5579 Error = BrightRed,
5580 Success = Green,
5581
5582 OriginalExpression = Cyan,
5583 ReconstructedExpression = Yellow,
5584
5585 SecondaryText = LightGrey,
5586 Headers = White
5587 };
5588
5589 // Use constructed object for RAII guard
5590 Colour( Code _colourCode );
5591 Colour( Colour const& other );
5592 ~Colour();
5593
5594 // Use static method for one-shot changes
5595 static void use( Code _colourCode );
5596
5597 private:
5598 bool m_moved;
5599 };
5600
operator <<(std::ostream & os,Colour const &)5601 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5602
5603 } // end namespace Catch
5604
5605 // #included from: catch_interfaces_reporter.h
5606 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5607
5608 #include <string>
5609 #include <ostream>
5610 #include <map>
5611
5612 namespace Catch
5613 {
5614 struct ReporterConfig {
ReporterConfigCatch::ReporterConfig5615 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
5616 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5617
ReporterConfigCatch::ReporterConfig5618 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
5619 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5620
streamCatch::ReporterConfig5621 std::ostream& stream() const { return *m_stream; }
fullConfigCatch::ReporterConfig5622 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
5623
5624 private:
5625 std::ostream* m_stream;
5626 Ptr<IConfig const> m_fullConfig;
5627 };
5628
5629 struct ReporterPreferences {
ReporterPreferencesCatch::ReporterPreferences5630 ReporterPreferences()
5631 : shouldRedirectStdOut( false )
5632 {}
5633
5634 bool shouldRedirectStdOut;
5635 };
5636
5637 template<typename T>
5638 struct LazyStat : Option<T> {
LazyStatCatch::LazyStat5639 LazyStat() : used( false ) {}
operator =Catch::LazyStat5640 LazyStat& operator=( T const& _value ) {
5641 Option<T>::operator=( _value );
5642 used = false;
5643 return *this;
5644 }
resetCatch::LazyStat5645 void reset() {
5646 Option<T>::reset();
5647 used = false;
5648 }
5649 bool used;
5650 };
5651
5652 struct TestRunInfo {
TestRunInfoCatch::TestRunInfo5653 TestRunInfo( std::string const& _name ) : name( _name ) {}
5654 std::string name;
5655 };
5656 struct GroupInfo {
GroupInfoCatch::GroupInfo5657 GroupInfo( std::string const& _name,
5658 std::size_t _groupIndex,
5659 std::size_t _groupsCount )
5660 : name( _name ),
5661 groupIndex( _groupIndex ),
5662 groupsCounts( _groupsCount )
5663 {}
5664
5665 std::string name;
5666 std::size_t groupIndex;
5667 std::size_t groupsCounts;
5668 };
5669
5670 struct AssertionStats {
AssertionStatsCatch::AssertionStats5671 AssertionStats( AssertionResult const& _assertionResult,
5672 std::vector<MessageInfo> const& _infoMessages,
5673 Totals const& _totals )
5674 : assertionResult( _assertionResult ),
5675 infoMessages( _infoMessages ),
5676 totals( _totals )
5677 {
5678 if( assertionResult.hasMessage() ) {
5679 // Copy message into messages list.
5680 // !TBD This should have been done earlier, somewhere
5681 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5682 builder << assertionResult.getMessage();
5683 builder.m_info.message = builder.m_stream.str();
5684
5685 infoMessages.push_back( builder.m_info );
5686 }
5687 }
5688 virtual ~AssertionStats();
5689
5690 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5691 AssertionStats( AssertionStats const& ) = default;
5692 AssertionStats( AssertionStats && ) = default;
5693 AssertionStats& operator = ( AssertionStats const& ) = default;
5694 AssertionStats& operator = ( AssertionStats && ) = default;
5695 # endif
5696
5697 AssertionResult assertionResult;
5698 std::vector<MessageInfo> infoMessages;
5699 Totals totals;
5700 };
5701
5702 struct SectionStats {
SectionStatsCatch::SectionStats5703 SectionStats( SectionInfo const& _sectionInfo,
5704 Counts const& _assertions,
5705 double _durationInSeconds,
5706 bool _missingAssertions )
5707 : sectionInfo( _sectionInfo ),
5708 assertions( _assertions ),
5709 durationInSeconds( _durationInSeconds ),
5710 missingAssertions( _missingAssertions )
5711 {}
5712 virtual ~SectionStats();
5713 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5714 SectionStats( SectionStats const& ) = default;
5715 SectionStats( SectionStats && ) = default;
5716 SectionStats& operator = ( SectionStats const& ) = default;
5717 SectionStats& operator = ( SectionStats && ) = default;
5718 # endif
5719
5720 SectionInfo sectionInfo;
5721 Counts assertions;
5722 double durationInSeconds;
5723 bool missingAssertions;
5724 };
5725
5726 struct TestCaseStats {
TestCaseStatsCatch::TestCaseStats5727 TestCaseStats( TestCaseInfo const& _testInfo,
5728 Totals const& _totals,
5729 std::string const& _stdOut,
5730 std::string const& _stdErr,
5731 bool _aborting )
5732 : testInfo( _testInfo ),
5733 totals( _totals ),
5734 stdOut( _stdOut ),
5735 stdErr( _stdErr ),
5736 aborting( _aborting )
5737 {}
5738 virtual ~TestCaseStats();
5739
5740 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5741 TestCaseStats( TestCaseStats const& ) = default;
5742 TestCaseStats( TestCaseStats && ) = default;
5743 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5744 TestCaseStats& operator = ( TestCaseStats && ) = default;
5745 # endif
5746
5747 TestCaseInfo testInfo;
5748 Totals totals;
5749 std::string stdOut;
5750 std::string stdErr;
5751 bool aborting;
5752 };
5753
5754 struct TestGroupStats {
TestGroupStatsCatch::TestGroupStats5755 TestGroupStats( GroupInfo const& _groupInfo,
5756 Totals const& _totals,
5757 bool _aborting )
5758 : groupInfo( _groupInfo ),
5759 totals( _totals ),
5760 aborting( _aborting )
5761 {}
TestGroupStatsCatch::TestGroupStats5762 TestGroupStats( GroupInfo const& _groupInfo )
5763 : groupInfo( _groupInfo ),
5764 aborting( false )
5765 {}
5766 virtual ~TestGroupStats();
5767
5768 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5769 TestGroupStats( TestGroupStats const& ) = default;
5770 TestGroupStats( TestGroupStats && ) = default;
5771 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5772 TestGroupStats& operator = ( TestGroupStats && ) = default;
5773 # endif
5774
5775 GroupInfo groupInfo;
5776 Totals totals;
5777 bool aborting;
5778 };
5779
5780 struct TestRunStats {
TestRunStatsCatch::TestRunStats5781 TestRunStats( TestRunInfo const& _runInfo,
5782 Totals const& _totals,
5783 bool _aborting )
5784 : runInfo( _runInfo ),
5785 totals( _totals ),
5786 aborting( _aborting )
5787 {}
5788 virtual ~TestRunStats();
5789
5790 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestRunStatsCatch::TestRunStats5791 TestRunStats( TestRunStats const& _other )
5792 : runInfo( _other.runInfo ),
5793 totals( _other.totals ),
5794 aborting( _other.aborting )
5795 {}
5796 # else
5797 TestRunStats( TestRunStats const& ) = default;
5798 TestRunStats( TestRunStats && ) = default;
5799 TestRunStats& operator = ( TestRunStats const& ) = default;
5800 TestRunStats& operator = ( TestRunStats && ) = default;
5801 # endif
5802
5803 TestRunInfo runInfo;
5804 Totals totals;
5805 bool aborting;
5806 };
5807
5808 class MultipleReporters;
5809
5810 struct IStreamingReporter : IShared {
5811 virtual ~IStreamingReporter();
5812
5813 // Implementing class must also provide the following static method:
5814 // static std::string getDescription();
5815
5816 virtual ReporterPreferences getPreferences() const = 0;
5817
5818 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5819
5820 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5821 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5822
5823 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5824 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5825
5826 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5827
5828 // The return value indicates if the messages buffer should be cleared:
5829 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
5830
5831 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5832 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5833 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5834 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
5835
5836 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
5837
tryAsMultiCatch::IStreamingReporter5838 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
5839 };
5840
5841 struct IReporterFactory : IShared {
5842 virtual ~IReporterFactory();
5843 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5844 virtual std::string getDescription() const = 0;
5845 };
5846
5847 struct IReporterRegistry {
5848 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5849 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5850
5851 virtual ~IReporterRegistry();
5852 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
5853 virtual FactoryMap const& getFactories() const = 0;
5854 virtual Listeners const& getListeners() const = 0;
5855 };
5856
5857 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5858
5859 }
5860
5861 #include <limits>
5862 #include <algorithm>
5863
5864 namespace Catch {
5865
listTests(Config const & config)5866 inline std::size_t listTests( Config const& config ) {
5867
5868 TestSpec testSpec = config.testSpec();
5869 if( config.testSpec().hasFilters() )
5870 Catch::cout() << "Matching test cases:\n";
5871 else {
5872 Catch::cout() << "All available test cases:\n";
5873 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5874 }
5875
5876 std::size_t matchedTests = 0;
5877 TextAttributes nameAttr, descAttr, tagsAttr;
5878 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5879 descAttr.setIndent( 4 );
5880 tagsAttr.setIndent( 6 );
5881
5882 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5883 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5884 it != itEnd;
5885 ++it ) {
5886 matchedTests++;
5887 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5888 Colour::Code colour = testCaseInfo.isHidden()
5889 ? Colour::SecondaryText
5890 : Colour::None;
5891 Colour colourGuard( colour );
5892
5893 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
5894 if( config.listExtraInfo() ) {
5895 Catch::cout() << " " << testCaseInfo.lineInfo << std::endl;
5896 std::string description = testCaseInfo.description;
5897 if( description.empty() )
5898 description = "(NO DESCRIPTION)";
5899 Catch::cout() << Text( description, descAttr ) << std::endl;
5900 }
5901 if( !testCaseInfo.tags.empty() )
5902 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
5903 }
5904
5905 if( !config.testSpec().hasFilters() )
5906 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
5907 else
5908 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
5909 return matchedTests;
5910 }
5911
listTestsNamesOnly(Config const & config)5912 inline std::size_t listTestsNamesOnly( Config const& config ) {
5913 TestSpec testSpec = config.testSpec();
5914 if( !config.testSpec().hasFilters() )
5915 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5916 std::size_t matchedTests = 0;
5917 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5918 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5919 it != itEnd;
5920 ++it ) {
5921 matchedTests++;
5922 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5923 if( startsWith( testCaseInfo.name, '#' ) )
5924 Catch::cout() << '"' << testCaseInfo.name << '"';
5925 else
5926 Catch::cout() << testCaseInfo.name;
5927 if ( config.listExtraInfo() )
5928 Catch::cout() << "\t@" << testCaseInfo.lineInfo;
5929 Catch::cout() << std::endl;
5930 }
5931 return matchedTests;
5932 }
5933
5934 struct TagInfo {
TagInfoCatch::TagInfo5935 TagInfo() : count ( 0 ) {}
addCatch::TagInfo5936 void add( std::string const& spelling ) {
5937 ++count;
5938 spellings.insert( spelling );
5939 }
allCatch::TagInfo5940 std::string all() const {
5941 std::string out;
5942 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5943 it != itEnd;
5944 ++it )
5945 out += "[" + *it + "]";
5946 return out;
5947 }
5948 std::set<std::string> spellings;
5949 std::size_t count;
5950 };
5951
listTags(Config const & config)5952 inline std::size_t listTags( Config const& config ) {
5953 TestSpec testSpec = config.testSpec();
5954 if( config.testSpec().hasFilters() )
5955 Catch::cout() << "Tags for matching test cases:\n";
5956 else {
5957 Catch::cout() << "All available tags:\n";
5958 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5959 }
5960
5961 std::map<std::string, TagInfo> tagCounts;
5962
5963 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5964 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5965 it != itEnd;
5966 ++it ) {
5967 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5968 tagItEnd = it->getTestCaseInfo().tags.end();
5969 tagIt != tagItEnd;
5970 ++tagIt ) {
5971 std::string tagName = *tagIt;
5972 std::string lcaseTagName = toLower( tagName );
5973 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
5974 if( countIt == tagCounts.end() )
5975 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5976 countIt->second.add( tagName );
5977 }
5978 }
5979
5980 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5981 countItEnd = tagCounts.end();
5982 countIt != countItEnd;
5983 ++countIt ) {
5984 std::ostringstream oss;
5985 oss << " " << std::setw(2) << countIt->second.count << " ";
5986 Text wrapper( countIt->second.all(), TextAttributes()
5987 .setInitialIndent( 0 )
5988 .setIndent( oss.str().size() )
5989 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
5990 Catch::cout() << oss.str() << wrapper << '\n';
5991 }
5992 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
5993 return tagCounts.size();
5994 }
5995
listReporters(Config const &)5996 inline std::size_t listReporters( Config const& /*config*/ ) {
5997 Catch::cout() << "Available reporters:\n";
5998 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
5999 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
6000 std::size_t maxNameLen = 0;
6001 for(it = itBegin; it != itEnd; ++it )
6002 maxNameLen = (std::max)( maxNameLen, it->first.size() );
6003
6004 for(it = itBegin; it != itEnd; ++it ) {
6005 Text wrapper( it->second->getDescription(), TextAttributes()
6006 .setInitialIndent( 0 )
6007 .setIndent( 7+maxNameLen )
6008 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
6009 Catch::cout() << " "
6010 << it->first
6011 << ':'
6012 << std::string( maxNameLen - it->first.size() + 2, ' ' )
6013 << wrapper << '\n';
6014 }
6015 Catch::cout() << std::endl;
6016 return factories.size();
6017 }
6018
list(Config const & config)6019 inline Option<std::size_t> list( Config const& config ) {
6020 Option<std::size_t> listedCount;
6021 if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) )
6022 listedCount = listedCount.valueOr(0) + listTests( config );
6023 if( config.listTestNamesOnly() )
6024 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
6025 if( config.listTags() )
6026 listedCount = listedCount.valueOr(0) + listTags( config );
6027 if( config.listReporters() )
6028 listedCount = listedCount.valueOr(0) + listReporters( config );
6029 return listedCount;
6030 }
6031
6032 } // end namespace Catch
6033
6034 // #included from: internal/catch_run_context.hpp
6035 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
6036
6037 // #included from: catch_test_case_tracker.hpp
6038 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
6039
6040 #include <algorithm>
6041 #include <string>
6042 #include <assert.h>
6043 #include <vector>
6044 #include <stdexcept>
6045
6046 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
6047
6048 namespace Catch {
6049 namespace TestCaseTracking {
6050
6051 struct NameAndLocation {
6052 std::string name;
6053 SourceLineInfo location;
6054
NameAndLocationCatch::TestCaseTracking::NameAndLocation6055 NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
6056 : name( _name ),
6057 location( _location )
6058 {}
6059 };
6060
6061 struct ITracker : SharedImpl<> {
6062 virtual ~ITracker();
6063
6064 // static queries
6065 virtual NameAndLocation const& nameAndLocation() const = 0;
6066
6067 // dynamic queries
6068 virtual bool isComplete() const = 0; // Successfully completed or failed
6069 virtual bool isSuccessfullyCompleted() const = 0;
6070 virtual bool isOpen() const = 0; // Started but not complete
6071 virtual bool hasChildren() const = 0;
6072
6073 virtual ITracker& parent() = 0;
6074
6075 // actions
6076 virtual void close() = 0; // Successfully complete
6077 virtual void fail() = 0;
6078 virtual void markAsNeedingAnotherRun() = 0;
6079
6080 virtual void addChild( Ptr<ITracker> const& child ) = 0;
6081 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
6082 virtual void openChild() = 0;
6083
6084 // Debug/ checking
6085 virtual bool isSectionTracker() const = 0;
6086 virtual bool isIndexTracker() const = 0;
6087 };
6088
6089 class TrackerContext {
6090
6091 enum RunState {
6092 NotStarted,
6093 Executing,
6094 CompletedCycle
6095 };
6096
6097 Ptr<ITracker> m_rootTracker;
6098 ITracker* m_currentTracker;
6099 RunState m_runState;
6100
6101 public:
6102
instance()6103 static TrackerContext& instance() {
6104 static TrackerContext s_instance;
6105 return s_instance;
6106 }
6107
TrackerContext()6108 TrackerContext()
6109 : m_currentTracker( CATCH_NULL ),
6110 m_runState( NotStarted )
6111 {}
6112
6113 ITracker& startRun();
6114
endRun()6115 void endRun() {
6116 m_rootTracker.reset();
6117 m_currentTracker = CATCH_NULL;
6118 m_runState = NotStarted;
6119 }
6120
startCycle()6121 void startCycle() {
6122 m_currentTracker = m_rootTracker.get();
6123 m_runState = Executing;
6124 }
completeCycle()6125 void completeCycle() {
6126 m_runState = CompletedCycle;
6127 }
6128
completedCycle() const6129 bool completedCycle() const {
6130 return m_runState == CompletedCycle;
6131 }
currentTracker()6132 ITracker& currentTracker() {
6133 return *m_currentTracker;
6134 }
setCurrentTracker(ITracker * tracker)6135 void setCurrentTracker( ITracker* tracker ) {
6136 m_currentTracker = tracker;
6137 }
6138 };
6139
6140 class TrackerBase : public ITracker {
6141 protected:
6142 enum CycleState {
6143 NotStarted,
6144 Executing,
6145 ExecutingChildren,
6146 NeedsAnotherRun,
6147 CompletedSuccessfully,
6148 Failed
6149 };
6150 class TrackerHasName {
6151 NameAndLocation m_nameAndLocation;
6152 public:
TrackerHasName(NameAndLocation const & nameAndLocation)6153 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
operator ()(Ptr<ITracker> const & tracker)6154 bool operator ()( Ptr<ITracker> const& tracker ) {
6155 return
6156 tracker->nameAndLocation().name == m_nameAndLocation.name &&
6157 tracker->nameAndLocation().location == m_nameAndLocation.location;
6158 }
6159 };
6160 typedef std::vector<Ptr<ITracker> > Children;
6161 NameAndLocation m_nameAndLocation;
6162 TrackerContext& m_ctx;
6163 ITracker* m_parent;
6164 Children m_children;
6165 CycleState m_runState;
6166 public:
TrackerBase(NameAndLocation const & nameAndLocation,TrackerContext & ctx,ITracker * parent)6167 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6168 : m_nameAndLocation( nameAndLocation ),
6169 m_ctx( ctx ),
6170 m_parent( parent ),
6171 m_runState( NotStarted )
6172 {}
6173 virtual ~TrackerBase();
6174
nameAndLocation() const6175 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
6176 return m_nameAndLocation;
6177 }
isComplete() const6178 virtual bool isComplete() const CATCH_OVERRIDE {
6179 return m_runState == CompletedSuccessfully || m_runState == Failed;
6180 }
isSuccessfullyCompleted() const6181 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
6182 return m_runState == CompletedSuccessfully;
6183 }
isOpen() const6184 virtual bool isOpen() const CATCH_OVERRIDE {
6185 return m_runState != NotStarted && !isComplete();
6186 }
hasChildren() const6187 virtual bool hasChildren() const CATCH_OVERRIDE {
6188 return !m_children.empty();
6189 }
6190
addChild(Ptr<ITracker> const & child)6191 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
6192 m_children.push_back( child );
6193 }
6194
findChild(NameAndLocation const & nameAndLocation)6195 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
6196 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
6197 return( it != m_children.end() )
6198 ? it->get()
6199 : CATCH_NULL;
6200 }
parent()6201 virtual ITracker& parent() CATCH_OVERRIDE {
6202 assert( m_parent ); // Should always be non-null except for root
6203 return *m_parent;
6204 }
6205
openChild()6206 virtual void openChild() CATCH_OVERRIDE {
6207 if( m_runState != ExecutingChildren ) {
6208 m_runState = ExecutingChildren;
6209 if( m_parent )
6210 m_parent->openChild();
6211 }
6212 }
6213
isSectionTracker() const6214 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
isIndexTracker() const6215 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
6216
open()6217 void open() {
6218 m_runState = Executing;
6219 moveToThis();
6220 if( m_parent )
6221 m_parent->openChild();
6222 }
6223
close()6224 virtual void close() CATCH_OVERRIDE {
6225
6226 // Close any still open children (e.g. generators)
6227 while( &m_ctx.currentTracker() != this )
6228 m_ctx.currentTracker().close();
6229
6230 switch( m_runState ) {
6231 case NotStarted:
6232 case CompletedSuccessfully:
6233 case Failed:
6234 throw std::logic_error( "Illogical state" );
6235
6236 case NeedsAnotherRun:
6237 break;;
6238
6239 case Executing:
6240 m_runState = CompletedSuccessfully;
6241 break;
6242 case ExecutingChildren:
6243 if( m_children.empty() || m_children.back()->isComplete() )
6244 m_runState = CompletedSuccessfully;
6245 break;
6246
6247 default:
6248 throw std::logic_error( "Unexpected state" );
6249 }
6250 moveToParent();
6251 m_ctx.completeCycle();
6252 }
fail()6253 virtual void fail() CATCH_OVERRIDE {
6254 m_runState = Failed;
6255 if( m_parent )
6256 m_parent->markAsNeedingAnotherRun();
6257 moveToParent();
6258 m_ctx.completeCycle();
6259 }
markAsNeedingAnotherRun()6260 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
6261 m_runState = NeedsAnotherRun;
6262 }
6263 private:
moveToParent()6264 void moveToParent() {
6265 assert( m_parent );
6266 m_ctx.setCurrentTracker( m_parent );
6267 }
moveToThis()6268 void moveToThis() {
6269 m_ctx.setCurrentTracker( this );
6270 }
6271 };
6272
6273 class SectionTracker : public TrackerBase {
6274 std::vector<std::string> m_filters;
6275 public:
SectionTracker(NameAndLocation const & nameAndLocation,TrackerContext & ctx,ITracker * parent)6276 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6277 : TrackerBase( nameAndLocation, ctx, parent )
6278 {
6279 if( parent ) {
6280 while( !parent->isSectionTracker() )
6281 parent = &parent->parent();
6282
6283 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
6284 addNextFilters( parentSection.m_filters );
6285 }
6286 }
6287 virtual ~SectionTracker();
6288
isSectionTracker() const6289 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
6290
acquire(TrackerContext & ctx,NameAndLocation const & nameAndLocation)6291 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
6292 SectionTracker* section = CATCH_NULL;
6293
6294 ITracker& currentTracker = ctx.currentTracker();
6295 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
6296 assert( childTracker );
6297 assert( childTracker->isSectionTracker() );
6298 section = static_cast<SectionTracker*>( childTracker );
6299 }
6300 else {
6301 section = new SectionTracker( nameAndLocation, ctx, ¤tTracker );
6302 currentTracker.addChild( section );
6303 }
6304 if( !ctx.completedCycle() )
6305 section->tryOpen();
6306 return *section;
6307 }
6308
tryOpen()6309 void tryOpen() {
6310 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
6311 open();
6312 }
6313
addInitialFilters(std::vector<std::string> const & filters)6314 void addInitialFilters( std::vector<std::string> const& filters ) {
6315 if( !filters.empty() ) {
6316 m_filters.push_back(""); // Root - should never be consulted
6317 m_filters.push_back(""); // Test Case - not a section filter
6318 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
6319 }
6320 }
addNextFilters(std::vector<std::string> const & filters)6321 void addNextFilters( std::vector<std::string> const& filters ) {
6322 if( filters.size() > 1 )
6323 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
6324 }
6325 };
6326
6327 class IndexTracker : public TrackerBase {
6328 int m_size;
6329 int m_index;
6330 public:
IndexTracker(NameAndLocation const & nameAndLocation,TrackerContext & ctx,ITracker * parent,int size)6331 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
6332 : TrackerBase( nameAndLocation, ctx, parent ),
6333 m_size( size ),
6334 m_index( -1 )
6335 {}
6336 virtual ~IndexTracker();
6337
isIndexTracker() const6338 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
6339
acquire(TrackerContext & ctx,NameAndLocation const & nameAndLocation,int size)6340 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
6341 IndexTracker* tracker = CATCH_NULL;
6342
6343 ITracker& currentTracker = ctx.currentTracker();
6344 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
6345 assert( childTracker );
6346 assert( childTracker->isIndexTracker() );
6347 tracker = static_cast<IndexTracker*>( childTracker );
6348 }
6349 else {
6350 tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size );
6351 currentTracker.addChild( tracker );
6352 }
6353
6354 if( !ctx.completedCycle() && !tracker->isComplete() ) {
6355 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
6356 tracker->moveNext();
6357 tracker->open();
6358 }
6359
6360 return *tracker;
6361 }
6362
index() const6363 int index() const { return m_index; }
6364
moveNext()6365 void moveNext() {
6366 m_index++;
6367 m_children.clear();
6368 }
6369
close()6370 virtual void close() CATCH_OVERRIDE {
6371 TrackerBase::close();
6372 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
6373 m_runState = Executing;
6374 }
6375 };
6376
startRun()6377 inline ITracker& TrackerContext::startRun() {
6378 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
6379 m_currentTracker = CATCH_NULL;
6380 m_runState = Executing;
6381 return *m_rootTracker;
6382 }
6383
6384 } // namespace TestCaseTracking
6385
6386 using TestCaseTracking::ITracker;
6387 using TestCaseTracking::TrackerContext;
6388 using TestCaseTracking::SectionTracker;
6389 using TestCaseTracking::IndexTracker;
6390
6391 } // namespace Catch
6392
6393 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
6394
6395 // #included from: catch_fatal_condition.hpp
6396 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
6397
6398 namespace Catch {
6399
6400 // Report the error condition
reportFatal(std::string const & message)6401 inline void reportFatal( std::string const& message ) {
6402 IContext& context = Catch::getCurrentContext();
6403 IResultCapture* resultCapture = context.getResultCapture();
6404 resultCapture->handleFatalErrorCondition( message );
6405 }
6406
6407 } // namespace Catch
6408
6409 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
6410 // #included from: catch_windows_h_proxy.h
6411
6412 #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
6413
6414 #ifdef CATCH_DEFINES_NOMINMAX
6415 # define NOMINMAX
6416 #endif
6417 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6418 # define WIN32_LEAN_AND_MEAN
6419 #endif
6420
6421 #ifdef __AFXDLL
6422 #include <AfxWin.h>
6423 #else
6424 #include <windows.h>
6425 #endif
6426
6427 #ifdef CATCH_DEFINES_NOMINMAX
6428 # undef NOMINMAX
6429 #endif
6430 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6431 # undef WIN32_LEAN_AND_MEAN
6432 #endif
6433
6434
6435 # if !defined ( CATCH_CONFIG_WINDOWS_SEH )
6436
6437 namespace Catch {
6438 struct FatalConditionHandler {
resetCatch::FatalConditionHandler6439 void reset() {}
6440 };
6441 }
6442
6443 # else // CATCH_CONFIG_WINDOWS_SEH is defined
6444
6445 namespace Catch {
6446
6447 struct SignalDefs { DWORD id; const char* name; };
6448 extern SignalDefs signalDefs[];
6449 // There is no 1-1 mapping between signals and windows exceptions.
6450 // Windows can easily distinguish between SO and SigSegV,
6451 // but SigInt, SigTerm, etc are handled differently.
6452 SignalDefs signalDefs[] = {
6453 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
6454 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
6455 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
6456 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
6457 };
6458
6459 struct FatalConditionHandler {
6460
handleVectoredExceptionCatch::FatalConditionHandler6461 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
6462 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6463 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
6464 reportFatal(signalDefs[i].name);
6465 }
6466 }
6467 // If its not an exception we care about, pass it along.
6468 // This stops us from eating debugger breaks etc.
6469 return EXCEPTION_CONTINUE_SEARCH;
6470 }
6471
FatalConditionHandlerCatch::FatalConditionHandler6472 FatalConditionHandler() {
6473 isSet = true;
6474 // 32k seems enough for Catch to handle stack overflow,
6475 // but the value was found experimentally, so there is no strong guarantee
6476 guaranteeSize = 32 * 1024;
6477 exceptionHandlerHandle = CATCH_NULL;
6478 // Register as first handler in current chain
6479 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
6480 // Pass in guarantee size to be filled
6481 SetThreadStackGuarantee(&guaranteeSize);
6482 }
6483
resetCatch::FatalConditionHandler6484 static void reset() {
6485 if (isSet) {
6486 // Unregister handler and restore the old guarantee
6487 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
6488 SetThreadStackGuarantee(&guaranteeSize);
6489 exceptionHandlerHandle = CATCH_NULL;
6490 isSet = false;
6491 }
6492 }
6493
~FatalConditionHandlerCatch::FatalConditionHandler6494 ~FatalConditionHandler() {
6495 reset();
6496 }
6497 private:
6498 static bool isSet;
6499 static ULONG guaranteeSize;
6500 static PVOID exceptionHandlerHandle;
6501 };
6502
6503 bool FatalConditionHandler::isSet = false;
6504 ULONG FatalConditionHandler::guaranteeSize = 0;
6505 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
6506
6507 } // namespace Catch
6508
6509 # endif // CATCH_CONFIG_WINDOWS_SEH
6510
6511 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
6512
6513 # if !defined(CATCH_CONFIG_POSIX_SIGNALS)
6514
6515 namespace Catch {
6516 struct FatalConditionHandler {
resetCatch::FatalConditionHandler6517 void reset() {}
6518 };
6519 }
6520
6521 # else // CATCH_CONFIG_POSIX_SIGNALS is defined
6522
6523 #include <signal.h>
6524
6525 namespace Catch {
6526
6527 struct SignalDefs {
6528 int id;
6529 const char* name;
6530 };
6531 extern SignalDefs signalDefs[];
6532 SignalDefs signalDefs[] = {
6533 { SIGINT, "SIGINT - Terminal interrupt signal" },
6534 { SIGILL, "SIGILL - Illegal instruction signal" },
6535 { SIGFPE, "SIGFPE - Floating point error signal" },
6536 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
6537 { SIGTERM, "SIGTERM - Termination request signal" },
6538 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
6539 };
6540
6541 struct FatalConditionHandler {
6542
6543 static bool isSet;
6544 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
6545 static stack_t oldSigStack;
6546 static char altStackMem[SIGSTKSZ];
6547
handleSignalCatch::FatalConditionHandler6548 static void handleSignal( int sig ) {
6549 std::string name = "<unknown signal>";
6550 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6551 SignalDefs &def = signalDefs[i];
6552 if (sig == def.id) {
6553 name = def.name;
6554 break;
6555 }
6556 }
6557 reset();
6558 reportFatal(name);
6559 raise( sig );
6560 }
6561
FatalConditionHandlerCatch::FatalConditionHandler6562 FatalConditionHandler() {
6563 isSet = true;
6564 stack_t sigStack;
6565 sigStack.ss_sp = altStackMem;
6566 sigStack.ss_size = SIGSTKSZ;
6567 sigStack.ss_flags = 0;
6568 sigaltstack(&sigStack, &oldSigStack);
6569 struct sigaction sa = { 0 };
6570
6571 sa.sa_handler = handleSignal;
6572 sa.sa_flags = SA_ONSTACK;
6573 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
6574 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
6575 }
6576 }
6577
~FatalConditionHandlerCatch::FatalConditionHandler6578 ~FatalConditionHandler() {
6579 reset();
6580 }
resetCatch::FatalConditionHandler6581 static void reset() {
6582 if( isSet ) {
6583 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
6584 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
6585 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
6586 }
6587 // Return the old stack
6588 sigaltstack(&oldSigStack, CATCH_NULL);
6589 isSet = false;
6590 }
6591 }
6592 };
6593
6594 bool FatalConditionHandler::isSet = false;
6595 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
6596 stack_t FatalConditionHandler::oldSigStack = {};
6597 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
6598
6599 } // namespace Catch
6600
6601 # endif // CATCH_CONFIG_POSIX_SIGNALS
6602
6603 #endif // not Windows
6604
6605 #include <set>
6606 #include <string>
6607
6608 namespace Catch {
6609
6610 class StreamRedirect {
6611
6612 public:
StreamRedirect(std::ostream & stream,std::string & targetString)6613 StreamRedirect( std::ostream& stream, std::string& targetString )
6614 : m_stream( stream ),
6615 m_prevBuf( stream.rdbuf() ),
6616 m_targetString( targetString )
6617 {
6618 stream.rdbuf( m_oss.rdbuf() );
6619 }
6620
~StreamRedirect()6621 ~StreamRedirect() {
6622 m_targetString += m_oss.str();
6623 m_stream.rdbuf( m_prevBuf );
6624 }
6625
6626 private:
6627 std::ostream& m_stream;
6628 std::streambuf* m_prevBuf;
6629 std::ostringstream m_oss;
6630 std::string& m_targetString;
6631 };
6632
6633 // StdErr has two constituent streams in C++, std::cerr and std::clog
6634 // This means that we need to redirect 2 streams into 1 to keep proper
6635 // order of writes and cannot use StreamRedirect on its own
6636 class StdErrRedirect {
6637 public:
StdErrRedirect(std::string & targetString)6638 StdErrRedirect(std::string& targetString)
6639 :m_cerrBuf( cerr().rdbuf() ), m_clogBuf(clog().rdbuf()),
6640 m_targetString(targetString){
6641 cerr().rdbuf(m_oss.rdbuf());
6642 clog().rdbuf(m_oss.rdbuf());
6643 }
~StdErrRedirect()6644 ~StdErrRedirect() {
6645 m_targetString += m_oss.str();
6646 cerr().rdbuf(m_cerrBuf);
6647 clog().rdbuf(m_clogBuf);
6648 }
6649 private:
6650 std::streambuf* m_cerrBuf;
6651 std::streambuf* m_clogBuf;
6652 std::ostringstream m_oss;
6653 std::string& m_targetString;
6654 };
6655
6656 ///////////////////////////////////////////////////////////////////////////
6657
6658 class RunContext : public IResultCapture, public IRunner {
6659
6660 RunContext( RunContext const& );
6661 void operator =( RunContext const& );
6662
6663 public:
6664
RunContext(Ptr<IConfig const> const & _config,Ptr<IStreamingReporter> const & reporter)6665 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
6666 : m_runInfo( _config->name() ),
6667 m_context( getCurrentMutableContext() ),
6668 m_activeTestCase( CATCH_NULL ),
6669 m_config( _config ),
6670 m_reporter( reporter ),
6671 m_shouldReportUnexpected ( true )
6672 {
6673 m_context.setRunner( this );
6674 m_context.setConfig( m_config );
6675 m_context.setResultCapture( this );
6676 m_reporter->testRunStarting( m_runInfo );
6677 }
6678
~RunContext()6679 virtual ~RunContext() {
6680 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
6681 }
6682
testGroupStarting(std::string const & testSpec,std::size_t groupIndex,std::size_t groupsCount)6683 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
6684 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
6685 }
testGroupEnded(std::string const & testSpec,Totals const & totals,std::size_t groupIndex,std::size_t groupsCount)6686 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
6687 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
6688 }
6689
runTest(TestCase const & testCase)6690 Totals runTest( TestCase const& testCase ) {
6691 Totals prevTotals = m_totals;
6692
6693 std::string redirectedCout;
6694 std::string redirectedCerr;
6695
6696 TestCaseInfo testInfo = testCase.getTestCaseInfo();
6697
6698 m_reporter->testCaseStarting( testInfo );
6699
6700 m_activeTestCase = &testCase;
6701
6702 do {
6703 ITracker& rootTracker = m_trackerContext.startRun();
6704 assert( rootTracker.isSectionTracker() );
6705 static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
6706 do {
6707 m_trackerContext.startCycle();
6708 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
6709 runCurrentTest( redirectedCout, redirectedCerr );
6710 }
6711 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
6712 }
6713 // !TBD: deprecated - this will be replaced by indexed trackers
6714 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
6715
6716 Totals deltaTotals = m_totals.delta( prevTotals );
6717 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
6718 deltaTotals.assertions.failed++;
6719 deltaTotals.testCases.passed--;
6720 deltaTotals.testCases.failed++;
6721 }
6722 m_totals.testCases += deltaTotals.testCases;
6723 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6724 deltaTotals,
6725 redirectedCout,
6726 redirectedCerr,
6727 aborting() ) );
6728
6729 m_activeTestCase = CATCH_NULL;
6730 m_testCaseTracker = CATCH_NULL;
6731
6732 return deltaTotals;
6733 }
6734
config() const6735 Ptr<IConfig const> config() const {
6736 return m_config;
6737 }
6738
6739 private: // IResultCapture
6740
assertionEnded(AssertionResult const & result)6741 virtual void assertionEnded( AssertionResult const& result ) {
6742 if( result.getResultType() == ResultWas::Ok ) {
6743 m_totals.assertions.passed++;
6744 }
6745 else if( !result.isOk() ) {
6746 if( m_activeTestCase->getTestCaseInfo().okToFail() )
6747 m_totals.assertions.failedButOk++;
6748 else
6749 m_totals.assertions.failed++;
6750 }
6751
6752 // We have no use for the return value (whether messages should be cleared), because messages were made scoped
6753 // and should be let to clear themselves out.
6754 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
6755
6756 // Reset working state
6757 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
6758 m_lastResult = result;
6759 }
6760
lastAssertionPassed()6761 virtual bool lastAssertionPassed()
6762 {
6763 return m_totals.assertions.passed == (m_prevPassed + 1);
6764 }
6765
assertionPassed()6766 virtual void assertionPassed()
6767 {
6768 m_totals.assertions.passed++;
6769 m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}";
6770 m_lastAssertionInfo.macroName = "";
6771 }
6772
assertionRun()6773 virtual void assertionRun()
6774 {
6775 m_prevPassed = m_totals.assertions.passed;
6776 }
6777
sectionStarted(SectionInfo const & sectionInfo,Counts & assertions)6778 virtual bool sectionStarted (
6779 SectionInfo const& sectionInfo,
6780 Counts& assertions
6781 )
6782 {
6783 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
6784 if( !sectionTracker.isOpen() )
6785 return false;
6786 m_activeSections.push_back( §ionTracker );
6787
6788 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
6789
6790 m_reporter->sectionStarting( sectionInfo );
6791
6792 assertions = m_totals.assertions;
6793
6794 return true;
6795 }
testForMissingAssertions(Counts & assertions)6796 bool testForMissingAssertions( Counts& assertions ) {
6797 if( assertions.total() != 0 )
6798 return false;
6799 if( !m_config->warnAboutMissingAssertions() )
6800 return false;
6801 if( m_trackerContext.currentTracker().hasChildren() )
6802 return false;
6803 m_totals.assertions.failed++;
6804 assertions.failed++;
6805 return true;
6806 }
6807
sectionEnded(SectionEndInfo const & endInfo)6808 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
6809 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
6810 bool missingAssertions = testForMissingAssertions( assertions );
6811
6812 if( !m_activeSections.empty() ) {
6813 m_activeSections.back()->close();
6814 m_activeSections.pop_back();
6815 }
6816
6817 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
6818 m_messages.clear();
6819 }
6820
sectionEndedEarly(SectionEndInfo const & endInfo)6821 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
6822 if( m_unfinishedSections.empty() )
6823 m_activeSections.back()->fail();
6824 else
6825 m_activeSections.back()->close();
6826 m_activeSections.pop_back();
6827
6828 m_unfinishedSections.push_back( endInfo );
6829 }
6830
pushScopedMessage(MessageInfo const & message)6831 virtual void pushScopedMessage( MessageInfo const& message ) {
6832 m_messages.push_back( message );
6833 }
6834
popScopedMessage(MessageInfo const & message)6835 virtual void popScopedMessage( MessageInfo const& message ) {
6836 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
6837 }
6838
getCurrentTestName() const6839 virtual std::string getCurrentTestName() const {
6840 return m_activeTestCase
6841 ? m_activeTestCase->getTestCaseInfo().name
6842 : std::string();
6843 }
6844
getLastResult() const6845 virtual const AssertionResult* getLastResult() const {
6846 return &m_lastResult;
6847 }
6848
exceptionEarlyReported()6849 virtual void exceptionEarlyReported() {
6850 m_shouldReportUnexpected = false;
6851 }
6852
handleFatalErrorCondition(std::string const & message)6853 virtual void handleFatalErrorCondition( std::string const& message ) {
6854 // Don't rebuild the result -- the stringification itself can cause more fatal errors
6855 // Instead, fake a result data.
6856 AssertionResultData tempResult;
6857 tempResult.resultType = ResultWas::FatalErrorCondition;
6858 tempResult.message = message;
6859 AssertionResult result(m_lastAssertionInfo, tempResult);
6860
6861 getResultCapture().assertionEnded(result);
6862
6863 handleUnfinishedSections();
6864
6865 // Recreate section for test case (as we will lose the one that was in scope)
6866 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6867 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6868
6869 Counts assertions;
6870 assertions.failed = 1;
6871 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6872 m_reporter->sectionEnded( testCaseSectionStats );
6873
6874 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6875
6876 Totals deltaTotals;
6877 deltaTotals.testCases.failed = 1;
6878 deltaTotals.assertions.failed = 1;
6879 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6880 deltaTotals,
6881 std::string(),
6882 std::string(),
6883 false ) );
6884 m_totals.testCases.failed++;
6885 testGroupEnded( std::string(), m_totals, 1, 1 );
6886 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6887 }
6888
6889 public:
6890 // !TBD We need to do this another way!
aborting() const6891 bool aborting() const {
6892 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
6893 }
6894
6895 private:
6896
runCurrentTest(std::string & redirectedCout,std::string & redirectedCerr)6897 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
6898 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6899 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6900 m_reporter->sectionStarting( testCaseSection );
6901 Counts prevAssertions = m_totals.assertions;
6902 double duration = 0;
6903 m_shouldReportUnexpected = true;
6904 try {
6905 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
6906
6907 seedRng( *m_config );
6908
6909 Timer timer;
6910 timer.start();
6911 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
6912 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6913 StdErrRedirect errRedir( redirectedCerr );
6914 invokeActiveTestCase();
6915 }
6916 else {
6917 invokeActiveTestCase();
6918 }
6919 duration = timer.getElapsedSeconds();
6920 }
6921 catch( TestFailureException& ) {
6922 // This just means the test was aborted due to failure
6923 }
6924 catch(...) {
6925 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
6926 // are reported without translation at the point of origin.
6927 if (m_shouldReportUnexpected) {
6928 makeUnexpectedResultBuilder().useActiveException();
6929 }
6930 }
6931 m_testCaseTracker->close();
6932 handleUnfinishedSections();
6933 m_messages.clear();
6934
6935 Counts assertions = m_totals.assertions - prevAssertions;
6936 bool missingAssertions = testForMissingAssertions( assertions );
6937
6938 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
6939 m_reporter->sectionEnded( testCaseSectionStats );
6940 }
6941
invokeActiveTestCase()6942 void invokeActiveTestCase() {
6943 FatalConditionHandler fatalConditionHandler; // Handle signals
6944 m_activeTestCase->invoke();
6945 fatalConditionHandler.reset();
6946 }
6947
6948 private:
6949
makeUnexpectedResultBuilder() const6950 ResultBuilder makeUnexpectedResultBuilder() const {
6951 return ResultBuilder( m_lastAssertionInfo.macroName,
6952 m_lastAssertionInfo.lineInfo,
6953 m_lastAssertionInfo.capturedExpression,
6954 m_lastAssertionInfo.resultDisposition );
6955 }
6956
handleUnfinishedSections()6957 void handleUnfinishedSections() {
6958 // If sections ended prematurely due to an exception we stored their
6959 // infos here so we can tear them down outside the unwind process.
6960 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
6961 itEnd = m_unfinishedSections.rend();
6962 it != itEnd;
6963 ++it )
6964 sectionEnded( *it );
6965 m_unfinishedSections.clear();
6966 }
6967
6968 TestRunInfo m_runInfo;
6969 IMutableContext& m_context;
6970 TestCase const* m_activeTestCase;
6971 ITracker* m_testCaseTracker;
6972 ITracker* m_currentSectionTracker;
6973 AssertionResult m_lastResult;
6974
6975 Ptr<IConfig const> m_config;
6976 Totals m_totals;
6977 Ptr<IStreamingReporter> m_reporter;
6978 std::vector<MessageInfo> m_messages;
6979 AssertionInfo m_lastAssertionInfo;
6980 std::vector<SectionEndInfo> m_unfinishedSections;
6981 std::vector<ITracker*> m_activeSections;
6982 TrackerContext m_trackerContext;
6983 size_t m_prevPassed;
6984 bool m_shouldReportUnexpected;
6985 };
6986
getResultCapture()6987 IResultCapture& getResultCapture() {
6988 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6989 return *capture;
6990 else
6991 throw std::logic_error( "No result capture instance" );
6992 }
6993
6994 } // end namespace Catch
6995
6996 // #included from: internal/catch_version.h
6997 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6998
6999 namespace Catch {
7000
7001 // Versioning information
7002 struct Version {
7003 Version( unsigned int _majorVersion,
7004 unsigned int _minorVersion,
7005 unsigned int _patchNumber,
7006 char const * const _branchName,
7007 unsigned int _buildNumber );
7008
7009 unsigned int const majorVersion;
7010 unsigned int const minorVersion;
7011 unsigned int const patchNumber;
7012
7013 // buildNumber is only used if branchName is not null
7014 char const * const branchName;
7015 unsigned int const buildNumber;
7016
7017 friend std::ostream& operator << ( std::ostream& os, Version const& version );
7018
7019 private:
7020 void operator=( Version const& );
7021 };
7022
7023 inline Version libraryVersion();
7024 }
7025
7026 #include <fstream>
7027 #include <stdlib.h>
7028 #include <limits>
7029
7030 namespace Catch {
7031
createReporter(std::string const & reporterName,Ptr<Config> const & config)7032 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
7033 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
7034 if( !reporter ) {
7035 std::ostringstream oss;
7036 oss << "No reporter registered with name: '" << reporterName << "'";
7037 throw std::domain_error( oss.str() );
7038 }
7039 return reporter;
7040 }
7041
7042 #if !defined(CATCH_CONFIG_DEFAULT_REPORTER)
7043 #define CATCH_CONFIG_DEFAULT_REPORTER "console"
7044 #endif
7045
makeReporter(Ptr<Config> const & config)7046 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
7047 std::vector<std::string> reporters = config->getReporterNames();
7048 if( reporters.empty() )
7049 reporters.push_back( CATCH_CONFIG_DEFAULT_REPORTER );
7050
7051 Ptr<IStreamingReporter> reporter;
7052 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
7053 it != itEnd;
7054 ++it )
7055 reporter = addReporter( reporter, createReporter( *it, config ) );
7056 return reporter;
7057 }
addListeners(Ptr<IConfig const> const & config,Ptr<IStreamingReporter> reporters)7058 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
7059 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
7060 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
7061 it != itEnd;
7062 ++it )
7063 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
7064 return reporters;
7065 }
7066
runTests(Ptr<Config> const & config)7067 Totals runTests( Ptr<Config> const& config ) {
7068
7069 Ptr<IConfig const> iconfig = config.get();
7070
7071 Ptr<IStreamingReporter> reporter = makeReporter( config );
7072 reporter = addListeners( iconfig, reporter );
7073
7074 RunContext context( iconfig, reporter );
7075
7076 Totals totals;
7077
7078 context.testGroupStarting( config->name(), 1, 1 );
7079
7080 TestSpec testSpec = config->testSpec();
7081 if( !testSpec.hasFilters() )
7082 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
7083
7084 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
7085 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
7086 it != itEnd;
7087 ++it ) {
7088 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
7089 totals += context.runTest( *it );
7090 else
7091 reporter->skipTest( *it );
7092 }
7093
7094 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
7095 return totals;
7096 }
7097
applyFilenamesAsTags(IConfig const & config)7098 void applyFilenamesAsTags( IConfig const& config ) {
7099 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
7100 for(std::size_t i = 0; i < tests.size(); ++i ) {
7101 TestCase& test = const_cast<TestCase&>( tests[i] );
7102 std::set<std::string> tags = test.tags;
7103
7104 std::string filename = test.lineInfo.file;
7105 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
7106 if( lastSlash != std::string::npos )
7107 filename = filename.substr( lastSlash+1 );
7108
7109 std::string::size_type lastDot = filename.find_last_of( '.' );
7110 if( lastDot != std::string::npos )
7111 filename = filename.substr( 0, lastDot );
7112
7113 tags.insert( '#' + filename );
7114 setTags( test, tags );
7115 }
7116 }
7117
7118 class Session : NonCopyable {
7119 static bool alreadyInstantiated;
7120
7121 public:
7122
7123 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
7124
Session()7125 Session()
7126 : m_cli( makeCommandLineParser() ) {
7127 if( alreadyInstantiated ) {
7128 std::string msg = "Only one instance of Catch::Session can ever be used";
7129 Catch::cerr() << msg << std::endl;
7130 throw std::logic_error( msg );
7131 }
7132 alreadyInstantiated = true;
7133 }
~Session()7134 ~Session() {
7135 Catch::cleanUp();
7136 }
7137
showHelp(std::string const & processName)7138 void showHelp( std::string const& processName ) {
7139 Catch::cout() << "\nCatch v" << libraryVersion() << "\n";
7140
7141 m_cli.usage( Catch::cout(), processName );
7142 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
7143 }
libIdentify()7144 void libIdentify() {
7145 Catch::cout()
7146 << std::left << std::setw(16) << "description: " << "A Catch test executable\n"
7147 << std::left << std::setw(16) << "category: " << "testframework\n"
7148 << std::left << std::setw(16) << "framework: " << "Catch Test\n"
7149 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
7150 }
7151
applyCommandLine(int argc,char const * const * const argv,OnUnusedOptions::DoWhat unusedOptionBehaviour=OnUnusedOptions::Fail)7152 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
7153 try {
7154 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
7155 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
7156 if( m_configData.showHelp )
7157 showHelp( m_configData.processName );
7158 if( m_configData.libIdentify )
7159 libIdentify();
7160 m_config.reset();
7161 }
7162 catch( std::exception& ex ) {
7163 {
7164 Colour colourGuard( Colour::Red );
7165 Catch::cerr()
7166 << "\nError(s) in input:\n"
7167 << Text( ex.what(), TextAttributes().setIndent(2) )
7168 << "\n\n";
7169 }
7170 m_cli.usage( Catch::cout(), m_configData.processName );
7171 return (std::numeric_limits<int>::max)();
7172 }
7173 return 0;
7174 }
7175
useConfigData(ConfigData const & _configData)7176 void useConfigData( ConfigData const& _configData ) {
7177 m_configData = _configData;
7178 m_config.reset();
7179 }
7180
run(int argc,char const * const * const argv)7181 int run( int argc, char const* const* const argv ) {
7182
7183 int returnCode = applyCommandLine( argc, argv );
7184 if( returnCode == 0 )
7185 returnCode = run();
7186 return returnCode;
7187 }
7188
7189 #if defined(WIN32) && defined(UNICODE)
run(int argc,wchar_t const * const * const argv)7190 int run( int argc, wchar_t const* const* const argv ) {
7191
7192 char **utf8Argv = new char *[ argc ];
7193
7194 for ( int i = 0; i < argc; ++i ) {
7195 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
7196
7197 utf8Argv[ i ] = new char[ bufSize ];
7198
7199 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
7200 }
7201
7202 int returnCode = applyCommandLine( argc, utf8Argv );
7203 if( returnCode == 0 )
7204 returnCode = run();
7205
7206 for ( int i = 0; i < argc; ++i )
7207 delete [] utf8Argv[ i ];
7208
7209 delete [] utf8Argv;
7210
7211 return returnCode;
7212 }
7213 #endif
7214
run()7215 int run() {
7216 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
7217 Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
7218 static_cast<void>(std::getchar());
7219 }
7220 int exitCode = runInternal();
7221 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
7222 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
7223 static_cast<void>(std::getchar());
7224 }
7225 return exitCode;
7226 }
7227
cli() const7228 Clara::CommandLine<ConfigData> const& cli() const {
7229 return m_cli;
7230 }
unusedTokens() const7231 std::vector<Clara::Parser::Token> const& unusedTokens() const {
7232 return m_unusedTokens;
7233 }
configData()7234 ConfigData& configData() {
7235 return m_configData;
7236 }
config()7237 Config& config() {
7238 if( !m_config )
7239 m_config = new Config( m_configData );
7240 return *m_config;
7241 }
7242 private:
7243
runInternal()7244 int runInternal() {
7245 if( m_configData.showHelp || m_configData.libIdentify )
7246 return 0;
7247
7248 try
7249 {
7250 config(); // Force config to be constructed
7251
7252 seedRng( *m_config );
7253
7254 if( m_configData.filenamesAsTags )
7255 applyFilenamesAsTags( *m_config );
7256
7257 // Handle list request
7258 if( Option<std::size_t> listed = list( config() ) )
7259 return static_cast<int>( *listed );
7260
7261 return static_cast<int>( runTests( m_config ).assertions.failed );
7262 }
7263 catch( std::exception& ex ) {
7264 Catch::cerr() << ex.what() << std::endl;
7265 return (std::numeric_limits<int>::max)();
7266 }
7267 }
7268
7269 Clara::CommandLine<ConfigData> m_cli;
7270 std::vector<Clara::Parser::Token> m_unusedTokens;
7271 ConfigData m_configData;
7272 Ptr<Config> m_config;
7273 };
7274
7275 bool Session::alreadyInstantiated = false;
7276
7277 } // end namespace Catch
7278
7279 // #included from: catch_registry_hub.hpp
7280 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
7281
7282 // #included from: catch_test_case_registry_impl.hpp
7283 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
7284
7285 #include <vector>
7286 #include <set>
7287 #include <sstream>
7288 #include <algorithm>
7289
7290 namespace Catch {
7291
7292 struct RandomNumberGenerator {
7293 typedef unsigned int result_type;
7294
operator ()Catch::RandomNumberGenerator7295 result_type operator()( result_type n ) const { return std::rand() % n; }
7296
7297 #ifdef CATCH_CONFIG_CPP11_SHUFFLE
result_typeCatch::RandomNumberGenerator7298 static constexpr result_type (min)() { return 0; }
result_typeCatch::RandomNumberGenerator7299 static constexpr result_type (max)() { return 1000000; }
operator ()Catch::RandomNumberGenerator7300 result_type operator()() const { return std::rand() % (max)(); }
7301 #endif
7302 template<typename V>
shuffleCatch::RandomNumberGenerator7303 static void shuffle( V& vector ) {
7304 RandomNumberGenerator rng;
7305 #ifdef CATCH_CONFIG_CPP11_SHUFFLE
7306 std::shuffle( vector.begin(), vector.end(), rng );
7307 #else
7308 std::random_shuffle( vector.begin(), vector.end(), rng );
7309 #endif
7310 }
7311 };
7312
sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)7313 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
7314
7315 std::vector<TestCase> sorted = unsortedTestCases;
7316
7317 switch( config.runOrder() ) {
7318 case RunTests::InLexicographicalOrder:
7319 std::sort( sorted.begin(), sorted.end() );
7320 break;
7321 case RunTests::InRandomOrder:
7322 {
7323 seedRng( config );
7324 RandomNumberGenerator::shuffle( sorted );
7325 }
7326 break;
7327 case RunTests::InDeclarationOrder:
7328 // already in declaration order
7329 break;
7330 }
7331 return sorted;
7332 }
matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)7333 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
7334 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
7335 }
7336
enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)7337 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
7338 std::set<TestCase> seenFunctions;
7339 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
7340 it != itEnd;
7341 ++it ) {
7342 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
7343 if( !prev.second ) {
7344 std::ostringstream ss;
7345
7346 ss << Colour( Colour::Red )
7347 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
7348 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
7349 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
7350
7351 throw std::runtime_error(ss.str());
7352 }
7353 }
7354 }
7355
filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)7356 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
7357 std::vector<TestCase> filtered;
7358 filtered.reserve( testCases.size() );
7359 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
7360 it != itEnd;
7361 ++it )
7362 if( matchTest( *it, testSpec, config ) )
7363 filtered.push_back( *it );
7364 return filtered;
7365 }
getAllTestCasesSorted(IConfig const & config)7366 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
7367 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
7368 }
7369
7370 class TestRegistry : public ITestCaseRegistry {
7371 public:
TestRegistry()7372 TestRegistry()
7373 : m_currentSortOrder( RunTests::InDeclarationOrder ),
7374 m_unnamedCount( 0 )
7375 {}
7376 virtual ~TestRegistry();
7377
registerTest(TestCase const & testCase)7378 virtual void registerTest( TestCase const& testCase ) {
7379 std::string name = testCase.getTestCaseInfo().name;
7380 if( name.empty() ) {
7381 std::ostringstream oss;
7382 oss << "Anonymous test case " << ++m_unnamedCount;
7383 return registerTest( testCase.withName( oss.str() ) );
7384 }
7385 m_functions.push_back( testCase );
7386 }
7387
getAllTests() const7388 virtual std::vector<TestCase> const& getAllTests() const {
7389 return m_functions;
7390 }
getAllTestsSorted(IConfig const & config) const7391 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
7392 if( m_sortedFunctions.empty() )
7393 enforceNoDuplicateTestCases( m_functions );
7394
7395 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
7396 m_sortedFunctions = sortTests( config, m_functions );
7397 m_currentSortOrder = config.runOrder();
7398 }
7399 return m_sortedFunctions;
7400 }
7401
7402 private:
7403 std::vector<TestCase> m_functions;
7404 mutable RunTests::InWhatOrder m_currentSortOrder;
7405 mutable std::vector<TestCase> m_sortedFunctions;
7406 size_t m_unnamedCount;
7407 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
7408 };
7409
7410 ///////////////////////////////////////////////////////////////////////////
7411
7412 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
7413 public:
7414
FreeFunctionTestCase(TestFunction fun)7415 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
7416
invoke() const7417 virtual void invoke() const {
7418 m_fun();
7419 }
7420
7421 private:
7422 virtual ~FreeFunctionTestCase();
7423
7424 TestFunction m_fun;
7425 };
7426
extractClassName(std::string const & classOrQualifiedMethodName)7427 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
7428 std::string className = classOrQualifiedMethodName;
7429 if( startsWith( className, '&' ) )
7430 {
7431 std::size_t lastColons = className.rfind( "::" );
7432 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
7433 if( penultimateColons == std::string::npos )
7434 penultimateColons = 1;
7435 className = className.substr( penultimateColons, lastColons-penultimateColons );
7436 }
7437 return className;
7438 }
7439
registerTestCase(ITestCase * testCase,char const * classOrQualifiedMethodName,NameAndDesc const & nameAndDesc,SourceLineInfo const & lineInfo)7440 void registerTestCase
7441 ( ITestCase* testCase,
7442 char const* classOrQualifiedMethodName,
7443 NameAndDesc const& nameAndDesc,
7444 SourceLineInfo const& lineInfo ) {
7445
7446 getMutableRegistryHub().registerTest
7447 ( makeTestCase
7448 ( testCase,
7449 extractClassName( classOrQualifiedMethodName ),
7450 nameAndDesc.name,
7451 nameAndDesc.description,
7452 lineInfo ) );
7453 }
registerTestCaseFunction(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)7454 void registerTestCaseFunction
7455 ( TestFunction function,
7456 SourceLineInfo const& lineInfo,
7457 NameAndDesc const& nameAndDesc ) {
7458 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
7459 }
7460
7461 ///////////////////////////////////////////////////////////////////////////
7462
AutoReg(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)7463 AutoReg::AutoReg
7464 ( TestFunction function,
7465 SourceLineInfo const& lineInfo,
7466 NameAndDesc const& nameAndDesc ) {
7467 registerTestCaseFunction( function, lineInfo, nameAndDesc );
7468 }
7469
~AutoReg()7470 AutoReg::~AutoReg() {}
7471
7472 } // end namespace Catch
7473
7474 // #included from: catch_reporter_registry.hpp
7475 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
7476
7477 #include <map>
7478
7479 namespace Catch {
7480
7481 class ReporterRegistry : public IReporterRegistry {
7482
7483 public:
7484
~ReporterRegistry()7485 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
7486
create(std::string const & name,Ptr<IConfig const> const & config) const7487 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
7488 FactoryMap::const_iterator it = m_factories.find( name );
7489 if( it == m_factories.end() )
7490 return CATCH_NULL;
7491 return it->second->create( ReporterConfig( config ) );
7492 }
7493
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)7494 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
7495 m_factories.insert( std::make_pair( name, factory ) );
7496 }
registerListener(Ptr<IReporterFactory> const & factory)7497 void registerListener( Ptr<IReporterFactory> const& factory ) {
7498 m_listeners.push_back( factory );
7499 }
7500
getFactories() const7501 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
7502 return m_factories;
7503 }
getListeners() const7504 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
7505 return m_listeners;
7506 }
7507
7508 private:
7509 FactoryMap m_factories;
7510 Listeners m_listeners;
7511 };
7512 }
7513
7514 // #included from: catch_exception_translator_registry.hpp
7515 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
7516
7517 #ifdef __OBJC__
7518 #import "Foundation/Foundation.h"
7519 #endif
7520
7521 namespace Catch {
7522
7523 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
7524 public:
~ExceptionTranslatorRegistry()7525 ~ExceptionTranslatorRegistry() {
7526 deleteAll( m_translators );
7527 }
7528
registerTranslator(const IExceptionTranslator * translator)7529 virtual void registerTranslator( const IExceptionTranslator* translator ) {
7530 m_translators.push_back( translator );
7531 }
7532
translateActiveException() const7533 virtual std::string translateActiveException() const {
7534 try {
7535 #ifdef __OBJC__
7536 // In Objective-C try objective-c exceptions first
7537 @try {
7538 return tryTranslators();
7539 }
7540 @catch (NSException *exception) {
7541 return Catch::toString( [exception description] );
7542 }
7543 #else
7544 return tryTranslators();
7545 #endif
7546 }
7547 catch( TestFailureException& ) {
7548 throw;
7549 }
7550 catch( std::exception& ex ) {
7551 return ex.what();
7552 }
7553 catch( std::string& msg ) {
7554 return msg;
7555 }
7556 catch( const char* msg ) {
7557 return msg;
7558 }
7559 catch(...) {
7560 return "Unknown exception";
7561 }
7562 }
7563
tryTranslators() const7564 std::string tryTranslators() const {
7565 if( m_translators.empty() )
7566 throw;
7567 else
7568 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
7569 }
7570
7571 private:
7572 std::vector<const IExceptionTranslator*> m_translators;
7573 };
7574 }
7575
7576 // #included from: catch_tag_alias_registry.h
7577 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
7578
7579 #include <map>
7580
7581 namespace Catch {
7582
7583 class TagAliasRegistry : public ITagAliasRegistry {
7584 public:
7585 virtual ~TagAliasRegistry();
7586 virtual Option<TagAlias> find( std::string const& alias ) const;
7587 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
7588 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
7589
7590 private:
7591 std::map<std::string, TagAlias> m_registry;
7592 };
7593
7594 } // end namespace Catch
7595
7596 namespace Catch {
7597
7598 namespace {
7599
7600 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
7601
7602 RegistryHub( RegistryHub const& );
7603 void operator=( RegistryHub const& );
7604
7605 public: // IRegistryHub
RegistryHub()7606 RegistryHub() {
7607 }
getReporterRegistry() const7608 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
7609 return m_reporterRegistry;
7610 }
getTestCaseRegistry() const7611 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
7612 return m_testCaseRegistry;
7613 }
getExceptionTranslatorRegistry()7614 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
7615 return m_exceptionTranslatorRegistry;
7616 }
getTagAliasRegistry() const7617 virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE {
7618 return m_tagAliasRegistry;
7619 }
7620
7621 public: // IMutableRegistryHub
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)7622 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
7623 m_reporterRegistry.registerReporter( name, factory );
7624 }
registerListener(Ptr<IReporterFactory> const & factory)7625 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
7626 m_reporterRegistry.registerListener( factory );
7627 }
registerTest(TestCase const & testInfo)7628 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
7629 m_testCaseRegistry.registerTest( testInfo );
7630 }
registerTranslator(const IExceptionTranslator * translator)7631 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
7632 m_exceptionTranslatorRegistry.registerTranslator( translator );
7633 }
registerTagAlias(std::string const & alias,std::string const & tag,SourceLineInfo const & lineInfo)7634 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE {
7635 m_tagAliasRegistry.add( alias, tag, lineInfo );
7636 }
7637
7638 private:
7639 TestRegistry m_testCaseRegistry;
7640 ReporterRegistry m_reporterRegistry;
7641 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
7642 TagAliasRegistry m_tagAliasRegistry;
7643 };
7644
7645 // Single, global, instance
getTheRegistryHub()7646 inline RegistryHub*& getTheRegistryHub() {
7647 static RegistryHub* theRegistryHub = CATCH_NULL;
7648 if( !theRegistryHub )
7649 theRegistryHub = new RegistryHub();
7650 return theRegistryHub;
7651 }
7652 }
7653
getRegistryHub()7654 IRegistryHub& getRegistryHub() {
7655 return *getTheRegistryHub();
7656 }
getMutableRegistryHub()7657 IMutableRegistryHub& getMutableRegistryHub() {
7658 return *getTheRegistryHub();
7659 }
cleanUp()7660 void cleanUp() {
7661 delete getTheRegistryHub();
7662 getTheRegistryHub() = CATCH_NULL;
7663 cleanUpContext();
7664 }
translateActiveException()7665 std::string translateActiveException() {
7666 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
7667 }
7668
7669 } // end namespace Catch
7670
7671 // #included from: catch_notimplemented_exception.hpp
7672 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
7673
7674 #include <sstream>
7675
7676 namespace Catch {
7677
NotImplementedException(SourceLineInfo const & lineInfo)7678 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
7679 : m_lineInfo( lineInfo ) {
7680 std::ostringstream oss;
7681 oss << lineInfo << ": function ";
7682 oss << "not implemented";
7683 m_what = oss.str();
7684 }
7685
what() const7686 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
7687 return m_what.c_str();
7688 }
7689
7690 } // end namespace Catch
7691
7692 // #included from: catch_context_impl.hpp
7693 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
7694
7695 // #included from: catch_stream.hpp
7696 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
7697
7698 #include <stdexcept>
7699 #include <cstdio>
7700 #include <iostream>
7701
7702 namespace Catch {
7703
7704 template<typename WriterF, size_t bufferSize=256>
7705 class StreamBufImpl : public StreamBufBase {
7706 char data[bufferSize];
7707 WriterF m_writer;
7708
7709 public:
StreamBufImpl()7710 StreamBufImpl() {
7711 setp( data, data + sizeof(data) );
7712 }
7713
~StreamBufImpl()7714 ~StreamBufImpl() CATCH_NOEXCEPT {
7715 sync();
7716 }
7717
7718 private:
overflow(int c)7719 int overflow( int c ) {
7720 sync();
7721
7722 if( c != EOF ) {
7723 if( pbase() == epptr() )
7724 m_writer( std::string( 1, static_cast<char>( c ) ) );
7725 else
7726 sputc( static_cast<char>( c ) );
7727 }
7728 return 0;
7729 }
7730
sync()7731 int sync() {
7732 if( pbase() != pptr() ) {
7733 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
7734 setp( pbase(), epptr() );
7735 }
7736 return 0;
7737 }
7738 };
7739
7740 ///////////////////////////////////////////////////////////////////////////
7741
FileStream(std::string const & filename)7742 FileStream::FileStream( std::string const& filename ) {
7743 m_ofs.open( filename.c_str() );
7744 if( m_ofs.fail() ) {
7745 std::ostringstream oss;
7746 oss << "Unable to open file: '" << filename << '\'';
7747 throw std::domain_error( oss.str() );
7748 }
7749 }
7750
stream() const7751 std::ostream& FileStream::stream() const {
7752 return m_ofs;
7753 }
7754
7755 struct OutputDebugWriter {
7756
operator ()Catch::OutputDebugWriter7757 void operator()( std::string const&str ) {
7758 writeToDebugConsole( str );
7759 }
7760 };
7761
DebugOutStream()7762 DebugOutStream::DebugOutStream()
7763 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
7764 m_os( m_streamBuf.get() )
7765 {}
7766
stream() const7767 std::ostream& DebugOutStream::stream() const {
7768 return m_os;
7769 }
7770
7771 // Store the streambuf from cout up-front because
7772 // cout may get redirected when running tests
CoutStream()7773 CoutStream::CoutStream()
7774 : m_os( Catch::cout().rdbuf() )
7775 {}
7776
stream() const7777 std::ostream& CoutStream::stream() const {
7778 return m_os;
7779 }
7780
7781 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()7782 std::ostream& cout() {
7783 return std::cout;
7784 }
cerr()7785 std::ostream& cerr() {
7786 return std::cerr;
7787 }
clog()7788 std::ostream& clog() {
7789 return std::clog;
7790 }
7791 #endif
7792 }
7793
7794 namespace Catch {
7795
7796 class Context : public IMutableContext {
7797
Context()7798 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
7799 Context( Context const& );
7800 void operator=( Context const& );
7801
7802 public:
~Context()7803 virtual ~Context() {
7804 deleteAllValues( m_generatorsByTestName );
7805 }
7806
7807 public: // IContext
getResultCapture()7808 virtual IResultCapture* getResultCapture() {
7809 return m_resultCapture;
7810 }
getRunner()7811 virtual IRunner* getRunner() {
7812 return m_runner;
7813 }
getGeneratorIndex(std::string const & fileInfo,size_t totalSize)7814 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
7815 return getGeneratorsForCurrentTest()
7816 .getGeneratorInfo( fileInfo, totalSize )
7817 .getCurrentIndex();
7818 }
advanceGeneratorsForCurrentTest()7819 virtual bool advanceGeneratorsForCurrentTest() {
7820 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7821 return generators && generators->moveNext();
7822 }
7823
getConfig() const7824 virtual Ptr<IConfig const> getConfig() const {
7825 return m_config;
7826 }
7827
7828 public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)7829 virtual void setResultCapture( IResultCapture* resultCapture ) {
7830 m_resultCapture = resultCapture;
7831 }
setRunner(IRunner * runner)7832 virtual void setRunner( IRunner* runner ) {
7833 m_runner = runner;
7834 }
setConfig(Ptr<IConfig const> const & config)7835 virtual void setConfig( Ptr<IConfig const> const& config ) {
7836 m_config = config;
7837 }
7838
7839 friend IMutableContext& getCurrentMutableContext();
7840
7841 private:
findGeneratorsForCurrentTest()7842 IGeneratorsForTest* findGeneratorsForCurrentTest() {
7843 std::string testName = getResultCapture()->getCurrentTestName();
7844
7845 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
7846 m_generatorsByTestName.find( testName );
7847 return it != m_generatorsByTestName.end()
7848 ? it->second
7849 : CATCH_NULL;
7850 }
7851
getGeneratorsForCurrentTest()7852 IGeneratorsForTest& getGeneratorsForCurrentTest() {
7853 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7854 if( !generators ) {
7855 std::string testName = getResultCapture()->getCurrentTestName();
7856 generators = createGeneratorsForTest();
7857 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
7858 }
7859 return *generators;
7860 }
7861
7862 private:
7863 Ptr<IConfig const> m_config;
7864 IRunner* m_runner;
7865 IResultCapture* m_resultCapture;
7866 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7867 };
7868
7869 namespace {
7870 Context* currentContext = CATCH_NULL;
7871 }
getCurrentMutableContext()7872 IMutableContext& getCurrentMutableContext() {
7873 if( !currentContext )
7874 currentContext = new Context();
7875 return *currentContext;
7876 }
getCurrentContext()7877 IContext& getCurrentContext() {
7878 return getCurrentMutableContext();
7879 }
7880
cleanUpContext()7881 void cleanUpContext() {
7882 delete currentContext;
7883 currentContext = CATCH_NULL;
7884 }
7885 }
7886
7887 // #included from: catch_console_colour_impl.hpp
7888 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7889
7890 // #included from: catch_errno_guard.hpp
7891 #define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
7892
7893 #include <cerrno>
7894
7895 namespace Catch {
7896
7897 class ErrnoGuard {
7898 public:
ErrnoGuard()7899 ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard()7900 ~ErrnoGuard() { errno = m_oldErrno; }
7901 private:
7902 int m_oldErrno;
7903 };
7904
7905 }
7906
7907 namespace Catch {
7908 namespace {
7909
7910 struct IColourImpl {
~IColourImplCatch::__anonc9f568750511::IColourImpl7911 virtual ~IColourImpl() {}
7912 virtual void use( Colour::Code _colourCode ) = 0;
7913 };
7914
7915 struct NoColourImpl : IColourImpl {
useCatch::__anonc9f568750511::NoColourImpl7916 void use( Colour::Code ) {}
7917
instanceCatch::__anonc9f568750511::NoColourImpl7918 static IColourImpl* instance() {
7919 static NoColourImpl s_instance;
7920 return &s_instance;
7921 }
7922 };
7923
7924 } // anon namespace
7925 } // namespace Catch
7926
7927 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7928 # ifdef CATCH_PLATFORM_WINDOWS
7929 # define CATCH_CONFIG_COLOUR_WINDOWS
7930 # else
7931 # define CATCH_CONFIG_COLOUR_ANSI
7932 # endif
7933 #endif
7934
7935 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
7936
7937 namespace Catch {
7938 namespace {
7939
7940 class Win32ColourImpl : public IColourImpl {
7941 public:
Win32ColourImpl()7942 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
7943 {
7944 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7945 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
7946 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7947 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
7948 }
7949
use(Colour::Code _colourCode)7950 virtual void use( Colour::Code _colourCode ) {
7951 switch( _colourCode ) {
7952 case Colour::None: return setTextAttribute( originalForegroundAttributes );
7953 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7954 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
7955 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
7956 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
7957 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7958 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7959 case Colour::Grey: return setTextAttribute( 0 );
7960
7961 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
7962 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7963 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
7964 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7965
7966 case Colour::Bright: throw std::logic_error( "not a colour" );
7967 }
7968 }
7969
7970 private:
setTextAttribute(WORD _textAttribute)7971 void setTextAttribute( WORD _textAttribute ) {
7972 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
7973 }
7974 HANDLE stdoutHandle;
7975 WORD originalForegroundAttributes;
7976 WORD originalBackgroundAttributes;
7977 };
7978
platformColourInstance()7979 IColourImpl* platformColourInstance() {
7980 static Win32ColourImpl s_instance;
7981
7982 Ptr<IConfig const> config = getCurrentContext().getConfig();
7983 UseColour::YesOrNo colourMode = config
7984 ? config->useColour()
7985 : UseColour::Auto;
7986 if( colourMode == UseColour::Auto )
7987 colourMode = !isDebuggerActive()
7988 ? UseColour::Yes
7989 : UseColour::No;
7990 return colourMode == UseColour::Yes
7991 ? &s_instance
7992 : NoColourImpl::instance();
7993 }
7994
7995 } // end anon namespace
7996 } // end namespace Catch
7997
7998 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
7999
8000 #include <unistd.h>
8001
8002 namespace Catch {
8003 namespace {
8004
8005 // use POSIX/ ANSI console terminal codes
8006 // Thanks to Adam Strzelecki for original contribution
8007 // (http://github.com/nanoant)
8008 // https://github.com/philsquared/Catch/pull/131
8009 class PosixColourImpl : public IColourImpl {
8010 public:
use(Colour::Code _colourCode)8011 virtual void use( Colour::Code _colourCode ) {
8012 switch( _colourCode ) {
8013 case Colour::None:
8014 case Colour::White: return setColour( "[0m" );
8015 case Colour::Red: return setColour( "[0;31m" );
8016 case Colour::Green: return setColour( "[0;32m" );
8017 case Colour::Blue: return setColour( "[0;34m" );
8018 case Colour::Cyan: return setColour( "[0;36m" );
8019 case Colour::Yellow: return setColour( "[0;33m" );
8020 case Colour::Grey: return setColour( "[1;30m" );
8021
8022 case Colour::LightGrey: return setColour( "[0;37m" );
8023 case Colour::BrightRed: return setColour( "[1;31m" );
8024 case Colour::BrightGreen: return setColour( "[1;32m" );
8025 case Colour::BrightWhite: return setColour( "[1;37m" );
8026
8027 case Colour::Bright: throw std::logic_error( "not a colour" );
8028 }
8029 }
instance()8030 static IColourImpl* instance() {
8031 static PosixColourImpl s_instance;
8032 return &s_instance;
8033 }
8034
8035 private:
setColour(const char * _escapeCode)8036 void setColour( const char* _escapeCode ) {
8037 Catch::cout() << '\033' << _escapeCode;
8038 }
8039 };
8040
platformColourInstance()8041 IColourImpl* platformColourInstance() {
8042 ErrnoGuard guard;
8043 Ptr<IConfig const> config = getCurrentContext().getConfig();
8044 UseColour::YesOrNo colourMode = config
8045 ? config->useColour()
8046 : UseColour::Auto;
8047 if( colourMode == UseColour::Auto )
8048 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
8049 ? UseColour::Yes
8050 : UseColour::No;
8051 return colourMode == UseColour::Yes
8052 ? PosixColourImpl::instance()
8053 : NoColourImpl::instance();
8054 }
8055
8056 } // end anon namespace
8057 } // end namespace Catch
8058
8059 #else // not Windows or ANSI ///////////////////////////////////////////////
8060
8061 namespace Catch {
8062
platformColourInstance()8063 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
8064
8065 } // end namespace Catch
8066
8067 #endif // Windows/ ANSI/ None
8068
8069 namespace Catch {
8070
Colour(Code _colourCode)8071 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
Colour(Colour const & _other)8072 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
~Colour()8073 Colour::~Colour(){ if( !m_moved ) use( None ); }
8074
use(Code _colourCode)8075 void Colour::use( Code _colourCode ) {
8076 static IColourImpl* impl = platformColourInstance();
8077 impl->use( _colourCode );
8078 }
8079
8080 } // end namespace Catch
8081
8082 // #included from: catch_generators_impl.hpp
8083 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
8084
8085 #include <vector>
8086 #include <string>
8087 #include <map>
8088
8089 namespace Catch {
8090
8091 struct GeneratorInfo : IGeneratorInfo {
8092
GeneratorInfoCatch::GeneratorInfo8093 GeneratorInfo( std::size_t size )
8094 : m_size( size ),
8095 m_currentIndex( 0 )
8096 {}
8097
moveNextCatch::GeneratorInfo8098 bool moveNext() {
8099 if( ++m_currentIndex == m_size ) {
8100 m_currentIndex = 0;
8101 return false;
8102 }
8103 return true;
8104 }
8105
getCurrentIndexCatch::GeneratorInfo8106 std::size_t getCurrentIndex() const {
8107 return m_currentIndex;
8108 }
8109
8110 std::size_t m_size;
8111 std::size_t m_currentIndex;
8112 };
8113
8114 ///////////////////////////////////////////////////////////////////////////
8115
8116 class GeneratorsForTest : public IGeneratorsForTest {
8117
8118 public:
~GeneratorsForTest()8119 ~GeneratorsForTest() {
8120 deleteAll( m_generatorsInOrder );
8121 }
8122
getGeneratorInfo(std::string const & fileInfo,std::size_t size)8123 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
8124 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
8125 if( it == m_generatorsByName.end() ) {
8126 IGeneratorInfo* info = new GeneratorInfo( size );
8127 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
8128 m_generatorsInOrder.push_back( info );
8129 return *info;
8130 }
8131 return *it->second;
8132 }
8133
moveNext()8134 bool moveNext() {
8135 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
8136 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
8137 for(; it != itEnd; ++it ) {
8138 if( (*it)->moveNext() )
8139 return true;
8140 }
8141 return false;
8142 }
8143
8144 private:
8145 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
8146 std::vector<IGeneratorInfo*> m_generatorsInOrder;
8147 };
8148
createGeneratorsForTest()8149 IGeneratorsForTest* createGeneratorsForTest()
8150 {
8151 return new GeneratorsForTest();
8152 }
8153
8154 } // end namespace Catch
8155
8156 // #included from: catch_assertionresult.hpp
8157 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
8158
8159 namespace Catch {
8160
AssertionInfo()8161 AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){}
8162
AssertionInfo(char const * _macroName,SourceLineInfo const & _lineInfo,char const * _capturedExpression,ResultDisposition::Flags _resultDisposition,char const * _secondArg)8163 AssertionInfo::AssertionInfo( char const * _macroName,
8164 SourceLineInfo const& _lineInfo,
8165 char const * _capturedExpression,
8166 ResultDisposition::Flags _resultDisposition,
8167 char const * _secondArg)
8168 : macroName( _macroName ),
8169 lineInfo( _lineInfo ),
8170 capturedExpression( _capturedExpression ),
8171 resultDisposition( _resultDisposition ),
8172 secondArg( _secondArg )
8173 {}
8174
AssertionResult()8175 AssertionResult::AssertionResult() {}
8176
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)8177 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
8178 : m_info( info ),
8179 m_resultData( data )
8180 {}
8181
~AssertionResult()8182 AssertionResult::~AssertionResult() {}
8183
8184 // Result was a success
succeeded() const8185 bool AssertionResult::succeeded() const {
8186 return Catch::isOk( m_resultData.resultType );
8187 }
8188
8189 // Result was a success, or failure is suppressed
isOk() const8190 bool AssertionResult::isOk() const {
8191 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
8192 }
8193
getResultType() const8194 ResultWas::OfType AssertionResult::getResultType() const {
8195 return m_resultData.resultType;
8196 }
8197
hasExpression() const8198 bool AssertionResult::hasExpression() const {
8199 return m_info.capturedExpression[0] != 0;
8200 }
8201
hasMessage() const8202 bool AssertionResult::hasMessage() const {
8203 return !m_resultData.message.empty();
8204 }
8205
capturedExpressionWithSecondArgument(char const * capturedExpression,char const * secondArg)8206 std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) {
8207 return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"')
8208 ? capturedExpression
8209 : std::string(capturedExpression) + ", " + secondArg;
8210 }
8211
getExpression() const8212 std::string AssertionResult::getExpression() const {
8213 if( isFalseTest( m_info.resultDisposition ) )
8214 return "!(" + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + ")";
8215 else
8216 return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
8217 }
getExpressionInMacro() const8218 std::string AssertionResult::getExpressionInMacro() const {
8219 if( m_info.macroName[0] == 0 )
8220 return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
8221 else
8222 return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )";
8223 }
8224
hasExpandedExpression() const8225 bool AssertionResult::hasExpandedExpression() const {
8226 return hasExpression() && getExpandedExpression() != getExpression();
8227 }
8228
getExpandedExpression() const8229 std::string AssertionResult::getExpandedExpression() const {
8230 return m_resultData.reconstructExpression();
8231 }
8232
getMessage() const8233 std::string AssertionResult::getMessage() const {
8234 return m_resultData.message;
8235 }
getSourceInfo() const8236 SourceLineInfo AssertionResult::getSourceInfo() const {
8237 return m_info.lineInfo;
8238 }
8239
getTestMacroName() const8240 std::string AssertionResult::getTestMacroName() const {
8241 return m_info.macroName;
8242 }
8243
discardDecomposedExpression() const8244 void AssertionResult::discardDecomposedExpression() const {
8245 m_resultData.decomposedExpression = CATCH_NULL;
8246 }
8247
expandDecomposedExpression() const8248 void AssertionResult::expandDecomposedExpression() const {
8249 m_resultData.reconstructExpression();
8250 }
8251
8252 } // end namespace Catch
8253
8254 // #included from: catch_test_case_info.hpp
8255 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
8256
8257 #include <cctype>
8258
8259 namespace Catch {
8260
parseSpecialTag(std::string const & tag)8261 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
8262 if( startsWith( tag, '.' ) ||
8263 tag == "hide" ||
8264 tag == "!hide" )
8265 return TestCaseInfo::IsHidden;
8266 else if( tag == "!throws" )
8267 return TestCaseInfo::Throws;
8268 else if( tag == "!shouldfail" )
8269 return TestCaseInfo::ShouldFail;
8270 else if( tag == "!mayfail" )
8271 return TestCaseInfo::MayFail;
8272 else if( tag == "!nonportable" )
8273 return TestCaseInfo::NonPortable;
8274 else
8275 return TestCaseInfo::None;
8276 }
isReservedTag(std::string const & tag)8277 inline bool isReservedTag( std::string const& tag ) {
8278 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
8279 }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)8280 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
8281 if( isReservedTag( tag ) ) {
8282 std::ostringstream ss;
8283 ss << Colour(Colour::Red)
8284 << "Tag name [" << tag << "] not allowed.\n"
8285 << "Tag names starting with non alpha-numeric characters are reserved\n"
8286 << Colour(Colour::FileName)
8287 << _lineInfo << '\n';
8288 throw std::runtime_error(ss.str());
8289 }
8290 }
8291
makeTestCase(ITestCase * _testCase,std::string const & _className,std::string const & _name,std::string const & _descOrTags,SourceLineInfo const & _lineInfo)8292 TestCase makeTestCase( ITestCase* _testCase,
8293 std::string const& _className,
8294 std::string const& _name,
8295 std::string const& _descOrTags,
8296 SourceLineInfo const& _lineInfo )
8297 {
8298 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
8299
8300 // Parse out tags
8301 std::set<std::string> tags;
8302 std::string desc, tag;
8303 bool inTag = false;
8304 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
8305 char c = _descOrTags[i];
8306 if( !inTag ) {
8307 if( c == '[' )
8308 inTag = true;
8309 else
8310 desc += c;
8311 }
8312 else {
8313 if( c == ']' ) {
8314 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
8315 if( prop == TestCaseInfo::IsHidden )
8316 isHidden = true;
8317 else if( prop == TestCaseInfo::None )
8318 enforceNotReservedTag( tag, _lineInfo );
8319
8320 tags.insert( tag );
8321 tag.clear();
8322 inTag = false;
8323 }
8324 else
8325 tag += c;
8326 }
8327 }
8328 if( isHidden ) {
8329 tags.insert( "hide" );
8330 tags.insert( "." );
8331 }
8332
8333 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
8334 return TestCase( _testCase, info );
8335 }
8336
setTags(TestCaseInfo & testCaseInfo,std::set<std::string> const & tags)8337 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
8338 {
8339 testCaseInfo.tags = tags;
8340 testCaseInfo.lcaseTags.clear();
8341
8342 std::ostringstream oss;
8343 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
8344 oss << '[' << *it << ']';
8345 std::string lcaseTag = toLower( *it );
8346 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
8347 testCaseInfo.lcaseTags.insert( lcaseTag );
8348 }
8349 testCaseInfo.tagsAsString = oss.str();
8350 }
8351
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::set<std::string> const & _tags,SourceLineInfo const & _lineInfo)8352 TestCaseInfo::TestCaseInfo( std::string const& _name,
8353 std::string const& _className,
8354 std::string const& _description,
8355 std::set<std::string> const& _tags,
8356 SourceLineInfo const& _lineInfo )
8357 : name( _name ),
8358 className( _className ),
8359 description( _description ),
8360 lineInfo( _lineInfo ),
8361 properties( None )
8362 {
8363 setTags( *this, _tags );
8364 }
8365
TestCaseInfo(TestCaseInfo const & other)8366 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
8367 : name( other.name ),
8368 className( other.className ),
8369 description( other.description ),
8370 tags( other.tags ),
8371 lcaseTags( other.lcaseTags ),
8372 tagsAsString( other.tagsAsString ),
8373 lineInfo( other.lineInfo ),
8374 properties( other.properties )
8375 {}
8376
isHidden() const8377 bool TestCaseInfo::isHidden() const {
8378 return ( properties & IsHidden ) != 0;
8379 }
throws() const8380 bool TestCaseInfo::throws() const {
8381 return ( properties & Throws ) != 0;
8382 }
okToFail() const8383 bool TestCaseInfo::okToFail() const {
8384 return ( properties & (ShouldFail | MayFail ) ) != 0;
8385 }
expectedToFail() const8386 bool TestCaseInfo::expectedToFail() const {
8387 return ( properties & (ShouldFail ) ) != 0;
8388 }
8389
TestCase(ITestCase * testCase,TestCaseInfo const & info)8390 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
8391
TestCase(TestCase const & other)8392 TestCase::TestCase( TestCase const& other )
8393 : TestCaseInfo( other ),
8394 test( other.test )
8395 {}
8396
withName(std::string const & _newName) const8397 TestCase TestCase::withName( std::string const& _newName ) const {
8398 TestCase other( *this );
8399 other.name = _newName;
8400 return other;
8401 }
8402
swap(TestCase & other)8403 void TestCase::swap( TestCase& other ) {
8404 test.swap( other.test );
8405 name.swap( other.name );
8406 className.swap( other.className );
8407 description.swap( other.description );
8408 tags.swap( other.tags );
8409 lcaseTags.swap( other.lcaseTags );
8410 tagsAsString.swap( other.tagsAsString );
8411 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
8412 std::swap( lineInfo, other.lineInfo );
8413 }
8414
invoke() const8415 void TestCase::invoke() const {
8416 test->invoke();
8417 }
8418
operator ==(TestCase const & other) const8419 bool TestCase::operator == ( TestCase const& other ) const {
8420 return test.get() == other.test.get() &&
8421 name == other.name &&
8422 className == other.className;
8423 }
8424
operator <(TestCase const & other) const8425 bool TestCase::operator < ( TestCase const& other ) const {
8426 return name < other.name;
8427 }
operator =(TestCase const & other)8428 TestCase& TestCase::operator = ( TestCase const& other ) {
8429 TestCase temp( other );
8430 swap( temp );
8431 return *this;
8432 }
8433
getTestCaseInfo() const8434 TestCaseInfo const& TestCase::getTestCaseInfo() const
8435 {
8436 return *this;
8437 }
8438
8439 } // end namespace Catch
8440
8441 // #included from: catch_version.hpp
8442 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
8443
8444 namespace Catch {
8445
Version(unsigned int _majorVersion,unsigned int _minorVersion,unsigned int _patchNumber,char const * const _branchName,unsigned int _buildNumber)8446 Version::Version
8447 ( unsigned int _majorVersion,
8448 unsigned int _minorVersion,
8449 unsigned int _patchNumber,
8450 char const * const _branchName,
8451 unsigned int _buildNumber )
8452 : majorVersion( _majorVersion ),
8453 minorVersion( _minorVersion ),
8454 patchNumber( _patchNumber ),
8455 branchName( _branchName ),
8456 buildNumber( _buildNumber )
8457 {}
8458
operator <<(std::ostream & os,Version const & version)8459 std::ostream& operator << ( std::ostream& os, Version const& version ) {
8460 os << version.majorVersion << '.'
8461 << version.minorVersion << '.'
8462 << version.patchNumber;
8463 // branchName is never null -> 0th char is \0 if it is empty
8464 if (version.branchName[0]) {
8465 os << '-' << version.branchName
8466 << '.' << version.buildNumber;
8467 }
8468 return os;
8469 }
8470
libraryVersion()8471 inline Version libraryVersion() {
8472 static Version version( 1, 12, 1, "", 0 );
8473 return version;
8474 }
8475
8476 }
8477
8478 // #included from: catch_message.hpp
8479 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
8480
8481 namespace Catch {
8482
MessageInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)8483 MessageInfo::MessageInfo( std::string const& _macroName,
8484 SourceLineInfo const& _lineInfo,
8485 ResultWas::OfType _type )
8486 : macroName( _macroName ),
8487 lineInfo( _lineInfo ),
8488 type( _type ),
8489 sequence( ++globalCount )
8490 {}
8491
8492 // This may need protecting if threading support is added
8493 unsigned int MessageInfo::globalCount = 0;
8494
8495 ////////////////////////////////////////////////////////////////////////////
8496
ScopedMessage(MessageBuilder const & builder)8497 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
8498 : m_info( builder.m_info )
8499 {
8500 m_info.message = builder.m_stream.str();
8501 getResultCapture().pushScopedMessage( m_info );
8502 }
ScopedMessage(ScopedMessage const & other)8503 ScopedMessage::ScopedMessage( ScopedMessage const& other )
8504 : m_info( other.m_info )
8505 {}
8506
8507 #if defined(_MSC_VER)
8508 #pragma warning(push)
8509 #pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17
8510 #endif
~ScopedMessage()8511 ScopedMessage::~ScopedMessage() {
8512 if ( !std::uncaught_exception() ){
8513 getResultCapture().popScopedMessage(m_info);
8514 }
8515 }
8516 #if defined(_MSC_VER)
8517 #pragma warning(pop)
8518 #endif
8519
8520 } // end namespace Catch
8521
8522 // #included from: catch_legacy_reporter_adapter.hpp
8523 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
8524
8525 // #included from: catch_legacy_reporter_adapter.h
8526 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
8527
8528 namespace Catch
8529 {
8530 // Deprecated
8531 struct IReporter : IShared {
8532 virtual ~IReporter();
8533
8534 virtual bool shouldRedirectStdout() const = 0;
8535
8536 virtual void StartTesting() = 0;
8537 virtual void EndTesting( Totals const& totals ) = 0;
8538 virtual void StartGroup( std::string const& groupName ) = 0;
8539 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
8540 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
8541 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
8542 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
8543 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
8544 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
8545 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
8546 virtual void Aborted() = 0;
8547 virtual void Result( AssertionResult const& result ) = 0;
8548 };
8549
8550 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
8551 {
8552 public:
8553 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
8554 virtual ~LegacyReporterAdapter();
8555
8556 virtual ReporterPreferences getPreferences() const;
8557 virtual void noMatchingTestCases( std::string const& );
8558 virtual void testRunStarting( TestRunInfo const& );
8559 virtual void testGroupStarting( GroupInfo const& groupInfo );
8560 virtual void testCaseStarting( TestCaseInfo const& testInfo );
8561 virtual void sectionStarting( SectionInfo const& sectionInfo );
8562 virtual void assertionStarting( AssertionInfo const& );
8563 virtual bool assertionEnded( AssertionStats const& assertionStats );
8564 virtual void sectionEnded( SectionStats const& sectionStats );
8565 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
8566 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
8567 virtual void testRunEnded( TestRunStats const& testRunStats );
8568 virtual void skipTest( TestCaseInfo const& );
8569
8570 private:
8571 Ptr<IReporter> m_legacyReporter;
8572 };
8573 }
8574
8575 namespace Catch
8576 {
LegacyReporterAdapter(Ptr<IReporter> const & legacyReporter)8577 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
8578 : m_legacyReporter( legacyReporter )
8579 {}
~LegacyReporterAdapter()8580 LegacyReporterAdapter::~LegacyReporterAdapter() {}
8581
getPreferences() const8582 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
8583 ReporterPreferences prefs;
8584 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
8585 return prefs;
8586 }
8587
noMatchingTestCases(std::string const &)8588 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
testRunStarting(TestRunInfo const &)8589 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
8590 m_legacyReporter->StartTesting();
8591 }
testGroupStarting(GroupInfo const & groupInfo)8592 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
8593 m_legacyReporter->StartGroup( groupInfo.name );
8594 }
testCaseStarting(TestCaseInfo const & testInfo)8595 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
8596 m_legacyReporter->StartTestCase( testInfo );
8597 }
sectionStarting(SectionInfo const & sectionInfo)8598 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
8599 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
8600 }
assertionStarting(AssertionInfo const &)8601 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
8602 // Not on legacy interface
8603 }
8604
assertionEnded(AssertionStats const & assertionStats)8605 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
8606 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8607 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8608 it != itEnd;
8609 ++it ) {
8610 if( it->type == ResultWas::Info ) {
8611 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
8612 rb << it->message;
8613 rb.setResultType( ResultWas::Info );
8614 AssertionResult result = rb.build();
8615 m_legacyReporter->Result( result );
8616 }
8617 }
8618 }
8619 m_legacyReporter->Result( assertionStats.assertionResult );
8620 return true;
8621 }
sectionEnded(SectionStats const & sectionStats)8622 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
8623 if( sectionStats.missingAssertions )
8624 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
8625 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
8626 }
testCaseEnded(TestCaseStats const & testCaseStats)8627 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
8628 m_legacyReporter->EndTestCase
8629 ( testCaseStats.testInfo,
8630 testCaseStats.totals,
8631 testCaseStats.stdOut,
8632 testCaseStats.stdErr );
8633 }
testGroupEnded(TestGroupStats const & testGroupStats)8634 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
8635 if( testGroupStats.aborting )
8636 m_legacyReporter->Aborted();
8637 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
8638 }
testRunEnded(TestRunStats const & testRunStats)8639 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
8640 m_legacyReporter->EndTesting( testRunStats.totals );
8641 }
skipTest(TestCaseInfo const &)8642 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
8643 }
8644 }
8645
8646 // #included from: catch_timer.hpp
8647
8648 #ifdef __clang__
8649 #pragma clang diagnostic push
8650 #pragma clang diagnostic ignored "-Wc++11-long-long"
8651 #endif
8652
8653 #ifdef CATCH_PLATFORM_WINDOWS
8654
8655 #else
8656
8657 #include <sys/time.h>
8658
8659 #endif
8660
8661 namespace Catch {
8662
8663 namespace {
8664 #ifdef CATCH_PLATFORM_WINDOWS
getCurrentTicks()8665 UInt64 getCurrentTicks() {
8666 static UInt64 hz=0, hzo=0;
8667 if (!hz) {
8668 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
8669 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
8670 }
8671 UInt64 t;
8672 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
8673 return ((t-hzo)*1000000)/hz;
8674 }
8675 #else
8676 UInt64 getCurrentTicks() {
8677 timeval t;
8678 gettimeofday(&t,CATCH_NULL);
8679 return static_cast<UInt64>( t.tv_sec ) * 1000000ull + static_cast<UInt64>( t.tv_usec );
8680 }
8681 #endif
8682 }
8683
start()8684 void Timer::start() {
8685 m_ticks = getCurrentTicks();
8686 }
getElapsedMicroseconds() const8687 unsigned int Timer::getElapsedMicroseconds() const {
8688 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
8689 }
getElapsedMilliseconds() const8690 unsigned int Timer::getElapsedMilliseconds() const {
8691 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
8692 }
getElapsedSeconds() const8693 double Timer::getElapsedSeconds() const {
8694 return getElapsedMicroseconds()/1000000.0;
8695 }
8696
8697 } // namespace Catch
8698
8699 #ifdef __clang__
8700 #pragma clang diagnostic pop
8701 #endif
8702 // #included from: catch_common.hpp
8703 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
8704
8705 #include <cstring>
8706 #include <cctype>
8707
8708 namespace Catch {
8709
startsWith(std::string const & s,std::string const & prefix)8710 bool startsWith( std::string const& s, std::string const& prefix ) {
8711 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
8712 }
startsWith(std::string const & s,char prefix)8713 bool startsWith( std::string const& s, char prefix ) {
8714 return !s.empty() && s[0] == prefix;
8715 }
endsWith(std::string const & s,std::string const & suffix)8716 bool endsWith( std::string const& s, std::string const& suffix ) {
8717 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
8718 }
endsWith(std::string const & s,char suffix)8719 bool endsWith( std::string const& s, char suffix ) {
8720 return !s.empty() && s[s.size()-1] == suffix;
8721 }
contains(std::string const & s,std::string const & infix)8722 bool contains( std::string const& s, std::string const& infix ) {
8723 return s.find( infix ) != std::string::npos;
8724 }
toLowerCh(char c)8725 char toLowerCh(char c) {
8726 return static_cast<char>( std::tolower( c ) );
8727 }
toLowerInPlace(std::string & s)8728 void toLowerInPlace( std::string& s ) {
8729 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
8730 }
toLower(std::string const & s)8731 std::string toLower( std::string const& s ) {
8732 std::string lc = s;
8733 toLowerInPlace( lc );
8734 return lc;
8735 }
trim(std::string const & str)8736 std::string trim( std::string const& str ) {
8737 static char const* whitespaceChars = "\n\r\t ";
8738 std::string::size_type start = str.find_first_not_of( whitespaceChars );
8739 std::string::size_type end = str.find_last_not_of( whitespaceChars );
8740
8741 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
8742 }
8743
replaceInPlace(std::string & str,std::string const & replaceThis,std::string const & withThis)8744 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
8745 bool replaced = false;
8746 std::size_t i = str.find( replaceThis );
8747 while( i != std::string::npos ) {
8748 replaced = true;
8749 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
8750 if( i < str.size()-withThis.size() )
8751 i = str.find( replaceThis, i+withThis.size() );
8752 else
8753 i = std::string::npos;
8754 }
8755 return replaced;
8756 }
8757
pluralise(std::size_t count,std::string const & label)8758 pluralise::pluralise( std::size_t count, std::string const& label )
8759 : m_count( count ),
8760 m_label( label )
8761 {}
8762
operator <<(std::ostream & os,pluralise const & pluraliser)8763 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
8764 os << pluraliser.m_count << ' ' << pluraliser.m_label;
8765 if( pluraliser.m_count != 1 )
8766 os << 's';
8767 return os;
8768 }
8769
SourceLineInfo()8770 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
SourceLineInfo(char const * _file,std::size_t _line)8771 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
8772 : file( _file ),
8773 line( _line )
8774 {}
empty() const8775