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