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