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