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