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