]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/compiler/cpp/tests/catch/catch.hpp
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / compiler / cpp / tests / catch / catch.hpp
CommitLineData
f67539c2
TL
1/*
2 * Catch v1.9.4
3 * Generated: 2017-05-16 13:51:55.506519
4 * ----------------------------------------------------------
5 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
7 *
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 */
11#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
13
14#define TWOBLUECUBES_CATCH_HPP_INCLUDED
15
16#ifdef __clang__
17# pragma clang system_header
18#elif defined __GNUC__
19# pragma GCC system_header
20#endif
21
22// #included from: internal/catch_suppress_warnings.h
23
24#ifdef __clang__
25# ifdef __ICC // icpc defines the __clang__ macro
26# pragma warning(push)
27# pragma warning(disable: 161 1682)
28# else // __ICC
29# pragma clang diagnostic ignored "-Wglobal-constructors"
30# pragma clang diagnostic ignored "-Wvariadic-macros"
31# pragma clang diagnostic ignored "-Wc99-extensions"
32# pragma clang diagnostic ignored "-Wunused-variable"
33# pragma clang diagnostic push
34# pragma clang diagnostic ignored "-Wpadded"
35# pragma clang diagnostic ignored "-Wc++98-compat"
36# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
37# pragma clang diagnostic ignored "-Wswitch-enum"
38# pragma clang diagnostic ignored "-Wcovered-switch-default"
39# endif
40#elif defined __GNUC__
41# pragma GCC diagnostic ignored "-Wvariadic-macros"
42# pragma GCC diagnostic ignored "-Wunused-variable"
43# pragma GCC diagnostic ignored "-Wparentheses"
44
45# pragma GCC diagnostic push
46# pragma GCC diagnostic ignored "-Wpadded"
47#endif
48#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
49# define CATCH_IMPL
50#endif
51
52#ifdef CATCH_IMPL
53# ifndef CLARA_CONFIG_MAIN
54# define CLARA_CONFIG_MAIN_NOT_DEFINED
55# define CLARA_CONFIG_MAIN
56# endif
57#endif
58
59// #included from: internal/catch_notimplemented_exception.h
60#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
61
62// #included from: catch_common.h
63#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
64
65// #included from: catch_compiler_capabilities.h
66#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
67
68// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
69// The following features are defined:
70//
71// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
72// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
73// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
74// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
75// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
76// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
77// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
78// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
79// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
80// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
81
82// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
83
84// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
85// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
86// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
87// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
88// ****************
89// Note to maintainers: if new toggles are added please document them
90// in configuration.md, too
91// ****************
92
93// In general each macro has a _NO_<feature name> form
94// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
95// Many features, at point of detection, define an _INTERNAL_ macro, so they
96// can be combined, en-mass, with the _NO_ forms later.
97
98// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
99
100#ifdef __cplusplus
101
102# if __cplusplus >= 201103L
103# define CATCH_CPP11_OR_GREATER
104# endif
105
106# if __cplusplus >= 201402L
107# define CATCH_CPP14_OR_GREATER
108# endif
109
110#endif
111
112#ifdef __clang__
113
114# if __has_feature(cxx_nullptr)
115# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
116# endif
117
118# if __has_feature(cxx_noexcept)
119# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
120# endif
121
122# if defined(CATCH_CPP11_OR_GREATER)
123# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
124 _Pragma( "clang diagnostic push" ) \
125 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" )
126# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
127 _Pragma( "clang diagnostic pop" )
128
129# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
130 _Pragma( "clang diagnostic push" ) \
131 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
132# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
133 _Pragma( "clang diagnostic pop" )
134# endif
135
136#endif // __clang__
137
138////////////////////////////////////////////////////////////////////////////////
139// We know some environments not to support full POSIX signals
140#if defined(__CYGWIN__) || defined(__QNX__)
141
142# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
143# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
144# endif
145
146#endif
147
148////////////////////////////////////////////////////////////////////////////////
149// Cygwin
150#ifdef __CYGWIN__
151
152// Required for some versions of Cygwin to declare gettimeofday
153// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
154# define _BSD_SOURCE
155
156#endif // __CYGWIN__
157
158////////////////////////////////////////////////////////////////////////////////
159// Borland
160#ifdef __BORLANDC__
161
162#endif // __BORLANDC__
163
164////////////////////////////////////////////////////////////////////////////////
165// EDG
166#ifdef __EDG_VERSION__
167
168#endif // __EDG_VERSION__
169
170////////////////////////////////////////////////////////////////////////////////
171// Digital Mars
172#ifdef __DMC__
173
174#endif // __DMC__
175
176////////////////////////////////////////////////////////////////////////////////
177// GCC
178#ifdef __GNUC__
179
180# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
181# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
182# endif
183
184// - otherwise more recent versions define __cplusplus >= 201103L
185// and will get picked up below
186
187#endif // __GNUC__
188
189////////////////////////////////////////////////////////////////////////////////
190// Visual C++
191#ifdef _MSC_VER
192
193#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
194
195#if (_MSC_VER >= 1600)
196# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
197# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
198#endif
199
200#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
201#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
202#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
203#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
204#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
205#endif
206
207#endif // _MSC_VER
208
209////////////////////////////////////////////////////////////////////////////////
210
211// Use variadic macros if the compiler supports them
212#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
213 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
214 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
215 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
216
217#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
218
219#endif
220
221// Use __COUNTER__ if the compiler supports it
222#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
223 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
224 ( defined __clang__ && __clang_major__ >= 3 )
225
226#define CATCH_INTERNAL_CONFIG_COUNTER
227
228#endif
229
230////////////////////////////////////////////////////////////////////////////////
231// C++ language feature support
232
233// catch all support for C++11
234#if defined(CATCH_CPP11_OR_GREATER)
235
236# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
237# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
238# endif
239
240# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
241# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
242# endif
243
244# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
245# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
246# endif
247
248# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
249# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
250# endif
251
252# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
253# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
254# endif
255
256# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
257# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
258# endif
259
260# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
261# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
262# endif
263
264# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
265# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
266# endif
267# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
268# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
269# endif
270# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
271# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
272# endif
273# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
274# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
275# endif
276
277#endif // __cplusplus >= 201103L
278
279// Now set the actual defines based on the above + anything the user has configured
280#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
281# define CATCH_CONFIG_CPP11_NULLPTR
282#endif
283#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
284# define CATCH_CONFIG_CPP11_NOEXCEPT
285#endif
286#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
287# define CATCH_CONFIG_CPP11_GENERATED_METHODS
288#endif
289#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
290# define CATCH_CONFIG_CPP11_IS_ENUM
291#endif
292#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
293# define CATCH_CONFIG_CPP11_TUPLE
294#endif
295#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
296# define CATCH_CONFIG_VARIADIC_MACROS
297#endif
298#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
299# define CATCH_CONFIG_CPP11_LONG_LONG
300#endif
301#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
302# define CATCH_CONFIG_CPP11_OVERRIDE
303#endif
304#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
305# define CATCH_CONFIG_CPP11_UNIQUE_PTR
306#endif
307// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
308// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
309// This does not affect compilation
310#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
311# define CATCH_CONFIG_COUNTER
312#endif
313#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
314# define CATCH_CONFIG_CPP11_SHUFFLE
315#endif
316# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
317# define CATCH_CONFIG_CPP11_TYPE_TRAITS
318# endif
319#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
320# define CATCH_CONFIG_WINDOWS_SEH
321#endif
322// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
323#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
324# define CATCH_CONFIG_POSIX_SIGNALS
325#endif
326
327#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
328# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
329# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
330#endif
331#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS)
332# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
333# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
334#endif
335
336// noexcept support:
337#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
338# define CATCH_NOEXCEPT noexcept
339# define CATCH_NOEXCEPT_IS(x) noexcept(x)
340#else
341# define CATCH_NOEXCEPT throw()
342# define CATCH_NOEXCEPT_IS(x)
343#endif
344
345// nullptr support
346#ifdef CATCH_CONFIG_CPP11_NULLPTR
347# define CATCH_NULL nullptr
348#else
349# define CATCH_NULL NULL
350#endif
351
352// override support
353#ifdef CATCH_CONFIG_CPP11_OVERRIDE
354# define CATCH_OVERRIDE override
355#else
356# define CATCH_OVERRIDE
357#endif
358
359// unique_ptr support
360#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
361# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
362#else
363# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
364#endif
365
366#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
367#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
368#ifdef CATCH_CONFIG_COUNTER
369# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
370#else
371# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
372#endif
373
374#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
375#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
376
377#include <sstream>
378#include <algorithm>
379
380namespace Catch {
381
382 struct IConfig;
383
384 struct CaseSensitive { enum Choice {
385 Yes,
386 No
387 }; };
388
389 class NonCopyable {
390#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
391 NonCopyable( NonCopyable const& ) = delete;
392 NonCopyable( NonCopyable && ) = delete;
393 NonCopyable& operator = ( NonCopyable const& ) = delete;
394 NonCopyable& operator = ( NonCopyable && ) = delete;
395#else
396 NonCopyable( NonCopyable const& info );
397 NonCopyable& operator = ( NonCopyable const& );
398#endif
399
400 protected:
401 NonCopyable() {}
402 virtual ~NonCopyable();
403 };
404
405 class SafeBool {
406 public:
407 typedef void (SafeBool::*type)() const;
408
409 static type makeSafe( bool value ) {
410 return value ? &SafeBool::trueValue : 0;
411 }
412 private:
413 void trueValue() const {}
414 };
415
416 template<typename ContainerT>
417 inline void deleteAll( ContainerT& container ) {
418 typename ContainerT::const_iterator it = container.begin();
419 typename ContainerT::const_iterator itEnd = container.end();
420 for(; it != itEnd; ++it )
421 delete *it;
422 }
423 template<typename AssociativeContainerT>
424 inline void deleteAllValues( AssociativeContainerT& container ) {
425 typename AssociativeContainerT::const_iterator it = container.begin();
426 typename AssociativeContainerT::const_iterator itEnd = container.end();
427 for(; it != itEnd; ++it )
428 delete it->second;
429 }
430
431 bool startsWith( std::string const& s, std::string const& prefix );
432 bool startsWith( std::string const& s, char prefix );
433 bool endsWith( std::string const& s, std::string const& suffix );
434 bool endsWith( std::string const& s, char suffix );
435 bool contains( std::string const& s, std::string const& infix );
436 void toLowerInPlace( std::string& s );
437 std::string toLower( std::string const& s );
438 std::string trim( std::string const& str );
439 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
440
441 struct pluralise {
442 pluralise( std::size_t count, std::string const& label );
443
444 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
445
446 std::size_t m_count;
447 std::string m_label;
448 };
449
450 struct SourceLineInfo {
451
452 SourceLineInfo();
453 SourceLineInfo( char const* _file, std::size_t _line );
454# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
455 SourceLineInfo(SourceLineInfo const& other) = default;
456 SourceLineInfo( SourceLineInfo && ) = default;
457 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
458 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
459# endif
460 bool empty() const;
461 bool operator == ( SourceLineInfo const& other ) const;
462 bool operator < ( SourceLineInfo const& other ) const;
463
464 char const* file;
465 std::size_t line;
466 };
467
468 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
469
470 // This is just here to avoid compiler warnings with macro constants and boolean literals
471 inline bool isTrue( bool value ){ return value; }
472 inline bool alwaysTrue() { return true; }
473 inline bool alwaysFalse() { return false; }
474
475 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
476
477 void seedRng( IConfig const& config );
478 unsigned int rngSeed();
479
480 // Use this in variadic streaming macros to allow
481 // >> +StreamEndStop
482 // as well as
483 // >> stuff +StreamEndStop
484 struct StreamEndStop {
485 std::string operator+() {
486 return std::string();
487 }
488 };
489 template<typename T>
490 T const& operator + ( T const& value, StreamEndStop ) {
491 return value;
492 }
493}
494
495#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
496#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
497
498namespace Catch {
499
500 class NotImplementedException : public std::exception
501 {
502 public:
503 NotImplementedException( SourceLineInfo const& lineInfo );
504 NotImplementedException( NotImplementedException const& ) {}
505
506 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
507
508 virtual const char* what() const CATCH_NOEXCEPT;
509
510 private:
511 std::string m_what;
512 SourceLineInfo m_lineInfo;
513 };
514
515} // end namespace Catch
516
517///////////////////////////////////////////////////////////////////////////////
518#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
519
520// #included from: internal/catch_context.h
521#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
522
523// #included from: catch_interfaces_generators.h
524#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
525
526#include <string>
527
528namespace Catch {
529
530 struct IGeneratorInfo {
531 virtual ~IGeneratorInfo();
532 virtual bool moveNext() = 0;
533 virtual std::size_t getCurrentIndex() const = 0;
534 };
535
536 struct IGeneratorsForTest {
537 virtual ~IGeneratorsForTest();
538
539 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
540 virtual bool moveNext() = 0;
541 };
542
543 IGeneratorsForTest* createGeneratorsForTest();
544
545} // end namespace Catch
546
547// #included from: catch_ptr.hpp
548#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
549
550#ifdef __clang__
551#pragma clang diagnostic push
552#pragma clang diagnostic ignored "-Wpadded"
553#endif
554
555namespace Catch {
556
557 // An intrusive reference counting smart pointer.
558 // T must implement addRef() and release() methods
559 // typically implementing the IShared interface
560 template<typename T>
561 class Ptr {
562 public:
563 Ptr() : m_p( CATCH_NULL ){}
564 Ptr( T* p ) : m_p( p ){
565 if( m_p )
566 m_p->addRef();
567 }
568 Ptr( Ptr const& other ) : m_p( other.m_p ){
569 if( m_p )
570 m_p->addRef();
571 }
572 ~Ptr(){
573 if( m_p )
574 m_p->release();
575 }
576 void reset() {
577 if( m_p )
578 m_p->release();
579 m_p = CATCH_NULL;
580 }
581 Ptr& operator = ( T* p ){
582 Ptr temp( p );
583 swap( temp );
584 return *this;
585 }
586 Ptr& operator = ( Ptr const& other ){
587 Ptr temp( other );
588 swap( temp );
589 return *this;
590 }
591 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
592 T* get() const{ return m_p; }
593 T& operator*() const { return *m_p; }
594 T* operator->() const { return m_p; }
595 bool operator !() const { return m_p == CATCH_NULL; }
596 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
597
598 private:
599 T* m_p;
600 };
601
602 struct IShared : NonCopyable {
603 virtual ~IShared();
604 virtual void addRef() const = 0;
605 virtual void release() const = 0;
606 };
607
608 template<typename T = IShared>
609 struct SharedImpl : T {
610
611 SharedImpl() : m_rc( 0 ){}
612
613 virtual void addRef() const {
614 ++m_rc;
615 }
616 virtual void release() const {
617 if( --m_rc == 0 )
618 delete this;
619 }
620
621 mutable unsigned int m_rc;
622 };
623
624} // end namespace Catch
625
626#ifdef __clang__
627#pragma clang diagnostic pop
628#endif
629
630namespace Catch {
631
632 class TestCase;
633 class Stream;
634 struct IResultCapture;
635 struct IRunner;
636 struct IGeneratorsForTest;
637 struct IConfig;
638
639 struct IContext
640 {
641 virtual ~IContext();
642
643 virtual IResultCapture* getResultCapture() = 0;
644 virtual IRunner* getRunner() = 0;
645 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
646 virtual bool advanceGeneratorsForCurrentTest() = 0;
647 virtual Ptr<IConfig const> getConfig() const = 0;
648 };
649
650 struct IMutableContext : IContext
651 {
652 virtual ~IMutableContext();
653 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
654 virtual void setRunner( IRunner* runner ) = 0;
655 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
656 };
657
658 IContext& getCurrentContext();
659 IMutableContext& getCurrentMutableContext();
660 void cleanUpContext();
661 Stream createStream( std::string const& streamName );
662
663}
664
665// #included from: internal/catch_test_registry.hpp
666#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
667
668// #included from: catch_interfaces_testcase.h
669#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
670
671#include <vector>
672
673namespace Catch {
674
675 class TestSpec;
676
677 struct ITestCase : IShared {
678 virtual void invoke () const = 0;
679 protected:
680 virtual ~ITestCase();
681 };
682
683 class TestCase;
684 struct IConfig;
685
686 struct ITestCaseRegistry {
687 virtual ~ITestCaseRegistry();
688 virtual std::vector<TestCase> const& getAllTests() const = 0;
689 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
690 };
691
692 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
693 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
694 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
695
696}
697
698namespace Catch {
699
700template<typename C>
701class MethodTestCase : public SharedImpl<ITestCase> {
702
703public:
704 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
705
706 virtual void invoke() const {
707 C obj;
708 (obj.*m_method)();
709 }
710
711private:
712 virtual ~MethodTestCase() {}
713
714 void (C::*m_method)();
715};
716
717typedef void(*TestFunction)();
718
719struct NameAndDesc {
720 NameAndDesc( const char* _name = "", const char* _description= "" )
721 : name( _name ), description( _description )
722 {}
723
724 const char* name;
725 const char* description;
726};
727
728void registerTestCase
729 ( ITestCase* testCase,
730 char const* className,
731 NameAndDesc const& nameAndDesc,
732 SourceLineInfo const& lineInfo );
733
734struct AutoReg {
735
736 AutoReg
737 ( TestFunction function,
738 SourceLineInfo const& lineInfo,
739 NameAndDesc const& nameAndDesc );
740
741 template<typename C>
742 AutoReg
743 ( void (C::*method)(),
744 char const* className,
745 NameAndDesc const& nameAndDesc,
746 SourceLineInfo const& lineInfo ) {
747
748 registerTestCase
749 ( new MethodTestCase<C>( method ),
750 className,
751 nameAndDesc,
752 lineInfo );
753 }
754
755 ~AutoReg();
756
757private:
758 AutoReg( AutoReg const& );
759 void operator= ( AutoReg const& );
760};
761
762void registerTestCaseFunction
763 ( TestFunction function,
764 SourceLineInfo const& lineInfo,
765 NameAndDesc const& nameAndDesc );
766
767} // end namespace Catch
768
769#ifdef CATCH_CONFIG_VARIADIC_MACROS
770 ///////////////////////////////////////////////////////////////////////////////
771 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
772 static void TestName(); \
773 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
774 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \
775 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
776 static void TestName()
777 #define INTERNAL_CATCH_TESTCASE( ... ) \
778 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
779
780 ///////////////////////////////////////////////////////////////////////////////
781 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
782 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
783 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \
784 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
785
786 ///////////////////////////////////////////////////////////////////////////////
787 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
788 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
789 namespace{ \
790 struct TestName : ClassName{ \
791 void test(); \
792 }; \
793 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
794 } \
795 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
796 void TestName::test()
797 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
798 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
799
800 ///////////////////////////////////////////////////////////////////////////////
801 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
802 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
803 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \
804 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
805
806#else
807 ///////////////////////////////////////////////////////////////////////////////
808 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
809 static void TestName(); \
810 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
811 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
812 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
813 static void TestName()
814 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
815 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
816
817 ///////////////////////////////////////////////////////////////////////////////
818 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
819 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
820 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \
821 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
822
823 ///////////////////////////////////////////////////////////////////////////////
824 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
825 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
826 namespace{ \
827 struct TestCaseName : ClassName{ \
828 void test(); \
829 }; \
830 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
831 } \
832 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
833 void TestCaseName::test()
834 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
835 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
836
837 ///////////////////////////////////////////////////////////////////////////////
838 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
839 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
840 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \
841 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
842
843#endif
844
845// #included from: internal/catch_capture.hpp
846#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
847
848// #included from: catch_result_builder.h
849#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
850
851// #included from: catch_result_type.h
852#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
853
854namespace Catch {
855
856 // ResultWas::OfType enum
857 struct ResultWas { enum OfType {
858 Unknown = -1,
859 Ok = 0,
860 Info = 1,
861 Warning = 2,
862
863 FailureBit = 0x10,
864
865 ExpressionFailed = FailureBit | 1,
866 ExplicitFailure = FailureBit | 2,
867
868 Exception = 0x100 | FailureBit,
869
870 ThrewException = Exception | 1,
871 DidntThrowException = Exception | 2,
872
873 FatalErrorCondition = 0x200 | FailureBit
874
875 }; };
876
877 inline bool isOk( ResultWas::OfType resultType ) {
878 return ( resultType & ResultWas::FailureBit ) == 0;
879 }
880 inline bool isJustInfo( int flags ) {
881 return flags == ResultWas::Info;
882 }
883
884 // ResultDisposition::Flags enum
885 struct ResultDisposition { enum Flags {
886 Normal = 0x01,
887
888 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
889 FalseTest = 0x04, // Prefix expression with !
890 SuppressFail = 0x08 // Failures are reported but do not fail the test
891 }; };
892
893 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
894 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
895 }
896
897 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
898 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
899 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
900
901} // end namespace Catch
902
903// #included from: catch_assertionresult.h
904#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
905
906#include <string>
907
908namespace Catch {
909
910 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
911
912 struct DecomposedExpression
913 {
914 virtual ~DecomposedExpression() {}
915 virtual bool isBinaryExpression() const {
916 return false;
917 }
918 virtual void reconstructExpression( std::string& dest ) const = 0;
919
920 // Only simple binary comparisons can be decomposed.
921 // If more complex check is required then wrap sub-expressions in parentheses.
922 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
923 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
924 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
925 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
926 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
927 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
928 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
929
930 private:
931 DecomposedExpression& operator = (DecomposedExpression const&);
932 };
933
934 struct AssertionInfo
935 {
936 AssertionInfo() {}
937 AssertionInfo( std::string const& _macroName,
938 SourceLineInfo const& _lineInfo,
939 std::string const& _capturedExpression,
940 ResultDisposition::Flags _resultDisposition );
941
942 std::string macroName;
943 SourceLineInfo lineInfo;
944 std::string capturedExpression;
945 ResultDisposition::Flags resultDisposition;
946 };
947
948 struct AssertionResultData
949 {
950 AssertionResultData() : decomposedExpression( CATCH_NULL )
951 , resultType( ResultWas::Unknown )
952 , negated( false )
953 , parenthesized( false ) {}
954
955 void negate( bool parenthesize ) {
956 negated = !negated;
957 parenthesized = parenthesize;
958 if( resultType == ResultWas::Ok )
959 resultType = ResultWas::ExpressionFailed;
960 else if( resultType == ResultWas::ExpressionFailed )
961 resultType = ResultWas::Ok;
962 }
963
964 std::string const& reconstructExpression() const {
965 if( decomposedExpression != CATCH_NULL ) {
966 decomposedExpression->reconstructExpression( reconstructedExpression );
967 if( parenthesized ) {
968 reconstructedExpression.insert( 0, 1, '(' );
969 reconstructedExpression.append( 1, ')' );
970 }
971 if( negated ) {
972 reconstructedExpression.insert( 0, 1, '!' );
973 }
974 decomposedExpression = CATCH_NULL;
975 }
976 return reconstructedExpression;
977 }
978
979 mutable DecomposedExpression const* decomposedExpression;
980 mutable std::string reconstructedExpression;
981 std::string message;
982 ResultWas::OfType resultType;
983 bool negated;
984 bool parenthesized;
985 };
986
987 class AssertionResult {
988 public:
989 AssertionResult();
990 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
991 ~AssertionResult();
992# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
993 AssertionResult( AssertionResult const& ) = default;
994 AssertionResult( AssertionResult && ) = default;
995 AssertionResult& operator = ( AssertionResult const& ) = default;
996 AssertionResult& operator = ( AssertionResult && ) = default;
997# endif
998
999 bool isOk() const;
1000 bool succeeded() const;
1001 ResultWas::OfType getResultType() const;
1002 bool hasExpression() const;
1003 bool hasMessage() const;
1004 std::string getExpression() const;
1005 std::string getExpressionInMacro() const;
1006 bool hasExpandedExpression() const;
1007 std::string getExpandedExpression() const;
1008 std::string getMessage() const;
1009 SourceLineInfo getSourceInfo() const;
1010 std::string getTestMacroName() const;
1011 void discardDecomposedExpression() const;
1012 void expandDecomposedExpression() const;
1013
1014 protected:
1015 AssertionInfo m_info;
1016 AssertionResultData m_resultData;
1017 };
1018
1019} // end namespace Catch
1020
1021// #included from: catch_matchers.hpp
1022#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
1023
1024namespace Catch {
1025namespace Matchers {
1026 namespace Impl {
1027
1028 template<typename ArgT> struct MatchAllOf;
1029 template<typename ArgT> struct MatchAnyOf;
1030 template<typename ArgT> struct MatchNotOf;
1031
1032 class MatcherUntypedBase {
1033 public:
1034 std::string toString() const {
1035 if( m_cachedToString.empty() )
1036 m_cachedToString = describe();
1037 return m_cachedToString;
1038 }
1039
1040 protected:
1041 virtual ~MatcherUntypedBase();
1042 virtual std::string describe() const = 0;
1043 mutable std::string m_cachedToString;
1044 private:
1045 MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
1046 };
1047
1048 template<typename ObjectT>
1049 struct MatcherMethod {
1050 virtual bool match( ObjectT const& arg ) const = 0;
1051 };
1052 template<typename PtrT>
1053 struct MatcherMethod<PtrT*> {
1054 virtual bool match( PtrT* arg ) const = 0;
1055 };
1056
1057 template<typename ObjectT, typename ComparatorT = ObjectT>
1058 struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
1059
1060 MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
1061 MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
1062 MatchNotOf<ComparatorT> operator ! () const;
1063 };
1064
1065 template<typename ArgT>
1066 struct MatchAllOf : MatcherBase<ArgT> {
1067 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1068 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1069 if (!m_matchers[i]->match(arg))
1070 return false;
1071 }
1072 return true;
1073 }
1074 virtual std::string describe() const CATCH_OVERRIDE {
1075 std::string description;
1076 description.reserve( 4 + m_matchers.size()*32 );
1077 description += "( ";
1078 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1079 if( i != 0 )
1080 description += " and ";
1081 description += m_matchers[i]->toString();
1082 }
1083 description += " )";
1084 return description;
1085 }
1086
1087 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
1088 m_matchers.push_back( &other );
1089 return *this;
1090 }
1091
1092 std::vector<MatcherBase<ArgT> const*> m_matchers;
1093 };
1094 template<typename ArgT>
1095 struct MatchAnyOf : MatcherBase<ArgT> {
1096
1097 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1098 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1099 if (m_matchers[i]->match(arg))
1100 return true;
1101 }
1102 return false;
1103 }
1104 virtual std::string describe() const CATCH_OVERRIDE {
1105 std::string description;
1106 description.reserve( 4 + m_matchers.size()*32 );
1107 description += "( ";
1108 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1109 if( i != 0 )
1110 description += " or ";
1111 description += m_matchers[i]->toString();
1112 }
1113 description += " )";
1114 return description;
1115 }
1116
1117 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
1118 m_matchers.push_back( &other );
1119 return *this;
1120 }
1121
1122 std::vector<MatcherBase<ArgT> const*> m_matchers;
1123 };
1124
1125 template<typename ArgT>
1126 struct MatchNotOf : MatcherBase<ArgT> {
1127
1128 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
1129
1130 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1131 return !m_underlyingMatcher.match( arg );
1132 }
1133
1134 virtual std::string describe() const CATCH_OVERRIDE {
1135 return "not " + m_underlyingMatcher.toString();
1136 }
1137 MatcherBase<ArgT> const& m_underlyingMatcher;
1138 };
1139
1140 template<typename ObjectT, typename ComparatorT>
1141 MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
1142 return MatchAllOf<ComparatorT>() && *this && other;
1143 }
1144 template<typename ObjectT, typename ComparatorT>
1145 MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
1146 return MatchAnyOf<ComparatorT>() || *this || other;
1147 }
1148 template<typename ObjectT, typename ComparatorT>
1149 MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
1150 return MatchNotOf<ComparatorT>( *this );
1151 }
1152
1153 } // namespace Impl
1154
1155 // The following functions create the actual matcher objects.
1156 // This allows the types to be inferred
1157 // - deprecated: prefer ||, && and !
1158 template<typename T>
1159 inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
1160 return Impl::MatchNotOf<T>( underlyingMatcher );
1161 }
1162 template<typename T>
1163 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1164 return Impl::MatchAllOf<T>() && m1 && m2;
1165 }
1166 template<typename T>
1167 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1168 return Impl::MatchAllOf<T>() && m1 && m2 && m3;
1169 }
1170 template<typename T>
1171 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1172 return Impl::MatchAnyOf<T>() || m1 || m2;
1173 }
1174 template<typename T>
1175 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1176 return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
1177 }
1178
1179} // namespace Matchers
1180
1181using namespace Matchers;
1182using Matchers::Impl::MatcherBase;
1183
1184} // namespace Catch
1185
1186namespace Catch {
1187
1188 struct TestFailureException{};
1189
1190 template<typename T> class ExpressionLhs;
1191
1192 struct CopyableStream {
1193 CopyableStream() {}
1194 CopyableStream( CopyableStream const& other ) {
1195 oss << other.oss.str();
1196 }
1197 CopyableStream& operator=( CopyableStream const& other ) {
1198 oss.str(std::string());
1199 oss << other.oss.str();
1200 return *this;
1201 }
1202 std::ostringstream oss;
1203 };
1204
1205 class ResultBuilder : public DecomposedExpression {
1206 public:
1207 ResultBuilder( char const* macroName,
1208 SourceLineInfo const& lineInfo,
1209 char const* capturedExpression,
1210 ResultDisposition::Flags resultDisposition,
1211 char const* secondArg = "" );
1212 ~ResultBuilder();
1213
1214 template<typename T>
1215 ExpressionLhs<T const&> operator <= ( T const& operand );
1216 ExpressionLhs<bool> operator <= ( bool value );
1217
1218 template<typename T>
1219 ResultBuilder& operator << ( T const& value ) {
1220 m_stream.oss << value;
1221 return *this;
1222 }
1223
1224 ResultBuilder& setResultType( ResultWas::OfType result );
1225 ResultBuilder& setResultType( bool result );
1226
1227 void endExpression( DecomposedExpression const& expr );
1228
1229 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
1230
1231 AssertionResult build() const;
1232 AssertionResult build( DecomposedExpression const& expr ) const;
1233
1234 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1235 void captureResult( ResultWas::OfType resultType );
1236 void captureExpression();
1237 void captureExpectedException( std::string const& expectedMessage );
1238 void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
1239 void handleResult( AssertionResult const& result );
1240 void react();
1241 bool shouldDebugBreak() const;
1242 bool allowThrows() const;
1243
1244 template<typename ArgT, typename MatcherT>
1245 void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
1246
1247 void setExceptionGuard();
1248 void unsetExceptionGuard();
1249
1250 private:
1251 AssertionInfo m_assertionInfo;
1252 AssertionResultData m_data;
1253 CopyableStream m_stream;
1254
1255 bool m_shouldDebugBreak;
1256 bool m_shouldThrow;
1257 bool m_guardException;
1258 };
1259
1260} // namespace Catch
1261
1262// Include after due to circular dependency:
1263// #included from: catch_expression_lhs.hpp
1264#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1265
1266// #included from: catch_evaluate.hpp
1267#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1268
1269#ifdef _MSC_VER
1270#pragma warning(push)
1271#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1272#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
1273#endif
1274
1275#include <cstddef>
1276
1277namespace Catch {
1278namespace Internal {
1279
1280 enum Operator {
1281 IsEqualTo,
1282 IsNotEqualTo,
1283 IsLessThan,
1284 IsGreaterThan,
1285 IsLessThanOrEqualTo,
1286 IsGreaterThanOrEqualTo
1287 };
1288
1289 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1290 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1291 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1292 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1293 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1294 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1295 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1296
1297 template<typename T>
1298 inline T& opCast(T const& t) { return const_cast<T&>(t); }
1299
1300// nullptr_t support based on pull request #154 from Konstantin Baumann
1301#ifdef CATCH_CONFIG_CPP11_NULLPTR
1302 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1303#endif // CATCH_CONFIG_CPP11_NULLPTR
1304
1305 // So the compare overloads can be operator agnostic we convey the operator as a template
1306 // enum, which is used to specialise an Evaluator for doing the comparison.
1307 template<typename T1, typename T2, Operator Op>
1308 class Evaluator{};
1309
1310 template<typename T1, typename T2>
1311 struct Evaluator<T1, T2, IsEqualTo> {
1312 static bool evaluate( T1 const& lhs, T2 const& rhs) {
1313 return bool( opCast( lhs ) == opCast( rhs ) );
1314 }
1315 };
1316 template<typename T1, typename T2>
1317 struct Evaluator<T1, T2, IsNotEqualTo> {
1318 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1319 return bool( opCast( lhs ) != opCast( rhs ) );
1320 }
1321 };
1322 template<typename T1, typename T2>
1323 struct Evaluator<T1, T2, IsLessThan> {
1324 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1325 return bool( opCast( lhs ) < opCast( rhs ) );
1326 }
1327 };
1328 template<typename T1, typename T2>
1329 struct Evaluator<T1, T2, IsGreaterThan> {
1330 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1331 return bool( opCast( lhs ) > opCast( rhs ) );
1332 }
1333 };
1334 template<typename T1, typename T2>
1335 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
1336 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1337 return bool( opCast( lhs ) >= opCast( rhs ) );
1338 }
1339 };
1340 template<typename T1, typename T2>
1341 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
1342 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1343 return bool( opCast( lhs ) <= opCast( rhs ) );
1344 }
1345 };
1346
1347 template<Operator Op, typename T1, typename T2>
1348 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
1349 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1350 }
1351
1352 // This level of indirection allows us to specialise for integer types
1353 // to avoid signed/ unsigned warnings
1354
1355 // "base" overload
1356 template<Operator Op, typename T1, typename T2>
1357 bool compare( T1 const& lhs, T2 const& rhs ) {
1358 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1359 }
1360
1361 // unsigned X to int
1362 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
1363 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1364 }
1365 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
1366 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1367 }
1368 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
1369 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1370 }
1371
1372 // unsigned X to long
1373 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
1374 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1375 }
1376 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
1377 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1378 }
1379 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
1380 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1381 }
1382
1383 // int to unsigned X
1384 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
1385 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1386 }
1387 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
1388 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1389 }
1390 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
1391 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1392 }
1393
1394 // long to unsigned X
1395 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
1396 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1397 }
1398 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
1399 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1400 }
1401 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
1402 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1403 }
1404
1405 // pointer to long (when comparing against NULL)
1406 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
1407 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1408 }
1409 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
1410 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1411 }
1412
1413 // pointer to int (when comparing against NULL)
1414 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
1415 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1416 }
1417 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
1418 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1419 }
1420
1421#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1422 // long long to unsigned X
1423 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1424 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1425 }
1426 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1427 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1428 }
1429 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1430 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1431 }
1432 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1433 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1434 }
1435
1436 // unsigned long long to X
1437 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1438 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1439 }
1440 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1441 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1442 }
1443 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1444 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1445 }
1446 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1447 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1448 }
1449
1450 // pointer to long long (when comparing against NULL)
1451 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1452 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1453 }
1454 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1455 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1456 }
1457#endif // CATCH_CONFIG_CPP11_LONG_LONG
1458
1459#ifdef CATCH_CONFIG_CPP11_NULLPTR
1460 // pointer to nullptr_t (when comparing against nullptr)
1461 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1462 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
1463 }
1464 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1465 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
1466 }
1467#endif // CATCH_CONFIG_CPP11_NULLPTR
1468
1469} // end of namespace Internal
1470} // end of namespace Catch
1471
1472#ifdef _MSC_VER
1473#pragma warning(pop)
1474#endif
1475
1476// #included from: catch_tostring.h
1477#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1478
1479#include <sstream>
1480#include <iomanip>
1481#include <limits>
1482#include <vector>
1483#include <cstddef>
1484
1485#ifdef __OBJC__
1486// #included from: catch_objc_arc.hpp
1487#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1488
1489#import <Foundation/Foundation.h>
1490
1491#ifdef __has_feature
1492#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1493#else
1494#define CATCH_ARC_ENABLED 0
1495#endif
1496
1497void arcSafeRelease( NSObject* obj );
1498id performOptionalSelector( id obj, SEL sel );
1499
1500#if !CATCH_ARC_ENABLED
1501inline void arcSafeRelease( NSObject* obj ) {
1502 [obj release];
1503}
1504inline id performOptionalSelector( id obj, SEL sel ) {
1505 if( [obj respondsToSelector: sel] )
1506 return [obj performSelector: sel];
1507 return nil;
1508}
1509#define CATCH_UNSAFE_UNRETAINED
1510#define CATCH_ARC_STRONG
1511#else
1512inline void arcSafeRelease( NSObject* ){}
1513inline id performOptionalSelector( id obj, SEL sel ) {
1514#ifdef __clang__
1515#pragma clang diagnostic push
1516#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1517#endif
1518 if( [obj respondsToSelector: sel] )
1519 return [obj performSelector: sel];
1520#ifdef __clang__
1521#pragma clang diagnostic pop
1522#endif
1523 return nil;
1524}
1525#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1526#define CATCH_ARC_STRONG __strong
1527#endif
1528
1529#endif
1530
1531#ifdef CATCH_CONFIG_CPP11_TUPLE
1532#include <tuple>
1533#endif
1534
1535#ifdef CATCH_CONFIG_CPP11_IS_ENUM
1536#include <type_traits>
1537#endif
1538
1539namespace Catch {
1540
1541// Why we're here.
1542template<typename T>
1543std::string toString( T const& value );
1544
1545// Built in overloads
1546
1547std::string toString( std::string const& value );
1548std::string toString( std::wstring const& value );
1549std::string toString( const char* const value );
1550std::string toString( char* const value );
1551std::string toString( const wchar_t* const value );
1552std::string toString( wchar_t* const value );
1553std::string toString( int value );
1554std::string toString( unsigned long value );
1555std::string toString( unsigned int value );
1556std::string toString( const double value );
1557std::string toString( const float value );
1558std::string toString( bool value );
1559std::string toString( char value );
1560std::string toString( signed char value );
1561std::string toString( unsigned char value );
1562
1563#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1564std::string toString( long long value );
1565std::string toString( unsigned long long value );
1566#endif
1567
1568#ifdef CATCH_CONFIG_CPP11_NULLPTR
1569std::string toString( std::nullptr_t );
1570#endif
1571
1572#ifdef __OBJC__
1573 std::string toString( NSString const * const& nsstring );
1574 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1575 std::string toString( NSObject* const& nsObject );
1576#endif
1577
1578namespace Detail {
1579
1580 extern const std::string unprintableString;
1581
1582 #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK)
1583 struct BorgType {
1584 template<typename T> BorgType( T const& );
1585 };
1586
1587 struct TrueType { char sizer[1]; };
1588 struct FalseType { char sizer[2]; };
1589
1590 TrueType& testStreamable( std::ostream& );
1591 FalseType testStreamable( FalseType );
1592
1593 FalseType operator<<( std::ostream const&, BorgType const& );
1594
1595 template<typename T>
1596 struct IsStreamInsertable {
1597 static std::ostream &s;
1598 static T const&t;
1599 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1600 };
1601#else
1602 template<typename T>
1603 class IsStreamInsertable {
1604 template<typename SS, typename TT>
1605 static auto test(int)
1606 -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
1607
1608 template<typename, typename>
1609 static auto test(...) -> std::false_type;
1610
1611 public:
1612 static const bool value = decltype(test<std::ostream,const T&>(0))::value;
1613 };
1614#endif
1615
1616#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1617 template<typename T,
1618 bool IsEnum = std::is_enum<T>::value
1619 >
1620 struct EnumStringMaker
1621 {
1622 static std::string convert( T const& ) { return unprintableString; }
1623 };
1624
1625 template<typename T>
1626 struct EnumStringMaker<T,true>
1627 {
1628 static std::string convert( T const& v )
1629 {
1630 return ::Catch::toString(
1631 static_cast<typename std::underlying_type<T>::type>(v)
1632 );
1633 }
1634 };
1635#endif
1636 template<bool C>
1637 struct StringMakerBase {
1638#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1639 template<typename T>
1640 static std::string convert( T const& v )
1641 {
1642 return EnumStringMaker<T>::convert( v );
1643 }
1644#else
1645 template<typename T>
1646 static std::string convert( T const& ) { return unprintableString; }
1647#endif
1648 };
1649
1650 template<>
1651 struct StringMakerBase<true> {
1652 template<typename T>
1653 static std::string convert( T const& _value ) {
1654 std::ostringstream oss;
1655 oss << _value;
1656 return oss.str();
1657 }
1658 };
1659
1660 std::string rawMemoryToString( const void *object, std::size_t size );
1661
1662 template<typename T>
1663 inline std::string rawMemoryToString( const T& object ) {
1664 return rawMemoryToString( &object, sizeof(object) );
1665 }
1666
1667} // end namespace Detail
1668
1669template<typename T>
1670struct StringMaker :
1671 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1672
1673template<typename T>
1674struct StringMaker<T*> {
1675 template<typename U>
1676 static std::string convert( U* p ) {
1677 if( !p )
1678 return "NULL";
1679 else
1680 return Detail::rawMemoryToString( p );
1681 }
1682};
1683
1684template<typename R, typename C>
1685struct StringMaker<R C::*> {
1686 static std::string convert( R C::* p ) {
1687 if( !p )
1688 return "NULL";
1689 else
1690 return Detail::rawMemoryToString( p );
1691 }
1692};
1693
1694namespace Detail {
1695 template<typename InputIterator>
1696 std::string rangeToString( InputIterator first, InputIterator last );
1697}
1698
1699//template<typename T, typename Allocator>
1700//struct StringMaker<std::vector<T, Allocator> > {
1701// static std::string convert( std::vector<T,Allocator> const& v ) {
1702// return Detail::rangeToString( v.begin(), v.end() );
1703// }
1704//};
1705
1706template<typename T, typename Allocator>
1707std::string toString( std::vector<T,Allocator> const& v ) {
1708 return Detail::rangeToString( v.begin(), v.end() );
1709}
1710
1711#ifdef CATCH_CONFIG_CPP11_TUPLE
1712
1713// toString for tuples
1714namespace TupleDetail {
1715 template<
1716 typename Tuple,
1717 std::size_t N = 0,
1718 bool = (N < std::tuple_size<Tuple>::value)
1719 >
1720 struct ElementPrinter {
1721 static void print( const Tuple& tuple, std::ostream& os )
1722 {
1723 os << ( N ? ", " : " " )
1724 << Catch::toString(std::get<N>(tuple));
1725 ElementPrinter<Tuple,N+1>::print(tuple,os);
1726 }
1727 };
1728
1729 template<
1730 typename Tuple,
1731 std::size_t N
1732 >
1733 struct ElementPrinter<Tuple,N,false> {
1734 static void print( const Tuple&, std::ostream& ) {}
1735 };
1736
1737}
1738
1739template<typename ...Types>
1740struct StringMaker<std::tuple<Types...>> {
1741
1742 static std::string convert( const std::tuple<Types...>& tuple )
1743 {
1744 std::ostringstream os;
1745 os << '{';
1746 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1747 os << " }";
1748 return os.str();
1749 }
1750};
1751#endif // CATCH_CONFIG_CPP11_TUPLE
1752
1753namespace Detail {
1754 template<typename T>
1755 std::string makeString( T const& value ) {
1756 return StringMaker<T>::convert( value );
1757 }
1758} // end namespace Detail
1759
1760/// \brief converts any type to a string
1761///
1762/// The default template forwards on to ostringstream - except when an
1763/// ostringstream overload does not exist - in which case it attempts to detect
1764/// that and writes {?}.
1765/// Overload (not specialise) this template for custom typs that you don't want
1766/// to provide an ostream overload for.
1767template<typename T>
1768std::string toString( T const& value ) {
1769 return StringMaker<T>::convert( value );
1770}
1771
1772 namespace Detail {
1773 template<typename InputIterator>
1774 std::string rangeToString( InputIterator first, InputIterator last ) {
1775 std::ostringstream oss;
1776 oss << "{ ";
1777 if( first != last ) {
1778 oss << Catch::toString( *first );
1779 for( ++first ; first != last ; ++first )
1780 oss << ", " << Catch::toString( *first );
1781 }
1782 oss << " }";
1783 return oss.str();
1784 }
1785}
1786
1787} // end namespace Catch
1788
1789namespace Catch {
1790
1791template<typename LhsT, Internal::Operator Op, typename RhsT>
1792class BinaryExpression;
1793
1794template<typename ArgT, typename MatcherT>
1795class MatchExpression;
1796
1797// Wraps the LHS of an expression and overloads comparison operators
1798// for also capturing those and RHS (if any)
1799template<typename T>
1800class ExpressionLhs : public DecomposedExpression {
1801public:
1802 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
1803
1804 ExpressionLhs& operator = ( const ExpressionLhs& );
1805
1806 template<typename RhsT>
1807 BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
1808 operator == ( RhsT const& rhs ) {
1809 return captureExpression<Internal::IsEqualTo>( rhs );
1810 }
1811
1812 template<typename RhsT>
1813 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
1814 operator != ( RhsT const& rhs ) {
1815 return captureExpression<Internal::IsNotEqualTo>( rhs );
1816 }
1817
1818 template<typename RhsT>
1819 BinaryExpression<T, Internal::IsLessThan, RhsT const&>
1820 operator < ( RhsT const& rhs ) {
1821 return captureExpression<Internal::IsLessThan>( rhs );
1822 }
1823
1824 template<typename RhsT>
1825 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
1826 operator > ( RhsT const& rhs ) {
1827 return captureExpression<Internal::IsGreaterThan>( rhs );
1828 }
1829
1830 template<typename RhsT>
1831 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
1832 operator <= ( RhsT const& rhs ) {
1833 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1834 }
1835
1836 template<typename RhsT>
1837 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
1838 operator >= ( RhsT const& rhs ) {
1839 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1840 }
1841
1842 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
1843 return captureExpression<Internal::IsEqualTo>( rhs );
1844 }
1845
1846 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
1847 return captureExpression<Internal::IsNotEqualTo>( rhs );
1848 }
1849
1850 void endExpression() {
1851 m_truthy = m_lhs ? true : false;
1852 m_rb
1853 .setResultType( m_truthy )
1854 .endExpression( *this );
1855 }
1856
1857 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1858 dest = Catch::toString( m_truthy );
1859 }
1860
1861private:
1862 template<Internal::Operator Op, typename RhsT>
1863 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
1864 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
1865 }
1866
1867 template<Internal::Operator Op>
1868 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
1869 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
1870 }
1871
1872private:
1873 ResultBuilder& m_rb;
1874 T m_lhs;
1875 bool m_truthy;
1876};
1877
1878template<typename LhsT, Internal::Operator Op, typename RhsT>
1879class BinaryExpression : public DecomposedExpression {
1880public:
1881 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
1882 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
1883
1884 BinaryExpression& operator = ( BinaryExpression& );
1885
1886 void endExpression() const {
1887 m_rb
1888 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
1889 .endExpression( *this );
1890 }
1891
1892 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1893 return true;
1894 }
1895
1896 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1897 std::string lhs = Catch::toString( m_lhs );
1898 std::string rhs = Catch::toString( m_rhs );
1899 char delim = lhs.size() + rhs.size() < 40 &&
1900 lhs.find('\n') == std::string::npos &&
1901 rhs.find('\n') == std::string::npos ? ' ' : '\n';
1902 dest.reserve( 7 + lhs.size() + rhs.size() );
1903 // 2 for spaces around operator
1904 // 2 for operator
1905 // 2 for parentheses (conditionally added later)
1906 // 1 for negation (conditionally added later)
1907 dest = lhs;
1908 dest += delim;
1909 dest += Internal::OperatorTraits<Op>::getName();
1910 dest += delim;
1911 dest += rhs;
1912 }
1913
1914private:
1915 ResultBuilder& m_rb;
1916 LhsT m_lhs;
1917 RhsT m_rhs;
1918};
1919
1920template<typename ArgT, typename MatcherT>
1921class MatchExpression : public DecomposedExpression {
1922public:
1923 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
1924 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
1925
1926 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1927 return true;
1928 }
1929
1930 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1931 std::string matcherAsString = m_matcher.toString();
1932 dest = Catch::toString( m_arg );
1933 dest += ' ';
1934 if( matcherAsString == Detail::unprintableString )
1935 dest += m_matcherString;
1936 else
1937 dest += matcherAsString;
1938 }
1939
1940private:
1941 ArgT m_arg;
1942 MatcherT m_matcher;
1943 char const* m_matcherString;
1944};
1945
1946} // end namespace Catch
1947
1948
1949namespace Catch {
1950
1951 template<typename T>
1952 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
1953 return ExpressionLhs<T const&>( *this, operand );
1954 }
1955
1956 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
1957 return ExpressionLhs<bool>( *this, value );
1958 }
1959
1960 template<typename ArgT, typename MatcherT>
1961 inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
1962 char const* matcherString ) {
1963 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
1964 setResultType( matcher.match( arg ) );
1965 endExpression( expr );
1966 }
1967
1968} // namespace Catch
1969
1970// #included from: catch_message.h
1971#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1972
1973#include <string>
1974
1975namespace Catch {
1976
1977 struct MessageInfo {
1978 MessageInfo( std::string const& _macroName,
1979 SourceLineInfo const& _lineInfo,
1980 ResultWas::OfType _type );
1981
1982 std::string macroName;
1983 SourceLineInfo lineInfo;
1984 ResultWas::OfType type;
1985 std::string message;
1986 unsigned int sequence;
1987
1988 bool operator == ( MessageInfo const& other ) const {
1989 return sequence == other.sequence;
1990 }
1991 bool operator < ( MessageInfo const& other ) const {
1992 return sequence < other.sequence;
1993 }
1994 private:
1995 static unsigned int globalCount;
1996 };
1997
1998 struct MessageBuilder {
1999 MessageBuilder( std::string const& macroName,
2000 SourceLineInfo const& lineInfo,
2001 ResultWas::OfType type )
2002 : m_info( macroName, lineInfo, type )
2003 {}
2004
2005 template<typename T>
2006 MessageBuilder& operator << ( T const& value ) {
2007 m_stream << value;
2008 return *this;
2009 }
2010
2011 MessageInfo m_info;
2012 std::ostringstream m_stream;
2013 };
2014
2015 class ScopedMessage {
2016 public:
2017 ScopedMessage( MessageBuilder const& builder );
2018 ScopedMessage( ScopedMessage const& other );
2019 ~ScopedMessage();
2020
2021 MessageInfo m_info;
2022 };
2023
2024} // end namespace Catch
2025
2026// #included from: catch_interfaces_capture.h
2027#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
2028
2029#include <string>
2030
2031namespace Catch {
2032
2033 class TestCase;
2034 class AssertionResult;
2035 struct AssertionInfo;
2036 struct SectionInfo;
2037 struct SectionEndInfo;
2038 struct MessageInfo;
2039 class ScopedMessageBuilder;
2040 struct Counts;
2041
2042 struct IResultCapture {
2043
2044 virtual ~IResultCapture();
2045
2046 virtual void assertionEnded( AssertionResult const& result ) = 0;
2047 virtual bool sectionStarted( SectionInfo const& sectionInfo,
2048 Counts& assertions ) = 0;
2049 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2050 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
2051 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2052 virtual void popScopedMessage( MessageInfo const& message ) = 0;
2053
2054 virtual std::string getCurrentTestName() const = 0;
2055 virtual const AssertionResult* getLastResult() const = 0;
2056
2057 virtual void exceptionEarlyReported() = 0;
2058
2059 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
2060 };
2061
2062 IResultCapture& getResultCapture();
2063}
2064
2065// #included from: catch_debugger.h
2066#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
2067
2068// #included from: catch_platform.h
2069#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2070
2071#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
2072# define CATCH_PLATFORM_MAC
2073#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
2074# define CATCH_PLATFORM_IPHONE
2075#elif defined(linux) || defined(__linux) || defined(__linux__)
2076# define CATCH_PLATFORM_LINUX
2077#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2078# define CATCH_PLATFORM_WINDOWS
2079# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
2080# define CATCH_DEFINES_NOMINMAX
2081# endif
2082# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
2083# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
2084# endif
2085#endif
2086
2087#include <string>
2088
2089namespace Catch{
2090
2091 bool isDebuggerActive();
2092 void writeToDebugConsole( std::string const& text );
2093}
2094
2095#ifdef CATCH_PLATFORM_MAC
2096
2097 // The following code snippet based on:
2098 // http://cocoawithlove.com/2008/03/break-into-debugger.html
2099 #if defined(__ppc64__) || defined(__ppc__)
2100 #define CATCH_TRAP() \
2101 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2102 : : : "memory","r0","r3","r4" )
2103 #else
2104 #define CATCH_TRAP() __asm__("int $3\n" : : )
2105 #endif
2106
2107#elif defined(CATCH_PLATFORM_LINUX)
2108 // If we can use inline assembler, do it because this allows us to break
2109 // directly at the location of the failing check instead of breaking inside
2110 // raise() called from it, i.e. one stack frame below.
2111 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
2112 #define CATCH_TRAP() asm volatile ("int $3")
2113 #else // Fall back to the generic way.
2114 #include <signal.h>
2115
2116 #define CATCH_TRAP() raise(SIGTRAP)
2117 #endif
2118#elif defined(_MSC_VER)
2119 #define CATCH_TRAP() __debugbreak()
2120#elif defined(__MINGW32__)
2121 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
2122 #define CATCH_TRAP() DebugBreak()
2123#endif
2124
2125#ifdef CATCH_TRAP
2126 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
2127#else
2128 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2129#endif
2130
2131// #included from: catch_interfaces_runner.h
2132#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2133
2134namespace Catch {
2135 class TestCase;
2136
2137 struct IRunner {
2138 virtual ~IRunner();
2139 virtual bool aborting() const = 0;
2140 };
2141}
2142
2143#if defined(CATCH_CONFIG_FAST_COMPILE)
2144///////////////////////////////////////////////////////////////////////////////
2145// We can speedup compilation significantly by breaking into debugger lower in
2146// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
2147// macro in each assertion
2148#define INTERNAL_CATCH_REACT( resultBuilder ) \
2149 resultBuilder.react();
2150
2151///////////////////////////////////////////////////////////////////////////////
2152// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2153// macros.
2154// This can potentially cause false negative, if the test code catches
2155// the exception before it propagates back up to the runner.
2156#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
2157 do { \
2158 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2159 __catchResult.setExceptionGuard(); \
2160 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2161 ( __catchResult <= expr ).endExpression(); \
2162 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2163 __catchResult.unsetExceptionGuard(); \
2164 INTERNAL_CATCH_REACT( __catchResult ) \
2165 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2166// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2167
2168#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
2169 do { \
2170 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2171 __catchResult.setExceptionGuard(); \
2172 __catchResult.captureMatch( arg, matcher, #matcher ); \
2173 __catchResult.unsetExceptionGuard(); \
2174 INTERNAL_CATCH_REACT( __catchResult ) \
2175 } while( Catch::alwaysFalse() )
2176
2177#else
2178///////////////////////////////////////////////////////////////////////////////
2179// In the event of a failure works out if the debugger needs to be invoked
2180// and/or an exception thrown and takes appropriate action.
2181// This needs to be done as a macro so the debugger will stop in the user
2182// source code rather than in Catch library code
2183#define INTERNAL_CATCH_REACT( resultBuilder ) \
2184 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2185 resultBuilder.react();
2186#endif
2187
2188///////////////////////////////////////////////////////////////////////////////
2189#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
2190 do { \
2191 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2192 try { \
2193 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2194 ( __catchResult <= expr ).endExpression(); \
2195 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2196 } \
2197 catch( ... ) { \
2198 __catchResult.useActiveException( resultDisposition ); \
2199 } \
2200 INTERNAL_CATCH_REACT( __catchResult ) \
2201 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2202 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2203
2204///////////////////////////////////////////////////////////////////////////////
2205#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \
2206 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
2207 if( Catch::getResultCapture().getLastResult()->succeeded() )
2208
2209///////////////////////////////////////////////////////////////////////////////
2210#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \
2211 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
2212 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2213
2214///////////////////////////////////////////////////////////////////////////////
2215#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
2216 do { \
2217 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2218 try { \
2219 static_cast<void>(expr); \
2220 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2221 } \
2222 catch( ... ) { \
2223 __catchResult.useActiveException( resultDisposition ); \
2224 } \
2225 INTERNAL_CATCH_REACT( __catchResult ) \
2226 } while( Catch::alwaysFalse() )
2227
2228///////////////////////////////////////////////////////////////////////////////
2229#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
2230 do { \
2231 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2232 if( __catchResult.allowThrows() ) \
2233 try { \
2234 static_cast<void>(expr); \
2235 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2236 } \
2237 catch( ... ) { \
2238 __catchResult.captureExpectedException( matcher ); \
2239 } \
2240 else \
2241 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2242 INTERNAL_CATCH_REACT( __catchResult ) \
2243 } while( Catch::alwaysFalse() )
2244
2245///////////////////////////////////////////////////////////////////////////////
2246#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
2247 do { \
2248 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
2249 if( __catchResult.allowThrows() ) \
2250 try { \
2251 static_cast<void>(expr); \
2252 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2253 } \
2254 catch( exceptionType ) { \
2255 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2256 } \
2257 catch( ... ) { \
2258 __catchResult.useActiveException( resultDisposition ); \
2259 } \
2260 else \
2261 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2262 INTERNAL_CATCH_REACT( __catchResult ) \
2263 } while( Catch::alwaysFalse() )
2264
2265///////////////////////////////////////////////////////////////////////////////
2266#ifdef CATCH_CONFIG_VARIADIC_MACROS
2267 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
2268 do { \
2269 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2270 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2271 __catchResult.captureResult( messageType ); \
2272 INTERNAL_CATCH_REACT( __catchResult ) \
2273 } while( Catch::alwaysFalse() )
2274#else
2275 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \
2276 do { \
2277 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2278 __catchResult << log + ::Catch::StreamEndStop(); \
2279 __catchResult.captureResult( messageType ); \
2280 INTERNAL_CATCH_REACT( __catchResult ) \
2281 } while( Catch::alwaysFalse() )
2282#endif
2283
2284///////////////////////////////////////////////////////////////////////////////
2285#define INTERNAL_CATCH_INFO( macroName, log ) \
2286 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2287
2288///////////////////////////////////////////////////////////////////////////////
2289#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
2290 do { \
2291 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2292 try { \
2293 __catchResult.captureMatch( arg, matcher, #matcher ); \
2294 } catch( ... ) { \
2295 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2296 } \
2297 INTERNAL_CATCH_REACT( __catchResult ) \
2298 } while( Catch::alwaysFalse() )
2299
2300// #included from: internal/catch_section.h
2301#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2302
2303// #included from: catch_section_info.h
2304#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2305
2306// #included from: catch_totals.hpp
2307#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2308
2309#include <cstddef>
2310
2311namespace Catch {
2312
2313 struct Counts {
2314 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2315
2316 Counts operator - ( Counts const& other ) const {
2317 Counts diff;
2318 diff.passed = passed - other.passed;
2319 diff.failed = failed - other.failed;
2320 diff.failedButOk = failedButOk - other.failedButOk;
2321 return diff;
2322 }
2323 Counts& operator += ( Counts const& other ) {
2324 passed += other.passed;
2325 failed += other.failed;
2326 failedButOk += other.failedButOk;
2327 return *this;
2328 }
2329
2330 std::size_t total() const {
2331 return passed + failed + failedButOk;
2332 }
2333 bool allPassed() const {
2334 return failed == 0 && failedButOk == 0;
2335 }
2336 bool allOk() const {
2337 return failed == 0;
2338 }
2339
2340 std::size_t passed;
2341 std::size_t failed;
2342 std::size_t failedButOk;
2343 };
2344
2345 struct Totals {
2346
2347 Totals operator - ( Totals const& other ) const {
2348 Totals diff;
2349 diff.assertions = assertions - other.assertions;
2350 diff.testCases = testCases - other.testCases;
2351 return diff;
2352 }
2353
2354 Totals delta( Totals const& prevTotals ) const {
2355 Totals diff = *this - prevTotals;
2356 if( diff.assertions.failed > 0 )
2357 ++diff.testCases.failed;
2358 else if( diff.assertions.failedButOk > 0 )
2359 ++diff.testCases.failedButOk;
2360 else
2361 ++diff.testCases.passed;
2362 return diff;
2363 }
2364
2365 Totals& operator += ( Totals const& other ) {
2366 assertions += other.assertions;
2367 testCases += other.testCases;
2368 return *this;
2369 }
2370
2371 Counts assertions;
2372 Counts testCases;
2373 };
2374}
2375
2376#include <string>
2377
2378namespace Catch {
2379
2380 struct SectionInfo {
2381 SectionInfo
2382 ( SourceLineInfo const& _lineInfo,
2383 std::string const& _name,
2384 std::string const& _description = std::string() );
2385
2386 std::string name;
2387 std::string description;
2388 SourceLineInfo lineInfo;
2389 };
2390
2391 struct SectionEndInfo {
2392 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2393 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2394 {}
2395
2396 SectionInfo sectionInfo;
2397 Counts prevAssertions;
2398 double durationInSeconds;
2399 };
2400
2401} // end namespace Catch
2402
2403// #included from: catch_timer.h
2404#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2405
2406#ifdef _MSC_VER
2407
2408namespace Catch {
2409 typedef unsigned long long UInt64;
2410}
2411#else
2412#include <stdint.h>
2413namespace Catch {
2414 typedef uint64_t UInt64;
2415}
2416#endif
2417
2418namespace Catch {
2419 class Timer {
2420 public:
2421 Timer() : m_ticks( 0 ) {}
2422 void start();
2423 unsigned int getElapsedMicroseconds() const;
2424 unsigned int getElapsedMilliseconds() const;
2425 double getElapsedSeconds() const;
2426
2427 private:
2428 UInt64 m_ticks;
2429 };
2430
2431} // namespace Catch
2432
2433#include <string>
2434
2435namespace Catch {
2436
2437 class Section : NonCopyable {
2438 public:
2439 Section( SectionInfo const& info );
2440 ~Section();
2441
2442 // This indicates whether the section should be executed or not
2443 operator bool() const;
2444
2445 private:
2446 SectionInfo m_info;
2447
2448 std::string m_name;
2449 Counts m_assertions;
2450 bool m_sectionIncluded;
2451 Timer m_timer;
2452 };
2453
2454} // end namespace Catch
2455
2456#ifdef CATCH_CONFIG_VARIADIC_MACROS
2457 #define INTERNAL_CATCH_SECTION( ... ) \
2458 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2459#else
2460 #define INTERNAL_CATCH_SECTION( name, desc ) \
2461 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2462#endif
2463
2464// #included from: internal/catch_generators.hpp
2465#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2466
2467#include <vector>
2468#include <string>
2469#include <stdlib.h>
2470
2471namespace Catch {
2472
2473template<typename T>
2474struct IGenerator {
2475 virtual ~IGenerator() {}
2476 virtual T getValue( std::size_t index ) const = 0;
2477 virtual std::size_t size () const = 0;
2478};
2479
2480template<typename T>
2481class BetweenGenerator : public IGenerator<T> {
2482public:
2483 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2484
2485 virtual T getValue( std::size_t index ) const {
2486 return m_from+static_cast<int>( index );
2487 }
2488
2489 virtual std::size_t size() const {
2490 return static_cast<std::size_t>( 1+m_to-m_from );
2491 }
2492
2493private:
2494
2495 T m_from;
2496 T m_to;
2497};
2498
2499template<typename T>
2500class ValuesGenerator : public IGenerator<T> {
2501public:
2502 ValuesGenerator(){}
2503
2504 void add( T value ) {
2505 m_values.push_back( value );
2506 }
2507
2508 virtual T getValue( std::size_t index ) const {
2509 return m_values[index];
2510 }
2511
2512 virtual std::size_t size() const {
2513 return m_values.size();
2514 }
2515
2516private:
2517 std::vector<T> m_values;
2518};
2519
2520template<typename T>
2521class CompositeGenerator {
2522public:
2523 CompositeGenerator() : m_totalSize( 0 ) {}
2524
2525 // *** Move semantics, similar to auto_ptr ***
2526 CompositeGenerator( CompositeGenerator& other )
2527 : m_fileInfo( other.m_fileInfo ),
2528 m_totalSize( 0 )
2529 {
2530 move( other );
2531 }
2532
2533 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2534 m_fileInfo = fileInfo;
2535 return *this;
2536 }
2537
2538 ~CompositeGenerator() {
2539 deleteAll( m_composed );
2540 }
2541
2542 operator T () const {
2543 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2544
2545 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2546 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2547 for( size_t index = 0; it != itEnd; ++it )
2548 {
2549 const IGenerator<T>* generator = *it;
2550 if( overallIndex >= index && overallIndex < index + generator->size() )
2551 {
2552 return generator->getValue( overallIndex-index );
2553 }
2554 index += generator->size();
2555 }
2556 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2557 return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
2558 }
2559
2560 void add( const IGenerator<T>* generator ) {
2561 m_totalSize += generator->size();
2562 m_composed.push_back( generator );
2563 }
2564
2565 CompositeGenerator& then( CompositeGenerator& other ) {
2566 move( other );
2567 return *this;
2568 }
2569
2570 CompositeGenerator& then( T value ) {
2571 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2572 valuesGen->add( value );
2573 add( valuesGen );
2574 return *this;
2575 }
2576
2577private:
2578
2579 void move( CompositeGenerator& other ) {
2580 m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() );
2581 m_totalSize += other.m_totalSize;
2582 other.m_composed.clear();
2583 }
2584
2585 std::vector<const IGenerator<T>*> m_composed;
2586 std::string m_fileInfo;
2587 size_t m_totalSize;
2588};
2589
2590namespace Generators
2591{
2592 template<typename T>
2593 CompositeGenerator<T> between( T from, T to ) {
2594 CompositeGenerator<T> generators;
2595 generators.add( new BetweenGenerator<T>( from, to ) );
2596 return generators;
2597 }
2598
2599 template<typename T>
2600 CompositeGenerator<T> values( T val1, T val2 ) {
2601 CompositeGenerator<T> generators;
2602 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2603 valuesGen->add( val1 );
2604 valuesGen->add( val2 );
2605 generators.add( valuesGen );
2606 return generators;
2607 }
2608
2609 template<typename T>
2610 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2611 CompositeGenerator<T> generators;
2612 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2613 valuesGen->add( val1 );
2614 valuesGen->add( val2 );
2615 valuesGen->add( val3 );
2616 generators.add( valuesGen );
2617 return generators;
2618 }
2619
2620 template<typename T>
2621 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2622 CompositeGenerator<T> generators;
2623 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2624 valuesGen->add( val1 );
2625 valuesGen->add( val2 );
2626 valuesGen->add( val3 );
2627 valuesGen->add( val4 );
2628 generators.add( valuesGen );
2629 return generators;
2630 }
2631
2632} // end namespace Generators
2633
2634using namespace Generators;
2635
2636} // end namespace Catch
2637
2638#define INTERNAL_CATCH_LINESTR2( line ) #line
2639#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2640
2641#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2642
2643// #included from: internal/catch_interfaces_exception.h
2644#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2645
2646#include <string>
2647#include <vector>
2648
2649// #included from: catch_interfaces_registry_hub.h
2650#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2651
2652#include <string>
2653
2654namespace Catch {
2655
2656 class TestCase;
2657 struct ITestCaseRegistry;
2658 struct IExceptionTranslatorRegistry;
2659 struct IExceptionTranslator;
2660 struct IReporterRegistry;
2661 struct IReporterFactory;
2662 struct ITagAliasRegistry;
2663
2664 struct IRegistryHub {
2665 virtual ~IRegistryHub();
2666
2667 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2668 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2669 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
2670
2671 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2672 };
2673
2674 struct IMutableRegistryHub {
2675 virtual ~IMutableRegistryHub();
2676 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2677 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
2678 virtual void registerTest( TestCase const& testInfo ) = 0;
2679 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2680 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
2681 };
2682
2683 IRegistryHub& getRegistryHub();
2684 IMutableRegistryHub& getMutableRegistryHub();
2685 void cleanUp();
2686 std::string translateActiveException();
2687
2688}
2689
2690namespace Catch {
2691
2692 typedef std::string(*exceptionTranslateFunction)();
2693
2694 struct IExceptionTranslator;
2695 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2696
2697 struct IExceptionTranslator {
2698 virtual ~IExceptionTranslator();
2699 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2700 };
2701
2702 struct IExceptionTranslatorRegistry {
2703 virtual ~IExceptionTranslatorRegistry();
2704
2705 virtual std::string translateActiveException() const = 0;
2706 };
2707
2708 class ExceptionTranslatorRegistrar {
2709 template<typename T>
2710 class ExceptionTranslator : public IExceptionTranslator {
2711 public:
2712
2713 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2714 : m_translateFunction( translateFunction )
2715 {}
2716
2717 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
2718 try {
2719 if( it == itEnd )
2720 throw;
2721 else
2722 return (*it)->translate( it+1, itEnd );
2723 }
2724 catch( T& ex ) {
2725 return m_translateFunction( ex );
2726 }
2727 }
2728
2729 protected:
2730 std::string(*m_translateFunction)( T& );
2731 };
2732
2733 public:
2734 template<typename T>
2735 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2736 getMutableRegistryHub().registerTranslator
2737 ( new ExceptionTranslator<T>( translateFunction ) );
2738 }
2739 };
2740}
2741
2742///////////////////////////////////////////////////////////////////////////////
2743#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2744 static std::string translatorName( signature ); \
2745 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2746 static std::string translatorName( signature )
2747
2748#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2749
2750// #included from: internal/catch_approx.hpp
2751#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2752
2753#include <cmath>
2754#include <limits>
2755
2756#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2757#include <type_traits>
2758#endif
2759
2760namespace Catch {
2761namespace Detail {
2762
2763 class Approx {
2764 public:
2765 explicit Approx ( double value )
2766 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2767 m_margin( 0.0 ),
2768 m_scale( 1.0 ),
2769 m_value( value )
2770 {}
2771
2772 Approx( Approx const& other )
2773 : m_epsilon( other.m_epsilon ),
2774 m_margin( other.m_margin ),
2775 m_scale( other.m_scale ),
2776 m_value( other.m_value )
2777 {}
2778
2779 static Approx custom() {
2780 return Approx( 0 );
2781 }
2782
2783#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2784
2785 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2786 Approx operator()( T value ) {
2787 Approx approx( static_cast<double>(value) );
2788 approx.epsilon( m_epsilon );
2789 approx.margin( m_margin );
2790 approx.scale( m_scale );
2791 return approx;
2792 }
2793
2794 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2795 explicit Approx( T value ): Approx(static_cast<double>(value))
2796 {}
2797
2798 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2799 friend bool operator == ( const T& lhs, Approx const& rhs ) {
2800 // Thanks to Richard Harris for his help refining this formula
2801 auto lhs_v = double(lhs);
2802 bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
2803 if (relativeOK) {
2804 return true;
2805 }
2806 return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
2807 }
2808
2809 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2810 friend bool operator == ( Approx const& lhs, const T& rhs ) {
2811 return operator==( rhs, lhs );
2812 }
2813
2814 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2815 friend bool operator != ( T lhs, Approx const& rhs ) {
2816 return !operator==( lhs, rhs );
2817 }
2818
2819 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2820 friend bool operator != ( Approx const& lhs, T rhs ) {
2821 return !operator==( rhs, lhs );
2822 }
2823
2824 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2825 friend bool operator <= ( T lhs, Approx const& rhs ) {
2826 return double(lhs) < rhs.m_value || lhs == rhs;
2827 }
2828
2829 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2830 friend bool operator <= ( Approx const& lhs, T rhs ) {
2831 return lhs.m_value < double(rhs) || lhs == rhs;
2832 }
2833
2834 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2835 friend bool operator >= ( T lhs, Approx const& rhs ) {
2836 return double(lhs) > rhs.m_value || lhs == rhs;
2837 }
2838
2839 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2840 friend bool operator >= ( Approx const& lhs, T rhs ) {
2841 return lhs.m_value > double(rhs) || lhs == rhs;
2842 }
2843
2844 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2845 Approx& epsilon( T newEpsilon ) {
2846 m_epsilon = double(newEpsilon);
2847 return *this;
2848 }
2849
2850 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2851 Approx& margin( T newMargin ) {
2852 m_margin = double(newMargin);
2853 return *this;
2854 }
2855
2856 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2857 Approx& scale( T newScale ) {
2858 m_scale = double(newScale);
2859 return *this;
2860 }
2861
2862#else
2863
2864 Approx operator()( double value ) {
2865 Approx approx( value );
2866 approx.epsilon( m_epsilon );
2867 approx.margin( m_margin );
2868 approx.scale( m_scale );
2869 return approx;
2870 }
2871
2872 friend bool operator == ( double lhs, Approx const& rhs ) {
2873 // Thanks to Richard Harris for his help refining this formula
2874 bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
2875 if (relativeOK) {
2876 return true;
2877 }
2878 return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
2879 }
2880
2881 friend bool operator == ( Approx const& lhs, double rhs ) {
2882 return operator==( rhs, lhs );
2883 }
2884
2885 friend bool operator != ( double lhs, Approx const& rhs ) {
2886 return !operator==( lhs, rhs );
2887 }
2888
2889 friend bool operator != ( Approx const& lhs, double rhs ) {
2890 return !operator==( rhs, lhs );
2891 }
2892
2893 friend bool operator <= ( double lhs, Approx const& rhs ) {
2894 return lhs < rhs.m_value || lhs == rhs;
2895 }
2896
2897 friend bool operator <= ( Approx const& lhs, double rhs ) {
2898 return lhs.m_value < rhs || lhs == rhs;
2899 }
2900
2901 friend bool operator >= ( double lhs, Approx const& rhs ) {
2902 return lhs > rhs.m_value || lhs == rhs;
2903 }
2904
2905 friend bool operator >= ( Approx const& lhs, double rhs ) {
2906 return lhs.m_value > rhs || lhs == rhs;
2907 }
2908
2909 Approx& epsilon( double newEpsilon ) {
2910 m_epsilon = newEpsilon;
2911 return *this;
2912 }
2913
2914 Approx& margin( double newMargin ) {
2915 m_margin = newMargin;
2916 return *this;
2917 }
2918
2919 Approx& scale( double newScale ) {
2920 m_scale = newScale;
2921 return *this;
2922 }
2923#endif
2924
2925 std::string toString() const {
2926 std::ostringstream oss;
2927 oss << "Approx( " << Catch::toString( m_value ) << " )";
2928 return oss.str();
2929 }
2930
2931 private:
2932 double m_epsilon;
2933 double m_margin;
2934 double m_scale;
2935 double m_value;
2936 };
2937}
2938
2939template<>
2940inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
2941 return value.toString();
2942}
2943
2944} // end namespace Catch
2945
2946// #included from: internal/catch_matchers_string.h
2947#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
2948
2949namespace Catch {
2950namespace Matchers {
2951
2952 namespace StdString {
2953
2954 struct CasedString
2955 {
2956 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
2957 std::string adjustString( std::string const& str ) const;
2958 std::string caseSensitivitySuffix() const;
2959
2960 CaseSensitive::Choice m_caseSensitivity;
2961 std::string m_str;
2962 };
2963
2964 struct StringMatcherBase : MatcherBase<std::string> {
2965 StringMatcherBase( std::string const& operation, CasedString const& comparator );
2966 virtual std::string describe() const CATCH_OVERRIDE;
2967
2968 CasedString m_comparator;
2969 std::string m_operation;
2970 };
2971
2972 struct EqualsMatcher : StringMatcherBase {
2973 EqualsMatcher( CasedString const& comparator );
2974 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2975 };
2976 struct ContainsMatcher : StringMatcherBase {
2977 ContainsMatcher( CasedString const& comparator );
2978 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2979 };
2980 struct StartsWithMatcher : StringMatcherBase {
2981 StartsWithMatcher( CasedString const& comparator );
2982 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2983 };
2984 struct EndsWithMatcher : StringMatcherBase {
2985 EndsWithMatcher( CasedString const& comparator );
2986 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2987 };
2988
2989 } // namespace StdString
2990
2991 // The following functions create the actual matcher objects.
2992 // This allows the types to be inferred
2993
2994 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2995 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2996 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2997 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2998
2999} // namespace Matchers
3000} // namespace Catch
3001
3002// #included from: internal/catch_matchers_vector.h
3003#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
3004
3005namespace Catch {
3006namespace Matchers {
3007
3008 namespace Vector {
3009
3010 template<typename T>
3011 struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
3012
3013 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
3014
3015 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3016 return std::find(v.begin(), v.end(), m_comparator) != v.end();
3017 }
3018
3019 virtual std::string describe() const CATCH_OVERRIDE {
3020 return "Contains: " + Catch::toString( m_comparator );
3021 }
3022
3023 T const& m_comparator;
3024 };
3025
3026 template<typename T>
3027 struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3028
3029 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3030
3031 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3032 // !TBD: see note in EqualsMatcher
3033 if (m_comparator.size() > v.size())
3034 return false;
3035 for (size_t i = 0; i < m_comparator.size(); ++i)
3036 if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
3037 return false;
3038 return true;
3039 }
3040 virtual std::string describe() const CATCH_OVERRIDE {
3041 return "Contains: " + Catch::toString( m_comparator );
3042 }
3043
3044 std::vector<T> const& m_comparator;
3045 };
3046
3047 template<typename T>
3048 struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3049
3050 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3051
3052 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3053 // !TBD: This currently works if all elements can be compared using !=
3054 // - a more general approach would be via a compare template that defaults
3055 // to using !=. but could be specialised for, e.g. std::vector<T> etc
3056 // - then just call that directly
3057 if (m_comparator.size() != v.size())
3058 return false;
3059 for (size_t i = 0; i < v.size(); ++i)
3060 if (m_comparator[i] != v[i])
3061 return false;
3062 return true;
3063 }
3064 virtual std::string describe() const CATCH_OVERRIDE {
3065 return "Equals: " + Catch::toString( m_comparator );
3066 }
3067 std::vector<T> const& m_comparator;
3068 };
3069
3070 } // namespace Vector
3071
3072 // The following functions create the actual matcher objects.
3073 // This allows the types to be inferred
3074
3075 template<typename T>
3076 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
3077 return Vector::ContainsMatcher<T>( comparator );
3078 }
3079
3080 template<typename T>
3081 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
3082 return Vector::ContainsElementMatcher<T>( comparator );
3083 }
3084
3085 template<typename T>
3086 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
3087 return Vector::EqualsMatcher<T>( comparator );
3088 }
3089
3090} // namespace Matchers
3091} // namespace Catch
3092
3093// #included from: internal/catch_interfaces_tag_alias_registry.h
3094#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
3095
3096// #included from: catch_tag_alias.h
3097#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
3098
3099#include <string>
3100
3101namespace Catch {
3102
3103 struct TagAlias {
3104 TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
3105
3106 std::string tag;
3107 SourceLineInfo lineInfo;
3108 };
3109
3110 struct RegistrarForTagAliases {
3111 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
3112 };
3113
3114} // end namespace Catch
3115
3116#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
3117// #included from: catch_option.hpp
3118#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3119
3120namespace Catch {
3121
3122 // An optional type
3123 template<typename T>
3124 class Option {
3125 public:
3126 Option() : nullableValue( CATCH_NULL ) {}
3127 Option( T const& _value )
3128 : nullableValue( new( storage ) T( _value ) )
3129 {}
3130 Option( Option const& _other )
3131 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
3132 {}
3133
3134 ~Option() {
3135 reset();
3136 }
3137
3138 Option& operator= ( Option const& _other ) {
3139 if( &_other != this ) {
3140 reset();
3141 if( _other )
3142 nullableValue = new( storage ) T( *_other );
3143 }
3144 return *this;
3145 }
3146 Option& operator = ( T const& _value ) {
3147 reset();
3148 nullableValue = new( storage ) T( _value );
3149 return *this;
3150 }
3151
3152 void reset() {
3153 if( nullableValue )
3154 nullableValue->~T();
3155 nullableValue = CATCH_NULL;
3156 }
3157
3158 T& operator*() { return *nullableValue; }
3159 T const& operator*() const { return *nullableValue; }
3160 T* operator->() { return nullableValue; }
3161 const T* operator->() const { return nullableValue; }
3162
3163 T valueOr( T const& defaultValue ) const {
3164 return nullableValue ? *nullableValue : defaultValue;
3165 }
3166
3167 bool some() const { return nullableValue != CATCH_NULL; }
3168 bool none() const { return nullableValue == CATCH_NULL; }
3169
3170 bool operator !() const { return nullableValue == CATCH_NULL; }
3171 operator SafeBool::type() const {
3172 return SafeBool::makeSafe( some() );
3173 }
3174
3175 private:
3176 T *nullableValue;
3177 union {
3178 char storage[sizeof(T)];
3179
3180 // These are here to force alignment for the storage
3181 long double dummy1;
3182 void (*dummy2)();
3183 long double dummy3;
3184#ifdef CATCH_CONFIG_CPP11_LONG_LONG
3185 long long dummy4;
3186#endif
3187 };
3188 };
3189
3190} // end namespace Catch
3191
3192namespace Catch {
3193
3194 struct ITagAliasRegistry {
3195 virtual ~ITagAliasRegistry();
3196 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
3197 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
3198
3199 static ITagAliasRegistry const& get();
3200 };
3201
3202} // end namespace Catch
3203
3204// These files are included here so the single_include script doesn't put them
3205// in the conditionally compiled sections
3206// #included from: internal/catch_test_case_info.h
3207#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
3208
3209#include <string>
3210#include <set>
3211
3212#ifdef __clang__
3213#pragma clang diagnostic push
3214#pragma clang diagnostic ignored "-Wpadded"
3215#endif
3216
3217namespace Catch {
3218
3219 struct ITestCase;
3220
3221 struct TestCaseInfo {
3222 enum SpecialProperties{
3223 None = 0,
3224 IsHidden = 1 << 1,
3225 ShouldFail = 1 << 2,
3226 MayFail = 1 << 3,
3227 Throws = 1 << 4,
3228 NonPortable = 1 << 5
3229 };
3230
3231 TestCaseInfo( std::string const& _name,
3232 std::string const& _className,
3233 std::string const& _description,
3234 std::set<std::string> const& _tags,
3235 SourceLineInfo const& _lineInfo );
3236
3237 TestCaseInfo( TestCaseInfo const& other );
3238
3239 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
3240
3241 bool isHidden() const;
3242 bool throws() const;
3243 bool okToFail() const;
3244 bool expectedToFail() const;
3245
3246 std::string name;
3247 std::string className;
3248 std::string description;
3249 std::set<std::string> tags;
3250 std::set<std::string> lcaseTags;
3251 std::string tagsAsString;
3252 SourceLineInfo lineInfo;
3253 SpecialProperties properties;
3254 };
3255
3256 class TestCase : public TestCaseInfo {
3257 public:
3258
3259 TestCase( ITestCase* testCase, TestCaseInfo const& info );
3260 TestCase( TestCase const& other );
3261
3262 TestCase withName( std::string const& _newName ) const;
3263
3264 void invoke() const;
3265
3266 TestCaseInfo const& getTestCaseInfo() const;
3267
3268 void swap( TestCase& other );
3269 bool operator == ( TestCase const& other ) const;
3270 bool operator < ( TestCase const& other ) const;
3271 TestCase& operator = ( TestCase const& other );
3272
3273 private:
3274 Ptr<ITestCase> test;
3275 };
3276
3277 TestCase makeTestCase( ITestCase* testCase,
3278 std::string const& className,
3279 std::string const& name,
3280 std::string const& description,
3281 SourceLineInfo const& lineInfo );
3282}
3283
3284#ifdef __clang__
3285#pragma clang diagnostic pop
3286#endif
3287
3288
3289#ifdef __OBJC__
3290// #included from: internal/catch_objc.hpp
3291#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
3292
3293#import <objc/runtime.h>
3294
3295#include <string>
3296
3297// NB. Any general catch headers included here must be included
3298// in catch.hpp first to make sure they are included by the single
3299// header for non obj-usage
3300
3301///////////////////////////////////////////////////////////////////////////////
3302// This protocol is really only here for (self) documenting purposes, since
3303// all its methods are optional.
3304@protocol OcFixture
3305
3306@optional
3307
3308-(void) setUp;
3309-(void) tearDown;
3310
3311@end
3312
3313namespace Catch {
3314
3315 class OcMethod : public SharedImpl<ITestCase> {
3316
3317 public:
3318 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3319
3320 virtual void invoke() const {
3321 id obj = [[m_cls alloc] init];
3322
3323 performOptionalSelector( obj, @selector(setUp) );
3324 performOptionalSelector( obj, m_sel );
3325 performOptionalSelector( obj, @selector(tearDown) );
3326
3327 arcSafeRelease( obj );
3328 }
3329 private:
3330 virtual ~OcMethod() {}
3331
3332 Class m_cls;
3333 SEL m_sel;
3334 };
3335
3336 namespace Detail{
3337
3338 inline std::string getAnnotation( Class cls,
3339 std::string const& annotationName,
3340 std::string const& testCaseName ) {
3341 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3342 SEL sel = NSSelectorFromString( selStr );
3343 arcSafeRelease( selStr );
3344 id value = performOptionalSelector( cls, sel );
3345 if( value )
3346 return [(NSString*)value UTF8String];
3347 return "";
3348 }
3349 }
3350
3351 inline size_t registerTestMethods() {
3352 size_t noTestMethods = 0;
3353 int noClasses = objc_getClassList( CATCH_NULL, 0 );
3354
3355 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
3356 objc_getClassList( classes, noClasses );
3357
3358 for( int c = 0; c < noClasses; c++ ) {
3359 Class cls = classes[c];
3360 {
3361 u_int count;
3362 Method* methods = class_copyMethodList( cls, &count );
3363 for( u_int m = 0; m < count ; m++ ) {
3364 SEL selector = method_getName(methods[m]);
3365 std::string methodName = sel_getName(selector);
3366 if( startsWith( methodName, "Catch_TestCase_" ) ) {
3367 std::string testCaseName = methodName.substr( 15 );
3368 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3369 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
3370 const char* className = class_getName( cls );
3371
3372 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
3373 noTestMethods++;
3374 }
3375 }
3376 free(methods);
3377 }
3378 }
3379 return noTestMethods;
3380 }
3381
3382 namespace Matchers {
3383 namespace Impl {
3384 namespace NSStringMatchers {
3385
3386 struct StringHolder : MatcherBase<NSString*>{
3387 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
3388 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
3389 StringHolder() {
3390 arcSafeRelease( m_substr );
3391 }
3392
3393 virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
3394 return false;
3395 }
3396
3397 NSString* m_substr;
3398 };
3399
3400 struct Equals : StringHolder {
3401 Equals( NSString* substr ) : StringHolder( substr ){}
3402
3403 virtual bool match( NSString* str ) const CATCH_OVERRIDE {
3404 return (str != nil || m_substr == nil ) &&
3405 [str isEqualToString:m_substr];
3406 }
3407
3408 virtual std::string describe() const CATCH_OVERRIDE {
3409 return "equals string: " + Catch::toString( m_substr );
3410 }
3411 };
3412
3413 struct Contains : StringHolder {
3414 Contains( NSString* substr ) : StringHolder( substr ){}
3415
3416 virtual bool match( NSString* str ) const {
3417 return (str != nil || m_substr == nil ) &&
3418 [str rangeOfString:m_substr].location != NSNotFound;
3419 }
3420
3421 virtual std::string describe() const CATCH_OVERRIDE {
3422 return "contains string: " + Catch::toString( m_substr );
3423 }
3424 };
3425
3426 struct StartsWith : StringHolder {
3427 StartsWith( NSString* substr ) : StringHolder( substr ){}
3428
3429 virtual bool match( NSString* str ) const {
3430 return (str != nil || m_substr == nil ) &&
3431 [str rangeOfString:m_substr].location == 0;
3432 }
3433
3434 virtual std::string describe() const CATCH_OVERRIDE {
3435 return "starts with: " + Catch::toString( m_substr );
3436 }
3437 };
3438 struct EndsWith : StringHolder {
3439 EndsWith( NSString* substr ) : StringHolder( substr ){}
3440
3441 virtual bool match( NSString* str ) const {
3442 return (str != nil || m_substr == nil ) &&
3443 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3444 }
3445
3446 virtual std::string describe() const CATCH_OVERRIDE {
3447 return "ends with: " + Catch::toString( m_substr );
3448 }
3449 };
3450
3451 } // namespace NSStringMatchers
3452 } // namespace Impl
3453
3454 inline Impl::NSStringMatchers::Equals
3455 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3456
3457 inline Impl::NSStringMatchers::Contains
3458 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
3459
3460 inline Impl::NSStringMatchers::StartsWith
3461 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
3462
3463 inline Impl::NSStringMatchers::EndsWith
3464 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3465
3466 } // namespace Matchers
3467
3468 using namespace Matchers;
3469
3470} // namespace Catch
3471
3472///////////////////////////////////////////////////////////////////////////////
3473#define OC_TEST_CASE( name, desc )\
3474+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3475{\
3476return @ name; \
3477}\
3478+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3479{ \
3480return @ desc; \
3481} \
3482-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3483
3484#endif
3485
3486#ifdef CATCH_IMPL
3487
3488// !TBD: Move the leak detector code into a separate header
3489#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
3490#include <crtdbg.h>
3491class LeakDetector {
3492public:
3493 LeakDetector() {
3494 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
3495 flag |= _CRTDBG_LEAK_CHECK_DF;
3496 flag |= _CRTDBG_ALLOC_MEM_DF;
3497 _CrtSetDbgFlag(flag);
3498 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3499 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3500 // Change this to leaking allocation's number to break there
3501 _CrtSetBreakAlloc(-1);
3502 }
3503};
3504#else
3505class LeakDetector {};
3506#endif
3507
3508LeakDetector leakDetector;
3509
3510// #included from: internal/catch_impl.hpp
3511#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3512
3513// Collect all the implementation files together here
3514// These are the equivalent of what would usually be cpp files
3515
3516#ifdef __clang__
3517#pragma clang diagnostic push
3518#pragma clang diagnostic ignored "-Wweak-vtables"
3519#endif
3520
3521// #included from: ../catch_session.hpp
3522#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3523
3524// #included from: internal/catch_commandline.hpp
3525#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3526
3527// #included from: catch_config.hpp
3528#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3529
3530// #included from: catch_test_spec_parser.hpp
3531#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3532
3533#ifdef __clang__
3534#pragma clang diagnostic push
3535#pragma clang diagnostic ignored "-Wpadded"
3536#endif
3537
3538// #included from: catch_test_spec.hpp
3539#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3540
3541#ifdef __clang__
3542#pragma clang diagnostic push
3543#pragma clang diagnostic ignored "-Wpadded"
3544#endif
3545
3546// #included from: catch_wildcard_pattern.hpp
3547#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3548
3549#include <stdexcept>
3550
3551namespace Catch
3552{
3553 class WildcardPattern {
3554 enum WildcardPosition {
3555 NoWildcard = 0,
3556 WildcardAtStart = 1,
3557 WildcardAtEnd = 2,
3558 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3559 };
3560
3561 public:
3562
3563 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
3564 : m_caseSensitivity( caseSensitivity ),
3565 m_wildcard( NoWildcard ),
3566 m_pattern( adjustCase( pattern ) )
3567 {
3568 if( startsWith( m_pattern, '*' ) ) {
3569 m_pattern = m_pattern.substr( 1 );
3570 m_wildcard = WildcardAtStart;
3571 }
3572 if( endsWith( m_pattern, '*' ) ) {
3573 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3574 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3575 }
3576 }
3577 virtual ~WildcardPattern();
3578 virtual bool matches( std::string const& str ) const {
3579 switch( m_wildcard ) {
3580 case NoWildcard:
3581 return m_pattern == adjustCase( str );
3582 case WildcardAtStart:
3583 return endsWith( adjustCase( str ), m_pattern );
3584 case WildcardAtEnd:
3585 return startsWith( adjustCase( str ), m_pattern );
3586 case WildcardAtBothEnds:
3587 return contains( adjustCase( str ), m_pattern );
3588 }
3589
3590#ifdef __clang__
3591#pragma clang diagnostic push
3592#pragma clang diagnostic ignored "-Wunreachable-code"
3593#endif
3594 throw std::logic_error( "Unknown enum" );
3595#ifdef __clang__
3596#pragma clang diagnostic pop
3597#endif
3598 }
3599 private:
3600 std::string adjustCase( std::string const& str ) const {
3601 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
3602 }
3603 CaseSensitive::Choice m_caseSensitivity;
3604 WildcardPosition m_wildcard;
3605 std::string m_pattern;
3606 };
3607}
3608
3609#include <string>
3610#include <vector>
3611
3612namespace Catch {
3613
3614 class TestSpec {
3615 struct Pattern : SharedImpl<> {
3616 virtual ~Pattern();
3617 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3618 };
3619 class NamePattern : public Pattern {
3620 public:
3621 NamePattern( std::string const& name )
3622 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
3623 {}
3624 virtual ~NamePattern();
3625 virtual bool matches( TestCaseInfo const& testCase ) const {
3626 return m_wildcardPattern.matches( toLower( testCase.name ) );
3627 }
3628 private:
3629 WildcardPattern m_wildcardPattern;
3630 };
3631
3632 class TagPattern : public Pattern {
3633 public:
3634 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3635 virtual ~TagPattern();
3636 virtual bool matches( TestCaseInfo const& testCase ) const {
3637 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
3638 }
3639 private:
3640 std::string m_tag;
3641 };
3642
3643 class ExcludedPattern : public Pattern {
3644 public:
3645 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3646 virtual ~ExcludedPattern();
3647 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3648 private:
3649 Ptr<Pattern> m_underlyingPattern;
3650 };
3651
3652 struct Filter {
3653 std::vector<Ptr<Pattern> > m_patterns;
3654
3655 bool matches( TestCaseInfo const& testCase ) const {
3656 // All patterns in a filter must match for the filter to be a match
3657 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
3658 if( !(*it)->matches( testCase ) )
3659 return false;
3660 }
3661 return true;
3662 }
3663 };
3664
3665 public:
3666 bool hasFilters() const {
3667 return !m_filters.empty();
3668 }
3669 bool matches( TestCaseInfo const& testCase ) const {
3670 // A TestSpec matches if any filter matches
3671 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3672 if( it->matches( testCase ) )
3673 return true;
3674 return false;
3675 }
3676
3677 private:
3678 std::vector<Filter> m_filters;
3679
3680 friend class TestSpecParser;
3681 };
3682}
3683
3684#ifdef __clang__
3685#pragma clang diagnostic pop
3686#endif
3687
3688namespace Catch {
3689
3690 class TestSpecParser {
3691 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
3692 Mode m_mode;
3693 bool m_exclusion;
3694 std::size_t m_start, m_pos;
3695 std::string m_arg;
3696 std::vector<std::size_t> m_escapeChars;
3697 TestSpec::Filter m_currentFilter;
3698 TestSpec m_testSpec;
3699 ITagAliasRegistry const* m_tagAliases;
3700
3701 public:
3702 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
3703
3704 TestSpecParser& parse( std::string const& arg ) {
3705 m_mode = None;
3706 m_exclusion = false;
3707 m_start = std::string::npos;
3708 m_arg = m_tagAliases->expandAliases( arg );
3709 m_escapeChars.clear();
3710 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3711 visitChar( m_arg[m_pos] );
3712 if( m_mode == Name )
3713 addPattern<TestSpec::NamePattern>();
3714 return *this;
3715 }
3716 TestSpec testSpec() {
3717 addFilter();
3718 return m_testSpec;
3719 }
3720 private:
3721 void visitChar( char c ) {
3722 if( m_mode == None ) {
3723 switch( c ) {
3724 case ' ': return;
3725 case '~': m_exclusion = true; return;
3726 case '[': return startNewMode( Tag, ++m_pos );
3727 case '"': return startNewMode( QuotedName, ++m_pos );
3728 case '\\': return escape();
3729 default: startNewMode( Name, m_pos ); break;
3730 }
3731 }
3732 if( m_mode == Name ) {
3733 if( c == ',' ) {
3734 addPattern<TestSpec::NamePattern>();
3735 addFilter();
3736 }
3737 else if( c == '[' ) {
3738 if( subString() == "exclude:" )
3739 m_exclusion = true;
3740 else
3741 addPattern<TestSpec::NamePattern>();
3742 startNewMode( Tag, ++m_pos );
3743 }
3744 else if( c == '\\' )
3745 escape();
3746 }
3747 else if( m_mode == EscapedName )
3748 m_mode = Name;
3749 else if( m_mode == QuotedName && c == '"' )
3750 addPattern<TestSpec::NamePattern>();
3751 else if( m_mode == Tag && c == ']' )
3752 addPattern<TestSpec::TagPattern>();
3753 }
3754 void startNewMode( Mode mode, std::size_t start ) {
3755 m_mode = mode;
3756 m_start = start;
3757 }
3758 void escape() {
3759 if( m_mode == None )
3760 m_start = m_pos;
3761 m_mode = EscapedName;
3762 m_escapeChars.push_back( m_pos );
3763 }
3764 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3765 template<typename T>
3766 void addPattern() {
3767 std::string token = subString();
3768 for( size_t i = 0; i < m_escapeChars.size(); ++i )
3769 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
3770 m_escapeChars.clear();
3771 if( startsWith( token, "exclude:" ) ) {
3772 m_exclusion = true;
3773 token = token.substr( 8 );
3774 }
3775 if( !token.empty() ) {
3776 Ptr<TestSpec::Pattern> pattern = new T( token );
3777 if( m_exclusion )
3778 pattern = new TestSpec::ExcludedPattern( pattern );
3779 m_currentFilter.m_patterns.push_back( pattern );
3780 }
3781 m_exclusion = false;
3782 m_mode = None;
3783 }
3784 void addFilter() {
3785 if( !m_currentFilter.m_patterns.empty() ) {
3786 m_testSpec.m_filters.push_back( m_currentFilter );
3787 m_currentFilter = TestSpec::Filter();
3788 }
3789 }
3790 };
3791 inline TestSpec parseTestSpec( std::string const& arg ) {
3792 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
3793 }
3794
3795} // namespace Catch
3796
3797#ifdef __clang__
3798#pragma clang diagnostic pop
3799#endif
3800
3801// #included from: catch_interfaces_config.h
3802#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3803
3804#include <iosfwd>
3805#include <string>
3806#include <vector>
3807
3808namespace Catch {
3809
3810 struct Verbosity { enum Level {
3811 NoOutput = 0,
3812 Quiet,
3813 Normal
3814 }; };
3815
3816 struct WarnAbout { enum What {
3817 Nothing = 0x00,
3818 NoAssertions = 0x01
3819 }; };
3820
3821 struct ShowDurations { enum OrNot {
3822 DefaultForReporter,
3823 Always,
3824 Never
3825 }; };
3826 struct RunTests { enum InWhatOrder {
3827 InDeclarationOrder,
3828 InLexicographicalOrder,
3829 InRandomOrder
3830 }; };
3831 struct UseColour { enum YesOrNo {
3832 Auto,
3833 Yes,
3834 No
3835 }; };
3836
3837 class TestSpec;
3838
3839 struct IConfig : IShared {
3840
3841 virtual ~IConfig();
3842
3843 virtual bool allowThrows() const = 0;
3844 virtual std::ostream& stream() const = 0;
3845 virtual std::string name() const = 0;
3846 virtual bool includeSuccessfulResults() const = 0;
3847 virtual bool shouldDebugBreak() const = 0;
3848 virtual bool warnAboutMissingAssertions() const = 0;
3849 virtual int abortAfter() const = 0;
3850 virtual bool showInvisibles() const = 0;
3851 virtual ShowDurations::OrNot showDurations() const = 0;
3852 virtual TestSpec const& testSpec() const = 0;
3853 virtual RunTests::InWhatOrder runOrder() const = 0;
3854 virtual unsigned int rngSeed() const = 0;
3855 virtual UseColour::YesOrNo useColour() const = 0;
3856 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
3857
3858 };
3859}
3860
3861// #included from: catch_stream.h
3862#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3863
3864// #included from: catch_streambuf.h
3865#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3866
3867#include <streambuf>
3868
3869namespace Catch {
3870
3871 class StreamBufBase : public std::streambuf {
3872 public:
3873 virtual ~StreamBufBase() CATCH_NOEXCEPT;
3874 };
3875}
3876
3877#include <streambuf>
3878#include <ostream>
3879#include <fstream>
3880#include <memory>
3881
3882namespace Catch {
3883
3884 std::ostream& cout();
3885 std::ostream& cerr();
3886
3887 struct IStream {
3888 virtual ~IStream() CATCH_NOEXCEPT;
3889 virtual std::ostream& stream() const = 0;
3890 };
3891
3892 class FileStream : public IStream {
3893 mutable std::ofstream m_ofs;
3894 public:
3895 FileStream( std::string const& filename );
3896 virtual ~FileStream() CATCH_NOEXCEPT;
3897 public: // IStream
3898 virtual std::ostream& stream() const CATCH_OVERRIDE;
3899 };
3900
3901 class CoutStream : public IStream {
3902 mutable std::ostream m_os;
3903 public:
3904 CoutStream();
3905 virtual ~CoutStream() CATCH_NOEXCEPT;
3906
3907 public: // IStream
3908 virtual std::ostream& stream() const CATCH_OVERRIDE;
3909 };
3910
3911 class DebugOutStream : public IStream {
3912 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
3913 mutable std::ostream m_os;
3914 public:
3915 DebugOutStream();
3916 virtual ~DebugOutStream() CATCH_NOEXCEPT;
3917
3918 public: // IStream
3919 virtual std::ostream& stream() const CATCH_OVERRIDE;
3920 };
3921}
3922
3923#include <memory>
3924#include <vector>
3925#include <string>
3926#include <stdexcept>
3927
3928#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3929#define CATCH_CONFIG_CONSOLE_WIDTH 80
3930#endif
3931
3932namespace Catch {
3933
3934 struct ConfigData {
3935
3936 ConfigData()
3937 : listTests( false ),
3938 listTags( false ),
3939 listReporters( false ),
3940 listTestNamesOnly( false ),
3941 showSuccessfulTests( false ),
3942 shouldDebugBreak( false ),
3943 noThrow( false ),
3944 showHelp( false ),
3945 showInvisibles( false ),
3946 filenamesAsTags( false ),
3947 abortAfter( -1 ),
3948 rngSeed( 0 ),
3949 verbosity( Verbosity::Normal ),
3950 warnings( WarnAbout::Nothing ),
3951 showDurations( ShowDurations::DefaultForReporter ),
3952 runOrder( RunTests::InDeclarationOrder ),
3953 useColour( UseColour::Auto )
3954 {}
3955
3956 bool listTests;
3957 bool listTags;
3958 bool listReporters;
3959 bool listTestNamesOnly;
3960
3961 bool showSuccessfulTests;
3962 bool shouldDebugBreak;
3963 bool noThrow;
3964 bool showHelp;
3965 bool showInvisibles;
3966 bool filenamesAsTags;
3967
3968 int abortAfter;
3969 unsigned int rngSeed;
3970
3971 Verbosity::Level verbosity;
3972 WarnAbout::What warnings;
3973 ShowDurations::OrNot showDurations;
3974 RunTests::InWhatOrder runOrder;
3975 UseColour::YesOrNo useColour;
3976
3977 std::string outputFilename;
3978 std::string name;
3979 std::string processName;
3980
3981 std::vector<std::string> reporterNames;
3982 std::vector<std::string> testsOrTags;
3983 std::vector<std::string> sectionsToRun;
3984 };
3985
3986 class Config : public SharedImpl<IConfig> {
3987 private:
3988 Config( Config const& other );
3989 Config& operator = ( Config const& other );
3990 virtual void dummy();
3991 public:
3992
3993 Config()
3994 {}
3995
3996 Config( ConfigData const& data )
3997 : m_data( data ),
3998 m_stream( openStream() )
3999 {
4000 if( !data.testsOrTags.empty() ) {
4001 TestSpecParser parser( ITagAliasRegistry::get() );
4002 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
4003 parser.parse( data.testsOrTags[i] );
4004 m_testSpec = parser.testSpec();
4005 }
4006 }
4007
4008 virtual ~Config() {}
4009
4010 std::string const& getFilename() const {
4011 return m_data.outputFilename ;
4012 }
4013
4014 bool listTests() const { return m_data.listTests; }
4015 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
4016 bool listTags() const { return m_data.listTags; }
4017 bool listReporters() const { return m_data.listReporters; }
4018
4019 std::string getProcessName() const { return m_data.processName; }
4020
4021 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
4022 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
4023
4024 virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
4025
4026 bool showHelp() const { return m_data.showHelp; }
4027
4028 // IConfig interface
4029 virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; }
4030 virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); }
4031 virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; }
4032 virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; }
4033 virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; }
4034 virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; }
4035 virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; }
4036 virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; }
4037 virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; }
4038 virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; }
4039 virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; }
4040 virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; }
4041
4042 private:
4043
4044 IStream const* openStream() {
4045 if( m_data.outputFilename.empty() )
4046 return new CoutStream();
4047 else if( m_data.outputFilename[0] == '%' ) {
4048 if( m_data.outputFilename == "%debug" )
4049 return new DebugOutStream();
4050 else
4051 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
4052 }
4053 else
4054 return new FileStream( m_data.outputFilename );
4055 }
4056 ConfigData m_data;
4057
4058 CATCH_AUTO_PTR( IStream const ) m_stream;
4059 TestSpec m_testSpec;
4060 };
4061
4062} // end namespace Catch
4063
4064// #included from: catch_clara.h
4065#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
4066
4067// Use Catch's value for console width (store Clara's off to the side, if present)
4068#ifdef CLARA_CONFIG_CONSOLE_WIDTH
4069#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
4070#undef CLARA_CONFIG_CONSOLE_WIDTH
4071#endif
4072#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4073
4074// Declare Clara inside the Catch namespace
4075#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
4076// #included from: ../external/clara.h
4077
4078// Version 0.0.2.4
4079
4080// Only use header guard if we are not using an outer namespace
4081#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
4082
4083#ifndef STITCH_CLARA_OPEN_NAMESPACE
4084#define TWOBLUECUBES_CLARA_H_INCLUDED
4085#define STITCH_CLARA_OPEN_NAMESPACE
4086#define STITCH_CLARA_CLOSE_NAMESPACE
4087#else
4088#define STITCH_CLARA_CLOSE_NAMESPACE }
4089#endif
4090
4091#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
4092
4093// ----------- #included from tbc_text_format.h -----------
4094
4095// Only use header guard if we are not using an outer namespace
4096#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
4097#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4098#define TBC_TEXT_FORMAT_H_INCLUDED
4099#endif
4100
4101#include <string>
4102#include <vector>
4103#include <sstream>
4104#include <algorithm>
4105#include <cctype>
4106
4107// Use optional outer namespace
4108#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4109namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4110#endif
4111
4112namespace Tbc {
4113
4114#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4115 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4116#else
4117 const unsigned int consoleWidth = 80;
4118#endif
4119
4120 struct TextAttributes {
4121 TextAttributes()
4122 : initialIndent( std::string::npos ),
4123 indent( 0 ),
4124 width( consoleWidth-1 ),
4125 tabChar( '\t' )
4126 {}
4127
4128 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
4129 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
4130 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
4131 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4132
4133 std::size_t initialIndent; // indent of first line, or npos
4134 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4135 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4136 char tabChar; // If this char is seen the indent is changed to current pos
4137 };
4138
4139 class Text {
4140 public:
4141 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4142 : attr( _attr )
4143 {
4144 std::string wrappableChars = " [({.,/|\\-";
4145 std::size_t indent = _attr.initialIndent != std::string::npos
4146 ? _attr.initialIndent
4147 : _attr.indent;
4148 std::string remainder = _str;
4149
4150 while( !remainder.empty() ) {
4151 if( lines.size() >= 1000 ) {
4152 lines.push_back( "... message truncated due to excessive size" );
4153 return;
4154 }
4155 std::size_t tabPos = std::string::npos;
4156 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4157 std::size_t pos = remainder.find_first_of( '\n' );
4158 if( pos <= width ) {
4159 width = pos;
4160 }
4161 pos = remainder.find_last_of( _attr.tabChar, width );
4162 if( pos != std::string::npos ) {
4163 tabPos = pos;
4164 if( remainder[width] == '\n' )
4165 width--;
4166 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4167 }
4168
4169 if( width == remainder.size() ) {
4170 spliceLine( indent, remainder, width );
4171 }
4172 else if( remainder[width] == '\n' ) {
4173 spliceLine( indent, remainder, width );
4174 if( width <= 1 || remainder.size() != 1 )
4175 remainder = remainder.substr( 1 );
4176 indent = _attr.indent;
4177 }
4178 else {
4179 pos = remainder.find_last_of( wrappableChars, width );
4180 if( pos != std::string::npos && pos > 0 ) {
4181 spliceLine( indent, remainder, pos );
4182 if( remainder[0] == ' ' )
4183 remainder = remainder.substr( 1 );
4184 }
4185 else {
4186 spliceLine( indent, remainder, width-1 );
4187 lines.back() += "-";
4188 }
4189 if( lines.size() == 1 )
4190 indent = _attr.indent;
4191 if( tabPos != std::string::npos )
4192 indent += tabPos;
4193 }
4194 }
4195 }
4196
4197 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4198 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4199 _remainder = _remainder.substr( _pos );
4200 }
4201
4202 typedef std::vector<std::string>::const_iterator const_iterator;
4203
4204 const_iterator begin() const { return lines.begin(); }
4205 const_iterator end() const { return lines.end(); }
4206 std::string const& last() const { return lines.back(); }
4207 std::size_t size() const { return lines.size(); }
4208 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
4209 std::string toString() const {
4210 std::ostringstream oss;
4211 oss << *this;
4212 return oss.str();
4213 }
4214
4215 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4216 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4217 it != itEnd; ++it ) {
4218 if( it != _text.begin() )
4219 _stream << "\n";
4220 _stream << *it;
4221 }
4222 return _stream;
4223 }
4224
4225 private:
4226 std::string str;
4227 TextAttributes attr;
4228 std::vector<std::string> lines;
4229 };
4230
4231} // end namespace Tbc
4232
4233#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4234} // end outer namespace
4235#endif
4236
4237#endif // TBC_TEXT_FORMAT_H_INCLUDED
4238
4239// ----------- end of #include from tbc_text_format.h -----------
4240// ........... back in clara.h
4241
4242#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
4243
4244// ----------- #included from clara_compilers.h -----------
4245
4246#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4247#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4248
4249// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
4250// The following features are defined:
4251//
4252// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
4253// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
4254// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
4255// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
4256// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
4257
4258// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
4259
4260// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
4261
4262// In general each macro has a _NO_<feature name> form
4263// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
4264// Many features, at point of detection, define an _INTERNAL_ macro, so they
4265// can be combined, en-mass, with the _NO_ forms later.
4266
4267// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
4268
4269#ifdef __clang__
4270
4271#if __has_feature(cxx_nullptr)
4272#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4273#endif
4274
4275#if __has_feature(cxx_noexcept)
4276#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4277#endif
4278
4279#endif // __clang__
4280
4281////////////////////////////////////////////////////////////////////////////////
4282// GCC
4283#ifdef __GNUC__
4284
4285#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
4286#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4287#endif
4288
4289// - otherwise more recent versions define __cplusplus >= 201103L
4290// and will get picked up below
4291
4292#endif // __GNUC__
4293
4294////////////////////////////////////////////////////////////////////////////////
4295// Visual C++
4296#ifdef _MSC_VER
4297
4298#if (_MSC_VER >= 1600)
4299#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4300#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4301#endif
4302
4303#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
4304#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4305#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4306#endif
4307
4308#endif // _MSC_VER
4309
4310////////////////////////////////////////////////////////////////////////////////
4311// C++ language feature support
4312
4313// catch all support for C++11
4314#if defined(__cplusplus) && __cplusplus >= 201103L
4315
4316#define CLARA_CPP11_OR_GREATER
4317
4318#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
4319#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4320#endif
4321
4322#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4323#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4324#endif
4325
4326#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4327#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4328#endif
4329
4330#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
4331#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
4332#endif
4333#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
4334#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4335#endif
4336
4337#endif // __cplusplus >= 201103L
4338
4339// Now set the actual defines based on the above + anything the user has configured
4340#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
4341#define CLARA_CONFIG_CPP11_NULLPTR
4342#endif
4343#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
4344#define CLARA_CONFIG_CPP11_NOEXCEPT
4345#endif
4346#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
4347#define CLARA_CONFIG_CPP11_GENERATED_METHODS
4348#endif
4349#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
4350#define CLARA_CONFIG_CPP11_OVERRIDE
4351#endif
4352#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
4353#define CLARA_CONFIG_CPP11_UNIQUE_PTR
4354#endif
4355
4356// noexcept support:
4357#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
4358#define CLARA_NOEXCEPT noexcept
4359# define CLARA_NOEXCEPT_IS(x) noexcept(x)
4360#else
4361#define CLARA_NOEXCEPT throw()
4362# define CLARA_NOEXCEPT_IS(x)
4363#endif
4364
4365// nullptr support
4366#ifdef CLARA_CONFIG_CPP11_NULLPTR
4367#define CLARA_NULL nullptr
4368#else
4369#define CLARA_NULL NULL
4370#endif
4371
4372// override support
4373#ifdef CLARA_CONFIG_CPP11_OVERRIDE
4374#define CLARA_OVERRIDE override
4375#else
4376#define CLARA_OVERRIDE
4377#endif
4378
4379// unique_ptr support
4380#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
4381# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
4382#else
4383# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
4384#endif
4385
4386#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4387
4388// ----------- end of #include from clara_compilers.h -----------
4389// ........... back in clara.h
4390
4391#include <map>
4392#include <stdexcept>
4393#include <memory>
4394
4395#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
4396#define CLARA_PLATFORM_WINDOWS
4397#endif
4398
4399// Use optional outer namespace
4400#ifdef STITCH_CLARA_OPEN_NAMESPACE
4401STITCH_CLARA_OPEN_NAMESPACE
4402#endif
4403
4404namespace Clara {
4405
4406 struct UnpositionalTag {};
4407
4408 extern UnpositionalTag _;
4409
4410#ifdef CLARA_CONFIG_MAIN
4411 UnpositionalTag _;
4412#endif
4413
4414 namespace Detail {
4415
4416#ifdef CLARA_CONSOLE_WIDTH
4417 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
4418#else
4419 const unsigned int consoleWidth = 80;
4420#endif
4421
4422 using namespace Tbc;
4423
4424 inline bool startsWith( std::string const& str, std::string const& prefix ) {
4425 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
4426 }
4427
4428 template<typename T> struct RemoveConstRef{ typedef T type; };
4429 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
4430 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
4431 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
4432
4433 template<typename T> struct IsBool { static const bool value = false; };
4434 template<> struct IsBool<bool> { static const bool value = true; };
4435
4436 template<typename T>
4437 void convertInto( std::string const& _source, T& _dest ) {
4438 std::stringstream ss;
4439 ss << _source;
4440 ss >> _dest;
4441 if( ss.fail() )
4442 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
4443 }
4444 inline void convertInto( std::string const& _source, std::string& _dest ) {
4445 _dest = _source;
4446 }
4447 char toLowerCh(char c) {
4448 return static_cast<char>( std::tolower( c ) );
4449 }
4450 inline void convertInto( std::string const& _source, bool& _dest ) {
4451 std::string sourceLC = _source;
4452 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
4453 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
4454 _dest = true;
4455 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
4456 _dest = false;
4457 else
4458 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
4459 }
4460
4461 template<typename ConfigT>
4462 struct IArgFunction {
4463 virtual ~IArgFunction() {}
4464#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
4465 IArgFunction() = default;
4466 IArgFunction( IArgFunction const& ) = default;
4467#endif
4468 virtual void set( ConfigT& config, std::string const& value ) const = 0;
4469 virtual bool takesArg() const = 0;
4470 virtual IArgFunction* clone() const = 0;
4471 };
4472
4473 template<typename ConfigT>
4474 class BoundArgFunction {
4475 public:
4476 BoundArgFunction() : functionObj( CLARA_NULL ) {}
4477 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
4478 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
4479 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
4480 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
4481 delete functionObj;
4482 functionObj = newFunctionObj;
4483 return *this;
4484 }
4485 ~BoundArgFunction() { delete functionObj; }
4486
4487 void set( ConfigT& config, std::string const& value ) const {
4488 functionObj->set( config, value );
4489 }
4490 bool takesArg() const { return functionObj->takesArg(); }
4491
4492 bool isSet() const {
4493 return functionObj != CLARA_NULL;
4494 }
4495 private:
4496 IArgFunction<ConfigT>* functionObj;
4497 };
4498
4499 template<typename C>
4500 struct NullBinder : IArgFunction<C>{
4501 virtual void set( C&, std::string const& ) const {}
4502 virtual bool takesArg() const { return true; }
4503 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4504 };
4505
4506 template<typename C, typename M>
4507 struct BoundDataMember : IArgFunction<C>{
4508 BoundDataMember( M C::* _member ) : member( _member ) {}
4509 virtual void set( C& p, std::string const& stringValue ) const {
4510 convertInto( stringValue, p.*member );
4511 }
4512 virtual bool takesArg() const { return !IsBool<M>::value; }
4513 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4514 M C::* member;
4515 };
4516 template<typename C, typename M>
4517 struct BoundUnaryMethod : IArgFunction<C>{
4518 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
4519 virtual void set( C& p, std::string const& stringValue ) const {
4520 typename RemoveConstRef<M>::type value;
4521 convertInto( stringValue, value );
4522 (p.*member)( value );
4523 }
4524 virtual bool takesArg() const { return !IsBool<M>::value; }
4525 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4526 void (C::*member)( M );
4527 };
4528 template<typename C>
4529 struct BoundNullaryMethod : IArgFunction<C>{
4530 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
4531 virtual void set( C& p, std::string const& stringValue ) const {
4532 bool value;
4533 convertInto( stringValue, value );
4534 if( value )
4535 (p.*member)();
4536 }
4537 virtual bool takesArg() const { return false; }
4538 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4539 void (C::*member)();
4540 };
4541
4542 template<typename C>
4543 struct BoundUnaryFunction : IArgFunction<C>{
4544 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
4545 virtual void set( C& obj, std::string const& stringValue ) const {
4546 bool value;
4547 convertInto( stringValue, value );
4548 if( value )
4549 function( obj );
4550 }
4551 virtual bool takesArg() const { return false; }
4552 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4553 void (*function)( C& );
4554 };
4555
4556 template<typename C, typename T>
4557 struct BoundBinaryFunction : IArgFunction<C>{
4558 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
4559 virtual void set( C& obj, std::string const& stringValue ) const {
4560 typename RemoveConstRef<T>::type value;
4561 convertInto( stringValue, value );
4562 function( obj, value );
4563 }
4564 virtual bool takesArg() const { return !IsBool<T>::value; }
4565 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4566 void (*function)( C&, T );
4567 };
4568
4569 } // namespace Detail
4570
4571 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
4572 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
4573 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4574 args[i] = argv[i];
4575
4576 return args;
4577 }
4578
4579 class Parser {
4580 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4581 Mode mode;
4582 std::size_t from;
4583 bool inQuotes;
4584 public:
4585
4586 struct Token {
4587 enum Type { Positional, ShortOpt, LongOpt };
4588 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4589 Type type;
4590 std::string data;
4591 };
4592
4593 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
4594
4595 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
4596 const std::string doubleDash = "--";
4597 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4598 parseIntoTokens( args[i], tokens);
4599 }
4600
4601 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
4602 for( std::size_t i = 0; i < arg.size(); ++i ) {
4603 char c = arg[i];
4604 if( c == '"' )
4605 inQuotes = !inQuotes;
4606 mode = handleMode( i, c, arg, tokens );
4607 }
4608 mode = handleMode( arg.size(), '\0', arg, tokens );
4609 }
4610 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4611 switch( mode ) {
4612 case None: return handleNone( i, c );
4613 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
4614 case ShortOpt:
4615 case LongOpt:
4616 case SlashOpt: return handleOpt( i, c, arg, tokens );
4617 case Positional: return handlePositional( i, c, arg, tokens );
4618 default: throw std::logic_error( "Unknown mode" );
4619 }
4620 }
4621
4622 Mode handleNone( std::size_t i, char c ) {
4623 if( inQuotes ) {
4624 from = i;
4625 return Positional;
4626 }
4627 switch( c ) {
4628 case '-': return MaybeShortOpt;
4629#ifdef CLARA_PLATFORM_WINDOWS
4630 case '/': from = i+1; return SlashOpt;
4631#endif
4632 default: from = i; return Positional;
4633 }
4634 }
4635 Mode handleMaybeShortOpt( std::size_t i, char c ) {
4636 switch( c ) {
4637 case '-': from = i+1; return LongOpt;
4638 default: from = i; return ShortOpt;
4639 }
4640 }
4641
4642 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4643 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
4644 return mode;
4645
4646 std::string optName = arg.substr( from, i-from );
4647 if( mode == ShortOpt )
4648 for( std::size_t j = 0; j < optName.size(); ++j )
4649 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
4650 else if( mode == SlashOpt && optName.size() == 1 )
4651 tokens.push_back( Token( Token::ShortOpt, optName ) );
4652 else
4653 tokens.push_back( Token( Token::LongOpt, optName ) );
4654 return None;
4655 }
4656 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4657 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
4658 return mode;
4659
4660 std::string data = arg.substr( from, i-from );
4661 tokens.push_back( Token( Token::Positional, data ) );
4662 return None;
4663 }
4664 };
4665
4666 template<typename ConfigT>
4667 struct CommonArgProperties {
4668 CommonArgProperties() {}
4669 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4670
4671 Detail::BoundArgFunction<ConfigT> boundField;
4672 std::string description;
4673 std::string detail;
4674 std::string placeholder; // Only value if boundField takes an arg
4675
4676 bool takesArg() const {
4677 return !placeholder.empty();
4678 }
4679 void validate() const {
4680 if( !boundField.isSet() )
4681 throw std::logic_error( "option not bound" );
4682 }
4683 };
4684 struct OptionArgProperties {
4685 std::vector<std::string> shortNames;
4686 std::string longName;
4687
4688 bool hasShortName( std::string const& shortName ) const {
4689 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4690 }
4691 bool hasLongName( std::string const& _longName ) const {
4692 return _longName == longName;
4693 }
4694 };
4695 struct PositionalArgProperties {
4696 PositionalArgProperties() : position( -1 ) {}
4697 int position; // -1 means non-positional (floating)
4698
4699 bool isFixedPositional() const {
4700 return position != -1;
4701 }
4702 };
4703
4704 template<typename ConfigT>
4705 class CommandLine {
4706
4707 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4708 Arg() {}
4709 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
4710
4711 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4712
4713 std::string dbgName() const {
4714 if( !longName.empty() )
4715 return "--" + longName;
4716 if( !shortNames.empty() )
4717 return "-" + shortNames[0];
4718 return "positional args";
4719 }
4720 std::string commands() const {
4721 std::ostringstream oss;
4722 bool first = true;
4723 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4724 for(; it != itEnd; ++it ) {
4725 if( first )
4726 first = false;
4727 else
4728 oss << ", ";
4729 oss << "-" << *it;
4730 }
4731 if( !longName.empty() ) {
4732 if( !first )
4733 oss << ", ";
4734 oss << "--" << longName;
4735 }
4736 if( !placeholder.empty() )
4737 oss << " <" << placeholder << ">";
4738 return oss.str();
4739 }
4740 };
4741
4742 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
4743
4744 friend void addOptName( Arg& arg, std::string const& optName )
4745 {
4746 if( optName.empty() )
4747 return;
4748 if( Detail::startsWith( optName, "--" ) ) {
4749 if( !arg.longName.empty() )
4750 throw std::logic_error( "Only one long opt may be specified. '"
4751 + arg.longName
4752 + "' already specified, now attempting to add '"
4753 + optName + "'" );
4754 arg.longName = optName.substr( 2 );
4755 }
4756 else if( Detail::startsWith( optName, "-" ) )
4757 arg.shortNames.push_back( optName.substr( 1 ) );
4758 else
4759 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4760 }
4761 friend void setPositionalArg( Arg& arg, int position )
4762 {
4763 arg.position = position;
4764 }
4765
4766 class ArgBuilder {
4767 public:
4768 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
4769
4770 // Bind a non-boolean data member (requires placeholder string)
4771 template<typename C, typename M>
4772 void bind( M C::* field, std::string const& placeholder ) {
4773 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4774 m_arg->placeholder = placeholder;
4775 }
4776 // Bind a boolean data member (no placeholder required)
4777 template<typename C>
4778 void bind( bool C::* field ) {
4779 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
4780 }
4781
4782 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4783 template<typename C, typename M>
4784 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4785 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4786 m_arg->placeholder = placeholder;
4787 }
4788
4789 // Bind a method taking a single, boolean argument (no placeholder string required)
4790 template<typename C>
4791 void bind( void (C::* unaryMethod)( bool ) ) {
4792 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
4793 }
4794
4795 // Bind a method that takes no arguments (will be called if opt is present)
4796 template<typename C>
4797 void bind( void (C::* nullaryMethod)() ) {
4798 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
4799 }
4800
4801 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4802 template<typename C>
4803 void bind( void (* unaryFunction)( C& ) ) {
4804 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
4805 }
4806
4807 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4808 template<typename C, typename T>
4809 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4810 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4811 m_arg->placeholder = placeholder;
4812 }
4813
4814 ArgBuilder& describe( std::string const& description ) {
4815 m_arg->description = description;
4816 return *this;
4817 }
4818 ArgBuilder& detail( std::string const& detail ) {
4819 m_arg->detail = detail;
4820 return *this;
4821 }
4822
4823 protected:
4824 Arg* m_arg;
4825 };
4826
4827 class OptBuilder : public ArgBuilder {
4828 public:
4829 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
4830 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4831
4832 OptBuilder& operator[]( std::string const& optName ) {
4833 addOptName( *ArgBuilder::m_arg, optName );
4834 return *this;
4835 }
4836 };
4837
4838 public:
4839
4840 CommandLine()
4841 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
4842 m_highestSpecifiedArgPosition( 0 ),
4843 m_throwOnUnrecognisedTokens( false )
4844 {}
4845 CommandLine( CommandLine const& other )
4846 : m_boundProcessName( other.m_boundProcessName ),
4847 m_options ( other.m_options ),
4848 m_positionalArgs( other.m_positionalArgs ),
4849 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4850 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
4851 {
4852 if( other.m_floatingArg.get() )
4853 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
4854 }
4855
4856 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4857 m_throwOnUnrecognisedTokens = shouldThrow;
4858 return *this;
4859 }
4860
4861 OptBuilder operator[]( std::string const& optName ) {
4862 m_options.push_back( Arg() );
4863 addOptName( m_options.back(), optName );
4864 OptBuilder builder( &m_options.back() );
4865 return builder;
4866 }
4867
4868 ArgBuilder operator[]( int position ) {
4869 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4870 if( position > m_highestSpecifiedArgPosition )
4871 m_highestSpecifiedArgPosition = position;
4872 setPositionalArg( m_positionalArgs[position], position );
4873 ArgBuilder builder( &m_positionalArgs[position] );
4874 return builder;
4875 }
4876
4877 // Invoke this with the _ instance
4878 ArgBuilder operator[]( UnpositionalTag ) {
4879 if( m_floatingArg.get() )
4880 throw std::logic_error( "Only one unpositional argument can be added" );
4881 m_floatingArg.reset( new Arg() );
4882 ArgBuilder builder( m_floatingArg.get() );
4883 return builder;
4884 }
4885
4886 template<typename C, typename M>
4887 void bindProcessName( M C::* field ) {
4888 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4889 }
4890 template<typename C, typename M>
4891 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4892 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
4893 }
4894
4895 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
4896 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4897 std::size_t maxWidth = 0;
4898 for( it = itBegin; it != itEnd; ++it )
4899 maxWidth = (std::max)( maxWidth, it->commands().size() );
4900
4901 for( it = itBegin; it != itEnd; ++it ) {
4902 Detail::Text usage( it->commands(), Detail::TextAttributes()
4903 .setWidth( maxWidth+indent )
4904 .setIndent( indent ) );
4905 Detail::Text desc( it->description, Detail::TextAttributes()
4906 .setWidth( width - maxWidth - 3 ) );
4907
4908 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4909 std::string usageCol = i < usage.size() ? usage[i] : "";
4910 os << usageCol;
4911
4912 if( i < desc.size() && !desc[i].empty() )
4913 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4914 << desc[i];
4915 os << "\n";
4916 }
4917 }
4918 }
4919 std::string optUsage() const {
4920 std::ostringstream oss;
4921 optUsage( oss );
4922 return oss.str();
4923 }
4924
4925 void argSynopsis( std::ostream& os ) const {
4926 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4927 if( i > 1 )
4928 os << " ";
4929 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4930 if( it != m_positionalArgs.end() )
4931 os << "<" << it->second.placeholder << ">";
4932 else if( m_floatingArg.get() )
4933 os << "<" << m_floatingArg->placeholder << ">";
4934 else
4935 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4936 }
4937 // !TBD No indication of mandatory args
4938 if( m_floatingArg.get() ) {
4939 if( m_highestSpecifiedArgPosition > 1 )
4940 os << " ";
4941 os << "[<" << m_floatingArg->placeholder << "> ...]";
4942 }
4943 }
4944 std::string argSynopsis() const {
4945 std::ostringstream oss;
4946 argSynopsis( oss );
4947 return oss.str();
4948 }
4949
4950 void usage( std::ostream& os, std::string const& procName ) const {
4951 validate();
4952 os << "usage:\n " << procName << " ";
4953 argSynopsis( os );
4954 if( !m_options.empty() ) {
4955 os << " [options]\n\nwhere options are: \n";
4956 optUsage( os, 2 );
4957 }
4958 os << "\n";
4959 }
4960 std::string usage( std::string const& procName ) const {
4961 std::ostringstream oss;
4962 usage( oss, procName );
4963 return oss.str();
4964 }
4965
4966 ConfigT parse( std::vector<std::string> const& args ) const {
4967 ConfigT config;
4968 parseInto( args, config );
4969 return config;
4970 }
4971
4972 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
4973 std::string processName = args.empty() ? std::string() : args[0];
4974 std::size_t lastSlash = processName.find_last_of( "/\\" );
4975 if( lastSlash != std::string::npos )
4976 processName = processName.substr( lastSlash+1 );
4977 m_boundProcessName.set( config, processName );
4978 std::vector<Parser::Token> tokens;
4979 Parser parser;
4980 parser.parseIntoTokens( args, tokens );
4981 return populate( tokens, config );
4982 }
4983
4984 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4985 validate();
4986 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4987 unusedTokens = populateFixedArgs( unusedTokens, config );
4988 unusedTokens = populateFloatingArgs( unusedTokens, config );
4989 return unusedTokens;
4990 }
4991
4992 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4993 std::vector<Parser::Token> unusedTokens;
4994 std::vector<std::string> errors;
4995 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4996 Parser::Token const& token = tokens[i];
4997 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4998 for(; it != itEnd; ++it ) {
4999 Arg const& arg = *it;
5000
5001 try {
5002 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
5003 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
5004 if( arg.takesArg() ) {
5005 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
5006 errors.push_back( "Expected argument to option: " + token.data );
5007 else
5008 arg.boundField.set( config, tokens[++i].data );
5009 }
5010 else {
5011 arg.boundField.set( config, "true" );
5012 }
5013 break;
5014 }
5015 }
5016 catch( std::exception& ex ) {
5017 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
5018 }
5019 }
5020 if( it == itEnd ) {
5021 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
5022 unusedTokens.push_back( token );
5023 else if( errors.empty() && m_throwOnUnrecognisedTokens )
5024 errors.push_back( "unrecognised option: " + token.data );
5025 }
5026 }
5027 if( !errors.empty() ) {
5028 std::ostringstream oss;
5029 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
5030 it != itEnd;
5031 ++it ) {
5032 if( it != errors.begin() )
5033 oss << "\n";
5034 oss << *it;
5035 }
5036 throw std::runtime_error( oss.str() );
5037 }
5038 return unusedTokens;
5039 }
5040 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5041 std::vector<Parser::Token> unusedTokens;
5042 int position = 1;
5043 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5044 Parser::Token const& token = tokens[i];
5045 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
5046 if( it != m_positionalArgs.end() )
5047 it->second.boundField.set( config, token.data );
5048 else
5049 unusedTokens.push_back( token );
5050 if( token.type == Parser::Token::Positional )
5051 position++;
5052 }
5053 return unusedTokens;
5054 }
5055 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5056 if( !m_floatingArg.get() )
5057 return tokens;
5058 std::vector<Parser::Token> unusedTokens;
5059 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5060 Parser::Token const& token = tokens[i];
5061 if( token.type == Parser::Token::Positional )
5062 m_floatingArg->boundField.set( config, token.data );
5063 else
5064 unusedTokens.push_back( token );
5065 }
5066 return unusedTokens;
5067 }
5068
5069 void validate() const
5070 {
5071 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
5072 throw std::logic_error( "No options or arguments specified" );
5073
5074 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
5075 itEnd = m_options.end();
5076 it != itEnd; ++it )
5077 it->validate();
5078 }
5079
5080 private:
5081 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
5082 std::vector<Arg> m_options;
5083 std::map<int, Arg> m_positionalArgs;
5084 ArgAutoPtr m_floatingArg;
5085 int m_highestSpecifiedArgPosition;
5086 bool m_throwOnUnrecognisedTokens;
5087 };
5088
5089} // end namespace Clara
5090
5091STITCH_CLARA_CLOSE_NAMESPACE
5092#undef STITCH_CLARA_OPEN_NAMESPACE
5093#undef STITCH_CLARA_CLOSE_NAMESPACE
5094
5095#endif // TWOBLUECUBES_CLARA_H_INCLUDED
5096#undef STITCH_CLARA_OPEN_NAMESPACE
5097
5098// Restore Clara's value for console width, if present
5099#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5100#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5101#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5102#endif
5103
5104#include <fstream>
5105#include <ctime>
5106
5107namespace Catch {
5108
5109 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
5110 inline void abortAfterX( ConfigData& config, int x ) {
5111 if( x < 1 )
5112 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
5113 config.abortAfter = x;
5114 }
5115 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
5116 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
5117 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
5118
5119 inline void addWarning( ConfigData& config, std::string const& _warning ) {
5120 if( _warning == "NoAssertions" )
5121 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
5122 else
5123 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
5124 }
5125 inline void setOrder( ConfigData& config, std::string const& order ) {
5126 if( startsWith( "declared", order ) )
5127 config.runOrder = RunTests::InDeclarationOrder;
5128 else if( startsWith( "lexical", order ) )
5129 config.runOrder = RunTests::InLexicographicalOrder;
5130 else if( startsWith( "random", order ) )
5131 config.runOrder = RunTests::InRandomOrder;
5132 else
5133 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
5134 }
5135 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
5136 if( seed == "time" ) {
5137 config.rngSeed = static_cast<unsigned int>( std::time(0) );
5138 }
5139 else {
5140 std::stringstream ss;
5141 ss << seed;
5142 ss >> config.rngSeed;
5143 if( ss.fail() )
5144 throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
5145 }
5146 }
5147 inline void setVerbosity( ConfigData& config, int level ) {
5148 // !TBD: accept strings?
5149 config.verbosity = static_cast<Verbosity::Level>( level );
5150 }
5151 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
5152 config.showDurations = _showDurations
5153 ? ShowDurations::Always
5154 : ShowDurations::Never;
5155 }
5156 inline void setUseColour( ConfigData& config, std::string const& value ) {
5157 std::string mode = toLower( value );
5158
5159 if( mode == "yes" )
5160 config.useColour = UseColour::Yes;
5161 else if( mode == "no" )
5162 config.useColour = UseColour::No;
5163 else if( mode == "auto" )
5164 config.useColour = UseColour::Auto;
5165 else
5166 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
5167 }
5168 inline void forceColour( ConfigData& config ) {
5169 config.useColour = UseColour::Yes;
5170 }
5171 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
5172 std::ifstream f( _filename.c_str() );
5173 if( !f.is_open() )
5174 throw std::domain_error( "Unable to load input file: " + _filename );
5175
5176 std::string line;
5177 while( std::getline( f, line ) ) {
5178 line = trim(line);
5179 if( !line.empty() && !startsWith( line, '#' ) ) {
5180 if( !startsWith( line, '"' ) )
5181 line = '"' + line + '"';
5182 addTestOrTags( config, line + ',' );
5183 }
5184 }
5185 }
5186
5187 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
5188
5189 using namespace Clara;
5190 CommandLine<ConfigData> cli;
5191
5192 cli.bindProcessName( &ConfigData::processName );
5193
5194 cli["-?"]["-h"]["--help"]
5195 .describe( "display usage information" )
5196 .bind( &ConfigData::showHelp );
5197
5198 cli["-l"]["--list-tests"]
5199 .describe( "list all/matching test cases" )
5200 .bind( &ConfigData::listTests );
5201
5202 cli["-t"]["--list-tags"]
5203 .describe( "list all/matching tags" )
5204 .bind( &ConfigData::listTags );
5205
5206 cli["-s"]["--success"]
5207 .describe( "include successful tests in output" )
5208 .bind( &ConfigData::showSuccessfulTests );
5209
5210 cli["-b"]["--break"]
5211 .describe( "break into debugger on failure" )
5212 .bind( &ConfigData::shouldDebugBreak );
5213
5214 cli["-e"]["--nothrow"]
5215 .describe( "skip exception tests" )
5216 .bind( &ConfigData::noThrow );
5217
5218 cli["-i"]["--invisibles"]
5219 .describe( "show invisibles (tabs, newlines)" )
5220 .bind( &ConfigData::showInvisibles );
5221
5222 cli["-o"]["--out"]
5223 .describe( "output filename" )
5224 .bind( &ConfigData::outputFilename, "filename" );
5225
5226 cli["-r"]["--reporter"]
5227// .placeholder( "name[:filename]" )
5228 .describe( "reporter to use (defaults to console)" )
5229 .bind( &addReporterName, "name" );
5230
5231 cli["-n"]["--name"]
5232 .describe( "suite name" )
5233 .bind( &ConfigData::name, "name" );
5234
5235 cli["-a"]["--abort"]
5236 .describe( "abort at first failure" )
5237 .bind( &abortAfterFirst );
5238
5239 cli["-x"]["--abortx"]
5240 .describe( "abort after x failures" )
5241 .bind( &abortAfterX, "no. failures" );
5242
5243 cli["-w"]["--warn"]
5244 .describe( "enable warnings" )
5245 .bind( &addWarning, "warning name" );
5246
5247// - needs updating if reinstated
5248// cli.into( &setVerbosity )
5249// .describe( "level of verbosity (0=no output)" )
5250// .shortOpt( "v")
5251// .longOpt( "verbosity" )
5252// .placeholder( "level" );
5253
5254 cli[_]
5255 .describe( "which test or tests to use" )
5256 .bind( &addTestOrTags, "test name, pattern or tags" );
5257
5258 cli["-d"]["--durations"]
5259 .describe( "show test durations" )
5260 .bind( &setShowDurations, "yes|no" );
5261
5262 cli["-f"]["--input-file"]
5263 .describe( "load test names to run from a file" )
5264 .bind( &loadTestNamesFromFile, "filename" );
5265
5266 cli["-#"]["--filenames-as-tags"]
5267 .describe( "adds a tag for the filename" )
5268 .bind( &ConfigData::filenamesAsTags );
5269
5270 cli["-c"]["--section"]
5271 .describe( "specify section to run" )
5272 .bind( &addSectionToRun, "section name" );
5273
5274 // Less common commands which don't have a short form
5275 cli["--list-test-names-only"]
5276 .describe( "list all/matching test cases names only" )
5277 .bind( &ConfigData::listTestNamesOnly );
5278
5279 cli["--list-reporters"]
5280 .describe( "list all reporters" )
5281 .bind( &ConfigData::listReporters );
5282
5283 cli["--order"]
5284 .describe( "test case order (defaults to decl)" )
5285 .bind( &setOrder, "decl|lex|rand" );
5286
5287 cli["--rng-seed"]
5288 .describe( "set a specific seed for random numbers" )
5289 .bind( &setRngSeed, "'time'|number" );
5290
5291 cli["--force-colour"]
5292 .describe( "force colourised output (deprecated)" )
5293 .bind( &forceColour );
5294
5295 cli["--use-colour"]
5296 .describe( "should output be colourised" )
5297 .bind( &setUseColour, "yes|no" );
5298
5299 return cli;
5300 }
5301
5302} // end namespace Catch
5303
5304// #included from: internal/catch_list.hpp
5305#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5306
5307// #included from: catch_text.h
5308#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
5309
5310#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
5311
5312#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
5313// #included from: ../external/tbc_text_format.h
5314// Only use header guard if we are not using an outer namespace
5315#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5316# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5317# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5318# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5319# endif
5320# else
5321# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5322# endif
5323#endif
5324#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5325#include <string>
5326#include <vector>
5327#include <sstream>
5328
5329// Use optional outer namespace
5330#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5331namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
5332#endif
5333
5334namespace Tbc {
5335
5336#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
5337 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
5338#else
5339 const unsigned int consoleWidth = 80;
5340#endif
5341
5342 struct TextAttributes {
5343 TextAttributes()
5344 : initialIndent( std::string::npos ),
5345 indent( 0 ),
5346 width( consoleWidth-1 )
5347 {}
5348
5349 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
5350 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
5351 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
5352
5353 std::size_t initialIndent; // indent of first line, or npos
5354 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
5355 std::size_t width; // maximum width of text, including indent. Longer text will wrap
5356 };
5357
5358 class Text {
5359 public:
5360 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
5361 : attr( _attr )
5362 {
5363 const std::string wrappableBeforeChars = "[({<\t";
5364 const std::string wrappableAfterChars = "])}>-,./|\\";
5365 const std::string wrappableInsteadOfChars = " \n\r";
5366 std::string indent = _attr.initialIndent != std::string::npos
5367 ? std::string( _attr.initialIndent, ' ' )
5368 : std::string( _attr.indent, ' ' );
5369
5370 typedef std::string::const_iterator iterator;
5371 iterator it = _str.begin();
5372 const iterator strEnd = _str.end();
5373
5374 while( it != strEnd ) {
5375
5376 if( lines.size() >= 1000 ) {
5377 lines.push_back( "... message truncated due to excessive size" );
5378 return;
5379 }
5380
5381 std::string suffix;
5382 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
5383 iterator itEnd = it+width;
5384 iterator itNext = _str.end();
5385
5386 iterator itNewLine = std::find( it, itEnd, '\n' );
5387 if( itNewLine != itEnd )
5388 itEnd = itNewLine;
5389
5390 if( itEnd != strEnd ) {
5391 bool foundWrapPoint = false;
5392 iterator findIt = itEnd;
5393 do {
5394 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
5395 itEnd = findIt+1;
5396 itNext = findIt+1;
5397 foundWrapPoint = true;
5398 }
5399 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
5400 itEnd = findIt;
5401 itNext = findIt;
5402 foundWrapPoint = true;
5403 }
5404 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
5405 itNext = findIt+1;
5406 itEnd = findIt;
5407 foundWrapPoint = true;
5408 }
5409 if( findIt == it )
5410 break;
5411 else
5412 --findIt;
5413 }
5414 while( !foundWrapPoint );
5415
5416 if( !foundWrapPoint ) {
5417 // No good wrap char, so we'll break mid word and add a hyphen
5418 --itEnd;
5419 itNext = itEnd;
5420 suffix = "-";
5421 }
5422 else {
5423 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
5424 --itEnd;
5425 }
5426 }
5427 lines.push_back( indent + std::string( it, itEnd ) + suffix );
5428
5429 if( indent.size() != _attr.indent )
5430 indent = std::string( _attr.indent, ' ' );
5431 it = itNext;
5432 }
5433 }
5434
5435 typedef std::vector<std::string>::const_iterator const_iterator;
5436
5437 const_iterator begin() const { return lines.begin(); }
5438 const_iterator end() const { return lines.end(); }
5439 std::string const& last() const { return lines.back(); }
5440 std::size_t size() const { return lines.size(); }
5441 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
5442 std::string toString() const {
5443 std::ostringstream oss;
5444 oss << *this;
5445 return oss.str();
5446 }
5447
5448 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
5449 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
5450 it != itEnd; ++it ) {
5451 if( it != _text.begin() )
5452 _stream << "\n";
5453 _stream << *it;
5454 }
5455 return _stream;
5456 }
5457
5458 private:
5459 std::string str;
5460 TextAttributes attr;
5461 std::vector<std::string> lines;
5462 };
5463
5464} // end namespace Tbc
5465
5466#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5467} // end outer namespace
5468#endif
5469
5470#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5471#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5472
5473namespace Catch {
5474 using Tbc::Text;
5475 using Tbc::TextAttributes;
5476}
5477
5478// #included from: catch_console_colour.hpp
5479#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
5480
5481namespace Catch {
5482
5483 struct Colour {
5484 enum Code {
5485 None = 0,
5486
5487 White,
5488 Red,
5489 Green,
5490 Blue,
5491 Cyan,
5492 Yellow,
5493 Grey,
5494
5495 Bright = 0x10,
5496
5497 BrightRed = Bright | Red,
5498 BrightGreen = Bright | Green,
5499 LightGrey = Bright | Grey,
5500 BrightWhite = Bright | White,
5501
5502 // By intention
5503 FileName = LightGrey,
5504 Warning = Yellow,
5505 ResultError = BrightRed,
5506 ResultSuccess = BrightGreen,
5507 ResultExpectedFailure = Warning,
5508
5509 Error = BrightRed,
5510 Success = Green,
5511
5512 OriginalExpression = Cyan,
5513 ReconstructedExpression = Yellow,
5514
5515 SecondaryText = LightGrey,
5516 Headers = White
5517 };
5518
5519 // Use constructed object for RAII guard
5520 Colour( Code _colourCode );
5521 Colour( Colour const& other );
5522 ~Colour();
5523
5524 // Use static method for one-shot changes
5525 static void use( Code _colourCode );
5526
5527 private:
5528 bool m_moved;
5529 };
5530
5531 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5532
5533} // end namespace Catch
5534
5535// #included from: catch_interfaces_reporter.h
5536#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5537
5538#include <string>
5539#include <ostream>
5540#include <map>
5541
5542namespace Catch
5543{
5544 struct ReporterConfig {
5545 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
5546 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5547
5548 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
5549 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5550
5551 std::ostream& stream() const { return *m_stream; }
5552 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
5553
5554 private:
5555 std::ostream* m_stream;
5556 Ptr<IConfig const> m_fullConfig;
5557 };
5558
5559 struct ReporterPreferences {
5560 ReporterPreferences()
5561 : shouldRedirectStdOut( false )
5562 {}
5563
5564 bool shouldRedirectStdOut;
5565 };
5566
5567 template<typename T>
5568 struct LazyStat : Option<T> {
5569 LazyStat() : used( false ) {}
5570 LazyStat& operator=( T const& _value ) {
5571 Option<T>::operator=( _value );
5572 used = false;
5573 return *this;
5574 }
5575 void reset() {
5576 Option<T>::reset();
5577 used = false;
5578 }
5579 bool used;
5580 };
5581
5582 struct TestRunInfo {
5583 TestRunInfo( std::string const& _name ) : name( _name ) {}
5584 std::string name;
5585 };
5586 struct GroupInfo {
5587 GroupInfo( std::string const& _name,
5588 std::size_t _groupIndex,
5589 std::size_t _groupsCount )
5590 : name( _name ),
5591 groupIndex( _groupIndex ),
5592 groupsCounts( _groupsCount )
5593 {}
5594
5595 std::string name;
5596 std::size_t groupIndex;
5597 std::size_t groupsCounts;
5598 };
5599
5600 struct AssertionStats {
5601 AssertionStats( AssertionResult const& _assertionResult,
5602 std::vector<MessageInfo> const& _infoMessages,
5603 Totals const& _totals )
5604 : assertionResult( _assertionResult ),
5605 infoMessages( _infoMessages ),
5606 totals( _totals )
5607 {
5608 if( assertionResult.hasMessage() ) {
5609 // Copy message into messages list.
5610 // !TBD This should have been done earlier, somewhere
5611 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5612 builder << assertionResult.getMessage();
5613 builder.m_info.message = builder.m_stream.str();
5614
5615 infoMessages.push_back( builder.m_info );
5616 }
5617 }
5618 virtual ~AssertionStats();
5619
5620# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5621 AssertionStats( AssertionStats const& ) = default;
5622 AssertionStats( AssertionStats && ) = default;
5623 AssertionStats& operator = ( AssertionStats const& ) = default;
5624 AssertionStats& operator = ( AssertionStats && ) = default;
5625# endif
5626
5627 AssertionResult assertionResult;
5628 std::vector<MessageInfo> infoMessages;
5629 Totals totals;
5630 };
5631
5632 struct SectionStats {
5633 SectionStats( SectionInfo const& _sectionInfo,
5634 Counts const& _assertions,
5635 double _durationInSeconds,
5636 bool _missingAssertions )
5637 : sectionInfo( _sectionInfo ),
5638 assertions( _assertions ),
5639 durationInSeconds( _durationInSeconds ),
5640 missingAssertions( _missingAssertions )
5641 {}
5642 virtual ~SectionStats();
5643# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5644 SectionStats( SectionStats const& ) = default;
5645 SectionStats( SectionStats && ) = default;
5646 SectionStats& operator = ( SectionStats const& ) = default;
5647 SectionStats& operator = ( SectionStats && ) = default;
5648# endif
5649
5650 SectionInfo sectionInfo;
5651 Counts assertions;
5652 double durationInSeconds;
5653 bool missingAssertions;
5654 };
5655
5656 struct TestCaseStats {
5657 TestCaseStats( TestCaseInfo const& _testInfo,
5658 Totals const& _totals,
5659 std::string const& _stdOut,
5660 std::string const& _stdErr,
5661 bool _aborting )
5662 : testInfo( _testInfo ),
5663 totals( _totals ),
5664 stdOut( _stdOut ),
5665 stdErr( _stdErr ),
5666 aborting( _aborting )
5667 {}
5668 virtual ~TestCaseStats();
5669
5670# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5671 TestCaseStats( TestCaseStats const& ) = default;
5672 TestCaseStats( TestCaseStats && ) = default;
5673 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5674 TestCaseStats& operator = ( TestCaseStats && ) = default;
5675# endif
5676
5677 TestCaseInfo testInfo;
5678 Totals totals;
5679 std::string stdOut;
5680 std::string stdErr;
5681 bool aborting;
5682 };
5683
5684 struct TestGroupStats {
5685 TestGroupStats( GroupInfo const& _groupInfo,
5686 Totals const& _totals,
5687 bool _aborting )
5688 : groupInfo( _groupInfo ),
5689 totals( _totals ),
5690 aborting( _aborting )
5691 {}
5692 TestGroupStats( GroupInfo const& _groupInfo )
5693 : groupInfo( _groupInfo ),
5694 aborting( false )
5695 {}
5696 virtual ~TestGroupStats();
5697
5698# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5699 TestGroupStats( TestGroupStats const& ) = default;
5700 TestGroupStats( TestGroupStats && ) = default;
5701 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5702 TestGroupStats& operator = ( TestGroupStats && ) = default;
5703# endif
5704
5705 GroupInfo groupInfo;
5706 Totals totals;
5707 bool aborting;
5708 };
5709
5710 struct TestRunStats {
5711 TestRunStats( TestRunInfo const& _runInfo,
5712 Totals const& _totals,
5713 bool _aborting )
5714 : runInfo( _runInfo ),
5715 totals( _totals ),
5716 aborting( _aborting )
5717 {}
5718 virtual ~TestRunStats();
5719
5720# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
5721 TestRunStats( TestRunStats const& _other )
5722 : runInfo( _other.runInfo ),
5723 totals( _other.totals ),
5724 aborting( _other.aborting )
5725 {}
5726# else
5727 TestRunStats( TestRunStats const& ) = default;
5728 TestRunStats( TestRunStats && ) = default;
5729 TestRunStats& operator = ( TestRunStats const& ) = default;
5730 TestRunStats& operator = ( TestRunStats && ) = default;
5731# endif
5732
5733 TestRunInfo runInfo;
5734 Totals totals;
5735 bool aborting;
5736 };
5737
5738 class MultipleReporters;
5739
5740 struct IStreamingReporter : IShared {
5741 virtual ~IStreamingReporter();
5742
5743 // Implementing class must also provide the following static method:
5744 // static std::string getDescription();
5745
5746 virtual ReporterPreferences getPreferences() const = 0;
5747
5748 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5749
5750 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5751 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5752
5753 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5754 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5755
5756 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5757
5758 // The return value indicates if the messages buffer should be cleared:
5759 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
5760
5761 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5762 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5763 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5764 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
5765
5766 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
5767
5768 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
5769 };
5770
5771 struct IReporterFactory : IShared {
5772 virtual ~IReporterFactory();
5773 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5774 virtual std::string getDescription() const = 0;
5775 };
5776
5777 struct IReporterRegistry {
5778 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5779 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5780
5781 virtual ~IReporterRegistry();
5782 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
5783 virtual FactoryMap const& getFactories() const = 0;
5784 virtual Listeners const& getListeners() const = 0;
5785 };
5786
5787 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5788
5789}
5790
5791#include <limits>
5792#include <algorithm>
5793
5794namespace Catch {
5795
5796 inline std::size_t listTests( Config const& config ) {
5797
5798 TestSpec testSpec = config.testSpec();
5799 if( config.testSpec().hasFilters() )
5800 Catch::cout() << "Matching test cases:\n";
5801 else {
5802 Catch::cout() << "All available test cases:\n";
5803 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5804 }
5805
5806 std::size_t matchedTests = 0;
5807 TextAttributes nameAttr, tagsAttr;
5808 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5809 tagsAttr.setIndent( 6 );
5810
5811 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5812 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5813 it != itEnd;
5814 ++it ) {
5815 matchedTests++;
5816 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5817 Colour::Code colour = testCaseInfo.isHidden()
5818 ? Colour::SecondaryText
5819 : Colour::None;
5820 Colour colourGuard( colour );
5821
5822 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
5823 if( !testCaseInfo.tags.empty() )
5824 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
5825 }
5826
5827 if( !config.testSpec().hasFilters() )
5828 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
5829 else
5830 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
5831 return matchedTests;
5832 }
5833
5834 inline std::size_t listTestsNamesOnly( Config const& config ) {
5835 TestSpec testSpec = config.testSpec();
5836 if( !config.testSpec().hasFilters() )
5837 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5838 std::size_t matchedTests = 0;
5839 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5840 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5841 it != itEnd;
5842 ++it ) {
5843 matchedTests++;
5844 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5845 if( startsWith( testCaseInfo.name, '#' ) )
5846 Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
5847 else
5848 Catch::cout() << testCaseInfo.name << std::endl;
5849 }
5850 return matchedTests;
5851 }
5852
5853 struct TagInfo {
5854 TagInfo() : count ( 0 ) {}
5855 void add( std::string const& spelling ) {
5856 ++count;
5857 spellings.insert( spelling );
5858 }
5859 std::string all() const {
5860 std::string out;
5861 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5862 it != itEnd;
5863 ++it )
5864 out += "[" + *it + "]";
5865 return out;
5866 }
5867 std::set<std::string> spellings;
5868 std::size_t count;
5869 };
5870
5871 inline std::size_t listTags( Config const& config ) {
5872 TestSpec testSpec = config.testSpec();
5873 if( config.testSpec().hasFilters() )
5874 Catch::cout() << "Tags for matching test cases:\n";
5875 else {
5876 Catch::cout() << "All available tags:\n";
5877 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5878 }
5879
5880 std::map<std::string, TagInfo> tagCounts;
5881
5882 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5883 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5884 it != itEnd;
5885 ++it ) {
5886 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5887 tagItEnd = it->getTestCaseInfo().tags.end();
5888 tagIt != tagItEnd;
5889 ++tagIt ) {
5890 std::string tagName = *tagIt;
5891 std::string lcaseTagName = toLower( tagName );
5892 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
5893 if( countIt == tagCounts.end() )
5894 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5895 countIt->second.add( tagName );
5896 }
5897 }
5898
5899 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5900 countItEnd = tagCounts.end();
5901 countIt != countItEnd;
5902 ++countIt ) {
5903 std::ostringstream oss;
5904 oss << " " << std::setw(2) << countIt->second.count << " ";
5905 Text wrapper( countIt->second.all(), TextAttributes()
5906 .setInitialIndent( 0 )
5907 .setIndent( oss.str().size() )
5908 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
5909 Catch::cout() << oss.str() << wrapper << '\n';
5910 }
5911 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
5912 return tagCounts.size();
5913 }
5914
5915 inline std::size_t listReporters( Config const& /*config*/ ) {
5916 Catch::cout() << "Available reporters:\n";
5917 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
5918 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5919 std::size_t maxNameLen = 0;
5920 for(it = itBegin; it != itEnd; ++it )
5921 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5922
5923 for(it = itBegin; it != itEnd; ++it ) {
5924 Text wrapper( it->second->getDescription(), TextAttributes()
5925 .setInitialIndent( 0 )
5926 .setIndent( 7+maxNameLen )
5927 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
5928 Catch::cout() << " "
5929 << it->first
5930 << ':'
5931 << std::string( maxNameLen - it->first.size() + 2, ' ' )
5932 << wrapper << '\n';
5933 }
5934 Catch::cout() << std::endl;
5935 return factories.size();
5936 }
5937
5938 inline Option<std::size_t> list( Config const& config ) {
5939 Option<std::size_t> listedCount;
5940 if( config.listTests() )
5941 listedCount = listedCount.valueOr(0) + listTests( config );
5942 if( config.listTestNamesOnly() )
5943 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
5944 if( config.listTags() )
5945 listedCount = listedCount.valueOr(0) + listTags( config );
5946 if( config.listReporters() )
5947 listedCount = listedCount.valueOr(0) + listReporters( config );
5948 return listedCount;
5949 }
5950
5951} // end namespace Catch
5952
5953// #included from: internal/catch_run_context.hpp
5954#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
5955
5956// #included from: catch_test_case_tracker.hpp
5957#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
5958
5959#include <algorithm>
5960#include <string>
5961#include <assert.h>
5962#include <vector>
5963#include <stdexcept>
5964
5965CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
5966
5967namespace Catch {
5968namespace TestCaseTracking {
5969
5970 struct NameAndLocation {
5971 std::string name;
5972 SourceLineInfo location;
5973
5974 NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
5975 : name( _name ),
5976 location( _location )
5977 {}
5978 };
5979
5980 struct ITracker : SharedImpl<> {
5981 virtual ~ITracker();
5982
5983 // static queries
5984 virtual NameAndLocation const& nameAndLocation() const = 0;
5985
5986 // dynamic queries
5987 virtual bool isComplete() const = 0; // Successfully completed or failed
5988 virtual bool isSuccessfullyCompleted() const = 0;
5989 virtual bool isOpen() const = 0; // Started but not complete
5990 virtual bool hasChildren() const = 0;
5991
5992 virtual ITracker& parent() = 0;
5993
5994 // actions
5995 virtual void close() = 0; // Successfully complete
5996 virtual void fail() = 0;
5997 virtual void markAsNeedingAnotherRun() = 0;
5998
5999 virtual void addChild( Ptr<ITracker> const& child ) = 0;
6000 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
6001 virtual void openChild() = 0;
6002
6003 // Debug/ checking
6004 virtual bool isSectionTracker() const = 0;
6005 virtual bool isIndexTracker() const = 0;
6006 };
6007
6008 class TrackerContext {
6009
6010 enum RunState {
6011 NotStarted,
6012 Executing,
6013 CompletedCycle
6014 };
6015
6016 Ptr<ITracker> m_rootTracker;
6017 ITracker* m_currentTracker;
6018 RunState m_runState;
6019
6020 public:
6021
6022 static TrackerContext& instance() {
6023 static TrackerContext s_instance;
6024 return s_instance;
6025 }
6026
6027 TrackerContext()
6028 : m_currentTracker( CATCH_NULL ),
6029 m_runState( NotStarted )
6030 {}
6031
6032 ITracker& startRun();
6033
6034 void endRun() {
6035 m_rootTracker.reset();
6036 m_currentTracker = CATCH_NULL;
6037 m_runState = NotStarted;
6038 }
6039
6040 void startCycle() {
6041 m_currentTracker = m_rootTracker.get();
6042 m_runState = Executing;
6043 }
6044 void completeCycle() {
6045 m_runState = CompletedCycle;
6046 }
6047
6048 bool completedCycle() const {
6049 return m_runState == CompletedCycle;
6050 }
6051 ITracker& currentTracker() {
6052 return *m_currentTracker;
6053 }
6054 void setCurrentTracker( ITracker* tracker ) {
6055 m_currentTracker = tracker;
6056 }
6057 };
6058
6059 class TrackerBase : public ITracker {
6060 protected:
6061 enum CycleState {
6062 NotStarted,
6063 Executing,
6064 ExecutingChildren,
6065 NeedsAnotherRun,
6066 CompletedSuccessfully,
6067 Failed
6068 };
6069 class TrackerHasName {
6070 NameAndLocation m_nameAndLocation;
6071 public:
6072 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
6073 bool operator ()( Ptr<ITracker> const& tracker ) {
6074 return
6075 tracker->nameAndLocation().name == m_nameAndLocation.name &&
6076 tracker->nameAndLocation().location == m_nameAndLocation.location;
6077 }
6078 };
6079 typedef std::vector<Ptr<ITracker> > Children;
6080 NameAndLocation m_nameAndLocation;
6081 TrackerContext& m_ctx;
6082 ITracker* m_parent;
6083 Children m_children;
6084 CycleState m_runState;
6085 public:
6086 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6087 : m_nameAndLocation( nameAndLocation ),
6088 m_ctx( ctx ),
6089 m_parent( parent ),
6090 m_runState( NotStarted )
6091 {}
6092 virtual ~TrackerBase();
6093
6094 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
6095 return m_nameAndLocation;
6096 }
6097 virtual bool isComplete() const CATCH_OVERRIDE {
6098 return m_runState == CompletedSuccessfully || m_runState == Failed;
6099 }
6100 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
6101 return m_runState == CompletedSuccessfully;
6102 }
6103 virtual bool isOpen() const CATCH_OVERRIDE {
6104 return m_runState != NotStarted && !isComplete();
6105 }
6106 virtual bool hasChildren() const CATCH_OVERRIDE {
6107 return !m_children.empty();
6108 }
6109
6110 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
6111 m_children.push_back( child );
6112 }
6113
6114 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
6115 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
6116 return( it != m_children.end() )
6117 ? it->get()
6118 : CATCH_NULL;
6119 }
6120 virtual ITracker& parent() CATCH_OVERRIDE {
6121 assert( m_parent ); // Should always be non-null except for root
6122 return *m_parent;
6123 }
6124
6125 virtual void openChild() CATCH_OVERRIDE {
6126 if( m_runState != ExecutingChildren ) {
6127 m_runState = ExecutingChildren;
6128 if( m_parent )
6129 m_parent->openChild();
6130 }
6131 }
6132
6133 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
6134 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
6135
6136 void open() {
6137 m_runState = Executing;
6138 moveToThis();
6139 if( m_parent )
6140 m_parent->openChild();
6141 }
6142
6143 virtual void close() CATCH_OVERRIDE {
6144
6145 // Close any still open children (e.g. generators)
6146 while( &m_ctx.currentTracker() != this )
6147 m_ctx.currentTracker().close();
6148
6149 switch( m_runState ) {
6150 case NotStarted:
6151 case CompletedSuccessfully:
6152 case Failed:
6153 throw std::logic_error( "Illogical state" );
6154
6155 case NeedsAnotherRun:
6156 break;;
6157
6158 case Executing:
6159 m_runState = CompletedSuccessfully;
6160 break;
6161 case ExecutingChildren:
6162 if( m_children.empty() || m_children.back()->isComplete() )
6163 m_runState = CompletedSuccessfully;
6164 break;
6165
6166 default:
6167 throw std::logic_error( "Unexpected state" );
6168 }
6169 moveToParent();
6170 m_ctx.completeCycle();
6171 }
6172 virtual void fail() CATCH_OVERRIDE {
6173 m_runState = Failed;
6174 if( m_parent )
6175 m_parent->markAsNeedingAnotherRun();
6176 moveToParent();
6177 m_ctx.completeCycle();
6178 }
6179 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
6180 m_runState = NeedsAnotherRun;
6181 }
6182 private:
6183 void moveToParent() {
6184 assert( m_parent );
6185 m_ctx.setCurrentTracker( m_parent );
6186 }
6187 void moveToThis() {
6188 m_ctx.setCurrentTracker( this );
6189 }
6190 };
6191
6192 class SectionTracker : public TrackerBase {
6193 std::vector<std::string> m_filters;
6194 public:
6195 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6196 : TrackerBase( nameAndLocation, ctx, parent )
6197 {
6198 if( parent ) {
6199 while( !parent->isSectionTracker() )
6200 parent = &parent->parent();
6201
6202 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
6203 addNextFilters( parentSection.m_filters );
6204 }
6205 }
6206 virtual ~SectionTracker();
6207
6208 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
6209
6210 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
6211 SectionTracker* section = CATCH_NULL;
6212
6213 ITracker& currentTracker = ctx.currentTracker();
6214 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
6215 assert( childTracker );
6216 assert( childTracker->isSectionTracker() );
6217 section = static_cast<SectionTracker*>( childTracker );
6218 }
6219 else {
6220 section = new SectionTracker( nameAndLocation, ctx, &currentTracker );
6221 currentTracker.addChild( section );
6222 }
6223 if( !ctx.completedCycle() )
6224 section->tryOpen();
6225 return *section;
6226 }
6227
6228 void tryOpen() {
6229 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
6230 open();
6231 }
6232
6233 void addInitialFilters( std::vector<std::string> const& filters ) {
6234 if( !filters.empty() ) {
6235 m_filters.push_back(""); // Root - should never be consulted
6236 m_filters.push_back(""); // Test Case - not a section filter
6237 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
6238 }
6239 }
6240 void addNextFilters( std::vector<std::string> const& filters ) {
6241 if( filters.size() > 1 )
6242 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
6243 }
6244 };
6245
6246 class IndexTracker : public TrackerBase {
6247 int m_size;
6248 int m_index;
6249 public:
6250 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
6251 : TrackerBase( nameAndLocation, ctx, parent ),
6252 m_size( size ),
6253 m_index( -1 )
6254 {}
6255 virtual ~IndexTracker();
6256
6257 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
6258
6259 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
6260 IndexTracker* tracker = CATCH_NULL;
6261
6262 ITracker& currentTracker = ctx.currentTracker();
6263 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
6264 assert( childTracker );
6265 assert( childTracker->isIndexTracker() );
6266 tracker = static_cast<IndexTracker*>( childTracker );
6267 }
6268 else {
6269 tracker = new IndexTracker( nameAndLocation, ctx, &currentTracker, size );
6270 currentTracker.addChild( tracker );
6271 }
6272
6273 if( !ctx.completedCycle() && !tracker->isComplete() ) {
6274 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
6275 tracker->moveNext();
6276 tracker->open();
6277 }
6278
6279 return *tracker;
6280 }
6281
6282 int index() const { return m_index; }
6283
6284 void moveNext() {
6285 m_index++;
6286 m_children.clear();
6287 }
6288
6289 virtual void close() CATCH_OVERRIDE {
6290 TrackerBase::close();
6291 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
6292 m_runState = Executing;
6293 }
6294 };
6295
6296 inline ITracker& TrackerContext::startRun() {
6297 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
6298 m_currentTracker = CATCH_NULL;
6299 m_runState = Executing;
6300 return *m_rootTracker;
6301 }
6302
6303} // namespace TestCaseTracking
6304
6305using TestCaseTracking::ITracker;
6306using TestCaseTracking::TrackerContext;
6307using TestCaseTracking::SectionTracker;
6308using TestCaseTracking::IndexTracker;
6309
6310} // namespace Catch
6311
6312CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
6313
6314// #included from: catch_fatal_condition.hpp
6315#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
6316
6317namespace Catch {
6318
6319 // Report the error condition
6320 inline void reportFatal( std::string const& message ) {
6321 IContext& context = Catch::getCurrentContext();
6322 IResultCapture* resultCapture = context.getResultCapture();
6323 resultCapture->handleFatalErrorCondition( message );
6324 }
6325
6326} // namespace Catch
6327
6328#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
6329// #included from: catch_windows_h_proxy.h
6330
6331#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
6332
6333#ifdef CATCH_DEFINES_NOMINMAX
6334# define NOMINMAX
6335#endif
6336#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6337# define WIN32_LEAN_AND_MEAN
6338#endif
6339
6340#ifdef __AFXDLL
6341#include <AfxWin.h>
6342#else
6343#include <windows.h>
6344#endif
6345
6346#ifdef CATCH_DEFINES_NOMINMAX
6347# undef NOMINMAX
6348#endif
6349#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6350# undef WIN32_LEAN_AND_MEAN
6351#endif
6352
6353
6354# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
6355
6356namespace Catch {
6357 struct FatalConditionHandler {
6358 void reset() {}
6359 };
6360}
6361
6362# else // CATCH_CONFIG_WINDOWS_SEH is defined
6363
6364namespace Catch {
6365
6366 struct SignalDefs { DWORD id; const char* name; };
6367 extern SignalDefs signalDefs[];
6368 // There is no 1-1 mapping between signals and windows exceptions.
6369 // Windows can easily distinguish between SO and SigSegV,
6370 // but SigInt, SigTerm, etc are handled differently.
6371 SignalDefs signalDefs[] = {
6372 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
6373 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
6374 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
6375 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
6376 };
6377
6378 struct FatalConditionHandler {
6379
6380 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
6381 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6382 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
6383 reportFatal(signalDefs[i].name);
6384 }
6385 }
6386 // If its not an exception we care about, pass it along.
6387 // This stops us from eating debugger breaks etc.
6388 return EXCEPTION_CONTINUE_SEARCH;
6389 }
6390
6391 FatalConditionHandler() {
6392 isSet = true;
6393 // 32k seems enough for Catch to handle stack overflow,
6394 // but the value was found experimentally, so there is no strong guarantee
6395 guaranteeSize = 32 * 1024;
6396 exceptionHandlerHandle = CATCH_NULL;
6397 // Register as first handler in current chain
6398 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
6399 // Pass in guarantee size to be filled
6400 SetThreadStackGuarantee(&guaranteeSize);
6401 }
6402
6403 static void reset() {
6404 if (isSet) {
6405 // Unregister handler and restore the old guarantee
6406 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
6407 SetThreadStackGuarantee(&guaranteeSize);
6408 exceptionHandlerHandle = CATCH_NULL;
6409 isSet = false;
6410 }
6411 }
6412
6413 ~FatalConditionHandler() {
6414 reset();
6415 }
6416 private:
6417 static bool isSet;
6418 static ULONG guaranteeSize;
6419 static PVOID exceptionHandlerHandle;
6420 };
6421
6422 bool FatalConditionHandler::isSet = false;
6423 ULONG FatalConditionHandler::guaranteeSize = 0;
6424 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
6425
6426} // namespace Catch
6427
6428# endif // CATCH_CONFIG_WINDOWS_SEH
6429
6430#else // Not Windows - assumed to be POSIX compatible //////////////////////////
6431
6432# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
6433
6434namespace Catch {
6435 struct FatalConditionHandler {
6436 void reset() {}
6437 };
6438}
6439
6440# else // CATCH_CONFIG_POSIX_SIGNALS is defined
6441
6442#include <signal.h>
6443
6444namespace Catch {
6445
6446 struct SignalDefs {
6447 int id;
6448 const char* name;
6449 };
6450 extern SignalDefs signalDefs[];
6451 SignalDefs signalDefs[] = {
6452 { SIGINT, "SIGINT - Terminal interrupt signal" },
6453 { SIGILL, "SIGILL - Illegal instruction signal" },
6454 { SIGFPE, "SIGFPE - Floating point error signal" },
6455 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
6456 { SIGTERM, "SIGTERM - Termination request signal" },
6457 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
6458 };
6459
6460 struct FatalConditionHandler {
6461
6462 static bool isSet;
6463 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
6464 static stack_t oldSigStack;
6465 static char altStackMem[SIGSTKSZ];
6466
6467 static void handleSignal( int sig ) {
6468 std::string name = "<unknown signal>";
6469 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6470 SignalDefs &def = signalDefs[i];
6471 if (sig == def.id) {
6472 name = def.name;
6473 break;
6474 }
6475 }
6476 reset();
6477 reportFatal(name);
6478 raise( sig );
6479 }
6480
6481 FatalConditionHandler() {
6482 isSet = true;
6483 stack_t sigStack;
6484 sigStack.ss_sp = altStackMem;
6485 sigStack.ss_size = SIGSTKSZ;
6486 sigStack.ss_flags = 0;
6487 sigaltstack(&sigStack, &oldSigStack);
6488 struct sigaction sa = { 0 };
6489
6490 sa.sa_handler = handleSignal;
6491 sa.sa_flags = SA_ONSTACK;
6492 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
6493 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
6494 }
6495 }
6496
6497 ~FatalConditionHandler() {
6498 reset();
6499 }
6500 static void reset() {
6501 if( isSet ) {
6502 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
6503 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
6504 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
6505 }
6506 // Return the old stack
6507 sigaltstack(&oldSigStack, CATCH_NULL);
6508 isSet = false;
6509 }
6510 }
6511 };
6512
6513 bool FatalConditionHandler::isSet = false;
6514 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
6515 stack_t FatalConditionHandler::oldSigStack = {};
6516 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
6517
6518} // namespace Catch
6519
6520# endif // CATCH_CONFIG_POSIX_SIGNALS
6521
6522#endif // not Windows
6523
6524#include <set>
6525#include <string>
6526
6527namespace Catch {
6528
6529 class StreamRedirect {
6530
6531 public:
6532 StreamRedirect( std::ostream& stream, std::string& targetString )
6533 : m_stream( stream ),
6534 m_prevBuf( stream.rdbuf() ),
6535 m_targetString( targetString )
6536 {
6537 stream.rdbuf( m_oss.rdbuf() );
6538 }
6539
6540 ~StreamRedirect() {
6541 m_targetString += m_oss.str();
6542 m_stream.rdbuf( m_prevBuf );
6543 }
6544
6545 private:
6546 std::ostream& m_stream;
6547 std::streambuf* m_prevBuf;
6548 std::ostringstream m_oss;
6549 std::string& m_targetString;
6550 };
6551
6552 ///////////////////////////////////////////////////////////////////////////
6553
6554 class RunContext : public IResultCapture, public IRunner {
6555
6556 RunContext( RunContext const& );
6557 void operator =( RunContext const& );
6558
6559 public:
6560
6561 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
6562 : m_runInfo( _config->name() ),
6563 m_context( getCurrentMutableContext() ),
6564 m_activeTestCase( CATCH_NULL ),
6565 m_config( _config ),
6566 m_reporter( reporter ),
6567 m_shouldReportUnexpected ( true )
6568 {
6569 m_context.setRunner( this );
6570 m_context.setConfig( m_config );
6571 m_context.setResultCapture( this );
6572 m_reporter->testRunStarting( m_runInfo );
6573 }
6574
6575 virtual ~RunContext() {
6576 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
6577 }
6578
6579 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
6580 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
6581 }
6582 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
6583 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
6584 }
6585
6586 Totals runTest( TestCase const& testCase ) {
6587 Totals prevTotals = m_totals;
6588
6589 std::string redirectedCout;
6590 std::string redirectedCerr;
6591
6592 TestCaseInfo testInfo = testCase.getTestCaseInfo();
6593
6594 m_reporter->testCaseStarting( testInfo );
6595
6596 m_activeTestCase = &testCase;
6597
6598 do {
6599 ITracker& rootTracker = m_trackerContext.startRun();
6600 assert( rootTracker.isSectionTracker() );
6601 static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
6602 do {
6603 m_trackerContext.startCycle();
6604 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
6605 runCurrentTest( redirectedCout, redirectedCerr );
6606 }
6607 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
6608 }
6609 // !TBD: deprecated - this will be replaced by indexed trackers
6610 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
6611
6612 Totals deltaTotals = m_totals.delta( prevTotals );
6613 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
6614 deltaTotals.assertions.failed++;
6615 deltaTotals.testCases.passed--;
6616 deltaTotals.testCases.failed++;
6617 }
6618 m_totals.testCases += deltaTotals.testCases;
6619 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6620 deltaTotals,
6621 redirectedCout,
6622 redirectedCerr,
6623 aborting() ) );
6624
6625 m_activeTestCase = CATCH_NULL;
6626 m_testCaseTracker = CATCH_NULL;
6627
6628 return deltaTotals;
6629 }
6630
6631 Ptr<IConfig const> config() const {
6632 return m_config;
6633 }
6634
6635 private: // IResultCapture
6636
6637 virtual void assertionEnded( AssertionResult const& result ) {
6638 if( result.getResultType() == ResultWas::Ok ) {
6639 m_totals.assertions.passed++;
6640 }
6641 else if( !result.isOk() ) {
6642 m_totals.assertions.failed++;
6643 }
6644
6645 // We have no use for the return value (whether messages should be cleared), because messages were made scoped
6646 // and should be let to clear themselves out.
6647 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
6648
6649 // Reset working state
6650 m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
6651 m_lastResult = result;
6652 }
6653
6654 virtual bool sectionStarted (
6655 SectionInfo const& sectionInfo,
6656 Counts& assertions
6657 )
6658 {
6659 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
6660 if( !sectionTracker.isOpen() )
6661 return false;
6662 m_activeSections.push_back( &sectionTracker );
6663
6664 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
6665
6666 m_reporter->sectionStarting( sectionInfo );
6667
6668 assertions = m_totals.assertions;
6669
6670 return true;
6671 }
6672 bool testForMissingAssertions( Counts& assertions ) {
6673 if( assertions.total() != 0 )
6674 return false;
6675 if( !m_config->warnAboutMissingAssertions() )
6676 return false;
6677 if( m_trackerContext.currentTracker().hasChildren() )
6678 return false;
6679 m_totals.assertions.failed++;
6680 assertions.failed++;
6681 return true;
6682 }
6683
6684 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
6685 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
6686 bool missingAssertions = testForMissingAssertions( assertions );
6687
6688 if( !m_activeSections.empty() ) {
6689 m_activeSections.back()->close();
6690 m_activeSections.pop_back();
6691 }
6692
6693 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
6694 m_messages.clear();
6695 }
6696
6697 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
6698 if( m_unfinishedSections.empty() )
6699 m_activeSections.back()->fail();
6700 else
6701 m_activeSections.back()->close();
6702 m_activeSections.pop_back();
6703
6704 m_unfinishedSections.push_back( endInfo );
6705 }
6706
6707 virtual void pushScopedMessage( MessageInfo const& message ) {
6708 m_messages.push_back( message );
6709 }
6710
6711 virtual void popScopedMessage( MessageInfo const& message ) {
6712 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
6713 }
6714
6715 virtual std::string getCurrentTestName() const {
6716 return m_activeTestCase
6717 ? m_activeTestCase->getTestCaseInfo().name
6718 : std::string();
6719 }
6720
6721 virtual const AssertionResult* getLastResult() const {
6722 return &m_lastResult;
6723 }
6724
6725 virtual void exceptionEarlyReported() {
6726 m_shouldReportUnexpected = false;
6727 }
6728
6729 virtual void handleFatalErrorCondition( std::string const& message ) {
6730 // Don't rebuild the result -- the stringification itself can cause more fatal errors
6731 // Instead, fake a result data.
6732 AssertionResultData tempResult;
6733 tempResult.resultType = ResultWas::FatalErrorCondition;
6734 tempResult.message = message;
6735 AssertionResult result(m_lastAssertionInfo, tempResult);
6736
6737 getResultCapture().assertionEnded(result);
6738
6739 handleUnfinishedSections();
6740
6741 // Recreate section for test case (as we will lose the one that was in scope)
6742 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6743 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6744
6745 Counts assertions;
6746 assertions.failed = 1;
6747 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6748 m_reporter->sectionEnded( testCaseSectionStats );
6749
6750 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6751
6752 Totals deltaTotals;
6753 deltaTotals.testCases.failed = 1;
6754 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6755 deltaTotals,
6756 std::string(),
6757 std::string(),
6758 false ) );
6759 m_totals.testCases.failed++;
6760 testGroupEnded( std::string(), m_totals, 1, 1 );
6761 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6762 }
6763
6764 public:
6765 // !TBD We need to do this another way!
6766 bool aborting() const {
6767 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
6768 }
6769
6770 private:
6771
6772 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
6773 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6774 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6775 m_reporter->sectionStarting( testCaseSection );
6776 Counts prevAssertions = m_totals.assertions;
6777 double duration = 0;
6778 m_shouldReportUnexpected = true;
6779 try {
6780 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
6781
6782 seedRng( *m_config );
6783
6784 Timer timer;
6785 timer.start();
6786 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
6787 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6788 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
6789 invokeActiveTestCase();
6790 }
6791 else {
6792 invokeActiveTestCase();
6793 }
6794 duration = timer.getElapsedSeconds();
6795 }
6796 catch( TestFailureException& ) {
6797 // This just means the test was aborted due to failure
6798 }
6799 catch(...) {
6800 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
6801 // are reported without translation at the point of origin.
6802 if (m_shouldReportUnexpected) {
6803 makeUnexpectedResultBuilder().useActiveException();
6804 }
6805 }
6806 m_testCaseTracker->close();
6807 handleUnfinishedSections();
6808 m_messages.clear();
6809
6810 Counts assertions = m_totals.assertions - prevAssertions;
6811 bool missingAssertions = testForMissingAssertions( assertions );
6812
6813 if( testCaseInfo.okToFail() ) {
6814 std::swap( assertions.failedButOk, assertions.failed );
6815 m_totals.assertions.failed -= assertions.failedButOk;
6816 m_totals.assertions.failedButOk += assertions.failedButOk;
6817 }
6818
6819 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
6820 m_reporter->sectionEnded( testCaseSectionStats );
6821 }
6822
6823 void invokeActiveTestCase() {
6824 FatalConditionHandler fatalConditionHandler; // Handle signals
6825 m_activeTestCase->invoke();
6826 fatalConditionHandler.reset();
6827 }
6828
6829 private:
6830
6831 ResultBuilder makeUnexpectedResultBuilder() const {
6832 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6833 m_lastAssertionInfo.lineInfo,
6834 m_lastAssertionInfo.capturedExpression.c_str(),
6835 m_lastAssertionInfo.resultDisposition );
6836 }
6837
6838 void handleUnfinishedSections() {
6839 // If sections ended prematurely due to an exception we stored their
6840 // infos here so we can tear them down outside the unwind process.
6841 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
6842 itEnd = m_unfinishedSections.rend();
6843 it != itEnd;
6844 ++it )
6845 sectionEnded( *it );
6846 m_unfinishedSections.clear();
6847 }
6848
6849 TestRunInfo m_runInfo;
6850 IMutableContext& m_context;
6851 TestCase const* m_activeTestCase;
6852 ITracker* m_testCaseTracker;
6853 ITracker* m_currentSectionTracker;
6854 AssertionResult m_lastResult;
6855
6856 Ptr<IConfig const> m_config;
6857 Totals m_totals;
6858 Ptr<IStreamingReporter> m_reporter;
6859 std::vector<MessageInfo> m_messages;
6860 AssertionInfo m_lastAssertionInfo;
6861 std::vector<SectionEndInfo> m_unfinishedSections;
6862 std::vector<ITracker*> m_activeSections;
6863 TrackerContext m_trackerContext;
6864 bool m_shouldReportUnexpected;
6865 };
6866
6867 IResultCapture& getResultCapture() {
6868 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6869 return *capture;
6870 else
6871 throw std::logic_error( "No result capture instance" );
6872 }
6873
6874} // end namespace Catch
6875
6876// #included from: internal/catch_version.h
6877#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6878
6879namespace Catch {
6880
6881 // Versioning information
6882 struct Version {
6883 Version( unsigned int _majorVersion,
6884 unsigned int _minorVersion,
6885 unsigned int _patchNumber,
6886 char const * const _branchName,
6887 unsigned int _buildNumber );
6888
6889 unsigned int const majorVersion;
6890 unsigned int const minorVersion;
6891 unsigned int const patchNumber;
6892
6893 // buildNumber is only used if branchName is not null
6894 char const * const branchName;
6895 unsigned int const buildNumber;
6896
6897 friend std::ostream& operator << ( std::ostream& os, Version const& version );
6898
6899 private:
6900 void operator=( Version const& );
6901 };
6902
6903 inline Version libraryVersion();
6904}
6905
6906#include <fstream>
6907#include <stdlib.h>
6908#include <limits>
6909
6910namespace Catch {
6911
6912 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
6913 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
6914 if( !reporter ) {
6915 std::ostringstream oss;
6916 oss << "No reporter registered with name: '" << reporterName << "'";
6917 throw std::domain_error( oss.str() );
6918 }
6919 return reporter;
6920 }
6921
6922 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
6923 std::vector<std::string> reporters = config->getReporterNames();
6924 if( reporters.empty() )
6925 reporters.push_back( "console" );
6926
6927 Ptr<IStreamingReporter> reporter;
6928 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6929 it != itEnd;
6930 ++it )
6931 reporter = addReporter( reporter, createReporter( *it, config ) );
6932 return reporter;
6933 }
6934 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
6935 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6936 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6937 it != itEnd;
6938 ++it )
6939 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6940 return reporters;
6941 }
6942
6943 Totals runTests( Ptr<Config> const& config ) {
6944
6945 Ptr<IConfig const> iconfig = config.get();
6946
6947 Ptr<IStreamingReporter> reporter = makeReporter( config );
6948 reporter = addListeners( iconfig, reporter );
6949
6950 RunContext context( iconfig, reporter );
6951
6952 Totals totals;
6953
6954 context.testGroupStarting( config->name(), 1, 1 );
6955
6956 TestSpec testSpec = config->testSpec();
6957 if( !testSpec.hasFilters() )
6958 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6959
6960 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
6961 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6962 it != itEnd;
6963 ++it ) {
6964 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
6965 totals += context.runTest( *it );
6966 else
6967 reporter->skipTest( *it );
6968 }
6969
6970 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
6971 return totals;
6972 }
6973
6974 void applyFilenamesAsTags( IConfig const& config ) {
6975 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
6976 for(std::size_t i = 0; i < tests.size(); ++i ) {
6977 TestCase& test = const_cast<TestCase&>( tests[i] );
6978 std::set<std::string> tags = test.tags;
6979
6980 std::string filename = test.lineInfo.file;
6981 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
6982 if( lastSlash != std::string::npos )
6983 filename = filename.substr( lastSlash+1 );
6984
6985 std::string::size_type lastDot = filename.find_last_of( "." );
6986 if( lastDot != std::string::npos )
6987 filename = filename.substr( 0, lastDot );
6988
6989 tags.insert( "#" + filename );
6990 setTags( test, tags );
6991 }
6992 }
6993
6994 class Session : NonCopyable {
6995 static bool alreadyInstantiated;
6996
6997 public:
6998
6999 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
7000
7001 Session()
7002 : m_cli( makeCommandLineParser() ) {
7003 if( alreadyInstantiated ) {
7004 std::string msg = "Only one instance of Catch::Session can ever be used";
7005 Catch::cerr() << msg << std::endl;
7006 throw std::logic_error( msg );
7007 }
7008 alreadyInstantiated = true;
7009 }
7010 ~Session() {
7011 Catch::cleanUp();
7012 }
7013
7014 void showHelp( std::string const& processName ) {
7015 Catch::cout() << "\nCatch v" << libraryVersion() << "\n";
7016
7017 m_cli.usage( Catch::cout(), processName );
7018 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
7019 }
7020
7021 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
7022 try {
7023 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
7024 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
7025 if( m_configData.showHelp )
7026 showHelp( m_configData.processName );
7027 m_config.reset();
7028 }
7029 catch( std::exception& ex ) {
7030 {
7031 Colour colourGuard( Colour::Red );
7032 Catch::cerr()
7033 << "\nError(s) in input:\n"
7034 << Text( ex.what(), TextAttributes().setIndent(2) )
7035 << "\n\n";
7036 }
7037 m_cli.usage( Catch::cout(), m_configData.processName );
7038 return (std::numeric_limits<int>::max)();
7039 }
7040 return 0;
7041 }
7042
7043 void useConfigData( ConfigData const& _configData ) {
7044 m_configData = _configData;
7045 m_config.reset();
7046 }
7047
7048 int run( int argc, char const* const* const argv ) {
7049
7050 int returnCode = applyCommandLine( argc, argv );
7051 if( returnCode == 0 )
7052 returnCode = run();
7053 return returnCode;
7054 }
7055
7056 #if defined(WIN32) && defined(UNICODE)
7057 int run( int argc, wchar_t const* const* const argv ) {
7058
7059 char **utf8Argv = new char *[ argc ];
7060
7061 for ( int i = 0; i < argc; ++i ) {
7062 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
7063
7064 utf8Argv[ i ] = new char[ bufSize ];
7065
7066 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
7067 }
7068
7069 int returnCode = applyCommandLine( argc, utf8Argv );
7070 if( returnCode == 0 )
7071 returnCode = run();
7072
7073 for ( int i = 0; i < argc; ++i )
7074 delete [] utf8Argv[ i ];
7075
7076 delete [] utf8Argv;
7077
7078 return returnCode;
7079 }
7080 #endif
7081
7082 int run() {
7083 if( m_configData.showHelp )
7084 return 0;
7085
7086 try
7087 {
7088 config(); // Force config to be constructed
7089
7090 seedRng( *m_config );
7091
7092 if( m_configData.filenamesAsTags )
7093 applyFilenamesAsTags( *m_config );
7094
7095 // Handle list request
7096 if( Option<std::size_t> listed = list( config() ) )
7097 return static_cast<int>( *listed );
7098
7099 return static_cast<int>( runTests( m_config ).assertions.failed );
7100 }
7101 catch( std::exception& ex ) {
7102 Catch::cerr() << ex.what() << std::endl;
7103 return (std::numeric_limits<int>::max)();
7104 }
7105 }
7106
7107 Clara::CommandLine<ConfigData> const& cli() const {
7108 return m_cli;
7109 }
7110 std::vector<Clara::Parser::Token> const& unusedTokens() const {
7111 return m_unusedTokens;
7112 }
7113 ConfigData& configData() {
7114 return m_configData;
7115 }
7116 Config& config() {
7117 if( !m_config )
7118 m_config = new Config( m_configData );
7119 return *m_config;
7120 }
7121 private:
7122 Clara::CommandLine<ConfigData> m_cli;
7123 std::vector<Clara::Parser::Token> m_unusedTokens;
7124 ConfigData m_configData;
7125 Ptr<Config> m_config;
7126 };
7127
7128 bool Session::alreadyInstantiated = false;
7129
7130} // end namespace Catch
7131
7132// #included from: catch_registry_hub.hpp
7133#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
7134
7135// #included from: catch_test_case_registry_impl.hpp
7136#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
7137
7138#include <vector>
7139#include <set>
7140#include <sstream>
7141#include <algorithm>
7142
7143namespace Catch {
7144
7145 struct RandomNumberGenerator {
7146 typedef std::ptrdiff_t result_type;
7147
7148 result_type operator()( result_type n ) const { return std::rand() % n; }
7149
7150#ifdef CATCH_CONFIG_CPP11_SHUFFLE
7151 static constexpr result_type min() { return 0; }
7152 static constexpr result_type max() { return 1000000; }
7153 result_type operator()() const { return std::rand() % max(); }
7154#endif
7155 template<typename V>
7156 static void shuffle( V& vector ) {
7157 RandomNumberGenerator rng;
7158#ifdef CATCH_CONFIG_CPP11_SHUFFLE
7159 std::shuffle( vector.begin(), vector.end(), rng );
7160#else
7161 std::random_shuffle( vector.begin(), vector.end(), rng );
7162#endif
7163 }
7164 };
7165
7166 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
7167
7168 std::vector<TestCase> sorted = unsortedTestCases;
7169
7170 switch( config.runOrder() ) {
7171 case RunTests::InLexicographicalOrder:
7172 std::sort( sorted.begin(), sorted.end() );
7173 break;
7174 case RunTests::InRandomOrder:
7175 {
7176 seedRng( config );
7177 RandomNumberGenerator::shuffle( sorted );
7178 }
7179 break;
7180 case RunTests::InDeclarationOrder:
7181 // already in declaration order
7182 break;
7183 }
7184 return sorted;
7185 }
7186 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
7187 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
7188 }
7189
7190 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
7191 std::set<TestCase> seenFunctions;
7192 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
7193 it != itEnd;
7194 ++it ) {
7195 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
7196 if( !prev.second ) {
7197 std::ostringstream ss;
7198
7199 ss << Colour( Colour::Red )
7200 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
7201 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
7202 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
7203
7204 throw std::runtime_error(ss.str());
7205 }
7206 }
7207 }
7208
7209 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
7210 std::vector<TestCase> filtered;
7211 filtered.reserve( testCases.size() );
7212 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
7213 it != itEnd;
7214 ++it )
7215 if( matchTest( *it, testSpec, config ) )
7216 filtered.push_back( *it );
7217 return filtered;
7218 }
7219 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
7220 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
7221 }
7222
7223 class TestRegistry : public ITestCaseRegistry {
7224 public:
7225 TestRegistry()
7226 : m_currentSortOrder( RunTests::InDeclarationOrder ),
7227 m_unnamedCount( 0 )
7228 {}
7229 virtual ~TestRegistry();
7230
7231 virtual void registerTest( TestCase const& testCase ) {
7232 std::string name = testCase.getTestCaseInfo().name;
7233 if( name.empty() ) {
7234 std::ostringstream oss;
7235 oss << "Anonymous test case " << ++m_unnamedCount;
7236 return registerTest( testCase.withName( oss.str() ) );
7237 }
7238 m_functions.push_back( testCase );
7239 }
7240
7241 virtual std::vector<TestCase> const& getAllTests() const {
7242 return m_functions;
7243 }
7244 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
7245 if( m_sortedFunctions.empty() )
7246 enforceNoDuplicateTestCases( m_functions );
7247
7248 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
7249 m_sortedFunctions = sortTests( config, m_functions );
7250 m_currentSortOrder = config.runOrder();
7251 }
7252 return m_sortedFunctions;
7253 }
7254
7255 private:
7256 std::vector<TestCase> m_functions;
7257 mutable RunTests::InWhatOrder m_currentSortOrder;
7258 mutable std::vector<TestCase> m_sortedFunctions;
7259 size_t m_unnamedCount;
7260 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
7261 };
7262
7263 ///////////////////////////////////////////////////////////////////////////
7264
7265 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
7266 public:
7267
7268 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
7269
7270 virtual void invoke() const {
7271 m_fun();
7272 }
7273
7274 private:
7275 virtual ~FreeFunctionTestCase();
7276
7277 TestFunction m_fun;
7278 };
7279
7280 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
7281 std::string className = classOrQualifiedMethodName;
7282 if( startsWith( className, '&' ) )
7283 {
7284 std::size_t lastColons = className.rfind( "::" );
7285 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
7286 if( penultimateColons == std::string::npos )
7287 penultimateColons = 1;
7288 className = className.substr( penultimateColons, lastColons-penultimateColons );
7289 }
7290 return className;
7291 }
7292
7293 void registerTestCase
7294 ( ITestCase* testCase,
7295 char const* classOrQualifiedMethodName,
7296 NameAndDesc const& nameAndDesc,
7297 SourceLineInfo const& lineInfo ) {
7298
7299 getMutableRegistryHub().registerTest
7300 ( makeTestCase
7301 ( testCase,
7302 extractClassName( classOrQualifiedMethodName ),
7303 nameAndDesc.name,
7304 nameAndDesc.description,
7305 lineInfo ) );
7306 }
7307 void registerTestCaseFunction
7308 ( TestFunction function,
7309 SourceLineInfo const& lineInfo,
7310 NameAndDesc const& nameAndDesc ) {
7311 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
7312 }
7313
7314 ///////////////////////////////////////////////////////////////////////////
7315
7316 AutoReg::AutoReg
7317 ( TestFunction function,
7318 SourceLineInfo const& lineInfo,
7319 NameAndDesc const& nameAndDesc ) {
7320 registerTestCaseFunction( function, lineInfo, nameAndDesc );
7321 }
7322
7323 AutoReg::~AutoReg() {}
7324
7325} // end namespace Catch
7326
7327// #included from: catch_reporter_registry.hpp
7328#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
7329
7330#include <map>
7331
7332namespace Catch {
7333
7334 class ReporterRegistry : public IReporterRegistry {
7335
7336 public:
7337
7338 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
7339
7340 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
7341 FactoryMap::const_iterator it = m_factories.find( name );
7342 if( it == m_factories.end() )
7343 return CATCH_NULL;
7344 return it->second->create( ReporterConfig( config ) );
7345 }
7346
7347 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
7348 m_factories.insert( std::make_pair( name, factory ) );
7349 }
7350 void registerListener( Ptr<IReporterFactory> const& factory ) {
7351 m_listeners.push_back( factory );
7352 }
7353
7354 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
7355 return m_factories;
7356 }
7357 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
7358 return m_listeners;
7359 }
7360
7361 private:
7362 FactoryMap m_factories;
7363 Listeners m_listeners;
7364 };
7365}
7366
7367// #included from: catch_exception_translator_registry.hpp
7368#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
7369
7370#ifdef __OBJC__
7371#import "Foundation/Foundation.h"
7372#endif
7373
7374namespace Catch {
7375
7376 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
7377 public:
7378 ~ExceptionTranslatorRegistry() {
7379 deleteAll( m_translators );
7380 }
7381
7382 virtual void registerTranslator( const IExceptionTranslator* translator ) {
7383 m_translators.push_back( translator );
7384 }
7385
7386 virtual std::string translateActiveException() const {
7387 try {
7388#ifdef __OBJC__
7389 // In Objective-C try objective-c exceptions first
7390 @try {
7391 return tryTranslators();
7392 }
7393 @catch (NSException *exception) {
7394 return Catch::toString( [exception description] );
7395 }
7396#else
7397 return tryTranslators();
7398#endif
7399 }
7400 catch( TestFailureException& ) {
7401 throw;
7402 }
7403 catch( std::exception& ex ) {
7404 return ex.what();
7405 }
7406 catch( std::string& msg ) {
7407 return msg;
7408 }
7409 catch( const char* msg ) {
7410 return msg;
7411 }
7412 catch(...) {
7413 return "Unknown exception";
7414 }
7415 }
7416
7417 std::string tryTranslators() const {
7418 if( m_translators.empty() )
7419 throw;
7420 else
7421 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
7422 }
7423
7424 private:
7425 std::vector<const IExceptionTranslator*> m_translators;
7426 };
7427}
7428
7429// #included from: catch_tag_alias_registry.h
7430#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
7431
7432#include <map>
7433
7434namespace Catch {
7435
7436 class TagAliasRegistry : public ITagAliasRegistry {
7437 public:
7438 virtual ~TagAliasRegistry();
7439 virtual Option<TagAlias> find( std::string const& alias ) const;
7440 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
7441 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
7442
7443 private:
7444 std::map<std::string, TagAlias> m_registry;
7445 };
7446
7447} // end namespace Catch
7448
7449namespace Catch {
7450
7451 namespace {
7452
7453 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
7454
7455 RegistryHub( RegistryHub const& );
7456 void operator=( RegistryHub const& );
7457
7458 public: // IRegistryHub
7459 RegistryHub() {
7460 }
7461 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
7462 return m_reporterRegistry;
7463 }
7464 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
7465 return m_testCaseRegistry;
7466 }
7467 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
7468 return m_exceptionTranslatorRegistry;
7469 }
7470 virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE {
7471 return m_tagAliasRegistry;
7472 }
7473
7474 public: // IMutableRegistryHub
7475 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
7476 m_reporterRegistry.registerReporter( name, factory );
7477 }
7478 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
7479 m_reporterRegistry.registerListener( factory );
7480 }
7481 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
7482 m_testCaseRegistry.registerTest( testInfo );
7483 }
7484 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
7485 m_exceptionTranslatorRegistry.registerTranslator( translator );
7486 }
7487 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE {
7488 m_tagAliasRegistry.add( alias, tag, lineInfo );
7489 }
7490
7491 private:
7492 TestRegistry m_testCaseRegistry;
7493 ReporterRegistry m_reporterRegistry;
7494 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
7495 TagAliasRegistry m_tagAliasRegistry;
7496 };
7497
7498 // Single, global, instance
7499 inline RegistryHub*& getTheRegistryHub() {
7500 static RegistryHub* theRegistryHub = CATCH_NULL;
7501 if( !theRegistryHub )
7502 theRegistryHub = new RegistryHub();
7503 return theRegistryHub;
7504 }
7505 }
7506
7507 IRegistryHub& getRegistryHub() {
7508 return *getTheRegistryHub();
7509 }
7510 IMutableRegistryHub& getMutableRegistryHub() {
7511 return *getTheRegistryHub();
7512 }
7513 void cleanUp() {
7514 delete getTheRegistryHub();
7515 getTheRegistryHub() = CATCH_NULL;
7516 cleanUpContext();
7517 }
7518 std::string translateActiveException() {
7519 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
7520 }
7521
7522} // end namespace Catch
7523
7524// #included from: catch_notimplemented_exception.hpp
7525#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
7526
7527#include <sstream>
7528
7529namespace Catch {
7530
7531 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
7532 : m_lineInfo( lineInfo ) {
7533 std::ostringstream oss;
7534 oss << lineInfo << ": function ";
7535 oss << "not implemented";
7536 m_what = oss.str();
7537 }
7538
7539 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
7540 return m_what.c_str();
7541 }
7542
7543} // end namespace Catch
7544
7545// #included from: catch_context_impl.hpp
7546#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
7547
7548// #included from: catch_stream.hpp
7549#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
7550
7551#include <stdexcept>
7552#include <cstdio>
7553#include <iostream>
7554
7555namespace Catch {
7556
7557 template<typename WriterF, size_t bufferSize=256>
7558 class StreamBufImpl : public StreamBufBase {
7559 char data[bufferSize];
7560 WriterF m_writer;
7561
7562 public:
7563 StreamBufImpl() {
7564 setp( data, data + sizeof(data) );
7565 }
7566
7567 ~StreamBufImpl() CATCH_NOEXCEPT {
7568 sync();
7569 }
7570
7571 private:
7572 int overflow( int c ) {
7573 sync();
7574
7575 if( c != EOF ) {
7576 if( pbase() == epptr() )
7577 m_writer( std::string( 1, static_cast<char>( c ) ) );
7578 else
7579 sputc( static_cast<char>( c ) );
7580 }
7581 return 0;
7582 }
7583
7584 int sync() {
7585 if( pbase() != pptr() ) {
7586 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
7587 setp( pbase(), epptr() );
7588 }
7589 return 0;
7590 }
7591 };
7592
7593 ///////////////////////////////////////////////////////////////////////////
7594
7595 FileStream::FileStream( std::string const& filename ) {
7596 m_ofs.open( filename.c_str() );
7597 if( m_ofs.fail() ) {
7598 std::ostringstream oss;
7599 oss << "Unable to open file: '" << filename << '\'';
7600 throw std::domain_error( oss.str() );
7601 }
7602 }
7603
7604 std::ostream& FileStream::stream() const {
7605 return m_ofs;
7606 }
7607
7608 struct OutputDebugWriter {
7609
7610 void operator()( std::string const&str ) {
7611 writeToDebugConsole( str );
7612 }
7613 };
7614
7615 DebugOutStream::DebugOutStream()
7616 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
7617 m_os( m_streamBuf.get() )
7618 {}
7619
7620 std::ostream& DebugOutStream::stream() const {
7621 return m_os;
7622 }
7623
7624 // Store the streambuf from cout up-front because
7625 // cout may get redirected when running tests
7626 CoutStream::CoutStream()
7627 : m_os( Catch::cout().rdbuf() )
7628 {}
7629
7630 std::ostream& CoutStream::stream() const {
7631 return m_os;
7632 }
7633
7634#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
7635 std::ostream& cout() {
7636 return std::cout;
7637 }
7638 std::ostream& cerr() {
7639 return std::cerr;
7640 }
7641#endif
7642}
7643
7644namespace Catch {
7645
7646 class Context : public IMutableContext {
7647
7648 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
7649 Context( Context const& );
7650 void operator=( Context const& );
7651
7652 public:
7653 virtual ~Context() {
7654 deleteAllValues( m_generatorsByTestName );
7655 }
7656
7657 public: // IContext
7658 virtual IResultCapture* getResultCapture() {
7659 return m_resultCapture;
7660 }
7661 virtual IRunner* getRunner() {
7662 return m_runner;
7663 }
7664 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
7665 return getGeneratorsForCurrentTest()
7666 .getGeneratorInfo( fileInfo, totalSize )
7667 .getCurrentIndex();
7668 }
7669 virtual bool advanceGeneratorsForCurrentTest() {
7670 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7671 return generators && generators->moveNext();
7672 }
7673
7674 virtual Ptr<IConfig const> getConfig() const {
7675 return m_config;
7676 }
7677
7678 public: // IMutableContext
7679 virtual void setResultCapture( IResultCapture* resultCapture ) {
7680 m_resultCapture = resultCapture;
7681 }
7682 virtual void setRunner( IRunner* runner ) {
7683 m_runner = runner;
7684 }
7685 virtual void setConfig( Ptr<IConfig const> const& config ) {
7686 m_config = config;
7687 }
7688
7689 friend IMutableContext& getCurrentMutableContext();
7690
7691 private:
7692 IGeneratorsForTest* findGeneratorsForCurrentTest() {
7693 std::string testName = getResultCapture()->getCurrentTestName();
7694
7695 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
7696 m_generatorsByTestName.find( testName );
7697 return it != m_generatorsByTestName.end()
7698 ? it->second
7699 : CATCH_NULL;
7700 }
7701
7702 IGeneratorsForTest& getGeneratorsForCurrentTest() {
7703 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7704 if( !generators ) {
7705 std::string testName = getResultCapture()->getCurrentTestName();
7706 generators = createGeneratorsForTest();
7707 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
7708 }
7709 return *generators;
7710 }
7711
7712 private:
7713 Ptr<IConfig const> m_config;
7714 IRunner* m_runner;
7715 IResultCapture* m_resultCapture;
7716 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7717 };
7718
7719 namespace {
7720 Context* currentContext = CATCH_NULL;
7721 }
7722 IMutableContext& getCurrentMutableContext() {
7723 if( !currentContext )
7724 currentContext = new Context();
7725 return *currentContext;
7726 }
7727 IContext& getCurrentContext() {
7728 return getCurrentMutableContext();
7729 }
7730
7731 void cleanUpContext() {
7732 delete currentContext;
7733 currentContext = CATCH_NULL;
7734 }
7735}
7736
7737// #included from: catch_console_colour_impl.hpp
7738#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7739
7740// #included from: catch_errno_guard.hpp
7741#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
7742
7743#include <cerrno>
7744
7745namespace Catch {
7746
7747 class ErrnoGuard {
7748 public:
7749 ErrnoGuard():m_oldErrno(errno){}
7750 ~ErrnoGuard() { errno = m_oldErrno; }
7751 private:
7752 int m_oldErrno;
7753 };
7754
7755}
7756
7757namespace Catch {
7758 namespace {
7759
7760 struct IColourImpl {
7761 virtual ~IColourImpl() {}
7762 virtual void use( Colour::Code _colourCode ) = 0;
7763 };
7764
7765 struct NoColourImpl : IColourImpl {
7766 void use( Colour::Code ) {}
7767
7768 static IColourImpl* instance() {
7769 static NoColourImpl s_instance;
7770 return &s_instance;
7771 }
7772 };
7773
7774 } // anon namespace
7775} // namespace Catch
7776
7777#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7778# ifdef CATCH_PLATFORM_WINDOWS
7779# define CATCH_CONFIG_COLOUR_WINDOWS
7780# else
7781# define CATCH_CONFIG_COLOUR_ANSI
7782# endif
7783#endif
7784
7785#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
7786
7787namespace Catch {
7788namespace {
7789
7790 class Win32ColourImpl : public IColourImpl {
7791 public:
7792 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
7793 {
7794 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7795 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
7796 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7797 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
7798 }
7799
7800 virtual void use( Colour::Code _colourCode ) {
7801 switch( _colourCode ) {
7802 case Colour::None: return setTextAttribute( originalForegroundAttributes );
7803 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7804 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
7805 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
7806 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
7807 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7808 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7809 case Colour::Grey: return setTextAttribute( 0 );
7810
7811 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
7812 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7813 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
7814 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7815
7816 case Colour::Bright: throw std::logic_error( "not a colour" );
7817 }
7818 }
7819
7820 private:
7821 void setTextAttribute( WORD _textAttribute ) {
7822 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
7823 }
7824 HANDLE stdoutHandle;
7825 WORD originalForegroundAttributes;
7826 WORD originalBackgroundAttributes;
7827 };
7828
7829 IColourImpl* platformColourInstance() {
7830 static Win32ColourImpl s_instance;
7831
7832 Ptr<IConfig const> config = getCurrentContext().getConfig();
7833 UseColour::YesOrNo colourMode = config
7834 ? config->useColour()
7835 : UseColour::Auto;
7836 if( colourMode == UseColour::Auto )
7837 colourMode = !isDebuggerActive()
7838 ? UseColour::Yes
7839 : UseColour::No;
7840 return colourMode == UseColour::Yes
7841 ? &s_instance
7842 : NoColourImpl::instance();
7843 }
7844
7845} // end anon namespace
7846} // end namespace Catch
7847
7848#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
7849
7850#include <unistd.h>
7851
7852namespace Catch {
7853namespace {
7854
7855 // use POSIX/ ANSI console terminal codes
7856 // Thanks to Adam Strzelecki for original contribution
7857 // (http://github.com/nanoant)
7858 // https://github.com/philsquared/Catch/pull/131
7859 class PosixColourImpl : public IColourImpl {
7860 public:
7861 virtual void use( Colour::Code _colourCode ) {
7862 switch( _colourCode ) {
7863 case Colour::None:
7864 case Colour::White: return setColour( "[0m" );
7865 case Colour::Red: return setColour( "[0;31m" );
7866 case Colour::Green: return setColour( "[0;32m" );
7867 case Colour::Blue: return setColour( "[0;34m" );
7868 case Colour::Cyan: return setColour( "[0;36m" );
7869 case Colour::Yellow: return setColour( "[0;33m" );
7870 case Colour::Grey: return setColour( "[1;30m" );
7871
7872 case Colour::LightGrey: return setColour( "[0;37m" );
7873 case Colour::BrightRed: return setColour( "[1;31m" );
7874 case Colour::BrightGreen: return setColour( "[1;32m" );
7875 case Colour::BrightWhite: return setColour( "[1;37m" );
7876
7877 case Colour::Bright: throw std::logic_error( "not a colour" );
7878 }
7879 }
7880 static IColourImpl* instance() {
7881 static PosixColourImpl s_instance;
7882 return &s_instance;
7883 }
7884
7885 private:
7886 void setColour( const char* _escapeCode ) {
7887 Catch::cout() << '\033' << _escapeCode;
7888 }
7889 };
7890
7891 IColourImpl* platformColourInstance() {
7892 ErrnoGuard guard;
7893 Ptr<IConfig const> config = getCurrentContext().getConfig();
7894 UseColour::YesOrNo colourMode = config
7895 ? config->useColour()
7896 : UseColour::Auto;
7897 if( colourMode == UseColour::Auto )
7898 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
7899 ? UseColour::Yes
7900 : UseColour::No;
7901 return colourMode == UseColour::Yes
7902 ? PosixColourImpl::instance()
7903 : NoColourImpl::instance();
7904 }
7905
7906} // end anon namespace
7907} // end namespace Catch
7908
7909#else // not Windows or ANSI ///////////////////////////////////////////////
7910
7911namespace Catch {
7912
7913 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
7914
7915} // end namespace Catch
7916
7917#endif // Windows/ ANSI/ None
7918
7919namespace Catch {
7920
7921 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7922 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
7923 Colour::~Colour(){ if( !m_moved ) use( None ); }
7924
7925 void Colour::use( Code _colourCode ) {
7926 static IColourImpl* impl = platformColourInstance();
7927 impl->use( _colourCode );
7928 }
7929
7930} // end namespace Catch
7931
7932// #included from: catch_generators_impl.hpp
7933#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7934
7935#include <vector>
7936#include <string>
7937#include <map>
7938
7939namespace Catch {
7940
7941 struct GeneratorInfo : IGeneratorInfo {
7942
7943 GeneratorInfo( std::size_t size )
7944 : m_size( size ),
7945 m_currentIndex( 0 )
7946 {}
7947
7948 bool moveNext() {
7949 if( ++m_currentIndex == m_size ) {
7950 m_currentIndex = 0;
7951 return false;
7952 }
7953 return true;
7954 }
7955
7956 std::size_t getCurrentIndex() const {
7957 return m_currentIndex;
7958 }
7959
7960 std::size_t m_size;
7961 std::size_t m_currentIndex;
7962 };
7963
7964 ///////////////////////////////////////////////////////////////////////////
7965
7966 class GeneratorsForTest : public IGeneratorsForTest {
7967
7968 public:
7969 ~GeneratorsForTest() {
7970 deleteAll( m_generatorsInOrder );
7971 }
7972
7973 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
7974 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7975 if( it == m_generatorsByName.end() ) {
7976 IGeneratorInfo* info = new GeneratorInfo( size );
7977 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
7978 m_generatorsInOrder.push_back( info );
7979 return *info;
7980 }
7981 return *it->second;
7982 }
7983
7984 bool moveNext() {
7985 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7986 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7987 for(; it != itEnd; ++it ) {
7988 if( (*it)->moveNext() )
7989 return true;
7990 }
7991 return false;
7992 }
7993
7994 private:
7995 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7996 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7997 };
7998
7999 IGeneratorsForTest* createGeneratorsForTest()
8000 {
8001 return new GeneratorsForTest();
8002 }
8003
8004} // end namespace Catch
8005
8006// #included from: catch_assertionresult.hpp
8007#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
8008
8009namespace Catch {
8010
8011 AssertionInfo::AssertionInfo( std::string const& _macroName,
8012 SourceLineInfo const& _lineInfo,
8013 std::string const& _capturedExpression,
8014 ResultDisposition::Flags _resultDisposition )
8015 : macroName( _macroName ),
8016 lineInfo( _lineInfo ),
8017 capturedExpression( _capturedExpression ),
8018 resultDisposition( _resultDisposition )
8019 {}
8020
8021 AssertionResult::AssertionResult() {}
8022
8023 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
8024 : m_info( info ),
8025 m_resultData( data )
8026 {}
8027
8028 AssertionResult::~AssertionResult() {}
8029
8030 // Result was a success
8031 bool AssertionResult::succeeded() const {
8032 return Catch::isOk( m_resultData.resultType );
8033 }
8034
8035 // Result was a success, or failure is suppressed
8036 bool AssertionResult::isOk() const {
8037 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
8038 }
8039
8040 ResultWas::OfType AssertionResult::getResultType() const {
8041 return m_resultData.resultType;
8042 }
8043
8044 bool AssertionResult::hasExpression() const {
8045 return !m_info.capturedExpression.empty();
8046 }
8047
8048 bool AssertionResult::hasMessage() const {
8049 return !m_resultData.message.empty();
8050 }
8051
8052 std::string AssertionResult::getExpression() const {
8053 if( isFalseTest( m_info.resultDisposition ) )
8054 return '!' + m_info.capturedExpression;
8055 else
8056 return m_info.capturedExpression;
8057 }
8058 std::string AssertionResult::getExpressionInMacro() const {
8059 if( m_info.macroName.empty() )
8060 return m_info.capturedExpression;
8061 else
8062 return m_info.macroName + "( " + m_info.capturedExpression + " )";
8063 }
8064
8065 bool AssertionResult::hasExpandedExpression() const {
8066 return hasExpression() && getExpandedExpression() != getExpression();
8067 }
8068
8069 std::string AssertionResult::getExpandedExpression() const {
8070 return m_resultData.reconstructExpression();
8071 }
8072
8073 std::string AssertionResult::getMessage() const {
8074 return m_resultData.message;
8075 }
8076 SourceLineInfo AssertionResult::getSourceInfo() const {
8077 return m_info.lineInfo;
8078 }
8079
8080 std::string AssertionResult::getTestMacroName() const {
8081 return m_info.macroName;
8082 }
8083
8084 void AssertionResult::discardDecomposedExpression() const {
8085 m_resultData.decomposedExpression = CATCH_NULL;
8086 }
8087
8088 void AssertionResult::expandDecomposedExpression() const {
8089 m_resultData.reconstructExpression();
8090 }
8091
8092} // end namespace Catch
8093
8094// #included from: catch_test_case_info.hpp
8095#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
8096
8097#include <cctype>
8098
8099namespace Catch {
8100
8101 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
8102 if( startsWith( tag, '.' ) ||
8103 tag == "hide" ||
8104 tag == "!hide" )
8105 return TestCaseInfo::IsHidden;
8106 else if( tag == "!throws" )
8107 return TestCaseInfo::Throws;
8108 else if( tag == "!shouldfail" )
8109 return TestCaseInfo::ShouldFail;
8110 else if( tag == "!mayfail" )
8111 return TestCaseInfo::MayFail;
8112 else if( tag == "!nonportable" )
8113 return TestCaseInfo::NonPortable;
8114 else
8115 return TestCaseInfo::None;
8116 }
8117 inline bool isReservedTag( std::string const& tag ) {
8118 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
8119 }
8120 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
8121 if( isReservedTag( tag ) ) {
8122 std::ostringstream ss;
8123 ss << Colour(Colour::Red)
8124 << "Tag name [" << tag << "] not allowed.\n"
8125 << "Tag names starting with non alpha-numeric characters are reserved\n"
8126 << Colour(Colour::FileName)
8127 << _lineInfo << '\n';
8128 throw std::runtime_error(ss.str());
8129 }
8130 }
8131
8132 TestCase makeTestCase( ITestCase* _testCase,
8133 std::string const& _className,
8134 std::string const& _name,
8135 std::string const& _descOrTags,
8136 SourceLineInfo const& _lineInfo )
8137 {
8138 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
8139
8140 // Parse out tags
8141 std::set<std::string> tags;
8142 std::string desc, tag;
8143 bool inTag = false;
8144 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
8145 char c = _descOrTags[i];
8146 if( !inTag ) {
8147 if( c == '[' )
8148 inTag = true;
8149 else
8150 desc += c;
8151 }
8152 else {
8153 if( c == ']' ) {
8154 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
8155 if( prop == TestCaseInfo::IsHidden )
8156 isHidden = true;
8157 else if( prop == TestCaseInfo::None )
8158 enforceNotReservedTag( tag, _lineInfo );
8159
8160 tags.insert( tag );
8161 tag.clear();
8162 inTag = false;
8163 }
8164 else
8165 tag += c;
8166 }
8167 }
8168 if( isHidden ) {
8169 tags.insert( "hide" );
8170 tags.insert( "." );
8171 }
8172
8173 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
8174 return TestCase( _testCase, info );
8175 }
8176
8177 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
8178 {
8179 testCaseInfo.tags = tags;
8180 testCaseInfo.lcaseTags.clear();
8181
8182 std::ostringstream oss;
8183 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
8184 oss << '[' << *it << ']';
8185 std::string lcaseTag = toLower( *it );
8186 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
8187 testCaseInfo.lcaseTags.insert( lcaseTag );
8188 }
8189 testCaseInfo.tagsAsString = oss.str();
8190 }
8191
8192 TestCaseInfo::TestCaseInfo( std::string const& _name,
8193 std::string const& _className,
8194 std::string const& _description,
8195 std::set<std::string> const& _tags,
8196 SourceLineInfo const& _lineInfo )
8197 : name( _name ),
8198 className( _className ),
8199 description( _description ),
8200 lineInfo( _lineInfo ),
8201 properties( None )
8202 {
8203 setTags( *this, _tags );
8204 }
8205
8206 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
8207 : name( other.name ),
8208 className( other.className ),
8209 description( other.description ),
8210 tags( other.tags ),
8211 lcaseTags( other.lcaseTags ),
8212 tagsAsString( other.tagsAsString ),
8213 lineInfo( other.lineInfo ),
8214 properties( other.properties )
8215 {}
8216
8217 bool TestCaseInfo::isHidden() const {
8218 return ( properties & IsHidden ) != 0;
8219 }
8220 bool TestCaseInfo::throws() const {
8221 return ( properties & Throws ) != 0;
8222 }
8223 bool TestCaseInfo::okToFail() const {
8224 return ( properties & (ShouldFail | MayFail ) ) != 0;
8225 }
8226 bool TestCaseInfo::expectedToFail() const {
8227 return ( properties & (ShouldFail ) ) != 0;
8228 }
8229
8230 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
8231
8232 TestCase::TestCase( TestCase const& other )
8233 : TestCaseInfo( other ),
8234 test( other.test )
8235 {}
8236
8237 TestCase TestCase::withName( std::string const& _newName ) const {
8238 TestCase other( *this );
8239 other.name = _newName;
8240 return other;
8241 }
8242
8243 void TestCase::swap( TestCase& other ) {
8244 test.swap( other.test );
8245 name.swap( other.name );
8246 className.swap( other.className );
8247 description.swap( other.description );
8248 tags.swap( other.tags );
8249 lcaseTags.swap( other.lcaseTags );
8250 tagsAsString.swap( other.tagsAsString );
8251 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
8252 std::swap( lineInfo, other.lineInfo );
8253 }
8254
8255 void TestCase::invoke() const {
8256 test->invoke();
8257 }
8258
8259 bool TestCase::operator == ( TestCase const& other ) const {
8260 return test.get() == other.test.get() &&
8261 name == other.name &&
8262 className == other.className;
8263 }
8264
8265 bool TestCase::operator < ( TestCase const& other ) const {
8266 return name < other.name;
8267 }
8268 TestCase& TestCase::operator = ( TestCase const& other ) {
8269 TestCase temp( other );
8270 swap( temp );
8271 return *this;
8272 }
8273
8274 TestCaseInfo const& TestCase::getTestCaseInfo() const
8275 {
8276 return *this;
8277 }
8278
8279} // end namespace Catch
8280
8281// #included from: catch_version.hpp
8282#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
8283
8284namespace Catch {
8285
8286 Version::Version
8287 ( unsigned int _majorVersion,
8288 unsigned int _minorVersion,
8289 unsigned int _patchNumber,
8290 char const * const _branchName,
8291 unsigned int _buildNumber )
8292 : majorVersion( _majorVersion ),
8293 minorVersion( _minorVersion ),
8294 patchNumber( _patchNumber ),
8295 branchName( _branchName ),
8296 buildNumber( _buildNumber )
8297 {}
8298
8299 std::ostream& operator << ( std::ostream& os, Version const& version ) {
8300 os << version.majorVersion << '.'
8301 << version.minorVersion << '.'
8302 << version.patchNumber;
8303 // branchName is never null -> 0th char is \0 if it is empty
8304 if (version.branchName[0]) {
8305 os << '-' << version.branchName
8306 << '.' << version.buildNumber;
8307 }
8308 return os;
8309 }
8310
8311 inline Version libraryVersion() {
8312 static Version version( 1, 9, 4, "", 0 );
8313 return version;
8314 }
8315
8316}
8317
8318// #included from: catch_message.hpp
8319#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
8320
8321namespace Catch {
8322
8323 MessageInfo::MessageInfo( std::string const& _macroName,
8324 SourceLineInfo const& _lineInfo,
8325 ResultWas::OfType _type )
8326 : macroName( _macroName ),
8327 lineInfo( _lineInfo ),
8328 type( _type ),
8329 sequence( ++globalCount )
8330 {}
8331
8332 // This may need protecting if threading support is added
8333 unsigned int MessageInfo::globalCount = 0;
8334
8335 ////////////////////////////////////////////////////////////////////////////
8336
8337 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
8338 : m_info( builder.m_info )
8339 {
8340 m_info.message = builder.m_stream.str();
8341 getResultCapture().pushScopedMessage( m_info );
8342 }
8343 ScopedMessage::ScopedMessage( ScopedMessage const& other )
8344 : m_info( other.m_info )
8345 {}
8346
8347 ScopedMessage::~ScopedMessage() {
8348 if ( !std::uncaught_exception() ){
8349 getResultCapture().popScopedMessage(m_info);
8350 }
8351 }
8352
8353} // end namespace Catch
8354
8355// #included from: catch_legacy_reporter_adapter.hpp
8356#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
8357
8358// #included from: catch_legacy_reporter_adapter.h
8359#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
8360
8361namespace Catch
8362{
8363 // Deprecated
8364 struct IReporter : IShared {
8365 virtual ~IReporter();
8366
8367 virtual bool shouldRedirectStdout() const = 0;
8368
8369 virtual void StartTesting() = 0;
8370 virtual void EndTesting( Totals const& totals ) = 0;
8371 virtual void StartGroup( std::string const& groupName ) = 0;
8372 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
8373 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
8374 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
8375 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
8376 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
8377 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
8378 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
8379 virtual void Aborted() = 0;
8380 virtual void Result( AssertionResult const& result ) = 0;
8381 };
8382
8383 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
8384 {
8385 public:
8386 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
8387 virtual ~LegacyReporterAdapter();
8388
8389 virtual ReporterPreferences getPreferences() const;
8390 virtual void noMatchingTestCases( std::string const& );
8391 virtual void testRunStarting( TestRunInfo const& );
8392 virtual void testGroupStarting( GroupInfo const& groupInfo );
8393 virtual void testCaseStarting( TestCaseInfo const& testInfo );
8394 virtual void sectionStarting( SectionInfo const& sectionInfo );
8395 virtual void assertionStarting( AssertionInfo const& );
8396 virtual bool assertionEnded( AssertionStats const& assertionStats );
8397 virtual void sectionEnded( SectionStats const& sectionStats );
8398 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
8399 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
8400 virtual void testRunEnded( TestRunStats const& testRunStats );
8401 virtual void skipTest( TestCaseInfo const& );
8402
8403 private:
8404 Ptr<IReporter> m_legacyReporter;
8405 };
8406}
8407
8408namespace Catch
8409{
8410 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
8411 : m_legacyReporter( legacyReporter )
8412 {}
8413 LegacyReporterAdapter::~LegacyReporterAdapter() {}
8414
8415 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
8416 ReporterPreferences prefs;
8417 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
8418 return prefs;
8419 }
8420
8421 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
8422 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
8423 m_legacyReporter->StartTesting();
8424 }
8425 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
8426 m_legacyReporter->StartGroup( groupInfo.name );
8427 }
8428 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
8429 m_legacyReporter->StartTestCase( testInfo );
8430 }
8431 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
8432 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
8433 }
8434 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
8435 // Not on legacy interface
8436 }
8437
8438 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
8439 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8440 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8441 it != itEnd;
8442 ++it ) {
8443 if( it->type == ResultWas::Info ) {
8444 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
8445 rb << it->message;
8446 rb.setResultType( ResultWas::Info );
8447 AssertionResult result = rb.build();
8448 m_legacyReporter->Result( result );
8449 }
8450 }
8451 }
8452 m_legacyReporter->Result( assertionStats.assertionResult );
8453 return true;
8454 }
8455 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
8456 if( sectionStats.missingAssertions )
8457 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
8458 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
8459 }
8460 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
8461 m_legacyReporter->EndTestCase
8462 ( testCaseStats.testInfo,
8463 testCaseStats.totals,
8464 testCaseStats.stdOut,
8465 testCaseStats.stdErr );
8466 }
8467 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
8468 if( testGroupStats.aborting )
8469 m_legacyReporter->Aborted();
8470 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
8471 }
8472 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
8473 m_legacyReporter->EndTesting( testRunStats.totals );
8474 }
8475 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
8476 }
8477}
8478
8479// #included from: catch_timer.hpp
8480
8481#ifdef __clang__
8482#pragma clang diagnostic push
8483#pragma clang diagnostic ignored "-Wc++11-long-long"
8484#endif
8485
8486#ifdef CATCH_PLATFORM_WINDOWS
8487
8488#else
8489
8490#include <sys/time.h>
8491
8492#endif
8493
8494namespace Catch {
8495
8496 namespace {
8497#ifdef CATCH_PLATFORM_WINDOWS
8498 UInt64 getCurrentTicks() {
8499 static UInt64 hz=0, hzo=0;
8500 if (!hz) {
8501 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
8502 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
8503 }
8504 UInt64 t;
8505 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
8506 return ((t-hzo)*1000000)/hz;
8507 }
8508#else
8509 UInt64 getCurrentTicks() {
8510 timeval t;
8511 gettimeofday(&t,CATCH_NULL);
8512 return static_cast<UInt64>( t.tv_sec ) * 1000000ull + static_cast<UInt64>( t.tv_usec );
8513 }
8514#endif
8515 }
8516
8517 void Timer::start() {
8518 m_ticks = getCurrentTicks();
8519 }
8520 unsigned int Timer::getElapsedMicroseconds() const {
8521 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
8522 }
8523 unsigned int Timer::getElapsedMilliseconds() const {
8524 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
8525 }
8526 double Timer::getElapsedSeconds() const {
8527 return getElapsedMicroseconds()/1000000.0;
8528 }
8529
8530} // namespace Catch
8531
8532#ifdef __clang__
8533#pragma clang diagnostic pop
8534#endif
8535// #included from: catch_common.hpp
8536#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
8537
8538#include <cstring>
8539#include <cctype>
8540
8541namespace Catch {
8542
8543 bool startsWith( std::string const& s, std::string const& prefix ) {
8544 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
8545 }
8546 bool startsWith( std::string const& s, char prefix ) {
8547 return !s.empty() && s[0] == prefix;
8548 }
8549 bool endsWith( std::string const& s, std::string const& suffix ) {
8550 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
8551 }
8552 bool endsWith( std::string const& s, char suffix ) {
8553 return !s.empty() && s[s.size()-1] == suffix;
8554 }
8555 bool contains( std::string const& s, std::string const& infix ) {
8556 return s.find( infix ) != std::string::npos;
8557 }
8558 char toLowerCh(char c) {
8559 return static_cast<char>( std::tolower( c ) );
8560 }
8561 void toLowerInPlace( std::string& s ) {
8562 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
8563 }
8564 std::string toLower( std::string const& s ) {
8565 std::string lc = s;
8566 toLowerInPlace( lc );
8567 return lc;
8568 }
8569 std::string trim( std::string const& str ) {
8570 static char const* whitespaceChars = "\n\r\t ";
8571 std::string::size_type start = str.find_first_not_of( whitespaceChars );
8572 std::string::size_type end = str.find_last_not_of( whitespaceChars );
8573
8574 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
8575 }
8576
8577 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
8578 bool replaced = false;
8579 std::size_t i = str.find( replaceThis );
8580 while( i != std::string::npos ) {
8581 replaced = true;
8582 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
8583 if( i < str.size()-withThis.size() )
8584 i = str.find( replaceThis, i+withThis.size() );
8585 else
8586 i = std::string::npos;
8587 }
8588 return replaced;
8589 }
8590
8591 pluralise::pluralise( std::size_t count, std::string const& label )
8592 : m_count( count ),
8593 m_label( label )
8594 {}
8595
8596 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
8597 os << pluraliser.m_count << ' ' << pluraliser.m_label;
8598 if( pluraliser.m_count != 1 )
8599 os << 's';
8600 return os;
8601 }
8602
8603 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
8604 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
8605 : file( _file ),
8606 line( _line )
8607 {}
8608 bool SourceLineInfo::empty() const {
8609 return file[0] == '\0';
8610 }
8611 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
8612 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
8613 }
8614 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
8615 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
8616 }
8617
8618 void seedRng( IConfig const& config ) {
8619 if( config.rngSeed() != 0 )
8620 std::srand( config.rngSeed() );
8621 }
8622 unsigned int rngSeed() {
8623 return getCurrentContext().getConfig()->rngSeed();
8624 }
8625
8626 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
8627#ifndef __GNUG__
8628 os << info.file << '(' << info.line << ')';
8629#else
8630 os << info.file << ':' << info.line;
8631#endif
8632 return os;
8633 }
8634
8635 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
8636 std::ostringstream oss;
8637 oss << locationInfo << ": Internal Catch error: '" << message << '\'';
8638 if( alwaysTrue() )
8639 throw std::logic_error( oss.str() );
8640 }
8641}
8642
8643// #included from: catch_section.hpp
8644#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
8645
8646namespace Catch {
8647
8648 SectionInfo::SectionInfo
8649 ( SourceLineInfo const& _lineInfo,
8650 std::string const& _name,
8651 std::string const& _description )
8652 : name( _name ),
8653 description( _description ),
8654 lineInfo( _lineInfo )
8655 {}
8656
8657 Section::Section( SectionInfo const& info )
8658 : m_info( info ),
8659 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
8660 {
8661 m_timer.start();
8662 }
8663
8664 Section::~Section() {
8665 if( m_sectionIncluded ) {
8666 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
8667 if( std::uncaught_exception() )
8668 getResultCapture().sectionEndedEarly( endInfo );
8669 else
8670 getResultCapture().sectionEnded( endInfo );
8671 }
8672 }
8673
8674 // This indicates whether the section should be executed or not
8675 Section::operator bool() const {
8676 return m_sectionIncluded;
8677 }
8678
8679} // end namespace Catch
8680
8681// #included from: catch_debugger.hpp
8682#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
8683
8684#ifdef CATCH_PLATFORM_MAC
8685
8686 #include <assert.h>
8687 #include <stdbool.h>
8688 #include <sys/types.h>
8689 #include <unistd.h>
8690 #include <sys/sysctl.h>
8691
8692 namespace Catch{
8693
8694 // The following function is taken directly from the following technical note:
8695 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
8696
8697 // Returns true if the current process is being debugged (either
8698 // running under the debugger or has a debugger attached post facto).
8699 bool isDebuggerActive(){
8700
8701 int mib[4];
8702 struct kinfo_proc info;
8703 size_t size;
8704
8705 // Initialize the flags so that, if sysctl fails for some bizarre
8706 // reason, we get a predictable result.
8707
8708 info.kp_proc.p_flag = 0;
8709
8710 // Initialize mib, which tells sysctl the info we want, in this case
8711 // we're looking for information about a specific process ID.
8712
8713 mib[0] = CTL_KERN;
8714 mib[1] = KERN_PROC;
8715 mib[2] = KERN_PROC_PID;
8716 mib[3] = getpid();
8717
8718 // Call sysctl.
8719
8720 size = sizeof(info);
8721 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
8722 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
8723 return false;
8724 }
8725
8726 // We're being debugged if the P_TRACED flag is set.
8727
8728 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8729 }
8730 } // namespace Catch
8731
8732#elif defined(CATCH_PLATFORM_LINUX)
8733 #include <fstream>
8734 #include <string>
8735
8736 namespace Catch{
8737 // The standard POSIX way of detecting a debugger is to attempt to
8738 // ptrace() the process, but this needs to be done from a child and not
8739 // this process itself to still allow attaching to this process later
8740 // if wanted, so is rather heavy. Under Linux we have the PID of the
8741 // "debugger" (which doesn't need to be gdb, of course, it could also
8742 // be strace, for example) in /proc/$PID/status, so just get it from
8743 // there instead.
8744 bool isDebuggerActive(){
8745 // Libstdc++ has a bug, where std::ifstream sets errno to 0
8746 // This way our users can properly assert over errno values
8747 ErrnoGuard guard;
8748 std::ifstream in("/proc/self/status");
8749 for( std::string line; std::getline(in, line); ) {
8750 static const int PREFIX_LEN = 11;
8751 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
8752 // We're traced if the PID is not 0 and no other PID starts
8753 // with 0 digit, so it's enough to check for just a single
8754 // character.
8755 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
8756 }
8757 }
8758
8759 return false;
8760 }
8761 } // namespace Catch
8762#elif defined(_MSC_VER)
8763 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8764 namespace Catch {
8765 bool isDebuggerActive() {
8766 return IsDebuggerPresent() != 0;
8767 }
8768 }
8769#elif defined(__MINGW32__)
8770 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8771 namespace Catch {
8772 bool isDebuggerActive() {
8773 return IsDebuggerPresent() != 0;
8774 }
8775 }
8776#else
8777 namespace Catch {
8778 inline bool isDebuggerActive() { return false; }
8779 }
8780#endif // Platform
8781
8782#ifdef CATCH_PLATFORM_WINDOWS
8783
8784 namespace Catch {
8785 void writeToDebugConsole( std::string const& text ) {
8786 ::OutputDebugStringA( text.c_str() );
8787 }
8788 }
8789#else
8790 namespace Catch {
8791 void writeToDebugConsole( std::string const& text ) {
8792 // !TBD: Need a version for Mac/ XCode and other IDEs
8793 Catch::cout() << text;
8794 }
8795 }
8796#endif // Platform
8797
8798// #included from: catch_tostring.hpp
8799#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8800
8801namespace Catch {
8802
8803namespace Detail {
8804
8805 const std::string unprintableString = "{?}";
8806
8807 namespace {
8808 const int hexThreshold = 255;
8809
8810 struct Endianness {
8811 enum Arch { Big, Little };
8812
8813 static Arch which() {
8814 union _{
8815 int asInt;
8816 char asChar[sizeof (int)];
8817 } u;
8818
8819 u.asInt = 1;
8820 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
8821 }
8822 };
8823 }
8824
8825 std::string rawMemoryToString( const void *object, std::size_t size )
8826 {
8827 // Reverse order for little endian architectures
8828 int i = 0, end = static_cast<int>( size ), inc = 1;
8829 if( Endianness::which() == Endianness::Little ) {
8830 i = end-1;
8831 end = inc = -1;
8832 }
8833
8834 unsigned char const *bytes = static_cast<unsigned char const *>(object);
8835 std::ostringstream os;
8836 os << "0x" << std::setfill('0') << std::hex;
8837 for( ; i != end; i += inc )
8838 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
8839 return os.str();
8840 }
8841}
8842
8843std::string toString( std::string const& value ) {
8844 std::string s = value;
8845 if( getCurrentContext().getConfig()->showInvisibles() ) {
8846 for(size_t i = 0; i < s.size(); ++i ) {
8847 std::string subs;
8848 switch( s[i] ) {
8849 case '\n': subs = "\\n"; break;
8850 case '\t': subs = "\\t"; break;
8851 default: break;
8852 }
8853 if( !subs.empty() ) {
8854 s = s.substr( 0, i ) + subs + s.substr( i+1 );
8855 ++i;
8856 }
8857 }
8858 }
8859 return '"' + s + '"';
8860}
8861std::string toString( std::wstring const& value ) {
8862
8863 std::string s;
8864 s.reserve( value.size() );
8865 for(size_t i = 0; i < value.size(); ++i )
8866 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
8867 return Catch::toString( s );
8868}
8869
8870std::string toString( const char* const value ) {
8871 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
8872}
8873
8874std::string toString( char* const value ) {
8875 return Catch::toString( static_cast<const char*>( value ) );
8876}
8877
8878std::string toString( const wchar_t* const value )
8879{
8880 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
8881}
8882
8883std::string toString( wchar_t* const value )
8884{
8885 return Catch::toString( static_cast<const wchar_t*>( value ) );
8886}
8887
8888std::string toString( int value ) {
8889 std::ostringstream oss;
8890 oss << value;
8891 if( value > Detail::hexThreshold )
8892 oss << " (0x" << std::hex << value << ')';
8893 return oss.str();
8894}
8895
8896std::string toString( unsigned long value ) {
8897 std::ostringstream oss;
8898 oss << value;
8899 if( value > Detail::hexThreshold )
8900 oss << " (0x" << std::hex << value << ')';
8901 return oss.str();
8902}
8903
8904std::string toString( unsigned int value ) {
8905 return Catch::toString( static_cast<unsigned long>( value ) );
8906}
8907
8908template<typename T>
8909std::string fpToString( T value, int precision ) {
8910 std::ostringstream oss;
8911 oss << std::setprecision( precision )
8912 << std::fixed
8913 << value;
8914 std::string d = oss.str();
8915 std::size_t i = d.find_last_not_of( '0' );
8916 if( i != std::string::npos && i != d.size()-1 ) {
8917 if( d[i] == '.' )
8918 i++;
8919 d = d.substr( 0, i+1 );
8920 }
8921 return d;
8922}
8923
8924std::string toString( const double value ) {
8925 return fpToString( value, 10 );
8926}
8927std::string toString( const float value ) {
8928 return fpToString( value, 5 ) + 'f';
8929}
8930
8931std::string toString( bool value ) {
8932 return value ? "true" : "false";
8933}
8934
8935std::string toString( char value ) {
8936 if ( value == '\r' )
8937 return "'\\r'";
8938 if ( value == '\f' )
8939 return "'\\f'";
8940 if ( value == '\n' )
8941 return "'\\n'";
8942 if ( value == '\t' )
8943 return "'\\t'";
8944 if ( '\0' <= value && value < ' ' )
8945 return toString( static_cast<unsigned int>( value ) );
8946 char chstr[] = "' '";
8947 chstr[1] = value;
8948 return chstr;
8949}
8950
8951std::string toString( signed char value ) {
8952 return toString( static_cast<char>( value ) );
8953}
8954
8955std::string toString( unsigned char value ) {
8956 return toString( static_cast<char>( value ) );
8957}
8958
8959#ifdef CATCH_CONFIG_CPP11_LONG_LONG
8960std::string toString( long long value ) {
8961 std::ostringstream oss;
8962 oss << value;
8963 if( value > Detail::hexThreshold )
8964 oss << " (0x" << std::hex << value << ')';
8965 return oss.str();
8966}
8967std::string toString( unsigned long long value ) {
8968 std::ostringstream oss;
8969 oss << value;
8970 if( value > Detail::hexThreshold )
8971 oss << " (0x" << std::hex << value << ')';
8972 return oss.str();
8973}
8974#endif
8975
8976#ifdef CATCH_CONFIG_CPP11_NULLPTR
8977std::string toString( std::nullptr_t ) {
8978 return "nullptr";
8979}
8980#endif
8981
8982#ifdef __OBJC__
8983 std::string toString( NSString const * const& nsstring ) {
8984 if( !nsstring )
8985 return "nil";
8986 return "@" + toString([nsstring UTF8String]);
8987 }
8988 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
8989 if( !nsstring )
8990 return "nil";
8991 return "@" + toString([nsstring UTF8String]);
8992 }
8993 std::string toString( NSObject* const& nsObject ) {
8994 return toString( [nsObject description] );
8995 }
8996#endif
8997
8998} // end namespace Catch
8999
9000// #included from: catch_result_builder.hpp
9001#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
9002
9003namespace Catch {
9004
9005 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
9006 return secondArg.empty() || secondArg == "\"\""
9007 ? capturedExpression
9008 : capturedExpression + ", " + secondArg;
9009 }
9010 ResultBuilder::ResultBuilder( char const* macroName,
9011 SourceLineInfo const& lineInfo,
9012 char const* capturedExpression,
9013 ResultDisposition::Flags resultDisposition,
9014 char const* secondArg )
9015 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
9016 m_shouldDebugBreak( false ),
9017 m_shouldThrow( false ),
9018 m_guardException( false )
9019 {}
9020
9021 ResultBuilder::~ResultBuilder() {
9022#if defined(CATCH_CONFIG_FAST_COMPILE)
9023 if ( m_guardException ) {
9024 m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
9025 captureResult( ResultWas::ThrewException );
9026 getCurrentContext().getResultCapture()->exceptionEarlyReported();
9027 }
9028#endif
9029 }
9030
9031 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
9032 m_data.resultType = result;
9033 return *this;
9034 }
9035 ResultBuilder& ResultBuilder::setResultType( bool result ) {
9036 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
9037 return *this;
9038 }
9039
9040 void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
9041 AssertionResult result = build( expr );
9042 handleResult( result );
9043 }
9044
9045 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
9046 m_assertionInfo.resultDisposition = resultDisposition;
9047 m_stream.oss << Catch::translateActiveException();
9048 captureResult( ResultWas::ThrewException );
9049 }
9050
9051 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
9052 setResultType( resultType );
9053 captureExpression();
9054 }
9055
9056 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
9057 if( expectedMessage.empty() )
9058 captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() );
9059 else
9060 captureExpectedException( Matchers::Equals( expectedMessage ) );
9061 }
9062
9063 void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) {
9064
9065 assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
9066 AssertionResultData data = m_data;
9067 data.resultType = ResultWas::Ok;
9068 data.reconstructedExpression = m_assertionInfo.capturedExpression;
9069
9070 std::string actualMessage = Catch::translateActiveException();
9071 if( !matcher.match( actualMessage ) ) {
9072 data.resultType = ResultWas::ExpressionFailed;
9073 data.reconstructedExpression = actualMessage;
9074 }
9075 AssertionResult result( m_assertionInfo, data );
9076 handleResult( result );
9077 }
9078
9079 void ResultBuilder::captureExpression() {
9080 AssertionResult result = build();
9081 handleResult( result );
9082 }
9083
9084 void ResultBuilder::handleResult( AssertionResult const& result )
9085 {
9086 getResultCapture().assertionEnded( result );
9087
9088 if( !result.isOk() ) {
9089 if( getCurrentContext().getConfig()->shouldDebugBreak() )
9090 m_shouldDebugBreak = true;
9091 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
9092 m_shouldThrow = true;
9093 }
9094 }
9095
9096 void ResultBuilder::react() {
9097#if defined(CATCH_CONFIG_FAST_COMPILE)
9098 if (m_shouldDebugBreak) {
9099 ///////////////////////////////////////////////////////////////////
9100 // To inspect the state during test, you need to go one level up the callstack
9101 // To go back to the test and change execution, jump over the throw statement
9102 ///////////////////////////////////////////////////////////////////
9103 CATCH_BREAK_INTO_DEBUGGER();
9104 }
9105#endif
9106 if( m_shouldThrow )
9107 throw Catch::TestFailureException();
9108 }
9109
9110 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
9111 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
9112
9113 AssertionResult ResultBuilder::build() const
9114 {
9115 return build( *this );
9116 }
9117
9118 // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
9119 // a temporary DecomposedExpression, which in turn holds references to
9120 // operands, possibly temporary as well.
9121 // It should immediately be passed to handleResult; if the expression
9122 // needs to be reported, its string expansion must be composed before
9123 // the temporaries are destroyed.
9124 AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
9125 {
9126 assert( m_data.resultType != ResultWas::Unknown );
9127 AssertionResultData data = m_data;
9128
9129 // Flip bool results if FalseTest flag is set
9130 if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
9131 data.negate( expr.isBinaryExpression() );
9132 }
9133
9134 data.message = m_stream.oss.str();
9135 data.decomposedExpression = &expr; // for lazy reconstruction
9136 return AssertionResult( m_assertionInfo, data );
9137 }
9138
9139 void ResultBuilder::reconstructExpression( std::string& dest ) const {
9140 dest = m_assertionInfo.capturedExpression;
9141 }
9142
9143 void ResultBuilder::setExceptionGuard() {
9144 m_guardException = true;
9145 }
9146 void ResultBuilder::unsetExceptionGuard() {
9147 m_guardException = false;
9148 }
9149
9150} // end namespace Catch
9151
9152// #included from: catch_tag_alias_registry.hpp
9153#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
9154
9155namespace Catch {
9156
9157 TagAliasRegistry::~TagAliasRegistry() {}
9158
9159 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
9160 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
9161 if( it != m_registry.end() )
9162 return it->second;
9163 else
9164 return Option<TagAlias>();
9165 }
9166
9167 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
9168 std::string expandedTestSpec = unexpandedTestSpec;
9169 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
9170 it != itEnd;
9171 ++it ) {
9172 std::size_t pos = expandedTestSpec.find( it->first );
9173 if( pos != std::string::npos ) {
9174 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
9175 it->second.tag +
9176 expandedTestSpec.substr( pos + it->first.size() );
9177 }
9178 }
9179 return expandedTestSpec;
9180 }
9181
9182 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
9183
9184 if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
9185 std::ostringstream oss;
9186 oss << Colour( Colour::Red )
9187 << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n"
9188 << Colour( Colour::FileName )
9189 << lineInfo << '\n';
9190 throw std::domain_error( oss.str().c_str() );
9191 }
9192 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
9193 std::ostringstream oss;
9194 oss << Colour( Colour::Red )
9195 << "error: tag alias, \"" << alias << "\" already registered.\n"
9196 << "\tFirst seen at "
9197 << Colour( Colour::Red ) << find(alias)->lineInfo << '\n'
9198 << Colour( Colour::Red ) << "\tRedefined at "
9199 << Colour( Colour::FileName) << lineInfo << '\n';
9200 throw std::domain_error( oss.str().c_str() );
9201 }
9202 }
9203
9204 ITagAliasRegistry::~ITagAliasRegistry() {}
9205
9206 ITagAliasRegistry const& ITagAliasRegistry::get() {
9207 return getRegistryHub().getTagAliasRegistry();
9208 }
9209
9210 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
9211 getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo );
9212 }
9213
9214} // end namespace Catch
9215
9216// #included from: catch_matchers_string.hpp
9217
9218namespace Catch {
9219namespace Matchers {
9220
9221 namespace StdString {
9222
9223 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
9224 : m_caseSensitivity( caseSensitivity ),
9225 m_str( adjustString( str ) )
9226 {}
9227 std::string CasedString::adjustString( std::string const& str ) const {
9228 return m_caseSensitivity == CaseSensitive::No
9229 ? toLower( str )
9230 : str;
9231 }
9232 std::string CasedString::caseSensitivitySuffix() const {
9233 return m_caseSensitivity == CaseSensitive::No
9234 ? " (case insensitive)"
9235 : std::string();
9236 }
9237
9238 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
9239 : m_comparator( comparator ),
9240 m_operation( operation ) {
9241 }
9242
9243 std::string StringMatcherBase::describe() const {
9244 std::string description;
9245 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9246 m_comparator.caseSensitivitySuffix().size());
9247 description += m_operation;
9248 description += ": \"";
9249 description += m_comparator.m_str;
9250 description += "\"";
9251 description += m_comparator.caseSensitivitySuffix();
9252 return description;
9253 }
9254
9255 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
9256
9257 bool EqualsMatcher::match( std::string const& source ) const {
9258 return m_comparator.adjustString( source ) == m_comparator.m_str;
9259 }
9260
9261 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
9262
9263 bool ContainsMatcher::match( std::string const& source ) const {
9264 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
9265 }
9266
9267 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
9268
9269 bool StartsWithMatcher::match( std::string const& source ) const {
9270 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9271 }
9272
9273 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
9274
9275 bool EndsWithMatcher::match( std::string const& source ) const {
9276 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9277 }
9278
9279 } // namespace StdString
9280
9281 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9282 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
9283 }
9284 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9285 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
9286 }
9287 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9288 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9289 }
9290 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9291 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9292 }
9293
9294} // namespace Matchers
9295} // namespace Catch
9296// #included from: ../reporters/catch_reporter_multi.hpp
9297#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
9298
9299namespace Catch {
9300
9301class MultipleReporters : public SharedImpl<IStreamingReporter> {
9302 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
9303 Reporters m_reporters;
9304
9305public:
9306 void add( Ptr<IStreamingReporter> const& reporter ) {
9307 m_reporters.push_back( reporter );
9308 }
9309
9310public: // IStreamingReporter
9311
9312 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9313 return m_reporters[0]->getPreferences();
9314 }
9315
9316 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
9317 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9318 it != itEnd;
9319 ++it )
9320 (*it)->noMatchingTestCases( spec );
9321 }
9322
9323 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
9324 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9325 it != itEnd;
9326 ++it )
9327 (*it)->testRunStarting( testRunInfo );
9328 }
9329
9330 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
9331 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9332 it != itEnd;
9333 ++it )
9334 (*it)->testGroupStarting( groupInfo );
9335 }
9336
9337 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9338 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9339 it != itEnd;
9340 ++it )
9341 (*it)->testCaseStarting( testInfo );
9342 }
9343
9344 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
9345 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9346 it != itEnd;
9347 ++it )
9348 (*it)->sectionStarting( sectionInfo );
9349 }
9350
9351 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
9352 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9353 it != itEnd;
9354 ++it )
9355 (*it)->assertionStarting( assertionInfo );
9356 }
9357
9358 // The return value indicates if the messages buffer should be cleared:
9359 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
9360 bool clearBuffer = false;
9361 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9362 it != itEnd;
9363 ++it )
9364 clearBuffer |= (*it)->assertionEnded( assertionStats );
9365 return clearBuffer;
9366 }
9367
9368 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
9369 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9370 it != itEnd;
9371 ++it )
9372 (*it)->sectionEnded( sectionStats );
9373 }
9374
9375 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
9376 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9377 it != itEnd;
9378 ++it )
9379 (*it)->testCaseEnded( testCaseStats );
9380 }
9381
9382 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
9383 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9384 it != itEnd;
9385 ++it )
9386 (*it)->testGroupEnded( testGroupStats );
9387 }
9388
9389 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9390 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9391 it != itEnd;
9392 ++it )
9393 (*it)->testRunEnded( testRunStats );
9394 }
9395
9396 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9397 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9398 it != itEnd;
9399 ++it )
9400 (*it)->skipTest( testInfo );
9401 }
9402
9403 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
9404 return this;
9405 }
9406
9407};
9408
9409Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
9410 Ptr<IStreamingReporter> resultingReporter;
9411
9412 if( existingReporter ) {
9413 MultipleReporters* multi = existingReporter->tryAsMulti();
9414 if( !multi ) {
9415 multi = new MultipleReporters;
9416 resultingReporter = Ptr<IStreamingReporter>( multi );
9417 if( existingReporter )
9418 multi->add( existingReporter );
9419 }
9420 else
9421 resultingReporter = existingReporter;
9422 multi->add( additionalReporter );
9423 }
9424 else
9425 resultingReporter = additionalReporter;
9426
9427 return resultingReporter;
9428}
9429
9430} // end namespace Catch
9431
9432// #included from: ../reporters/catch_reporter_xml.hpp
9433#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
9434
9435// #included from: catch_reporter_bases.hpp
9436#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
9437
9438#include <cstring>
9439#include <cfloat>
9440#include <cstdio>
9441#include <assert.h>
9442
9443namespace Catch {
9444
9445 namespace {
9446 // Because formatting using c++ streams is stateful, drop down to C is required
9447 // Alternatively we could use stringstream, but its performance is... not good.
9448 std::string getFormattedDuration( double duration ) {
9449 // Max exponent + 1 is required to represent the whole part
9450 // + 1 for decimal point
9451 // + 3 for the 3 decimal places
9452 // + 1 for null terminator
9453 const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
9454 char buffer[maxDoubleSize];
9455
9456 // Save previous errno, to prevent sprintf from overwriting it
9457 ErrnoGuard guard;
9458#ifdef _MSC_VER
9459 sprintf_s(buffer, "%.3f", duration);
9460#else
9461 sprintf(buffer, "%.3f", duration);
9462#endif
9463 return std::string(buffer);
9464 }
9465 }
9466
9467 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
9468
9469 StreamingReporterBase( ReporterConfig const& _config )
9470 : m_config( _config.fullConfig() ),
9471 stream( _config.stream() )
9472 {
9473 m_reporterPrefs.shouldRedirectStdOut = false;
9474 }
9475
9476 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9477 return m_reporterPrefs;
9478 }
9479
9480 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
9481
9482 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
9483
9484 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
9485 currentTestRunInfo = _testRunInfo;
9486 }
9487 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
9488 currentGroupInfo = _groupInfo;
9489 }
9490
9491 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
9492 currentTestCaseInfo = _testInfo;
9493 }
9494 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
9495 m_sectionStack.push_back( _sectionInfo );
9496 }
9497
9498 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
9499 m_sectionStack.pop_back();
9500 }
9501 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
9502 currentTestCaseInfo.reset();
9503 }
9504 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
9505 currentGroupInfo.reset();
9506 }
9507 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
9508 currentTestCaseInfo.reset();
9509 currentGroupInfo.reset();
9510 currentTestRunInfo.reset();
9511 }
9512
9513 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
9514 // Don't do anything with this by default.
9515 // It can optionally be overridden in the derived class.
9516 }
9517
9518 Ptr<IConfig const> m_config;
9519 std::ostream& stream;
9520
9521 LazyStat<TestRunInfo> currentTestRunInfo;
9522 LazyStat<GroupInfo> currentGroupInfo;
9523 LazyStat<TestCaseInfo> currentTestCaseInfo;
9524
9525 std::vector<SectionInfo> m_sectionStack;
9526 ReporterPreferences m_reporterPrefs;
9527 };
9528
9529 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
9530 template<typename T, typename ChildNodeT>
9531 struct Node : SharedImpl<> {
9532 explicit Node( T const& _value ) : value( _value ) {}
9533 virtual ~Node() {}
9534
9535 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
9536 T value;
9537 ChildNodes children;
9538 };
9539 struct SectionNode : SharedImpl<> {
9540 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
9541 virtual ~SectionNode();
9542
9543 bool operator == ( SectionNode const& other ) const {
9544 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
9545 }
9546 bool operator == ( Ptr<SectionNode> const& other ) const {
9547 return operator==( *other );
9548 }
9549
9550 SectionStats stats;
9551 typedef std::vector<Ptr<SectionNode> > ChildSections;
9552 typedef std::vector<AssertionStats> Assertions;
9553 ChildSections childSections;
9554 Assertions assertions;
9555 std::string stdOut;
9556 std::string stdErr;
9557 };
9558
9559 struct BySectionInfo {
9560 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
9561 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
9562 bool operator() ( Ptr<SectionNode> const& node ) const {
9563 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
9564 }
9565 private:
9566 void operator=( BySectionInfo const& );
9567 SectionInfo const& m_other;
9568 };
9569
9570 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
9571 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
9572 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
9573
9574 CumulativeReporterBase( ReporterConfig const& _config )
9575 : m_config( _config.fullConfig() ),
9576 stream( _config.stream() )
9577 {
9578 m_reporterPrefs.shouldRedirectStdOut = false;
9579 }
9580 ~CumulativeReporterBase();
9581
9582 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9583 return m_reporterPrefs;
9584 }
9585
9586 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
9587 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
9588
9589 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
9590
9591 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
9592 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
9593 Ptr<SectionNode> node;
9594 if( m_sectionStack.empty() ) {
9595 if( !m_rootSection )
9596 m_rootSection = new SectionNode( incompleteStats );
9597 node = m_rootSection;
9598 }
9599 else {
9600 SectionNode& parentNode = *m_sectionStack.back();
9601 SectionNode::ChildSections::const_iterator it =
9602 std::find_if( parentNode.childSections.begin(),
9603 parentNode.childSections.end(),
9604 BySectionInfo( sectionInfo ) );
9605 if( it == parentNode.childSections.end() ) {
9606 node = new SectionNode( incompleteStats );
9607 parentNode.childSections.push_back( node );
9608 }
9609 else
9610 node = *it;
9611 }
9612 m_sectionStack.push_back( node );
9613 m_deepestSection = node;
9614 }
9615
9616 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
9617
9618 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
9619 assert( !m_sectionStack.empty() );
9620 SectionNode& sectionNode = *m_sectionStack.back();
9621 sectionNode.assertions.push_back( assertionStats );
9622 // AssertionResult holds a pointer to a temporary DecomposedExpression,
9623 // which getExpandedExpression() calls to build the expression string.
9624 // Our section stack copy of the assertionResult will likely outlive the
9625 // temporary, so it must be expanded or discarded now to avoid calling
9626 // a destroyed object later.
9627 prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
9628 return true;
9629 }
9630 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
9631 assert( !m_sectionStack.empty() );
9632 SectionNode& node = *m_sectionStack.back();
9633 node.stats = sectionStats;
9634 m_sectionStack.pop_back();
9635 }
9636 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
9637 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
9638 assert( m_sectionStack.size() == 0 );
9639 node->children.push_back( m_rootSection );
9640 m_testCases.push_back( node );
9641 m_rootSection.reset();
9642
9643 assert( m_deepestSection );
9644 m_deepestSection->stdOut = testCaseStats.stdOut;
9645 m_deepestSection->stdErr = testCaseStats.stdErr;
9646 }
9647 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
9648 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
9649 node->children.swap( m_testCases );
9650 m_testGroups.push_back( node );
9651 }
9652 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9653 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
9654 node->children.swap( m_testGroups );
9655 m_testRuns.push_back( node );
9656 testRunEndedCumulative();
9657 }
9658 virtual void testRunEndedCumulative() = 0;
9659
9660 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
9661
9662 virtual void prepareExpandedExpression( AssertionResult& result ) const {
9663 if( result.isOk() )
9664 result.discardDecomposedExpression();
9665 else
9666 result.expandDecomposedExpression();
9667 }
9668
9669 Ptr<IConfig const> m_config;
9670 std::ostream& stream;
9671 std::vector<AssertionStats> m_assertions;
9672 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
9673 std::vector<Ptr<TestCaseNode> > m_testCases;
9674 std::vector<Ptr<TestGroupNode> > m_testGroups;
9675
9676 std::vector<Ptr<TestRunNode> > m_testRuns;
9677
9678 Ptr<SectionNode> m_rootSection;
9679 Ptr<SectionNode> m_deepestSection;
9680 std::vector<Ptr<SectionNode> > m_sectionStack;
9681 ReporterPreferences m_reporterPrefs;
9682
9683 };
9684
9685 template<char C>
9686 char const* getLineOfChars() {
9687 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
9688 if( !*line ) {
9689 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
9690 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
9691 }
9692 return line;
9693 }
9694
9695 struct TestEventListenerBase : StreamingReporterBase {
9696 TestEventListenerBase( ReporterConfig const& _config )
9697 : StreamingReporterBase( _config )
9698 {}
9699
9700 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
9701 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
9702 return false;
9703 }
9704 };
9705
9706} // end namespace Catch
9707
9708// #included from: ../internal/catch_reporter_registrars.hpp
9709#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
9710
9711namespace Catch {
9712
9713 template<typename T>
9714 class LegacyReporterRegistrar {
9715
9716 class ReporterFactory : public IReporterFactory {
9717 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9718 return new LegacyReporterAdapter( new T( config ) );
9719 }
9720
9721 virtual std::string getDescription() const {
9722 return T::getDescription();
9723 }
9724 };
9725
9726 public:
9727
9728 LegacyReporterRegistrar( std::string const& name ) {
9729 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9730 }
9731 };
9732
9733 template<typename T>
9734 class ReporterRegistrar {
9735
9736 class ReporterFactory : public SharedImpl<IReporterFactory> {
9737
9738 // *** Please Note ***:
9739 // - If you end up here looking at a compiler error because it's trying to register
9740 // your custom reporter class be aware that the native reporter interface has changed
9741 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
9742 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
9743 // However please consider updating to the new interface as the old one is now
9744 // deprecated and will probably be removed quite soon!
9745 // Please contact me via github if you have any questions at all about this.
9746 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
9747 // no idea who is actually using custom reporters at all (possibly no-one!).
9748 // The new interface is designed to minimise exposure to interface changes in the future.
9749 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9750 return new T( config );
9751 }
9752
9753 virtual std::string getDescription() const {
9754 return T::getDescription();
9755 }
9756 };
9757
9758 public:
9759
9760 ReporterRegistrar( std::string const& name ) {
9761 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9762 }
9763 };
9764
9765 template<typename T>
9766 class ListenerRegistrar {
9767
9768 class ListenerFactory : public SharedImpl<IReporterFactory> {
9769
9770 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9771 return new T( config );
9772 }
9773 virtual std::string getDescription() const {
9774 return std::string();
9775 }
9776 };
9777
9778 public:
9779
9780 ListenerRegistrar() {
9781 getMutableRegistryHub().registerListener( new ListenerFactory() );
9782 }
9783 };
9784}
9785
9786#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
9787 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
9788
9789#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
9790 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
9791
9792// Deprecated - use the form without INTERNAL_
9793#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
9794 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9795
9796#define CATCH_REGISTER_LISTENER( listenerType ) \
9797 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9798
9799// #included from: ../internal/catch_xmlwriter.hpp
9800#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
9801
9802#include <sstream>
9803#include <string>
9804#include <vector>
9805#include <iomanip>
9806
9807namespace Catch {
9808
9809 class XmlEncode {
9810 public:
9811 enum ForWhat { ForTextNodes, ForAttributes };
9812
9813 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
9814 : m_str( str ),
9815 m_forWhat( forWhat )
9816 {}
9817
9818 void encodeTo( std::ostream& os ) const {
9819
9820 // Apostrophe escaping not necessary if we always use " to write attributes
9821 // (see: http://www.w3.org/TR/xml/#syntax)
9822
9823 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
9824 char c = m_str[i];
9825 switch( c ) {
9826 case '<': os << "&lt;"; break;
9827 case '&': os << "&amp;"; break;
9828
9829 case '>':
9830 // See: http://www.w3.org/TR/xml/#syntax
9831 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
9832 os << "&gt;";
9833 else
9834 os << c;
9835 break;
9836
9837 case '\"':
9838 if( m_forWhat == ForAttributes )
9839 os << "&quot;";
9840 else
9841 os << c;
9842 break;
9843
9844 default:
9845 // Escape control chars - based on contribution by @espenalb in PR #465 and
9846 // by @mrpi PR #588
9847 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
9848 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
9849 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
9850 << static_cast<int>( c );
9851 }
9852 else
9853 os << c;
9854 }
9855 }
9856 }
9857
9858 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
9859 xmlEncode.encodeTo( os );
9860 return os;
9861 }
9862
9863 private:
9864 std::string m_str;
9865 ForWhat m_forWhat;
9866 };
9867
9868 class XmlWriter {
9869 public:
9870
9871 class ScopedElement {
9872 public:
9873 ScopedElement( XmlWriter* writer )
9874 : m_writer( writer )
9875 {}
9876
9877 ScopedElement( ScopedElement const& other )
9878 : m_writer( other.m_writer ){
9879 other.m_writer = CATCH_NULL;
9880 }
9881
9882 ~ScopedElement() {
9883 if( m_writer )
9884 m_writer->endElement();
9885 }
9886
9887 ScopedElement& writeText( std::string const& text, bool indent = true ) {
9888 m_writer->writeText( text, indent );
9889 return *this;
9890 }
9891
9892 template<typename T>
9893 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
9894 m_writer->writeAttribute( name, attribute );
9895 return *this;
9896 }
9897
9898 private:
9899 mutable XmlWriter* m_writer;
9900 };
9901
9902 XmlWriter()
9903 : m_tagIsOpen( false ),
9904 m_needsNewline( false ),
9905 m_os( Catch::cout() )
9906 {
9907 writeDeclaration();
9908 }
9909
9910 XmlWriter( std::ostream& os )
9911 : m_tagIsOpen( false ),
9912 m_needsNewline( false ),
9913 m_os( os )
9914 {
9915 writeDeclaration();
9916 }
9917
9918 ~XmlWriter() {
9919 while( !m_tags.empty() )
9920 endElement();
9921 }
9922
9923 XmlWriter& startElement( std::string const& name ) {
9924 ensureTagClosed();
9925 newlineIfNecessary();
9926 m_os << m_indent << '<' << name;
9927 m_tags.push_back( name );
9928 m_indent += " ";
9929 m_tagIsOpen = true;
9930 return *this;
9931 }
9932
9933 ScopedElement scopedElement( std::string const& name ) {
9934 ScopedElement scoped( this );
9935 startElement( name );
9936 return scoped;
9937 }
9938
9939 XmlWriter& endElement() {
9940 newlineIfNecessary();
9941 m_indent = m_indent.substr( 0, m_indent.size()-2 );
9942 if( m_tagIsOpen ) {
9943 m_os << "/>";
9944 m_tagIsOpen = false;
9945 }
9946 else {
9947 m_os << m_indent << "</" << m_tags.back() << ">";
9948 }
9949 m_os << std::endl;
9950 m_tags.pop_back();
9951 return *this;
9952 }
9953
9954 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
9955 if( !name.empty() && !attribute.empty() )
9956 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
9957 return *this;
9958 }
9959
9960 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
9961 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
9962 return *this;
9963 }
9964
9965 template<typename T>
9966 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
9967 std::ostringstream oss;
9968 oss << attribute;
9969 return writeAttribute( name, oss.str() );
9970 }
9971
9972 XmlWriter& writeText( std::string const& text, bool indent = true ) {
9973 if( !text.empty() ){
9974 bool tagWasOpen = m_tagIsOpen;
9975 ensureTagClosed();
9976 if( tagWasOpen && indent )
9977 m_os << m_indent;
9978 m_os << XmlEncode( text );
9979 m_needsNewline = true;
9980 }
9981 return *this;
9982 }
9983
9984 XmlWriter& writeComment( std::string const& text ) {
9985 ensureTagClosed();
9986 m_os << m_indent << "<!--" << text << "-->";
9987 m_needsNewline = true;
9988 return *this;
9989 }
9990
9991 void writeStylesheetRef( std::string const& url ) {
9992 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
9993 }
9994
9995 XmlWriter& writeBlankLine() {
9996 ensureTagClosed();
9997 m_os << '\n';
9998 return *this;
9999 }
10000
10001 void ensureTagClosed() {
10002 if( m_tagIsOpen ) {
10003 m_os << ">" << std::endl;
10004 m_tagIsOpen = false;
10005 }
10006 }
10007
10008 private:
10009 XmlWriter( XmlWriter const& );
10010 void operator=( XmlWriter const& );
10011
10012 void writeDeclaration() {
10013 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
10014 }
10015
10016 void newlineIfNecessary() {
10017 if( m_needsNewline ) {
10018 m_os << std::endl;
10019 m_needsNewline = false;
10020 }
10021 }
10022
10023 bool m_tagIsOpen;
10024 bool m_needsNewline;
10025 std::vector<std::string> m_tags;
10026 std::string m_indent;
10027 std::ostream& m_os;
10028 };
10029
10030}
10031// #included from: catch_reenable_warnings.h
10032
10033#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
10034
10035#ifdef __clang__
10036# ifdef __ICC // icpc defines the __clang__ macro
10037# pragma warning(pop)
10038# else
10039# pragma clang diagnostic pop
10040# endif
10041#elif defined __GNUC__
10042# pragma GCC diagnostic pop
10043#endif
10044
10045
10046namespace Catch {
10047 class XmlReporter : public StreamingReporterBase {
10048 public:
10049 XmlReporter( ReporterConfig const& _config )
10050 : StreamingReporterBase( _config ),
10051 m_xml(_config.stream()),
10052 m_sectionDepth( 0 )
10053 {
10054 m_reporterPrefs.shouldRedirectStdOut = true;
10055 }
10056
10057 virtual ~XmlReporter() CATCH_OVERRIDE;
10058
10059 static std::string getDescription() {
10060 return "Reports test results as an XML document";
10061 }
10062
10063 virtual std::string getStylesheetRef() const {
10064 return std::string();
10065 }
10066
10067 void writeSourceInfo( SourceLineInfo const& sourceInfo ) {
10068 m_xml
10069 .writeAttribute( "filename", sourceInfo.file )
10070 .writeAttribute( "line", sourceInfo.line );
10071 }
10072
10073 public: // StreamingReporterBase
10074
10075 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
10076 StreamingReporterBase::noMatchingTestCases( s );
10077 }
10078
10079 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
10080 StreamingReporterBase::testRunStarting( testInfo );
10081 std::string stylesheetRef = getStylesheetRef();
10082 if( !stylesheetRef.empty() )
10083 m_xml.writeStylesheetRef( stylesheetRef );
10084 m_xml.startElement( "Catch" );
10085 if( !m_config->name().empty() )
10086 m_xml.writeAttribute( "name", m_config->name() );
10087 }
10088
10089 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
10090 StreamingReporterBase::testGroupStarting( groupInfo );
10091 m_xml.startElement( "Group" )
10092 .writeAttribute( "name", groupInfo.name );
10093 }
10094
10095 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
10096 StreamingReporterBase::testCaseStarting(testInfo);
10097 m_xml.startElement( "TestCase" )
10098 .writeAttribute( "name", trim( testInfo.name ) )
10099 .writeAttribute( "description", testInfo.description )
10100 .writeAttribute( "tags", testInfo.tagsAsString );
10101
10102 writeSourceInfo( testInfo.lineInfo );
10103
10104 if ( m_config->showDurations() == ShowDurations::Always )
10105 m_testCaseTimer.start();
10106 m_xml.ensureTagClosed();
10107 }
10108
10109 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
10110 StreamingReporterBase::sectionStarting( sectionInfo );
10111 if( m_sectionDepth++ > 0 ) {
10112 m_xml.startElement( "Section" )
10113 .writeAttribute( "name", trim( sectionInfo.name ) )
10114 .writeAttribute( "description", sectionInfo.description );
10115 writeSourceInfo( sectionInfo.lineInfo );
10116 m_xml.ensureTagClosed();
10117 }
10118 }
10119
10120 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
10121
10122 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
10123
10124 AssertionResult const& result = assertionStats.assertionResult;
10125
10126 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
10127
10128 if( includeResults ) {
10129 // Print any info messages in <Info> tags.
10130 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
10131 it != itEnd;
10132 ++it ) {
10133 if( it->type == ResultWas::Info ) {
10134 m_xml.scopedElement( "Info" )
10135 .writeText( it->message );
10136 } else if ( it->type == ResultWas::Warning ) {
10137 m_xml.scopedElement( "Warning" )
10138 .writeText( it->message );
10139 }
10140 }
10141 }
10142
10143 // Drop out if result was successful but we're not printing them.
10144 if( !includeResults && result.getResultType() != ResultWas::Warning )
10145 return true;
10146
10147 // Print the expression if there is one.
10148 if( result.hasExpression() ) {
10149 m_xml.startElement( "Expression" )
10150 .writeAttribute( "success", result.succeeded() )
10151 .writeAttribute( "type", result.getTestMacroName() );
10152
10153 writeSourceInfo( result.getSourceInfo() );
10154
10155 m_xml.scopedElement( "Original" )
10156 .writeText( result.getExpression() );
10157 m_xml.scopedElement( "Expanded" )
10158 .writeText( result.getExpandedExpression() );
10159 }
10160
10161 // And... Print a result applicable to each result type.
10162 switch( result.getResultType() ) {
10163 case ResultWas::ThrewException:
10164 m_xml.startElement( "Exception" );
10165 writeSourceInfo( result.getSourceInfo() );
10166 m_xml.writeText( result.getMessage() );
10167 m_xml.endElement();
10168 break;
10169 case ResultWas::FatalErrorCondition:
10170 m_xml.startElement( "FatalErrorCondition" );
10171 writeSourceInfo( result.getSourceInfo() );
10172 m_xml.writeText( result.getMessage() );
10173 m_xml.endElement();
10174 break;
10175 case ResultWas::Info:
10176 m_xml.scopedElement( "Info" )
10177 .writeText( result.getMessage() );
10178 break;
10179 case ResultWas::Warning:
10180 // Warning will already have been written
10181 break;
10182 case ResultWas::ExplicitFailure:
10183 m_xml.startElement( "Failure" );
10184 writeSourceInfo( result.getSourceInfo() );
10185 m_xml.writeText( result.getMessage() );
10186 m_xml.endElement();
10187 break;
10188 default:
10189 break;
10190 }
10191
10192 if( result.hasExpression() )
10193 m_xml.endElement();
10194
10195 return true;
10196 }
10197
10198 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
10199 StreamingReporterBase::sectionEnded( sectionStats );
10200 if( --m_sectionDepth > 0 ) {
10201 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
10202 e.writeAttribute( "successes", sectionStats.assertions.passed );
10203 e.writeAttribute( "failures", sectionStats.assertions.failed );
10204 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
10205
10206 if ( m_config->showDurations() == ShowDurations::Always )
10207 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
10208
10209 m_xml.endElement();
10210 }
10211 }
10212
10213 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
10214 StreamingReporterBase::testCaseEnded( testCaseStats );
10215 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
10216 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
10217
10218 if ( m_config->showDurations() == ShowDurations::Always )
10219 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
10220
10221 if( !testCaseStats.stdOut.empty() )
10222 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
10223 if( !testCaseStats.stdErr.empty() )
10224 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
10225
10226 m_xml.endElement();
10227 }
10228
10229 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
10230 StreamingReporterBase::testGroupEnded( testGroupStats );
10231 // TODO: Check testGroupStats.aborting and act accordingly.
10232 m_xml.scopedElement( "OverallResults" )
10233 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
10234 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
10235 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
10236 m_xml.endElement();
10237 }
10238
10239 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
10240 StreamingReporterBase::testRunEnded( testRunStats );
10241 m_xml.scopedElement( "OverallResults" )
10242 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
10243 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
10244 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
10245 m_xml.endElement();
10246 }
10247
10248 private:
10249 Timer m_testCaseTimer;
10250 XmlWriter m_xml;
10251 int m_sectionDepth;
10252 };
10253
10254 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
10255
10256} // end namespace Catch
10257
10258// #included from: ../reporters/catch_reporter_junit.hpp
10259#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
10260
10261#include <assert.h>
10262
10263namespace Catch {
10264
10265 namespace {
10266 std::string getCurrentTimestamp() {
10267 // Beware, this is not reentrant because of backward compatibility issues
10268 // Also, UTC only, again because of backward compatibility (%z is C++11)
10269 time_t rawtime;
10270 std::time(&rawtime);
10271 const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
10272
10273#ifdef _MSC_VER
10274 std::tm timeInfo = {};
10275 gmtime_s(&timeInfo, &rawtime);
10276#else
10277 std::tm* timeInfo;
10278 timeInfo = std::gmtime(&rawtime);
10279#endif
10280
10281 char timeStamp[timeStampSize];
10282 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
10283
10284#ifdef _MSC_VER
10285 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
10286#else
10287 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
10288#endif
10289 return std::string(timeStamp);
10290 }
10291
10292 }
10293
10294 class JunitReporter : public CumulativeReporterBase {
10295 public:
10296 JunitReporter( ReporterConfig const& _config )
10297 : CumulativeReporterBase( _config ),
10298 xml( _config.stream() ),
10299 m_okToFail( false )
10300 {
10301 m_reporterPrefs.shouldRedirectStdOut = true;
10302 }
10303
10304 virtual ~JunitReporter() CATCH_OVERRIDE;
10305
10306 static std::string getDescription() {
10307 return "Reports test results in an XML format that looks like Ant's junitreport target";
10308 }
10309
10310 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
10311
10312 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
10313 CumulativeReporterBase::testRunStarting( runInfo );
10314 xml.startElement( "testsuites" );
10315 }
10316
10317 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
10318 suiteTimer.start();
10319 stdOutForSuite.str("");
10320 stdErrForSuite.str("");
10321 unexpectedExceptions = 0;
10322 CumulativeReporterBase::testGroupStarting( groupInfo );
10323 }
10324
10325 virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE {
10326 m_okToFail = testCaseInfo.okToFail();
10327 }
10328 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
10329 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
10330 unexpectedExceptions++;
10331 return CumulativeReporterBase::assertionEnded( assertionStats );
10332 }
10333
10334 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
10335 stdOutForSuite << testCaseStats.stdOut;
10336 stdErrForSuite << testCaseStats.stdErr;
10337 CumulativeReporterBase::testCaseEnded( testCaseStats );
10338 }
10339
10340 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
10341 double suiteTime = suiteTimer.getElapsedSeconds();
10342 CumulativeReporterBase::testGroupEnded( testGroupStats );
10343 writeGroup( *m_testGroups.back(), suiteTime );
10344 }
10345
10346 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
10347 xml.endElement();
10348 }
10349
10350 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
10351 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
10352 TestGroupStats const& stats = groupNode.value;
10353 xml.writeAttribute( "name", stats.groupInfo.name );
10354 xml.writeAttribute( "errors", unexpectedExceptions );
10355 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
10356 xml.writeAttribute( "tests", stats.totals.assertions.total() );
10357 xml.writeAttribute( "hostname", "tbd" ); // !TBD
10358 if( m_config->showDurations() == ShowDurations::Never )
10359 xml.writeAttribute( "time", "" );
10360 else
10361 xml.writeAttribute( "time", suiteTime );
10362 xml.writeAttribute( "timestamp", getCurrentTimestamp() );
10363
10364 // Write test cases
10365 for( TestGroupNode::ChildNodes::const_iterator
10366 it = groupNode.children.begin(), itEnd = groupNode.children.end();
10367 it != itEnd;
10368 ++it )
10369 writeTestCase( **it );
10370
10371 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
10372 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
10373 }
10374
10375 void writeTestCase( TestCaseNode const& testCaseNode ) {
10376 TestCaseStats const& stats = testCaseNode.value;
10377
10378 // All test cases have exactly one section - which represents the
10379 // test case itself. That section may have 0-n nested sections
10380 assert( testCaseNode.children.size() == 1 );
10381 SectionNode const& rootSection = *testCaseNode.children.front();
10382
10383 std::string className = stats.testInfo.className;
10384
10385 if( className.empty() ) {
10386 if( rootSection.childSections.empty() )
10387 className = "global";
10388 }
10389 writeSection( className, "", rootSection );
10390 }
10391
10392 void writeSection( std::string const& className,
10393 std::string const& rootName,
10394 SectionNode const& sectionNode ) {
10395 std::string name = trim( sectionNode.stats.sectionInfo.name );
10396 if( !rootName.empty() )
10397 name = rootName + '/' + name;
10398
10399 if( !sectionNode.assertions.empty() ||
10400 !sectionNode.stdOut.empty() ||
10401 !sectionNode.stdErr.empty() ) {
10402 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
10403 if( className.empty() ) {
10404 xml.writeAttribute( "classname", name );
10405 xml.writeAttribute( "name", "root" );
10406 }
10407 else {
10408 xml.writeAttribute( "classname", className );
10409 xml.writeAttribute( "name", name );
10410 }
10411 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
10412
10413 writeAssertions( sectionNode );
10414
10415 if( !sectionNode.stdOut.empty() )
10416 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
10417 if( !sectionNode.stdErr.empty() )
10418 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
10419 }
10420 for( SectionNode::ChildSections::const_iterator
10421 it = sectionNode.childSections.begin(),
10422 itEnd = sectionNode.childSections.end();
10423 it != itEnd;
10424 ++it )
10425 if( className.empty() )
10426 writeSection( name, "", **it );
10427 else
10428 writeSection( className, name, **it );
10429 }
10430
10431 void writeAssertions( SectionNode const& sectionNode ) {
10432 for( SectionNode::Assertions::const_iterator
10433 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
10434 it != itEnd;
10435 ++it )
10436 writeAssertion( *it );
10437 }
10438 void writeAssertion( AssertionStats const& stats ) {
10439 AssertionResult const& result = stats.assertionResult;
10440 if( !result.isOk() ) {
10441 std::string elementName;
10442 switch( result.getResultType() ) {
10443 case ResultWas::ThrewException:
10444 case ResultWas::FatalErrorCondition:
10445 elementName = "error";
10446 break;
10447 case ResultWas::ExplicitFailure:
10448 elementName = "failure";
10449 break;
10450 case ResultWas::ExpressionFailed:
10451 elementName = "failure";
10452 break;
10453 case ResultWas::DidntThrowException:
10454 elementName = "failure";
10455 break;
10456
10457 // We should never see these here:
10458 case ResultWas::Info:
10459 case ResultWas::Warning:
10460 case ResultWas::Ok:
10461 case ResultWas::Unknown:
10462 case ResultWas::FailureBit:
10463 case ResultWas::Exception:
10464 elementName = "internalError";
10465 break;
10466 }
10467
10468 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
10469
10470 xml.writeAttribute( "message", result.getExpandedExpression() );
10471 xml.writeAttribute( "type", result.getTestMacroName() );
10472
10473 std::ostringstream oss;
10474 if( !result.getMessage().empty() )
10475 oss << result.getMessage() << '\n';
10476 for( std::vector<MessageInfo>::const_iterator
10477 it = stats.infoMessages.begin(),
10478 itEnd = stats.infoMessages.end();
10479 it != itEnd;
10480 ++it )
10481 if( it->type == ResultWas::Info )
10482 oss << it->message << '\n';
10483
10484 oss << "at " << result.getSourceInfo();
10485 xml.writeText( oss.str(), false );
10486 }
10487 }
10488
10489 XmlWriter xml;
10490 Timer suiteTimer;
10491 std::ostringstream stdOutForSuite;
10492 std::ostringstream stdErrForSuite;
10493 unsigned int unexpectedExceptions;
10494 bool m_okToFail;
10495 };
10496
10497 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
10498
10499} // end namespace Catch
10500
10501// #included from: ../reporters/catch_reporter_console.hpp
10502#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
10503
10504#include <cfloat>
10505#include <cstdio>
10506
10507namespace Catch {
10508
10509 struct ConsoleReporter : StreamingReporterBase {
10510 ConsoleReporter( ReporterConfig const& _config )
10511 : StreamingReporterBase( _config ),
10512 m_headerPrinted( false )
10513 {}
10514
10515 virtual ~ConsoleReporter() CATCH_OVERRIDE;
10516 static std::string getDescription() {
10517 return "Reports test results as plain lines of text";
10518 }
10519
10520 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
10521 stream << "No test cases matched '" << spec << '\'' << std::endl;
10522 }
10523
10524 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
10525 }
10526
10527 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
10528 AssertionResult const& result = _assertionStats.assertionResult;
10529
10530 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
10531
10532 // Drop out if result was successful but we're not printing them.
10533 if( !includeResults && result.getResultType() != ResultWas::Warning )
10534 return false;
10535
10536 lazyPrint();
10537
10538 AssertionPrinter printer( stream, _assertionStats, includeResults );
10539 printer.print();
10540 stream << std::endl;
10541 return true;
10542 }
10543
10544 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
10545 m_headerPrinted = false;
10546 StreamingReporterBase::sectionStarting( _sectionInfo );
10547 }
10548 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
10549 if( _sectionStats.missingAssertions ) {
10550 lazyPrint();
10551 Colour colour( Colour::ResultError );
10552 if( m_sectionStack.size() > 1 )
10553 stream << "\nNo assertions in section";
10554 else
10555 stream << "\nNo assertions in test case";
10556 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
10557 }
10558 if( m_config->showDurations() == ShowDurations::Always ) {
10559 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
10560 }
10561 if( m_headerPrinted ) {
10562 m_headerPrinted = false;
10563 }
10564 StreamingReporterBase::sectionEnded( _sectionStats );
10565 }
10566
10567 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
10568 StreamingReporterBase::testCaseEnded( _testCaseStats );
10569 m_headerPrinted = false;
10570 }
10571 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
10572 if( currentGroupInfo.used ) {
10573 printSummaryDivider();
10574 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
10575 printTotals( _testGroupStats.totals );
10576 stream << '\n' << std::endl;
10577 }
10578 StreamingReporterBase::testGroupEnded( _testGroupStats );
10579 }
10580 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
10581 printTotalsDivider( _testRunStats.totals );
10582 printTotals( _testRunStats.totals );
10583 stream << std::endl;
10584 StreamingReporterBase::testRunEnded( _testRunStats );
10585 }
10586
10587 private:
10588
10589 class AssertionPrinter {
10590 void operator= ( AssertionPrinter const& );
10591 public:
10592 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10593 : stream( _stream ),
10594 stats( _stats ),
10595 result( _stats.assertionResult ),
10596 colour( Colour::None ),
10597 message( result.getMessage() ),
10598 messages( _stats.infoMessages ),
10599 printInfoMessages( _printInfoMessages )
10600 {
10601 switch( result.getResultType() ) {
10602 case ResultWas::Ok:
10603 colour = Colour::Success;
10604 passOrFail = "PASSED";
10605 //if( result.hasMessage() )
10606 if( _stats.infoMessages.size() == 1 )
10607 messageLabel = "with message";
10608 if( _stats.infoMessages.size() > 1 )
10609 messageLabel = "with messages";
10610 break;
10611 case ResultWas::ExpressionFailed:
10612 if( result.isOk() ) {
10613 colour = Colour::Success;
10614 passOrFail = "FAILED - but was ok";
10615 }
10616 else {
10617 colour = Colour::Error;
10618 passOrFail = "FAILED";
10619 }
10620 if( _stats.infoMessages.size() == 1 )
10621 messageLabel = "with message";
10622 if( _stats.infoMessages.size() > 1 )
10623 messageLabel = "with messages";
10624 break;
10625 case ResultWas::ThrewException:
10626 colour = Colour::Error;
10627 passOrFail = "FAILED";
10628 messageLabel = "due to unexpected exception with ";
10629 if (_stats.infoMessages.size() == 1)
10630 messageLabel += "message";
10631 if (_stats.infoMessages.size() > 1)
10632 messageLabel += "messages";
10633 break;
10634 case ResultWas::FatalErrorCondition:
10635 colour = Colour::Error;
10636 passOrFail = "FAILED";
10637 messageLabel = "due to a fatal error condition";
10638 break;
10639 case ResultWas::DidntThrowException:
10640 colour = Colour::Error;
10641 passOrFail = "FAILED";
10642 messageLabel = "because no exception was thrown where one was expected";
10643 break;
10644 case ResultWas::Info:
10645 messageLabel = "info";
10646 break;
10647 case ResultWas::Warning:
10648 messageLabel = "warning";
10649 break;
10650 case ResultWas::ExplicitFailure:
10651 passOrFail = "FAILED";
10652 colour = Colour::Error;
10653 if( _stats.infoMessages.size() == 1 )
10654 messageLabel = "explicitly with message";
10655 if( _stats.infoMessages.size() > 1 )
10656 messageLabel = "explicitly with messages";
10657 break;
10658 // These cases are here to prevent compiler warnings
10659 case ResultWas::Unknown:
10660 case ResultWas::FailureBit:
10661 case ResultWas::Exception:
10662 passOrFail = "** internal error **";
10663 colour = Colour::Error;
10664 break;
10665 }
10666 }
10667
10668 void print() const {
10669 printSourceInfo();
10670 if( stats.totals.assertions.total() > 0 ) {
10671 if( result.isOk() )
10672 stream << '\n';
10673 printResultType();
10674 printOriginalExpression();
10675 printReconstructedExpression();
10676 }
10677 else {
10678 stream << '\n';
10679 }
10680 printMessage();
10681 }
10682
10683 private:
10684 void printResultType() const {
10685 if( !passOrFail.empty() ) {
10686 Colour colourGuard( colour );
10687 stream << passOrFail << ":\n";
10688 }
10689 }
10690 void printOriginalExpression() const {
10691 if( result.hasExpression() ) {
10692 Colour colourGuard( Colour::OriginalExpression );
10693 stream << " ";
10694 stream << result.getExpressionInMacro();
10695 stream << '\n';
10696 }
10697 }
10698 void printReconstructedExpression() const {
10699 if( result.hasExpandedExpression() ) {
10700 stream << "with expansion:\n";
10701 Colour colourGuard( Colour::ReconstructedExpression );
10702 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
10703 }
10704 }
10705 void printMessage() const {
10706 if( !messageLabel.empty() )
10707 stream << messageLabel << ':' << '\n';
10708 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
10709 it != itEnd;
10710 ++it ) {
10711 // If this assertion is a warning ignore any INFO messages
10712 if( printInfoMessages || it->type != ResultWas::Info )
10713 stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
10714 }
10715 }
10716 void printSourceInfo() const {
10717 Colour colourGuard( Colour::FileName );
10718 stream << result.getSourceInfo() << ": ";
10719 }
10720
10721 std::ostream& stream;
10722 AssertionStats const& stats;
10723 AssertionResult const& result;
10724 Colour::Code colour;
10725 std::string passOrFail;
10726 std::string messageLabel;
10727 std::string message;
10728 std::vector<MessageInfo> messages;
10729 bool printInfoMessages;
10730 };
10731
10732 void lazyPrint() {
10733
10734 if( !currentTestRunInfo.used )
10735 lazyPrintRunInfo();
10736 if( !currentGroupInfo.used )
10737 lazyPrintGroupInfo();
10738
10739 if( !m_headerPrinted ) {
10740 printTestCaseAndSectionHeader();
10741 m_headerPrinted = true;
10742 }
10743 }
10744 void lazyPrintRunInfo() {
10745 stream << '\n' << getLineOfChars<'~'>() << '\n';
10746 Colour colour( Colour::SecondaryText );
10747 stream << currentTestRunInfo->name
10748 << " is a Catch v" << libraryVersion() << " host application.\n"
10749 << "Run with -? for options\n\n";
10750
10751 if( m_config->rngSeed() != 0 )
10752 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
10753
10754 currentTestRunInfo.used = true;
10755 }
10756 void lazyPrintGroupInfo() {
10757 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
10758 printClosedHeader( "Group: " + currentGroupInfo->name );
10759 currentGroupInfo.used = true;
10760 }
10761 }
10762 void printTestCaseAndSectionHeader() {
10763 assert( !m_sectionStack.empty() );
10764 printOpenHeader( currentTestCaseInfo->name );
10765
10766 if( m_sectionStack.size() > 1 ) {
10767 Colour colourGuard( Colour::Headers );
10768
10769 std::vector<SectionInfo>::const_iterator
10770 it = m_sectionStack.begin()+1, // Skip first section (test case)
10771 itEnd = m_sectionStack.end();
10772 for( ; it != itEnd; ++it )
10773 printHeaderString( it->name, 2 );
10774 }
10775
10776 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
10777
10778 if( !lineInfo.empty() ){
10779 stream << getLineOfChars<'-'>() << '\n';
10780 Colour colourGuard( Colour::FileName );
10781 stream << lineInfo << '\n';
10782 }
10783 stream << getLineOfChars<'.'>() << '\n' << std::endl;
10784 }
10785
10786 void printClosedHeader( std::string const& _name ) {
10787 printOpenHeader( _name );
10788 stream << getLineOfChars<'.'>() << '\n';
10789 }
10790 void printOpenHeader( std::string const& _name ) {
10791 stream << getLineOfChars<'-'>() << '\n';
10792 {
10793 Colour colourGuard( Colour::Headers );
10794 printHeaderString( _name );
10795 }
10796 }
10797
10798 // if string has a : in first line will set indent to follow it on
10799 // subsequent lines
10800 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
10801 std::size_t i = _string.find( ": " );
10802 if( i != std::string::npos )
10803 i+=2;
10804 else
10805 i = 0;
10806 stream << Text( _string, TextAttributes()
10807 .setIndent( indent+i)
10808 .setInitialIndent( indent ) ) << '\n';
10809 }
10810
10811 struct SummaryColumn {
10812
10813 SummaryColumn( std::string const& _label, Colour::Code _colour )
10814 : label( _label ),
10815 colour( _colour )
10816 {}
10817 SummaryColumn addRow( std::size_t count ) {
10818 std::ostringstream oss;
10819 oss << count;
10820 std::string row = oss.str();
10821 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
10822 while( it->size() < row.size() )
10823 *it = ' ' + *it;
10824 while( it->size() > row.size() )
10825 row = ' ' + row;
10826 }
10827 rows.push_back( row );
10828 return *this;
10829 }
10830
10831 std::string label;
10832 Colour::Code colour;
10833 std::vector<std::string> rows;
10834
10835 };
10836
10837 void printTotals( Totals const& totals ) {
10838 if( totals.testCases.total() == 0 ) {
10839 stream << Colour( Colour::Warning ) << "No tests ran\n";
10840 }
10841 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
10842 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
10843 stream << " ("
10844 << pluralise( totals.assertions.passed, "assertion" ) << " in "
10845 << pluralise( totals.testCases.passed, "test case" ) << ')'
10846 << '\n';
10847 }
10848 else {
10849
10850 std::vector<SummaryColumn> columns;
10851 columns.push_back( SummaryColumn( "", Colour::None )
10852 .addRow( totals.testCases.total() )
10853 .addRow( totals.assertions.total() ) );
10854 columns.push_back( SummaryColumn( "passed", Colour::Success )
10855 .addRow( totals.testCases.passed )
10856 .addRow( totals.assertions.passed ) );
10857 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
10858 .addRow( totals.testCases.failed )
10859 .addRow( totals.assertions.failed ) );
10860 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
10861 .addRow( totals.testCases.failedButOk )
10862 .addRow( totals.assertions.failedButOk ) );
10863
10864 printSummaryRow( "test cases", columns, 0 );
10865 printSummaryRow( "assertions", columns, 1 );
10866 }
10867 }
10868 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
10869 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
10870 std::string value = it->rows[row];
10871 if( it->label.empty() ) {
10872 stream << label << ": ";
10873 if( value != "0" )
10874 stream << value;
10875 else
10876 stream << Colour( Colour::Warning ) << "- none -";
10877 }
10878 else if( value != "0" ) {
10879 stream << Colour( Colour::LightGrey ) << " | ";
10880 stream << Colour( it->colour )
10881 << value << ' ' << it->label;
10882 }
10883 }
10884 stream << '\n';
10885 }
10886
10887 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
10888 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
10889 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
10890 }
10891 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
10892 if( i > j && i > k )
10893 return i;
10894 else if( j > k )
10895 return j;
10896 else
10897 return k;
10898 }
10899
10900 void printTotalsDivider( Totals const& totals ) {
10901 if( totals.testCases.total() > 0 ) {
10902 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
10903 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
10904 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
10905 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
10906 findMax( failedRatio, failedButOkRatio, passedRatio )++;
10907 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
10908 findMax( failedRatio, failedButOkRatio, passedRatio )--;
10909
10910 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
10911 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
10912 if( totals.testCases.allPassed() )
10913 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
10914 else
10915 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
10916 }
10917 else {
10918 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
10919 }
10920 stream << '\n';
10921 }
10922 void printSummaryDivider() {
10923 stream << getLineOfChars<'-'>() << '\n';
10924 }
10925
10926 private:
10927 bool m_headerPrinted;
10928 };
10929
10930 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
10931
10932} // end namespace Catch
10933
10934// #included from: ../reporters/catch_reporter_compact.hpp
10935#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
10936
10937namespace Catch {
10938
10939 struct CompactReporter : StreamingReporterBase {
10940
10941 CompactReporter( ReporterConfig const& _config )
10942 : StreamingReporterBase( _config )
10943 {}
10944
10945 virtual ~CompactReporter();
10946
10947 static std::string getDescription() {
10948 return "Reports test results on a single line, suitable for IDEs";
10949 }
10950
10951 virtual ReporterPreferences getPreferences() const {
10952 ReporterPreferences prefs;
10953 prefs.shouldRedirectStdOut = false;
10954 return prefs;
10955 }
10956
10957 virtual void noMatchingTestCases( std::string const& spec ) {
10958 stream << "No test cases matched '" << spec << '\'' << std::endl;
10959 }
10960
10961 virtual void assertionStarting( AssertionInfo const& ) {}
10962
10963 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
10964 AssertionResult const& result = _assertionStats.assertionResult;
10965
10966 bool printInfoMessages = true;
10967
10968 // Drop out if result was successful and we're not printing those
10969 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10970 if( result.getResultType() != ResultWas::Warning )
10971 return false;
10972 printInfoMessages = false;
10973 }
10974
10975 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
10976 printer.print();
10977
10978 stream << std::endl;
10979 return true;
10980 }
10981
10982 virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE {
10983 if (m_config->showDurations() == ShowDurations::Always) {
10984 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
10985 }
10986 }
10987
10988 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
10989 printTotals( _testRunStats.totals );
10990 stream << '\n' << std::endl;
10991 StreamingReporterBase::testRunEnded( _testRunStats );
10992 }
10993
10994 private:
10995 class AssertionPrinter {
10996 void operator= ( AssertionPrinter const& );
10997 public:
10998 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10999 : stream( _stream )
11000 , stats( _stats )
11001 , result( _stats.assertionResult )
11002 , messages( _stats.infoMessages )
11003 , itMessage( _stats.infoMessages.begin() )
11004 , printInfoMessages( _printInfoMessages )
11005 {}
11006
11007 void print() {
11008 printSourceInfo();
11009
11010 itMessage = messages.begin();
11011
11012 switch( result.getResultType() ) {
11013 case ResultWas::Ok:
11014 printResultType( Colour::ResultSuccess, passedString() );
11015 printOriginalExpression();
11016 printReconstructedExpression();
11017 if ( ! result.hasExpression() )
11018 printRemainingMessages( Colour::None );
11019 else
11020 printRemainingMessages();
11021 break;
11022 case ResultWas::ExpressionFailed:
11023 if( result.isOk() )
11024 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
11025 else
11026 printResultType( Colour::Error, failedString() );
11027 printOriginalExpression();
11028 printReconstructedExpression();
11029 printRemainingMessages();
11030 break;
11031 case ResultWas::ThrewException:
11032 printResultType( Colour::Error, failedString() );
11033 printIssue( "unexpected exception with message:" );
11034 printMessage();
11035 printExpressionWas();
11036 printRemainingMessages();
11037 break;
11038 case ResultWas::FatalErrorCondition:
11039 printResultType( Colour::Error, failedString() );
11040 printIssue( "fatal error condition with message:" );
11041 printMessage();
11042 printExpressionWas();
11043 printRemainingMessages();
11044 break;
11045 case ResultWas::DidntThrowException:
11046 printResultType( Colour::Error, failedString() );
11047 printIssue( "expected exception, got none" );
11048 printExpressionWas();
11049 printRemainingMessages();
11050 break;
11051 case ResultWas::Info:
11052 printResultType( Colour::None, "info" );
11053 printMessage();
11054 printRemainingMessages();
11055 break;
11056 case ResultWas::Warning:
11057 printResultType( Colour::None, "warning" );
11058 printMessage();
11059 printRemainingMessages();
11060 break;
11061 case ResultWas::ExplicitFailure:
11062 printResultType( Colour::Error, failedString() );
11063 printIssue( "explicitly" );
11064 printRemainingMessages( Colour::None );
11065 break;
11066 // These cases are here to prevent compiler warnings
11067 case ResultWas::Unknown:
11068 case ResultWas::FailureBit:
11069 case ResultWas::Exception:
11070 printResultType( Colour::Error, "** internal error **" );
11071 break;
11072 }
11073 }
11074
11075 private:
11076 // Colour::LightGrey
11077
11078 static Colour::Code dimColour() { return Colour::FileName; }
11079
11080#ifdef CATCH_PLATFORM_MAC
11081 static const char* failedString() { return "FAILED"; }
11082 static const char* passedString() { return "PASSED"; }
11083#else
11084 static const char* failedString() { return "failed"; }
11085 static const char* passedString() { return "passed"; }
11086#endif
11087
11088 void printSourceInfo() const {
11089 Colour colourGuard( Colour::FileName );
11090 stream << result.getSourceInfo() << ':';
11091 }
11092
11093 void printResultType( Colour::Code colour, std::string const& passOrFail ) const {
11094 if( !passOrFail.empty() ) {
11095 {
11096 Colour colourGuard( colour );
11097 stream << ' ' << passOrFail;
11098 }
11099 stream << ':';
11100 }
11101 }
11102
11103 void printIssue( std::string const& issue ) const {
11104 stream << ' ' << issue;
11105 }
11106
11107 void printExpressionWas() {
11108 if( result.hasExpression() ) {
11109 stream << ';';
11110 {
11111 Colour colour( dimColour() );
11112 stream << " expression was:";
11113 }
11114 printOriginalExpression();
11115 }
11116 }
11117
11118 void printOriginalExpression() const {
11119 if( result.hasExpression() ) {
11120 stream << ' ' << result.getExpression();
11121 }
11122 }
11123
11124 void printReconstructedExpression() const {
11125 if( result.hasExpandedExpression() ) {
11126 {
11127 Colour colour( dimColour() );
11128 stream << " for: ";
11129 }
11130 stream << result.getExpandedExpression();
11131 }
11132 }
11133
11134 void printMessage() {
11135 if ( itMessage != messages.end() ) {
11136 stream << " '" << itMessage->message << '\'';
11137 ++itMessage;
11138 }
11139 }
11140
11141 void printRemainingMessages( Colour::Code colour = dimColour() ) {
11142 if ( itMessage == messages.end() )
11143 return;
11144
11145 // using messages.end() directly yields compilation error:
11146 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11147 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
11148
11149 {
11150 Colour colourGuard( colour );
11151 stream << " with " << pluralise( N, "message" ) << ':';
11152 }
11153
11154 for(; itMessage != itEnd; ) {
11155 // If this assertion is a warning ignore any INFO messages
11156 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
11157 stream << " '" << itMessage->message << '\'';
11158 if ( ++itMessage != itEnd ) {
11159 Colour colourGuard( dimColour() );
11160 stream << " and";
11161 }
11162 }
11163 }
11164 }
11165
11166 private:
11167 std::ostream& stream;
11168 AssertionStats const& stats;
11169 AssertionResult const& result;
11170 std::vector<MessageInfo> messages;
11171 std::vector<MessageInfo>::const_iterator itMessage;
11172 bool printInfoMessages;
11173 };
11174
11175 // Colour, message variants:
11176 // - white: No tests ran.
11177 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
11178 // - white: Passed [both/all] N test cases (no assertions).
11179 // - red: Failed N tests cases, failed M assertions.
11180 // - green: Passed [both/all] N tests cases with M assertions.
11181
11182 std::string bothOrAll( std::size_t count ) const {
11183 return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
11184 }
11185
11186 void printTotals( const Totals& totals ) const {
11187 if( totals.testCases.total() == 0 ) {
11188 stream << "No tests ran.";
11189 }
11190 else if( totals.testCases.failed == totals.testCases.total() ) {
11191 Colour colour( Colour::ResultError );
11192 const std::string qualify_assertions_failed =
11193 totals.assertions.failed == totals.assertions.total() ?
11194 bothOrAll( totals.assertions.failed ) : std::string();
11195 stream <<
11196 "Failed " << bothOrAll( totals.testCases.failed )
11197 << pluralise( totals.testCases.failed, "test case" ) << ", "
11198 "failed " << qualify_assertions_failed <<
11199 pluralise( totals.assertions.failed, "assertion" ) << '.';
11200 }
11201 else if( totals.assertions.total() == 0 ) {
11202 stream <<
11203 "Passed " << bothOrAll( totals.testCases.total() )
11204 << pluralise( totals.testCases.total(), "test case" )
11205 << " (no assertions).";
11206 }
11207 else if( totals.assertions.failed ) {
11208 Colour colour( Colour::ResultError );
11209 stream <<
11210 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
11211 "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
11212 }
11213 else {
11214 Colour colour( Colour::ResultSuccess );
11215 stream <<
11216 "Passed " << bothOrAll( totals.testCases.passed )
11217 << pluralise( totals.testCases.passed, "test case" ) <<
11218 " with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
11219 }
11220 }
11221 };
11222
11223 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
11224
11225} // end namespace Catch
11226
11227namespace Catch {
11228 // These are all here to avoid warnings about not having any out of line
11229 // virtual methods
11230 NonCopyable::~NonCopyable() {}
11231 IShared::~IShared() {}
11232 IStream::~IStream() CATCH_NOEXCEPT {}
11233 FileStream::~FileStream() CATCH_NOEXCEPT {}
11234 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
11235 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
11236 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
11237 IContext::~IContext() {}
11238 IResultCapture::~IResultCapture() {}
11239 ITestCase::~ITestCase() {}
11240 ITestCaseRegistry::~ITestCaseRegistry() {}
11241 IRegistryHub::~IRegistryHub() {}
11242 IMutableRegistryHub::~IMutableRegistryHub() {}
11243 IExceptionTranslator::~IExceptionTranslator() {}
11244 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
11245 IReporter::~IReporter() {}
11246 IReporterFactory::~IReporterFactory() {}
11247 IReporterRegistry::~IReporterRegistry() {}
11248 IStreamingReporter::~IStreamingReporter() {}
11249 AssertionStats::~AssertionStats() {}
11250 SectionStats::~SectionStats() {}
11251 TestCaseStats::~TestCaseStats() {}
11252 TestGroupStats::~TestGroupStats() {}
11253 TestRunStats::~TestRunStats() {}
11254 CumulativeReporterBase::SectionNode::~SectionNode() {}
11255 CumulativeReporterBase::~CumulativeReporterBase() {}
11256
11257 StreamingReporterBase::~StreamingReporterBase() {}
11258 ConsoleReporter::~ConsoleReporter() {}
11259 CompactReporter::~CompactReporter() {}
11260 IRunner::~IRunner() {}
11261 IMutableContext::~IMutableContext() {}
11262 IConfig::~IConfig() {}
11263 XmlReporter::~XmlReporter() {}
11264 JunitReporter::~JunitReporter() {}
11265 TestRegistry::~TestRegistry() {}
11266 FreeFunctionTestCase::~FreeFunctionTestCase() {}
11267 IGeneratorInfo::~IGeneratorInfo() {}
11268 IGeneratorsForTest::~IGeneratorsForTest() {}
11269 WildcardPattern::~WildcardPattern() {}
11270 TestSpec::Pattern::~Pattern() {}
11271 TestSpec::NamePattern::~NamePattern() {}
11272 TestSpec::TagPattern::~TagPattern() {}
11273 TestSpec::ExcludedPattern::~ExcludedPattern() {}
11274 Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
11275
11276 void Config::dummy() {}
11277
11278 namespace TestCaseTracking {
11279 ITracker::~ITracker() {}
11280 TrackerBase::~TrackerBase() {}
11281 SectionTracker::~SectionTracker() {}
11282 IndexTracker::~IndexTracker() {}
11283 }
11284}
11285
11286#ifdef __clang__
11287#pragma clang diagnostic pop
11288#endif
11289
11290#endif
11291
11292#ifdef CATCH_CONFIG_MAIN
11293// #included from: internal/catch_default_main.hpp
11294#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
11295
11296#ifndef __OBJC__
11297
11298#if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
11299// Standard C/C++ Win32 Unicode wmain entry point
11300extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
11301#else
11302// Standard C/C++ main entry point
11303int main (int argc, char * argv[]) {
11304#endif
11305
11306 int result = Catch::Session().run( argc, argv );
11307 return ( result < 0xff ? result : 0xff );
11308}
11309
11310#else // __OBJC__
11311
11312// Objective-C entry point
11313int main (int argc, char * const argv[]) {
11314#if !CATCH_ARC_ENABLED
11315 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
11316#endif
11317
11318 Catch::registerTestMethods();
11319 int result = Catch::Session().run( argc, (char* const*)argv );
11320
11321#if !CATCH_ARC_ENABLED
11322 [pool drain];
11323#endif
11324
11325 return ( result < 0xff ? result : 0xff );
11326}
11327
11328#endif // __OBJC__
11329
11330#endif
11331
11332#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
11333# undef CLARA_CONFIG_MAIN
11334#endif
11335
11336//////
11337
11338// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
11339#ifdef CATCH_CONFIG_PREFIX_ALL
11340
11341#if defined(CATCH_CONFIG_FAST_COMPILE)
11342#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
11343#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11344#else
11345#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
11346#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11347#endif
11348
11349#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
11350#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
11351#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11352#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
11353
11354#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
11355#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
11356#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
11357#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
11358#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
11359
11360#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
11361#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
11362#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11363#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
11364
11365#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11366
11367#if defined(CATCH_CONFIG_FAST_COMPILE)
11368#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11369#else
11370#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11371#endif
11372
11373#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
11374#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
11375#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
11376#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
11377#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
11378
11379#ifdef CATCH_CONFIG_VARIADIC_MACROS
11380 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
11381 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
11382 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
11383 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
11384 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
11385 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
11386 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11387 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11388#else
11389 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
11390 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
11391 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
11392 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
11393 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
11394 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
11395 #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
11396 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
11397#endif
11398#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
11399
11400#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
11401#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
11402
11403#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11404
11405// "BDD-style" convenience wrappers
11406#ifdef CATCH_CONFIG_VARIADIC_MACROS
11407#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
11408#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
11409#else
11410#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
11411#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
11412#endif
11413#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
11414#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
11415#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
11416#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
11417#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
11418
11419// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
11420#else
11421
11422#if defined(CATCH_CONFIG_FAST_COMPILE)
11423#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr )
11424#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11425
11426#else
11427#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr )
11428#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11429#endif
11430
11431#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
11432#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
11433#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11434#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
11435
11436#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
11437#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
11438#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
11439#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
11440#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
11441
11442#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
11443#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
11444#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11445#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
11446
11447#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11448
11449#if defined(CATCH_CONFIG_FAST_COMPILE)
11450#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11451#else
11452#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11453#endif
11454
11455#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
11456#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
11457#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
11458#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
11459#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
11460
11461#ifdef CATCH_CONFIG_VARIADIC_MACROS
11462#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
11463#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
11464#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
11465#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
11466#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
11467#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
11468#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11469#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11470#else
11471#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
11472 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
11473 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
11474 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
11475 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
11476 #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
11477 #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
11478 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
11479#endif
11480#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
11481
11482#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
11483#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
11484
11485#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11486
11487#endif
11488
11489#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
11490
11491// "BDD-style" convenience wrappers
11492#ifdef CATCH_CONFIG_VARIADIC_MACROS
11493#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
11494#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
11495#else
11496#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
11497#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
11498#endif
11499#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
11500#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
11501#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
11502#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
11503#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
11504
11505using Catch::Detail::Approx;
11506
11507#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
11508