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