blob: 7e5881ee58b31ad81d53674cbf35de781a788f89 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nash859760a2013-12-14 14:34:05 +00002 * CATCH v1.0 build 18 (master branch)
3 * Generated: 2013-12-14 14:32:59.401645
Phil Nash4df051b2012-05-22 22:22:22 +01004 * ----------------------------------------------------------
Phil Nashaec1e5e2012-05-09 19:37:51 +01005 * 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.
Phil Nash89d1e6c2011-05-24 08:23:02 +01007 *
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)
Phil Nash89d1e6c2011-05-24 08:23:02 +010010 */
Phil Nashaec1e5e2012-05-09 19:37:51 +010011#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010013
Phil Nash3b80af72012-08-09 07:47:30 +010014#define TWOBLUECUBES_CATCH_HPP_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +010015
Phil Nash5bc030d2012-08-16 18:48:50 +010016#ifdef __clang__
Phil Nashce612bf2012-11-01 08:27:09 +000017#pragma clang diagnostic ignored "-Wglobal-constructors"
Phil Nash93906752013-03-16 20:21:51 +000018#pragma clang diagnostic ignored "-Wvariadic-macros"
Phil Nash859760a2013-12-14 14:34:05 +000019#pragma clang diagnostic ignored "-Wc99-extensions"
Phil Nasha695eb92012-08-13 07:46:10 +010020#pragma clang diagnostic push
21#pragma clang diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010022#endif
Phil Nasha695eb92012-08-13 07:46:10 +010023
Phil Nash3b80af72012-08-09 07:47:30 +010024// #included from: internal/catch_notimplemented_exception.h
25#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010026
Phil Nash89d1e6c2011-05-24 08:23:02 +010027// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010028#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010029
Phil Nash89d1e6c2011-05-24 08:23:02 +010030#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
31#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
32#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
33
34#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
35#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
36
Phil Nash89d1e6c2011-05-24 08:23:02 +010037#include <sstream>
38#include <stdexcept>
39#include <algorithm>
40
Phil Nash8defc712013-04-24 19:10:02 +010041// #included from: catch_compiler_capabilities.h
42#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
43
44// Much of the following code is based on Boost (1.53)
45
Phil Nash859760a2013-12-14 14:34:05 +000046#ifdef __clang__
47#define CATCH_CONFIG_CPP11_NULLPTR
48
49#if __has_feature(cxx_nullptr)
50
51#define CATCH_CONFIG_CPP11_NULLPTR
52
53#endif
54
55#endif // __clang__
56
Phil Nash8defc712013-04-24 19:10:02 +010057////////////////////////////////////////////////////////////////////////////////
58// Borland
59#ifdef __BORLANDC__
60
61#if (__BORLANDC__ > 0x582 )
62//#define CATCH_CONFIG_SFINAE // Not confirmed
63#endif
64
65#endif // __BORLANDC__
66
67////////////////////////////////////////////////////////////////////////////////
68// EDG
69#ifdef __EDG_VERSION__
70
71#if (__EDG_VERSION__ > 238 )
72//#define CATCH_CONFIG_SFINAE // Not confirmed
73#endif
74
75#endif // __EDG_VERSION__
76
77////////////////////////////////////////////////////////////////////////////////
78// Digital Mars
79#ifdef __DMC__
80
81#if (__DMC__ > 0x840 )
82//#define CATCH_CONFIG_SFINAE // Not confirmed
83#endif
84
85#endif // __DMC__
86
87////////////////////////////////////////////////////////////////////////////////
88// GCC
89#ifdef __GNUC__
90
91#if __GNUC__ < 3
92
93#if (__GNUC_MINOR__ >= 96 )
94//#define CATCH_CONFIG_SFINAE
95#endif
96
97#elif __GNUC__ >= 3
98
99// #define CATCH_CONFIG_SFINAE // Taking this out completely for now
100
101#endif // __GNUC__ < 3
102
Phil Nash859760a2013-12-14 14:34:05 +0000103#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__GXX_EXPERIMENTAL_CXX0X__)
104
105#define CATCH_CONFIG_CPP11_NULLPTR
106#endif
107
Phil Nash8defc712013-04-24 19:10:02 +0100108#endif // __GNUC__
109
110////////////////////////////////////////////////////////////////////////////////
111// Visual C++
112#ifdef _MSC_VER
113
114#if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
115//#define CATCH_CONFIG_SFINAE // Not confirmed
116#endif
117
118#endif // _MSC_VER
119
120// Use variadic macros if the compiler supports them
121#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
122 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
123 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
124 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
Phil Nash786959d2013-06-07 19:07:50 +0100125
126#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS
127#define CATCH_CONFIG_VARIADIC_MACROS
128#endif
129
Phil Nash8defc712013-04-24 19:10:02 +0100130#endif
131
Phil Nash89d2a3f2012-05-16 15:09:17 +0100132namespace Catch {
133
Phil Nasha04981b2013-03-08 09:30:25 +0000134 class NonCopyable {
Phil Nash8defc712013-04-24 19:10:02 +0100135 NonCopyable( NonCopyable const& );
136 void operator = ( NonCopyable const& );
Phil Nasha04981b2013-03-08 09:30:25 +0000137 protected:
138 NonCopyable() {}
139 virtual ~NonCopyable();
140 };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100141
Phil Nash163088a2012-05-31 19:40:26 +0100142 class SafeBool {
143 public:
144 typedef void (SafeBool::*type)() const;
145
146 static type makeSafe( bool value ) {
147 return value ? &SafeBool::trueValue : 0;
148 }
149 private:
150 void trueValue() const {}
151 };
152
Phil Nash89d1e6c2011-05-24 08:23:02 +0100153 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100154 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100155 typename ContainerT::const_iterator it = container.begin();
156 typename ContainerT::const_iterator itEnd = container.end();
157 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100158 delete *it;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100159 }
160 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100161 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100162 typename AssociativeContainerT::const_iterator it = container.begin();
163 typename AssociativeContainerT::const_iterator itEnd = container.end();
164 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100165 delete it->second;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100166 }
167
Phil Nash3649fdf2013-12-03 18:53:55 +0000168 bool startsWith( std::string const& s, std::string const& prefix );
169 bool endsWith( std::string const& s, std::string const& suffix );
170 bool contains( std::string const& s, std::string const& infix );
171 void toLowerInPlace( std::string& s );
172 std::string toLower( std::string const& s );
173 std::string trim( std::string const& str );
Phil Nash4c97fc52012-08-24 08:23:50 +0100174
175 struct pluralise {
Phil Nash3649fdf2013-12-03 18:53:55 +0000176 pluralise( std::size_t count, std::string const& label );
Phil Nash4c97fc52012-08-24 08:23:50 +0100177
Phil Nash3649fdf2013-12-03 18:53:55 +0000178 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
Phil Nash4c97fc52012-08-24 08:23:50 +0100179
180 std::size_t m_count;
181 std::string m_label;
182 };
Phil Nash56d5c422012-08-23 20:08:50 +0100183
Phil Nash89d2a3f2012-05-16 15:09:17 +0100184 struct SourceLineInfo {
185
Phil Nash3649fdf2013-12-03 18:53:55 +0000186 SourceLineInfo();
Phil Nashde49ec42013-12-04 20:25:14 +0000187 SourceLineInfo( char const* _file, std::size_t _line );
Phil Nash3649fdf2013-12-03 18:53:55 +0000188 SourceLineInfo( SourceLineInfo const& other );
189 bool empty() const;
190 bool operator == ( SourceLineInfo const& other ) const;
191
Phil Nash6e0f58d2012-02-15 18:37:21 +0000192 std::string file;
193 std::size_t line;
194 };
195
Phil Nash3649fdf2013-12-03 18:53:55 +0000196 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
Phil Nash6e0f58d2012-02-15 18:37:21 +0000197
Phil Nash8defc712013-04-24 19:10:02 +0100198 // This is just here to avoid compiler warnings with macro constants and boolean literals
199 inline bool isTrue( bool value ){ return value; }
200
Phil Nash3649fdf2013-12-03 18:53:55 +0000201 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
Phil Nash859760a2013-12-14 14:34:05 +0000202
203 // Use this in variadic streaming macros to allow
204 // >> +StreamEndStop
205 // as well as
206 // >> stuff +StreamEndStop
207 struct StreamEndStop {
208 std::string operator+() {
209 return std::string();
210 }
211 };
212 template<typename T>
213 T const& operator + ( T const& value, StreamEndStop ) {
214 return value;
215 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100216}
217
Phil Nasha695eb92012-08-13 07:46:10 +0100218#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
219#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100220
Phil Nash3b80af72012-08-09 07:47:30 +0100221#include <ostream>
222
223namespace Catch {
224
225 class NotImplementedException : public std::exception
226 {
227 public:
Phil Nash8defc712013-04-24 19:10:02 +0100228 NotImplementedException( SourceLineInfo const& lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +0100229
230 virtual ~NotImplementedException() throw() {}
231
232 virtual const char* what() const throw();
233
234 private:
235 std::string m_what;
236 SourceLineInfo m_lineInfo;
237 };
238
239} // end namespace Catch
240
241///////////////////////////////////////////////////////////////////////////////
242#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
243
244// #included from: internal/catch_context.h
245#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
246
Phil Nasha70fbe32012-08-31 08:10:36 +0100247// #included from: catch_interfaces_generators.h
248#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100249
Phil Nasha70fbe32012-08-31 08:10:36 +0100250#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000251
Phil Nash89d2a3f2012-05-16 15:09:17 +0100252namespace Catch {
253
Phil Nasha70fbe32012-08-31 08:10:36 +0100254 struct IGeneratorInfo {
255 virtual ~IGeneratorInfo();
256 virtual bool moveNext() = 0;
257 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000258 };
259
Phil Nasha70fbe32012-08-31 08:10:36 +0100260 struct IGeneratorsForTest {
261 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100262
Phil Nash8defc712013-04-24 19:10:02 +0100263 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +0100264 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000265 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100266
267 IGeneratorsForTest* createGeneratorsForTest();
268
269} // end namespace Catch
270
Phil Nash49e6d532012-05-05 19:35:35 +0100271// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100272#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100273
Phil Nash37186a12013-03-13 12:19:30 +0000274#ifdef __clang__
275#pragma clang diagnostic push
276#pragma clang diagnostic ignored "-Wpadded"
277#endif
278
Phil Nash89d2a3f2012-05-16 15:09:17 +0100279namespace Catch {
280
Phil Nash49e6d532012-05-05 19:35:35 +0100281 // An intrusive reference counting smart pointer.
282 // T must implement addRef() and release() methods
283 // typically implementing the IShared interface
284 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100285 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100286 public:
287 Ptr() : m_p( NULL ){}
288 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100289 if( m_p )
290 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100291 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000292 Ptr( Ptr const& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100293 if( m_p )
294 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100295 }
296 ~Ptr(){
297 if( m_p )
298 m_p->release();
299 }
Phil Nashff03cdf2012-12-06 08:44:51 +0000300 void reset() {
301 if( m_p )
302 m_p->release();
303 m_p = NULL;
304 }
Phil Nash49e6d532012-05-05 19:35:35 +0100305 Ptr& operator = ( T* p ){
306 Ptr temp( p );
307 swap( temp );
308 return *this;
309 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000310 Ptr& operator = ( Ptr const& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100311 Ptr temp( other );
312 swap( temp );
313 return *this;
314 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000315 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
316 T* get() { return m_p; }
317 const T* get() const{ return m_p; }
318 T& operator*() const { return *m_p; }
319 T* operator->() const { return m_p; }
320 bool operator !() const { return m_p == NULL; }
Phil Nashff03cdf2012-12-06 08:44:51 +0000321 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
Phil Nash49e6d532012-05-05 19:35:35 +0100322
323 private:
324 T* m_p;
325 };
326
327 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100328 virtual ~IShared();
Phil Nasha1fbfea2012-12-01 23:57:18 +0000329 virtual void addRef() const = 0;
330 virtual void release() const = 0;
Phil Nash49e6d532012-05-05 19:35:35 +0100331 };
332
Phil Nasha1fbfea2012-12-01 23:57:18 +0000333 template<typename T = IShared>
Phil Nash49e6d532012-05-05 19:35:35 +0100334 struct SharedImpl : T {
335
336 SharedImpl() : m_rc( 0 ){}
337
Phil Nasha1fbfea2012-12-01 23:57:18 +0000338 virtual void addRef() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100339 ++m_rc;
340 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000341 virtual void release() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100342 if( --m_rc == 0 )
343 delete this;
344 }
345
Phil Nasha1fbfea2012-12-01 23:57:18 +0000346 mutable unsigned int m_rc;
Phil Nash49e6d532012-05-05 19:35:35 +0100347 };
348
349} // end namespace Catch
350
Phil Nash37186a12013-03-13 12:19:30 +0000351#ifdef __clang__
352#pragma clang diagnostic pop
353#endif
354
Phil Nash786959d2013-06-07 19:07:50 +0100355#include <memory>
356#include <vector>
357#include <stdlib.h>
358
359namespace Catch {
360
361 class TestCase;
362 class Stream;
363 struct IResultCapture;
364 struct IRunner;
365 struct IGeneratorsForTest;
366 struct IConfig;
367
368 struct IContext
369 {
370 virtual ~IContext();
371
372 virtual IResultCapture& getResultCapture() = 0;
373 virtual IRunner& getRunner() = 0;
374 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
375 virtual bool advanceGeneratorsForCurrentTest() = 0;
376 virtual Ptr<IConfig const> getConfig() const = 0;
377 };
378
379 struct IMutableContext : IContext
380 {
381 virtual ~IMutableContext();
382 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
383 virtual void setRunner( IRunner* runner ) = 0;
384 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
385 };
386
387 IContext& getCurrentContext();
388 IMutableContext& getCurrentMutableContext();
389 void cleanUpContext();
390 Stream createStream( std::string const& streamName );
391
392}
393
394// #included from: internal/catch_test_registry.hpp
395#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
396
397// #included from: catch_interfaces_testcase.h
398#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
399
Phil Nash0f9c5512012-06-02 23:12:42 +0100400#include <vector>
401
402namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100403
404 class TestCaseFilters;
405
Phil Nash5bc030d2012-08-16 18:48:50 +0100406 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100407 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100408 protected:
409 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100410 };
411
Phil Nasha1fbfea2012-12-01 23:57:18 +0000412 class TestCase;
Phil Nash0f9c5512012-06-02 23:12:42 +0100413
414 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100415 virtual ~ITestCaseRegistry();
Phil Nash8defc712013-04-24 19:10:02 +0100416 virtual std::vector<TestCase> const& getAllTests() const = 0;
417 virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100418 };
419}
420
Phil Nash89d2a3f2012-05-16 15:09:17 +0100421namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100422
423template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100424class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100425
Phil Nash176eb812012-05-11 08:17:16 +0100426public:
427 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100428
Phil Nash176eb812012-05-11 08:17:16 +0100429 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100430 C obj;
431 (obj.*m_method)();
432 }
433
Phil Nash89d1e6c2011-05-24 08:23:02 +0100434private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100435 virtual ~MethodTestCase() {}
436
Phil Nash89d1e6c2011-05-24 08:23:02 +0100437 void (C::*m_method)();
438};
439
440typedef void(*TestFunction)();
441
Phil Nash93906752013-03-16 20:21:51 +0000442struct NameAndDesc {
443 NameAndDesc( const char* _name = "", const char* _description= "" )
444 : name( _name ), description( _description )
445 {}
446
447 const char* name;
448 const char* description;
449};
450
Phil Nash89d2a3f2012-05-16 15:09:17 +0100451struct AutoReg {
452
Phil Nash176eb812012-05-11 08:17:16 +0100453 AutoReg( TestFunction function,
Phil Nash93906752013-03-16 20:21:51 +0000454 SourceLineInfo const& lineInfo,
455 NameAndDesc const& nameAndDesc );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100456
Phil Nash89d1e6c2011-05-24 08:23:02 +0100457 template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100458 AutoReg( void (C::*method)(),
Phil Nash93906752013-03-16 20:21:51 +0000459 char const* className,
460 NameAndDesc const& nameAndDesc,
461 SourceLineInfo const& lineInfo ) {
462 registerTestCase( new MethodTestCase<C>( method ),
463 className,
464 nameAndDesc,
465 lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100466 }
467
Phil Nash176eb812012-05-11 08:17:16 +0100468 void registerTestCase( ITestCase* testCase,
Phil Nash93906752013-03-16 20:21:51 +0000469 char const* className,
470 NameAndDesc const& nameAndDesc,
471 SourceLineInfo const& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100472
Phil Nash176eb812012-05-11 08:17:16 +0100473 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100474
475private:
Phil Nash8defc712013-04-24 19:10:02 +0100476 AutoReg( AutoReg const& );
477 void operator= ( AutoReg const& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100478};
479
480} // end namespace Catch
481
Phil Nash93906752013-03-16 20:21:51 +0000482#ifdef CATCH_CONFIG_VARIADIC_MACROS
483 ///////////////////////////////////////////////////////////////////////////////
484 #define INTERNAL_CATCH_TESTCASE( ... ) \
Phil Nash786959d2013-06-07 19:07:50 +0100485 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
486 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
487 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100488
Phil Nash93906752013-03-16 20:21:51 +0000489 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000490 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
491 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100492
Phil Nash93906752013-03-16 20:21:51 +0000493 ///////////////////////////////////////////////////////////////////////////////
Phil Nash786959d2013-06-07 19:07:50 +0100494 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
Phil Nash93906752013-03-16 20:21:51 +0000495 namespace{ \
Phil Nash786959d2013-06-07 19:07:50 +0100496 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000497 void test(); \
498 }; \
Phil Nash786959d2013-06-07 19:07:50 +0100499 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000500 } \
Phil Nash786959d2013-06-07 19:07:50 +0100501 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100502
Phil Nash93906752013-03-16 20:21:51 +0000503#else
504 ///////////////////////////////////////////////////////////////////////////////
505 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nash786959d2013-06-07 19:07:50 +0100506 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
507 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
508 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
Phil Nash93906752013-03-16 20:21:51 +0000509
510 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000511 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
512 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
513
514 ///////////////////////////////////////////////////////////////////////////////
Phil Nash786959d2013-06-07 19:07:50 +0100515 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
Phil Nash93906752013-03-16 20:21:51 +0000516 namespace{ \
Phil Nash786959d2013-06-07 19:07:50 +0100517 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000518 void test(); \
519 }; \
Phil Nash786959d2013-06-07 19:07:50 +0100520 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000521 } \
Phil Nash786959d2013-06-07 19:07:50 +0100522 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
Phil Nash93906752013-03-16 20:21:51 +0000523
524#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100525
526// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100527#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100528
Phil Nashce612bf2012-11-01 08:27:09 +0000529// #included from: catch_expression_decomposer.hpp
530#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100531
Phil Nashce612bf2012-11-01 08:27:09 +0000532// #included from: catch_expression_lhs.hpp
533#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
Phil Nash176eb812012-05-11 08:17:16 +0100534
Phil Nashce612bf2012-11-01 08:27:09 +0000535// #included from: catch_expressionresult_builder.h
536#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100537
Phil Nashd31737f2012-05-09 19:04:00 +0100538// #included from: catch_tostring.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100539#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100540
Phil Nash19279252013-04-20 21:07:32 +0100541// #included from: catch_sfinae.hpp
542#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
543
544// Try to detect if the current compiler supports SFINAE
Phil Nash19279252013-04-20 21:07:32 +0100545
Phil Nash19279252013-04-20 21:07:32 +0100546namespace Catch {
547
548 struct TrueType {
549 static const bool value = true;
550 typedef void Enable;
551 char sizer[1];
552 };
553 struct FalseType {
554 static const bool value = false;
555 typedef void Disable;
556 char sizer[2];
557 };
558
Phil Nash471eba22013-04-22 18:55:12 +0100559#ifdef CATCH_CONFIG_SFINAE
Phil Nashdd520442013-04-20 23:20:05 +0100560
Phil Nash19279252013-04-20 21:07:32 +0100561 template<bool> struct NotABooleanExpression;
562
563 template<bool c> struct If : NotABooleanExpression<c> {};
564 template<> struct If<true> : TrueType {};
565 template<> struct If<false> : FalseType {};
566
567 template<int size> struct SizedIf;
568 template<> struct SizedIf<sizeof(TrueType)> : TrueType {};
569 template<> struct SizedIf<sizeof(FalseType)> : FalseType {};
570
Phil Nash471eba22013-04-22 18:55:12 +0100571#endif // CATCH_CONFIG_SFINAE
Phil Nash19279252013-04-20 21:07:32 +0100572
Phil Nashdd520442013-04-20 23:20:05 +0100573} // end namespace Catch
574
Phil Nashd31737f2012-05-09 19:04:00 +0100575#include <sstream>
Phil Nash767f1582013-03-04 12:19:15 +0100576#include <iomanip>
577#include <limits>
Phil Nash53205182013-11-09 07:47:09 +0000578#include <vector>
Phil Nashd31737f2012-05-09 19:04:00 +0100579
Phil Nash0dc9e432012-08-01 08:17:07 +0100580#ifdef __OBJC__
581// #included from: catch_objc_arc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100582#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
Phil Nash0dc9e432012-08-01 08:17:07 +0100583
584#import <Foundation/Foundation.h>
585
586#ifdef __has_feature
587#define CATCH_ARC_ENABLED __has_feature(objc_arc)
588#else
589#define CATCH_ARC_ENABLED 0
590#endif
591
592void arcSafeRelease( NSObject* obj );
593id performOptionalSelector( id obj, SEL sel );
594
595#if !CATCH_ARC_ENABLED
596inline void arcSafeRelease( NSObject* obj ) {
597 [obj release];
598}
599inline id performOptionalSelector( id obj, SEL sel ) {
600 if( [obj respondsToSelector: sel] )
601 return [obj performSelector: sel];
602 return nil;
603}
604#define CATCH_UNSAFE_UNRETAINED
605#define CATCH_ARC_STRONG
606#else
607inline void arcSafeRelease( NSObject* ){}
608inline id performOptionalSelector( id obj, SEL sel ) {
Phil Nash5bc030d2012-08-16 18:48:50 +0100609#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100610#pragma clang diagnostic push
611#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
Phil Nash5bc030d2012-08-16 18:48:50 +0100612#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100613 if( [obj respondsToSelector: sel] )
614 return [obj performSelector: sel];
Phil Nash5bc030d2012-08-16 18:48:50 +0100615#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100616#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +0100617#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100618 return nil;
619}
620#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
621#define CATCH_ARC_STRONG __strong
622#endif
623
624#endif
625
Phil Nash89d2a3f2012-05-16 15:09:17 +0100626namespace Catch {
627namespace Detail {
628
Phil Nashdd520442013-04-20 23:20:05 +0100629// SFINAE is currently disabled by default for all compilers.
630// If the non SFINAE version of IsStreamInsertable is ambiguous for you
Phil Nash471eba22013-04-22 18:55:12 +0100631// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
632#ifdef CATCH_CONFIG_SFINAE
Phil Nashdd520442013-04-20 23:20:05 +0100633
Phil Nash19279252013-04-20 21:07:32 +0100634 template<typename T>
635 class IsStreamInsertableHelper {
636 template<int N> struct TrueIfSizeable : TrueType {};
637
638 template<typename T2>
639 static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
640 static FalseType dummy(...);
641
642 public:
643 typedef SizedIf<sizeof(dummy((T*)0))> type;
Phil Nashd31737f2012-05-09 19:04:00 +0100644 };
645
Phil Nash19279252013-04-20 21:07:32 +0100646 template<typename T>
647 struct IsStreamInsertable : IsStreamInsertableHelper<T>::type {};
648
Phil Nash19279252013-04-20 21:07:32 +0100649#else
650
Phil Nashdd520442013-04-20 23:20:05 +0100651 struct BorgType {
652 template<typename T> BorgType( T const& );
653 };
Phil Nashd31737f2012-05-09 19:04:00 +0100654
Phil Nashdd520442013-04-20 23:20:05 +0100655 TrueType& testStreamable( std::ostream& );
656 FalseType testStreamable( FalseType );
657
658 FalseType operator<<( std::ostream const&, BorgType const& );
Phil Nashd31737f2012-05-09 19:04:00 +0100659
660 template<typename T>
Phil Nashdd520442013-04-20 23:20:05 +0100661 struct IsStreamInsertable {
662 static std::ostream &s;
Phil Nash8defc712013-04-24 19:10:02 +0100663 static T const&t;
Phil Nashdd520442013-04-20 23:20:05 +0100664 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
665 };
Phil Nashd31737f2012-05-09 19:04:00 +0100666
Phil Nashdd520442013-04-20 23:20:05 +0100667#endif
668
669 template<bool C>
670 struct StringMakerBase {
671 template<typename T>
672 static std::string convert( T const& ) { return "{?}"; }
673 };
674
675 template<>
676 struct StringMakerBase<true> {
677 template<typename T>
678 static std::string convert( T const& _value ) {
679 std::ostringstream oss;
680 oss << _value;
681 return oss.str();
682 }
Phil Nashd31737f2012-05-09 19:04:00 +0100683 };
684
Phil Nash767f1582013-03-04 12:19:15 +0100685} // end namespace Detail
Phil Nashd31737f2012-05-09 19:04:00 +0100686
Phil Nash767f1582013-03-04 12:19:15 +0100687template<typename T>
Phil Nash1e2f1d12013-09-14 19:58:45 +0100688std::string toString( T const& value );
689
690template<typename T>
Phil Nashdd520442013-04-20 23:20:05 +0100691struct StringMaker :
692 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
Phil Nash19279252013-04-20 21:07:32 +0100693
Phil Nash767f1582013-03-04 12:19:15 +0100694template<typename T>
695struct StringMaker<T*> {
Phil Nash503d5d02013-07-03 08:25:11 +0100696 template<typename U>
697 static std::string convert( U* p ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100698 if( !p )
699 return INTERNAL_CATCH_STRINGIFY( NULL );
700 std::ostringstream oss;
701 oss << p;
702 return oss.str();
703 }
Phil Nash767f1582013-03-04 12:19:15 +0100704};
Phil Nashd31737f2012-05-09 19:04:00 +0100705
Andy Sawyer0dbcf212013-09-17 22:22:47 +0100706namespace Detail {
707 template<typename InputIterator>
Andy Sawyer7974e1c2013-09-21 19:08:23 +0100708 std::string rangeToString( InputIterator first, InputIterator last );
Andy Sawyer0dbcf212013-09-17 22:22:47 +0100709}
710
711template<typename T, typename Allocator>
712struct StringMaker<std::vector<T, Allocator> > {
713 static std::string convert( std::vector<T,Allocator> const& v ) {
714 return Detail::rangeToString( v.begin(), v.end() );
715 }
Phil Nash767f1582013-03-04 12:19:15 +0100716};
Phil Nashd31737f2012-05-09 19:04:00 +0100717
Phil Nash767f1582013-03-04 12:19:15 +0100718namespace Detail {
719 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +0100720 inline std::string makeString( T const& value ) {
Phil Nash767f1582013-03-04 12:19:15 +0100721 return StringMaker<T>::convert( value );
722 }
Phil Nashd31737f2012-05-09 19:04:00 +0100723} // end namespace Detail
724
725/// \brief converts any type to a string
726///
727/// The default template forwards on to ostringstream - except when an
728/// ostringstream overload does not exist - in which case it attempts to detect
729/// that and writes {?}.
730/// Overload (not specialise) this template for custom typs that you don't want
731/// to provide an ostream overload for.
732template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +0100733std::string toString( T const& value ) {
Phil Nash767f1582013-03-04 12:19:15 +0100734 return StringMaker<T>::convert( value );
Phil Nashd31737f2012-05-09 19:04:00 +0100735}
736
737// Built in overloads
738
Phil Nash8defc712013-04-24 19:10:02 +0100739inline std::string toString( std::string const& value ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100740 return "\"" + value + "\"";
741}
742
Phil Nash8defc712013-04-24 19:10:02 +0100743inline std::string toString( std::wstring const& value ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100744 std::ostringstream oss;
745 oss << "\"";
746 for(size_t i = 0; i < value.size(); ++i )
747 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
748 oss << "\"";
749 return oss.str();
750}
751
752inline std::string toString( const char* const value ) {
753 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
754}
755
756inline std::string toString( char* const value ) {
757 return Catch::toString( static_cast<const char*>( value ) );
758}
759
760inline std::string toString( int value ) {
761 std::ostringstream oss;
762 oss << value;
763 return oss.str();
764}
765
766inline std::string toString( unsigned long value ) {
767 std::ostringstream oss;
768 if( value > 8192 )
769 oss << "0x" << std::hex << value;
770 else
771 oss << value;
772 return oss.str();
773}
774
775inline std::string toString( unsigned int value ) {
Phil Nash62179662012-05-11 19:06:43 +0100776 return toString( static_cast<unsigned long>( value ) );
Phil Nashd31737f2012-05-09 19:04:00 +0100777}
778
779inline std::string toString( const double value ) {
780 std::ostringstream oss;
Phil Nashaa7123b2013-08-15 19:01:00 +0100781 oss << std::setprecision( 10 )
782 << std::fixed
Phil Nash767f1582013-03-04 12:19:15 +0100783 << value;
Phil Nashaa7123b2013-08-15 19:01:00 +0100784 std::string d = oss.str();
785 std::size_t i = d.find_last_not_of( '0' );
786 if( i != std::string::npos && i != d.size()-1 ) {
787 if( d[i] == '.' )
788 i++;
789 d = d.substr( 0, i+1 );
790 }
791 return d;
Phil Nashd31737f2012-05-09 19:04:00 +0100792}
793
794inline std::string toString( bool value ) {
795 return value ? "true" : "false";
796}
797
Phil Nash78372d02012-06-06 08:06:40 +0100798inline std::string toString( char value ) {
799 return value < ' '
Phil Nashcf5ced52012-12-14 07:50:08 +0000800 ? toString( static_cast<unsigned int>( value ) )
Phil Nash78372d02012-06-06 08:06:40 +0100801 : Detail::makeString( value );
802}
803
804inline std::string toString( signed char value ) {
805 return toString( static_cast<char>( value ) );
806}
807
Phil Nashcf5ced52012-12-14 07:50:08 +0000808inline std::string toString( unsigned char value ) {
809 return toString( static_cast<char>( value ) );
810}
811
Phil Nash176eb812012-05-11 08:17:16 +0100812#ifdef CATCH_CONFIG_CPP11_NULLPTR
Phil Nash06e959b2012-05-25 08:52:05 +0100813inline std::string toString( std::nullptr_t ) {
Phil Nash176eb812012-05-11 08:17:16 +0100814 return "nullptr";
815}
816#endif
817
Phil Nash0dc9e432012-08-01 08:17:07 +0100818#ifdef __OBJC__
Phil Nash0dc9e432012-08-01 08:17:07 +0100819 inline std::string toString( NSString const * const& nsstring ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000820 if( !nsstring )
821 return "nil";
Phil Nash0dc9e432012-08-01 08:17:07 +0100822 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
823 }
824 inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000825 if( !nsstring )
826 return "nil";
Phil Nash0dc9e432012-08-01 08:17:07 +0100827 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
828 }
829 inline std::string toString( NSObject* const& nsObject ) {
830 return toString( [nsObject description] );
831 }
832#endif
833
Andy Sawyer7974e1c2013-09-21 19:08:23 +0100834 namespace Detail {
835 template<typename InputIterator>
836 std::string rangeToString( InputIterator first, InputIterator last ) {
837 std::ostringstream oss;
838 oss << "{ ";
839 if( first != last ) {
840 oss << toString( *first );
841 for( ++first ; first != last ; ++first ) {
842 oss << ", " << toString( *first );
843 }
844 }
845 oss << " }";
846 return oss.str();
847 }
848}
849
Phil Nashd31737f2012-05-09 19:04:00 +0100850} // end namespace Catch
851
Phil Nashce612bf2012-11-01 08:27:09 +0000852// #included from: catch_assertionresult.h
853#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100854
Phil Nash89d1e6c2011-05-24 08:23:02 +0100855#include <string>
856// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100857#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100858
Phil Nash89d2a3f2012-05-16 15:09:17 +0100859namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100860
Phil Nash90a35942012-11-13 22:04:29 +0000861 // ResultWas::OfType enum
862 struct ResultWas { enum OfType {
863 Unknown = -1,
864 Ok = 0,
865 Info = 1,
866 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100867
Phil Nash90a35942012-11-13 22:04:29 +0000868 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100869
Phil Nash90a35942012-11-13 22:04:29 +0000870 ExpressionFailed = FailureBit | 1,
871 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100872
Phil Nash90a35942012-11-13 22:04:29 +0000873 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100874
Phil Nash90a35942012-11-13 22:04:29 +0000875 ThrewException = Exception | 1,
876 DidntThrowException = Exception | 2
Phil Nash89d1e6c2011-05-24 08:23:02 +0100877
Phil Nash90a35942012-11-13 22:04:29 +0000878 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100879
Phil Nash90a35942012-11-13 22:04:29 +0000880 inline bool isOk( ResultWas::OfType resultType ) {
881 return ( resultType & ResultWas::FailureBit ) == 0;
882 }
Phil Nasha2773812013-02-02 20:37:58 +0000883 inline bool isJustInfo( int flags ) {
884 return flags == ResultWas::Info;
885 }
Phil Nash67305122012-10-09 11:48:55 +0100886
Phil Nash90a35942012-11-13 22:04:29 +0000887 // ResultAction::Value enum
888 struct ResultAction { enum Value {
889 None,
890 Failed = 1, // Failure - but no debug break if Debug bit not set
891 Debug = 2, // If this bit is set, invoke the debugger
892 Abort = 4 // Test run should abort
893 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100894
Phil Nash90a35942012-11-13 22:04:29 +0000895 // ResultDisposition::Flags enum
896 struct ResultDisposition { enum Flags {
897 Normal = 0x00,
898
899 ContinueOnFailure = 0x01, // Failures fail test, but execution continues
900 NegateResult = 0x02, // Prefix expressiom with !
901 SuppressFail = 0x04 // Failures are reported but do not fail the test
902 }; };
903
904 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
905 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
906 }
907
Phil Nash3e2e3182012-11-17 10:49:24 +0000908 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
909 inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; }
910 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nash90a35942012-11-13 22:04:29 +0000911
912} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100913
914
Phil Nash89d2a3f2012-05-16 15:09:17 +0100915namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100916
Phil Nashce612bf2012-11-01 08:27:09 +0000917 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100918 {
Phil Nashce612bf2012-11-01 08:27:09 +0000919 AssertionInfo() {}
Phil Nash8defc712013-04-24 19:10:02 +0100920 AssertionInfo( std::string const& _macroName,
921 SourceLineInfo const& _lineInfo,
922 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +0000923 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100924
925 std::string macroName;
926 SourceLineInfo lineInfo;
927 std::string capturedExpression;
Phil Nash90a35942012-11-13 22:04:29 +0000928 ResultDisposition::Flags resultDisposition;
Phil Nashce612bf2012-11-01 08:27:09 +0000929 };
930
931 struct AssertionResultData
932 {
933 AssertionResultData() : resultType( ResultWas::Unknown ) {}
934
Phil Nash67305122012-10-09 11:48:55 +0100935 std::string reconstructedExpression;
936 std::string message;
937 ResultWas::OfType resultType;
938 };
939
Phil Nashce612bf2012-11-01 08:27:09 +0000940 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100941 public:
Phil Nashce612bf2012-11-01 08:27:09 +0000942 AssertionResult();
Phil Nash8defc712013-04-24 19:10:02 +0100943 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
Phil Nashce612bf2012-11-01 08:27:09 +0000944 ~AssertionResult();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100945
Phil Nash90a35942012-11-13 22:04:29 +0000946 bool isOk() const;
947 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100948 ResultWas::OfType getResultType() const;
949 bool hasExpression() const;
950 bool hasMessage() const;
951 std::string getExpression() const;
Phil Nash786959d2013-06-07 19:07:50 +0100952 std::string getExpressionInMacro() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100953 bool hasExpandedExpression() const;
954 std::string getExpandedExpression() const;
955 std::string getMessage() const;
Phil Nashce612bf2012-11-01 08:27:09 +0000956 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100957 std::string getTestMacroName() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100958
959 protected:
Phil Nashce612bf2012-11-01 08:27:09 +0000960 AssertionInfo m_info;
961 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100962 };
963
964} // end namespace Catch
965
Phil Nash89d1e6c2011-05-24 08:23:02 +0100966// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100967#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100968
Phil Nashdd26e882013-03-25 09:25:31 +0000969#ifdef _MSC_VER
970#pragma warning(push)
971#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
972#endif
973
Phil Nash89d2a3f2012-05-16 15:09:17 +0100974namespace Catch {
975namespace Internal {
976
977 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100978 IsEqualTo,
979 IsNotEqualTo,
980 IsLessThan,
981 IsGreaterThan,
982 IsLessThanOrEqualTo,
983 IsGreaterThanOrEqualTo
984 };
985
Phil Nash371db8b2012-05-21 18:52:09 +0100986 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
987 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
988 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
989 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
990 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
991 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
992 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100993
Phil Nash471eba22013-04-22 18:55:12 +0100994 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +0100995 inline T& opCast(T const& t) { return const_cast<T&>(t); }
Phil Nash471eba22013-04-22 18:55:12 +0100996
997// nullptr_t support based on pull request #154 from Konstantin Baumann
998#ifdef CATCH_CONFIG_CPP11_NULLPTR
999 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1000#endif // CATCH_CONFIG_CPP11_NULLPTR
1001
Phil Nash89d1e6c2011-05-24 08:23:02 +01001002 // So the compare overloads can be operator agnostic we convey the operator as a template
1003 // enum, which is used to specialise an Evaluator for doing the comparison.
1004 template<typename T1, typename T2, Operator Op>
1005 class Evaluator{};
1006
1007 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001008 struct Evaluator<T1, T2, IsEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001009 static bool evaluate( T1 const& lhs, T2 const& rhs) {
Phil Nash471eba22013-04-22 18:55:12 +01001010 return opCast( lhs ) == opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001011 }
1012 };
1013 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001014 struct Evaluator<T1, T2, IsNotEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001015 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001016 return opCast( lhs ) != opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001017 }
1018 };
1019 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001020 struct Evaluator<T1, T2, IsLessThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001021 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001022 return opCast( lhs ) < opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001023 }
1024 };
1025 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001026 struct Evaluator<T1, T2, IsGreaterThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001027 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001028 return opCast( lhs ) > opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001029 }
1030 };
1031 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001032 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001033 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001034 return opCast( lhs ) >= opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001035 }
1036 };
1037 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001038 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001039 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nash471eba22013-04-22 18:55:12 +01001040 return opCast( lhs ) <= opCast( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001041 }
1042 };
1043
1044 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001045 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001046 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1047 }
1048
Phil Nash90a35942012-11-13 22:04:29 +00001049 // This level of indirection allows us to specialise for integer types
1050 // to avoid signed/ unsigned warnings
1051
Phil Nash89d1e6c2011-05-24 08:23:02 +01001052 // "base" overload
1053 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001054 bool compare( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001055 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1056 }
1057
1058 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +01001059 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001060 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1061 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001062 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001063 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1064 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001065 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001066 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1067 }
1068
1069 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +01001070 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001071 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1072 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001073 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001074 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1075 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001076 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001077 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1078 }
1079
1080 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001081 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001082 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1083 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001084 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001085 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1086 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001087 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001088 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1089 }
1090
1091 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001092 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001093 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001094 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001095 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001096 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001097 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001098 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001099 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001100 }
1101
Phil Nash06e959b2012-05-25 08:52:05 +01001102 // pointer to long (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001103 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001104 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +01001105 }
Phil Nash90a35942012-11-13 22:04:29 +00001106 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +01001107 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001108 }
1109
Phil Nash06e959b2012-05-25 08:52:05 +01001110 // pointer to int (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001111 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001112 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1113 }
Phil Nash90a35942012-11-13 22:04:29 +00001114 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001115 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1116 }
1117
Phil Nash471eba22013-04-22 18:55:12 +01001118#ifdef CATCH_CONFIG_CPP11_NULLPTR
1119 // pointer to nullptr_t (when comparing against nullptr)
1120 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1121 return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
1122 }
1123 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1124 return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
1125 }
1126#endif // CATCH_CONFIG_CPP11_NULLPTR
1127
Phil Nash89d1e6c2011-05-24 08:23:02 +01001128} // end of namespace Internal
1129} // end of namespace Catch
1130
Phil Nashdd26e882013-03-25 09:25:31 +00001131#ifdef _MSC_VER
1132#pragma warning(pop)
1133#endif
1134
Phil Nash89d2a3f2012-05-16 15:09:17 +01001135namespace Catch {
Phil Nashf51d3162011-12-28 10:37:31 +00001136
Phil Nashcd688302013-06-29 12:11:32 +01001137struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1138
Phil Nashce612bf2012-11-01 08:27:09 +00001139// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
1140// the result of evaluating it. This is used to build an AssertionResult object
1141class ExpressionResultBuilder {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001142public:
1143
Phil Nashce612bf2012-11-01 08:27:09 +00001144 ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown );
Phil Nash8defc712013-04-24 19:10:02 +01001145 ExpressionResultBuilder( ExpressionResultBuilder const& other );
1146 ExpressionResultBuilder& operator=(ExpressionResultBuilder const& other );
Phil Nashd31737f2012-05-09 19:04:00 +01001147
Phil Nashce612bf2012-11-01 08:27:09 +00001148 ExpressionResultBuilder& setResultType( ResultWas::OfType result );
1149 ExpressionResultBuilder& setResultType( bool result );
Phil Nash8defc712013-04-24 19:10:02 +01001150 ExpressionResultBuilder& setLhs( std::string const& lhs );
1151 ExpressionResultBuilder& setRhs( std::string const& rhs );
1152 ExpressionResultBuilder& setOp( std::string const& op );
Phil Nash78d95a02012-03-04 21:22:36 +00001153
Phil Nash90a35942012-11-13 22:04:29 +00001154 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +01001155
Phil Nashce612bf2012-11-01 08:27:09 +00001156 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001157 ExpressionResultBuilder& operator << ( T const& value ) {
Phil Nashce612bf2012-11-01 08:27:09 +00001158 m_stream << value;
1159 return *this;
Phil Nash67305122012-10-09 11:48:55 +01001160 }
1161
Phil Nash8defc712013-04-24 19:10:02 +01001162 std::string reconstructExpression( AssertionInfo const& info ) const;
Phil Nashce612bf2012-11-01 08:27:09 +00001163
Phil Nash8defc712013-04-24 19:10:02 +01001164 AssertionResult buildResult( AssertionInfo const& info ) const;
Phil Nashce612bf2012-11-01 08:27:09 +00001165
Phil Nashcd688302013-06-29 12:11:32 +01001166 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1167 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1168
Phil Nash89d1e6c2011-05-24 08:23:02 +01001169private:
Phil Nashce612bf2012-11-01 08:27:09 +00001170 AssertionResultData m_data;
1171 struct ExprComponents {
1172 ExprComponents() : shouldNegate( false ) {}
1173 bool shouldNegate;
1174 std::string lhs, rhs, op;
1175 } m_exprComponents;
1176 std::ostringstream m_stream;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001177};
1178
Phil Nashd31737f2012-05-09 19:04:00 +01001179} // end namespace Catch
1180
Phil Nash89d2a3f2012-05-16 15:09:17 +01001181namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001182
Phil Nashce612bf2012-11-01 08:27:09 +00001183// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all
1184// in an ExpressionResultBuilder object
Phil Nash176eb812012-05-11 08:17:16 +01001185template<typename T>
Phil Nashce612bf2012-11-01 08:27:09 +00001186class ExpressionLhs {
Phil Nash8defc712013-04-24 19:10:02 +01001187 void operator = ( ExpressionLhs const& );
Phil Nash176eb812012-05-11 08:17:16 +01001188
1189public:
Wichert Akkermanfec10532012-11-16 10:47:33 +01001190 ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
Phil Nash176eb812012-05-11 08:17:16 +01001191
1192 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001193 ExpressionResultBuilder& operator == ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001194 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001195 }
1196
1197 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001198 ExpressionResultBuilder& operator != ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001199 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001200 }
1201
1202 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001203 ExpressionResultBuilder& operator < ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001204 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001205 }
1206
1207 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001208 ExpressionResultBuilder& operator > ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001209 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001210 }
1211
1212 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001213 ExpressionResultBuilder& operator <= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001214 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001215 }
1216
1217 template<typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001218 ExpressionResultBuilder& operator >= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001219 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001220 }
1221
Phil Nashce612bf2012-11-01 08:27:09 +00001222 ExpressionResultBuilder& operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001223 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001224 }
1225
Phil Nashce612bf2012-11-01 08:27:09 +00001226 ExpressionResultBuilder& operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001227 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001228 }
1229
Phil Nash90a35942012-11-13 22:04:29 +00001230 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) {
Phil Nashce612bf2012-11-01 08:27:09 +00001231 bool value = m_lhs ? true : false;
1232 return m_result
1233 .setLhs( Catch::toString( value ) )
1234 .setResultType( value )
Phil Nash90a35942012-11-13 22:04:29 +00001235 .endExpression( resultDisposition );
Phil Nash176eb812012-05-11 08:17:16 +01001236 }
1237
Phil Nashce612bf2012-11-01 08:27:09 +00001238 // Only simple binary expressions are allowed on the LHS.
1239 // If more complex compositions are required then place the sub expression in parentheses
Phil Nash8defc712013-04-24 19:10:02 +01001240 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1241 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1242 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1243 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
Phil Nashcd688302013-06-29 12:11:32 +01001244 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1245 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
Phil Nash176eb812012-05-11 08:17:16 +01001246
1247private:
Phil Nash9902ac92012-10-09 20:58:33 +01001248 template<Internal::Operator Op, typename RhsT>
Phil Nash8defc712013-04-24 19:10:02 +01001249 ExpressionResultBuilder& captureExpression( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001250 return m_result
Phil Nashce612bf2012-11-01 08:27:09 +00001251 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1252 .setLhs( Catch::toString( m_lhs ) )
Phil Nash9902ac92012-10-09 20:58:33 +01001253 .setRhs( Catch::toString( rhs ) )
1254 .setOp( Internal::OperatorTraits<Op>::getName() );
1255 }
1256
1257private:
Phil Nashce612bf2012-11-01 08:27:09 +00001258 ExpressionResultBuilder m_result;
Phil Nash176eb812012-05-11 08:17:16 +01001259 T m_lhs;
1260};
1261
Phil Nash176eb812012-05-11 08:17:16 +01001262} // end namespace Catch
1263
Phil Nash89d2a3f2012-05-16 15:09:17 +01001264namespace Catch {
1265
Phil Nashce612bf2012-11-01 08:27:09 +00001266// Captures the LHS of the expression and wraps it in an Expression Lhs object
1267class ExpressionDecomposer {
Phil Nash89d2a3f2012-05-16 15:09:17 +01001268public:
1269
Phil Nash89d2a3f2012-05-16 15:09:17 +01001270 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001271 ExpressionLhs<T const&> operator->* ( T const& operand ) {
1272 return ExpressionLhs<T const&>( operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001273 }
1274
Phil Nashce612bf2012-11-01 08:27:09 +00001275 ExpressionLhs<bool> operator->* ( bool value ) {
1276 return ExpressionLhs<bool>( value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001277 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001278};
1279
1280} // end namespace Catch
1281
Phil Nasha2773812013-02-02 20:37:58 +00001282// #included from: catch_message.h
1283#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1284
1285#include <string>
1286
1287namespace Catch {
1288
1289 struct MessageInfo {
1290 MessageInfo( std::string const& _macroName,
1291 SourceLineInfo const& _lineInfo,
1292 ResultWas::OfType _type );
1293
1294 std::string macroName;
1295 SourceLineInfo lineInfo;
1296 ResultWas::OfType type;
1297 std::string message;
1298 unsigned int sequence;
1299
1300 bool operator == ( MessageInfo const& other ) const {
1301 return sequence == other.sequence;
1302 }
1303 bool operator < ( MessageInfo const& other ) const {
1304 return sequence < other.sequence;
1305 }
1306 private:
1307 static unsigned int globalCount;
1308 };
1309
Phil Nashb5fd5a62013-06-28 17:09:57 +01001310 struct MessageBuilder {
1311 MessageBuilder( std::string const& macroName,
1312 SourceLineInfo const& lineInfo,
1313 ResultWas::OfType type )
1314 : m_info( macroName, lineInfo, type )
1315 {}
Phil Nasha2773812013-02-02 20:37:58 +00001316
1317 template<typename T>
Phil Nashb5fd5a62013-06-28 17:09:57 +01001318 MessageBuilder& operator << ( T const& value ) {
1319 m_stream << value;
Phil Nasha2773812013-02-02 20:37:58 +00001320 return *this;
1321 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01001322
1323 MessageInfo m_info;
1324 std::ostringstream m_stream;
Phil Nasha2773812013-02-02 20:37:58 +00001325 };
1326
Phil Nashb5fd5a62013-06-28 17:09:57 +01001327 class ScopedMessage {
Phil Nasha2773812013-02-02 20:37:58 +00001328 public:
Phil Nashb5fd5a62013-06-28 17:09:57 +01001329 ScopedMessage( MessageBuilder const& builder );
1330 ~ScopedMessage();
1331
1332 MessageInfo m_info;
Phil Nasha2773812013-02-02 20:37:58 +00001333 };
1334
1335} // end namespace Catch
1336
Phil Nashd31737f2012-05-09 19:04:00 +01001337// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001338#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001339
Phil Nashd31737f2012-05-09 19:04:00 +01001340#include <string>
1341
Phil Nash89d2a3f2012-05-16 15:09:17 +01001342namespace Catch {
1343
Phil Nasha1fbfea2012-12-01 23:57:18 +00001344 class TestCase;
Phil Nashce612bf2012-11-01 08:27:09 +00001345 class ExpressionResultBuilder;
1346 class AssertionResult;
1347 struct AssertionInfo;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001348 struct SectionInfo;
Phil Nashb5fd5a62013-06-28 17:09:57 +01001349 struct MessageInfo;
Phil Nasha2773812013-02-02 20:37:58 +00001350 class ScopedMessageBuilder;
Phil Nash3649fdf2013-12-03 18:53:55 +00001351 struct Counts;
Phil Nashd31737f2012-05-09 19:04:00 +01001352
Phil Nash89d2a3f2012-05-16 15:09:17 +01001353 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001354
Phil Nasha695eb92012-08-13 07:46:10 +01001355 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001356
Phil Nasha2773812013-02-02 20:37:58 +00001357 virtual void assertionEnded( AssertionResult const& result ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001358 virtual bool sectionStarted( SectionInfo const& sectionInfo,
Phil Nash89d2a3f2012-05-16 15:09:17 +01001359 Counts& assertions ) = 0;
Phil Nashaa7123b2013-08-15 19:01:00 +01001360 virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
Phil Nashb5fd5a62013-06-28 17:09:57 +01001361 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1362 virtual void popScopedMessage( MessageInfo const& message ) = 0;
Phil Nasha2773812013-02-02 20:37:58 +00001363
Phil Nash89d2a3f2012-05-16 15:09:17 +01001364 virtual bool shouldDebugBreak() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001365
Phil Nasha1fbfea2012-12-01 23:57:18 +00001366 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001367
Phil Nash89d2a3f2012-05-16 15:09:17 +01001368 virtual std::string getCurrentTestName() const = 0;
Phil Nashce612bf2012-11-01 08:27:09 +00001369 virtual const AssertionResult* getLastResult() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001370 };
1371}
1372
Phil Nash3649fdf2013-12-03 18:53:55 +00001373// #included from: catch_debugger.h
1374#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001375
Phil Nash04a33642013-08-16 19:09:09 +01001376// #included from: catch_platform.h
1377#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1378
Phil Nashd31737f2012-05-09 19:04:00 +01001379#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1380#define CATCH_PLATFORM_MAC
1381#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1382#define CATCH_PLATFORM_IPHONE
Phil Nash04a33642013-08-16 19:09:09 +01001383#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
Phil Nashd31737f2012-05-09 19:04:00 +01001384#define CATCH_PLATFORM_WINDOWS
1385#endif
1386
Phil Nash3649fdf2013-12-03 18:53:55 +00001387#include <string>
1388
1389namespace Catch{
1390
1391 bool isDebuggerActive();
1392 void writeToDebugConsole( std::string const& text );
1393}
1394
Phil Nashd31737f2012-05-09 19:04:00 +01001395#ifdef CATCH_PLATFORM_MAC
1396
Phil Nash3649fdf2013-12-03 18:53:55 +00001397 // The following code snippet based on:
Phil Nashd31737f2012-05-09 19:04:00 +01001398 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1399 #ifdef DEBUG
1400 #if defined(__ppc64__) || defined(__ppc__)
Phil Nash3649fdf2013-12-03 18:53:55 +00001401 #define CATCH_BREAK_INTO_DEBUGGER() \
1402 if( Catch::isDebuggerActive() ) { \
1403 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1404 : : : "memory","r0","r3","r4" ); \
1405 }
Phil Nashd31737f2012-05-09 19:04:00 +01001406 #else
Phil Nash3649fdf2013-12-03 18:53:55 +00001407 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
Phil Nashd31737f2012-05-09 19:04:00 +01001408 #endif
Phil Nashd31737f2012-05-09 19:04:00 +01001409 #endif
1410
1411#elif defined(_MSC_VER)
Phil Nash3649fdf2013-12-03 18:53:55 +00001412 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
Phil Nash176eb812012-05-11 08:17:16 +01001413#elif defined(__MINGW32__)
Phil Nash176eb812012-05-11 08:17:16 +01001414 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
Phil Nash3649fdf2013-12-03 18:53:55 +00001415 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
Phil Nashd31737f2012-05-09 19:04:00 +01001416#endif
1417
Phil Nash3649fdf2013-12-03 18:53:55 +00001418#ifndef CATCH_BREAK_INTO_DEBUGGER
Phil Nasha6d74bd2013-12-11 08:28:15 +00001419#define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true );
Phil Nash3649fdf2013-12-03 18:53:55 +00001420#endif
Phil Nashd31737f2012-05-09 19:04:00 +01001421
Phil Nash3b80af72012-08-09 07:47:30 +01001422// #included from: catch_interfaces_registry_hub.h
1423#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1424
Phil Nasha70fbe32012-08-31 08:10:36 +01001425#include <string>
Phil Nash37186a12013-03-13 12:19:30 +00001426
Phil Nasha70fbe32012-08-31 08:10:36 +01001427namespace Catch {
1428
Phil Nash3649fdf2013-12-03 18:53:55 +00001429 class TestCase;
1430 struct ITestCaseRegistry;
1431 struct IExceptionTranslatorRegistry;
1432 struct IExceptionTranslator;
1433 struct IReporterRegistry;
1434 struct IReporterFactory;
Phil Nasha70fbe32012-08-31 08:10:36 +01001435
Phil Nash3649fdf2013-12-03 18:53:55 +00001436 struct IRegistryHub {
1437 virtual ~IRegistryHub();
Phil Nasha70fbe32012-08-31 08:10:36 +01001438
Phil Nash3649fdf2013-12-03 18:53:55 +00001439 virtual IReporterRegistry const& getReporterRegistry() const = 0;
1440 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
1441 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001442 };
1443
Phil Nash3649fdf2013-12-03 18:53:55 +00001444 struct IMutableRegistryHub {
1445 virtual ~IMutableRegistryHub();
1446 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
1447 virtual void registerTest( TestCase const& testInfo ) = 0;
1448 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01001449 };
Phil Nasha1fbfea2012-12-01 23:57:18 +00001450
Phil Nash3649fdf2013-12-03 18:53:55 +00001451 IRegistryHub& getRegistryHub();
1452 IMutableRegistryHub& getMutableRegistryHub();
1453 void cleanUp();
1454 std::string translateActiveException();
Phil Nasha70fbe32012-08-31 08:10:36 +01001455
1456}
1457
1458// #included from: catch_interfaces_config.h
1459#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
1460
Phil Nash786959d2013-06-07 19:07:50 +01001461#include <iostream>
1462#include <string>
1463
Phil Nasha70fbe32012-08-31 08:10:36 +01001464namespace Catch {
1465
Phil Nashaa7123b2013-08-15 19:01:00 +01001466 struct Verbosity { enum Level {
1467 NoOutput = 0,
1468 Quiet,
1469 Normal
1470 }; };
1471
1472 struct WarnAbout { enum What {
1473 Nothing = 0x00,
1474 NoAssertions = 0x01
1475 }; };
1476
1477 struct ShowDurations { enum OrNot {
1478 DefaultForReporter,
1479 Always,
1480 Never
1481 }; };
1482
Phil Nash786959d2013-06-07 19:07:50 +01001483 struct IConfig : IShared {
Phil Nasha70fbe32012-08-31 08:10:36 +01001484
1485 virtual ~IConfig();
1486
1487 virtual bool allowThrows() const = 0;
Phil Nash786959d2013-06-07 19:07:50 +01001488 virtual std::ostream& stream() const = 0;
1489 virtual std::string name() const = 0;
1490 virtual bool includeSuccessfulResults() const = 0;
1491 virtual bool shouldDebugBreak() const = 0;
1492 virtual bool warnAboutMissingAssertions() const = 0;
1493 virtual int abortAfter() const = 0;
Phil Nashaa7123b2013-08-15 19:01:00 +01001494 virtual ShowDurations::OrNot showDurations() const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01001495 };
1496}
1497
Phil Nashce612bf2012-11-01 08:27:09 +00001498#include <ostream>
1499
1500namespace Catch {
1501
1502 inline IResultCapture& getResultCapture() {
1503 return getCurrentContext().getResultCapture();
1504 }
1505
1506 template<typename MatcherT>
Phil Nash8defc712013-04-24 19:10:02 +01001507 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
1508 std::string const& matcherCallAsString ) {
Phil Nashce612bf2012-11-01 08:27:09 +00001509 std::string matcherAsString = matcher.toString();
1510 if( matcherAsString == "{?}" )
1511 matcherAsString = matcherCallAsString;
1512 return ExpressionResultBuilder()
1513 .setRhs( matcherAsString )
1514 .setOp( "matches" );
1515 }
1516
1517 template<typename MatcherT, typename ArgT>
Phil Nash8defc712013-04-24 19:10:02 +01001518 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
1519 ArgT const& arg,
1520 std::string const& matcherCallAsString ) {
Phil Nashce612bf2012-11-01 08:27:09 +00001521 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
1522 .setLhs( Catch::toString( arg ) )
1523 .setResultType( matcher.match( arg ) );
1524 }
1525
1526 template<typename MatcherT, typename ArgT>
Phil Nash8defc712013-04-24 19:10:02 +01001527 ExpressionResultBuilder expressionResultBuilderFromMatcher( MatcherT const& matcher,
Phil Nashce612bf2012-11-01 08:27:09 +00001528 ArgT* arg,
Phil Nash8defc712013-04-24 19:10:02 +01001529 std::string const& matcherCallAsString ) {
Phil Nashce612bf2012-11-01 08:27:09 +00001530 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
1531 .setLhs( Catch::toString( arg ) )
1532 .setResultType( matcher.match( arg ) );
1533 }
1534
1535struct TestFailureException{};
1536
Phil Nashce612bf2012-11-01 08:27:09 +00001537} // end namespace Catch
1538
1539///////////////////////////////////////////////////////////////////////////////
1540#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
1541
1542///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001543#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001544 if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
Phil Nash3649fdf2013-12-03 18:53:55 +00001545 if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
Phil Nashce612bf2012-11-01 08:27:09 +00001546 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
Phil Nash90a35942012-11-13 22:04:29 +00001547 if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
Phil Nash3df6c0d2013-03-11 18:38:29 +00001548 Catch::isTrue( false && originalExpr ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001549 }
1550
1551///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001552#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
1553 Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition );
Phil Nashce612bf2012-11-01 08:27:09 +00001554
1555///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001556#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001557 do { \
Phil Nash90a35942012-11-13 22:04:29 +00001558 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001559 try { \
Phil Nash90a35942012-11-13 22:04:29 +00001560 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001561 } catch( Catch::TestFailureException& ) { \
1562 throw; \
1563 } catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00001564 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
1565 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001566 } \
1567 } while( Catch::isTrue( false ) )
1568
1569///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001570#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
1571 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1572 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00001573
1574///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001575#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
1576 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1577 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00001578
1579///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001580#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001581 do { \
Phil Nash90a35942012-11-13 22:04:29 +00001582 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001583 try { \
1584 expr; \
Phil Nash90a35942012-11-13 22:04:29 +00001585 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001586 } \
1587 catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00001588 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001589 } \
1590} while( Catch::isTrue( false ) )
1591
1592///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001593#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001594 try { \
1595 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1596 expr; \
Phil Nash90a35942012-11-13 22:04:29 +00001597 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001598 } \
1599 } \
1600 catch( Catch::TestFailureException& ) { \
1601 throw; \
1602 } \
1603 catch( exceptionType ) { \
Phil Nash90a35942012-11-13 22:04:29 +00001604 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001605 }
1606
1607///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001608#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001609 do { \
Phil Nash90a35942012-11-13 22:04:29 +00001610 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
1611 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001612 } while( Catch::isTrue( false ) )
1613
1614///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001615#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001616 do { \
Phil Nash90a35942012-11-13 22:04:29 +00001617 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
1618 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001619 catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00001620 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
1621 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001622 } \
1623 } while( Catch::isTrue( false ) )
1624
1625///////////////////////////////////////////////////////////////////////////////
Phil Nash859760a2013-12-14 14:34:05 +00001626#ifdef CATCH_CONFIG_VARIADIC_MACROS
1627 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
1628 do { \
1629 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
1630 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \
1631 } while( Catch::isTrue( false ) )
1632#else
1633 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
1634 do { \
1635 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
1636 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
1637 } while( Catch::isTrue( false ) )
1638#endif
Phil Nashce612bf2012-11-01 08:27:09 +00001639
1640///////////////////////////////////////////////////////////////////////////////
Phil Nashb5fd5a62013-06-28 17:09:57 +01001641#define INTERNAL_CATCH_INFO( log, macroName ) \
1642 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
Phil Nashce612bf2012-11-01 08:27:09 +00001643
1644///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00001645#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00001646 do { \
Phil Nash90a35942012-11-13 22:04:29 +00001647 INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001648 try { \
Phil Nash90a35942012-11-13 22:04:29 +00001649 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001650 } catch( Catch::TestFailureException& ) { \
1651 throw; \
1652 } catch( ... ) { \
Phil Nash90a35942012-11-13 22:04:29 +00001653 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
1654 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nashce612bf2012-11-01 08:27:09 +00001655 } \
1656 } while( Catch::isTrue( false ) )
1657
Phil Nash3649fdf2013-12-03 18:53:55 +00001658// #included from: internal/catch_section.h
1659#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
1660
1661// #included from: catch_section_info.h
1662#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
1663
1664namespace Catch {
1665
1666 struct SectionInfo {
1667 SectionInfo( std::string const& _name,
1668 std::string const& _description,
1669 SourceLineInfo const& _lineInfo )
1670 : name( _name ),
1671 description( _description ),
1672 lineInfo( _lineInfo )
1673 {}
1674
1675 std::string name;
1676 std::string description;
1677 SourceLineInfo lineInfo;
1678 };
1679
1680} // end namespace Catch
1681
1682// #included from: catch_totals.hpp
1683#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1684
1685#include <cstddef>
1686
1687namespace Catch {
1688
1689 struct Counts {
1690 Counts() : passed( 0 ), failed( 0 ) {}
1691
1692 Counts operator - ( Counts const& other ) const {
1693 Counts diff;
1694 diff.passed = passed - other.passed;
1695 diff.failed = failed - other.failed;
1696 return diff;
1697 }
1698 Counts& operator += ( Counts const& other ) {
1699 passed += other.passed;
1700 failed += other.failed;
1701 return *this;
1702 }
1703
1704 std::size_t total() const {
1705 return passed + failed;
1706 }
1707
1708 std::size_t passed;
1709 std::size_t failed;
1710 };
1711
1712 struct Totals {
1713
1714 Totals operator - ( Totals const& other ) const {
1715 Totals diff;
1716 diff.assertions = assertions - other.assertions;
1717 diff.testCases = testCases - other.testCases;
1718 return diff;
1719 }
1720
1721 Totals delta( Totals const& prevTotals ) const {
1722 Totals diff = *this - prevTotals;
1723 if( diff.assertions.failed > 0 )
1724 ++diff.testCases.failed;
1725 else
1726 ++diff.testCases.passed;
1727 return diff;
1728 }
1729
1730 Totals& operator += ( Totals const& other ) {
1731 assertions += other.assertions;
1732 testCases += other.testCases;
1733 return *this;
1734 }
1735
1736 Counts assertions;
1737 Counts testCases;
1738 };
1739}
Phil Nashce612bf2012-11-01 08:27:09 +00001740
Phil Nashaa7123b2013-08-15 19:01:00 +01001741// #included from: catch_timer.h
1742#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
1743
Phil Nash04a33642013-08-16 19:09:09 +01001744#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01001745typedef unsigned long long uint64_t;
1746#else
1747#include <stdint.h>
1748#endif
1749
1750namespace Catch {
1751
1752 class Timer {
1753 public:
1754 Timer() : m_ticks( 0 ) {}
1755 void start();
1756 unsigned int getElapsedNanoseconds() const;
1757 unsigned int getElapsedMilliseconds() const;
1758 double getElapsedSeconds() const;
1759
1760 private:
1761 uint64_t m_ticks;
1762 };
1763
1764} // namespace Catch
1765
Phil Nashce612bf2012-11-01 08:27:09 +00001766#include <string>
1767
1768namespace Catch {
1769
1770 class Section {
1771 public:
Phil Nash8defc712013-04-24 19:10:02 +01001772 Section( SourceLineInfo const& lineInfo,
1773 std::string const& name,
Phil Nash3649fdf2013-12-03 18:53:55 +00001774 std::string const& description = "" );
1775 ~Section();
Phil Nashce612bf2012-11-01 08:27:09 +00001776
1777 // This indicates whether the section should be executed or not
Phil Nash3649fdf2013-12-03 18:53:55 +00001778 operator bool();
Phil Nashce612bf2012-11-01 08:27:09 +00001779
1780 private:
Phil Nash3649fdf2013-12-03 18:53:55 +00001781
Phil Nasha1fbfea2012-12-01 23:57:18 +00001782 SectionInfo m_info;
Phil Nashce612bf2012-11-01 08:27:09 +00001783
1784 std::string m_name;
1785 Counts m_assertions;
1786 bool m_sectionIncluded;
Phil Nashaa7123b2013-08-15 19:01:00 +01001787 Timer m_timer;
Phil Nashce612bf2012-11-01 08:27:09 +00001788 };
1789
1790} // end namespace Catch
1791
Phil Nash93906752013-03-16 20:21:51 +00001792#ifdef CATCH_CONFIG_VARIADIC_MACROS
1793 #define INTERNAL_CATCH_SECTION( ... ) \
1794 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
1795#else
1796 #define INTERNAL_CATCH_SECTION( name, desc ) \
1797 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
1798#endif
Phil Nashce612bf2012-11-01 08:27:09 +00001799
1800// #included from: internal/catch_generators.hpp
1801#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1802
1803#include <iterator>
1804#include <vector>
1805#include <string>
1806#include <stdlib.h>
1807
1808namespace Catch {
1809
1810template<typename T>
1811struct IGenerator {
1812 virtual ~IGenerator() {}
1813 virtual T getValue( std::size_t index ) const = 0;
1814 virtual std::size_t size () const = 0;
1815};
1816
1817template<typename T>
1818class BetweenGenerator : public IGenerator<T> {
1819public:
1820 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
1821
1822 virtual T getValue( std::size_t index ) const {
Phil Nash2e7d9662013-01-16 09:44:43 +00001823 return m_from+static_cast<int>( index );
Phil Nashce612bf2012-11-01 08:27:09 +00001824 }
1825
1826 virtual std::size_t size() const {
1827 return static_cast<std::size_t>( 1+m_to-m_from );
1828 }
1829
1830private:
1831
1832 T m_from;
1833 T m_to;
1834};
1835
1836template<typename T>
1837class ValuesGenerator : public IGenerator<T> {
1838public:
1839 ValuesGenerator(){}
1840
1841 void add( T value ) {
1842 m_values.push_back( value );
1843 }
1844
1845 virtual T getValue( std::size_t index ) const {
1846 return m_values[index];
1847 }
1848
1849 virtual std::size_t size() const {
1850 return m_values.size();
1851 }
1852
1853private:
1854 std::vector<T> m_values;
1855};
1856
1857template<typename T>
1858class CompositeGenerator {
1859public:
1860 CompositeGenerator() : m_totalSize( 0 ) {}
1861
Phil Nasha04981b2013-03-08 09:30:25 +00001862 // *** Move semantics, similar to auto_ptr ***
Phil Nashce612bf2012-11-01 08:27:09 +00001863 CompositeGenerator( CompositeGenerator& other )
1864 : m_fileInfo( other.m_fileInfo ),
1865 m_totalSize( 0 )
1866 {
Phil Nasha04981b2013-03-08 09:30:25 +00001867 move( other );
Phil Nashce612bf2012-11-01 08:27:09 +00001868 }
1869
1870 CompositeGenerator& setFileInfo( const char* fileInfo ) {
1871 m_fileInfo = fileInfo;
1872 return *this;
1873 }
1874
1875 ~CompositeGenerator() {
1876 deleteAll( m_composed );
1877 }
1878
1879 operator T () const {
1880 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
1881
1882 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1883 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1884 for( size_t index = 0; it != itEnd; ++it )
1885 {
1886 const IGenerator<T>* generator = *it;
1887 if( overallIndex >= index && overallIndex < index + generator->size() )
1888 {
1889 return generator->getValue( overallIndex-index );
1890 }
1891 index += generator->size();
1892 }
1893 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
Phil Nasha04981b2013-03-08 09:30:25 +00001894 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
Phil Nashce612bf2012-11-01 08:27:09 +00001895 }
1896
1897 void add( const IGenerator<T>* generator ) {
1898 m_totalSize += generator->size();
1899 m_composed.push_back( generator );
1900 }
1901
1902 CompositeGenerator& then( CompositeGenerator& other ) {
1903 move( other );
1904 return *this;
1905 }
1906
1907 CompositeGenerator& then( T value ) {
1908 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1909 valuesGen->add( value );
1910 add( valuesGen );
1911 return *this;
1912 }
1913
1914private:
1915
1916 void move( CompositeGenerator& other ) {
1917 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1918 m_totalSize += other.m_totalSize;
1919 other.m_composed.clear();
1920 }
1921
1922 std::vector<const IGenerator<T>*> m_composed;
1923 std::string m_fileInfo;
1924 size_t m_totalSize;
1925};
1926
1927namespace Generators
1928{
1929 template<typename T>
1930 CompositeGenerator<T> between( T from, T to ) {
1931 CompositeGenerator<T> generators;
1932 generators.add( new BetweenGenerator<T>( from, to ) );
1933 return generators;
1934 }
1935
1936 template<typename T>
1937 CompositeGenerator<T> values( T val1, T val2 ) {
1938 CompositeGenerator<T> generators;
1939 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1940 valuesGen->add( val1 );
1941 valuesGen->add( val2 );
1942 generators.add( valuesGen );
1943 return generators;
1944 }
1945
1946 template<typename T>
1947 CompositeGenerator<T> values( T val1, T val2, T val3 ){
1948 CompositeGenerator<T> generators;
1949 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1950 valuesGen->add( val1 );
1951 valuesGen->add( val2 );
1952 valuesGen->add( val3 );
1953 generators.add( valuesGen );
1954 return generators;
1955 }
1956
1957 template<typename T>
1958 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
1959 CompositeGenerator<T> generators;
1960 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1961 valuesGen->add( val1 );
1962 valuesGen->add( val2 );
1963 valuesGen->add( val3 );
1964 valuesGen->add( val4 );
1965 generators.add( valuesGen );
1966 return generators;
1967 }
1968
1969} // end namespace Generators
1970
1971using namespace Generators;
1972
1973} // end namespace Catch
1974
1975#define INTERNAL_CATCH_LINESTR2( line ) #line
1976#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
1977
1978#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
1979
1980// #included from: internal/catch_interfaces_exception.h
1981#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
1982
1983#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +01001984
Phil Nash89d2a3f2012-05-16 15:09:17 +01001985namespace Catch {
1986
Phil Nash89d1e6c2011-05-24 08:23:02 +01001987 typedef std::string(*exceptionTranslateFunction)();
1988
Phil Nash89d2a3f2012-05-16 15:09:17 +01001989 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01001990 virtual ~IExceptionTranslator();
Phil Nash89d1e6c2011-05-24 08:23:02 +01001991 virtual std::string translate() const = 0;
1992 };
1993
Phil Nash89d2a3f2012-05-16 15:09:17 +01001994 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01001995 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01001996
Phil Nash89d2a3f2012-05-16 15:09:17 +01001997 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001998 };
1999
Phil Nash89d2a3f2012-05-16 15:09:17 +01002000 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002001 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002002 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002003 public:
2004
Phil Nash89d2a3f2012-05-16 15:09:17 +01002005 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002006 : m_translateFunction( translateFunction )
2007 {}
2008
Phil Nash89d2a3f2012-05-16 15:09:17 +01002009 virtual std::string translate() const {
2010 try {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002011 throw;
2012 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002013 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002014 return m_translateFunction( ex );
2015 }
2016 }
2017
2018 protected:
2019 std::string(*m_translateFunction)( T& );
2020 };
2021
2022 public:
2023 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002024 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002025 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002026 ( new ExceptionTranslator<T>( translateFunction ) );
2027 }
2028 };
2029}
2030
2031///////////////////////////////////////////////////////////////////////////////
2032#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2033 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2034 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2035 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2036
2037// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002038#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002039
Phil Nash89d1e6c2011-05-24 08:23:02 +01002040#include <cmath>
2041#include <limits>
2042
Phil Nash89d2a3f2012-05-16 15:09:17 +01002043namespace Catch {
2044namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002045
Phil Nash89d2a3f2012-05-16 15:09:17 +01002046 class Approx {
2047 public:
2048 explicit Approx ( double value )
2049 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2050 m_scale( 1.0 ),
2051 m_value( value )
2052 {}
Phil Nashf721a962011-06-07 14:13:57 +01002053
Phil Nash8defc712013-04-24 19:10:02 +01002054 Approx( Approx const& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01002055 : m_epsilon( other.m_epsilon ),
2056 m_scale( other.m_scale ),
2057 m_value( other.m_value )
2058 {}
Phil Nashf721a962011-06-07 14:13:57 +01002059
Phil Nash89d2a3f2012-05-16 15:09:17 +01002060 static Approx custom() {
2061 return Approx( 0 );
2062 }
Phil Nashf721a962011-06-07 14:13:57 +01002063
Phil Nash89d2a3f2012-05-16 15:09:17 +01002064 Approx operator()( double value ) {
2065 Approx approx( value );
2066 approx.epsilon( m_epsilon );
2067 approx.scale( m_scale );
2068 return approx;
2069 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002070
Phil Nash8defc712013-04-24 19:10:02 +01002071 friend bool operator == ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002072 // Thanks to Richard Harris for his help refining this formula
2073 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2074 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002075
Phil Nash8defc712013-04-24 19:10:02 +01002076 friend bool operator == ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002077 return operator==( rhs, lhs );
2078 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002079
Phil Nash8defc712013-04-24 19:10:02 +01002080 friend bool operator != ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002081 return !operator==( lhs, rhs );
2082 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002083
Phil Nash8defc712013-04-24 19:10:02 +01002084 friend bool operator != ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002085 return !operator==( rhs, lhs );
2086 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002087
Phil Nash89d2a3f2012-05-16 15:09:17 +01002088 Approx& epsilon( double newEpsilon ) {
2089 m_epsilon = newEpsilon;
2090 return *this;
2091 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002092
Phil Nash89d2a3f2012-05-16 15:09:17 +01002093 Approx& scale( double newScale ) {
2094 m_scale = newScale;
2095 return *this;
2096 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002097
Phil Nash89d2a3f2012-05-16 15:09:17 +01002098 std::string toString() const {
2099 std::ostringstream oss;
Phil Nash67305122012-10-09 11:48:55 +01002100 oss << "Approx( " << m_value << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002101 return oss.str();
2102 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002103
Phil Nash89d2a3f2012-05-16 15:09:17 +01002104 private:
2105 double m_epsilon;
2106 double m_scale;
2107 double m_value;
2108 };
2109}
2110
2111template<>
Phil Nash8defc712013-04-24 19:10:02 +01002112inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002113 return value.toString();
2114}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002115
2116} // end namespace Catch
2117
Phil Nash371db8b2012-05-21 18:52:09 +01002118// #included from: internal/catch_matchers.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002119#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002120
2121namespace Catch {
2122namespace Matchers {
2123 namespace Impl {
Phil Nash9444bbc2012-10-12 07:58:17 +01002124
2125 template<typename ExpressionT>
2126 struct Matcher : SharedImpl<IShared>
2127 {
Phil Nasha8c65432013-02-19 08:46:09 +00002128 typedef ExpressionT ExpressionType;
2129
Phil Nash9444bbc2012-10-12 07:58:17 +01002130 virtual ~Matcher() {}
2131 virtual Ptr<Matcher> clone() const = 0;
Phil Nashff03cdf2012-12-06 08:44:51 +00002132 virtual bool match( ExpressionT const& expr ) const = 0;
Phil Nash9444bbc2012-10-12 07:58:17 +01002133 virtual std::string toString() const = 0;
2134 };
2135
2136 template<typename DerivedT, typename ExpressionT>
2137 struct MatcherImpl : Matcher<ExpressionT> {
2138
2139 virtual Ptr<Matcher<ExpressionT> > clone() const {
Phil Nash8defc712013-04-24 19:10:02 +01002140 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
Phil Nash9444bbc2012-10-12 07:58:17 +01002141 }
2142 };
2143
2144 namespace Generic {
2145
2146 template<typename ExpressionT>
2147 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
2148 public:
2149
2150 AllOf() {}
Phil Nash8defc712013-04-24 19:10:02 +01002151 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
Phil Nash9444bbc2012-10-12 07:58:17 +01002152
Phil Nash8defc712013-04-24 19:10:02 +01002153 AllOf& add( Matcher<ExpressionT> const& matcher ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01002154 m_matchers.push_back( matcher.clone() );
2155 return *this;
2156 }
Phil Nash8defc712013-04-24 19:10:02 +01002157 virtual bool match( ExpressionT const& expr ) const
Phil Nash9444bbc2012-10-12 07:58:17 +01002158 {
2159 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2160 if( !m_matchers[i]->match( expr ) )
2161 return false;
2162 return true;
2163 }
2164 virtual std::string toString() const {
2165 std::ostringstream oss;
2166 oss << "( ";
2167 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2168 if( i != 0 )
2169 oss << " and ";
2170 oss << m_matchers[i]->toString();
2171 }
2172 oss << " )";
2173 return oss.str();
2174 }
2175
2176 private:
2177 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2178 };
2179
2180 template<typename ExpressionT>
2181 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
2182 public:
2183
2184 AnyOf() {}
Phil Nash8defc712013-04-24 19:10:02 +01002185 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
Phil Nash9444bbc2012-10-12 07:58:17 +01002186
Phil Nash8defc712013-04-24 19:10:02 +01002187 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01002188 m_matchers.push_back( matcher.clone() );
2189 return *this;
2190 }
Phil Nash8defc712013-04-24 19:10:02 +01002191 virtual bool match( ExpressionT const& expr ) const
Phil Nash9444bbc2012-10-12 07:58:17 +01002192 {
2193 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2194 if( m_matchers[i]->match( expr ) )
2195 return true;
2196 return false;
2197 }
2198 virtual std::string toString() const {
2199 std::ostringstream oss;
2200 oss << "( ";
2201 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2202 if( i != 0 )
2203 oss << " or ";
2204 oss << m_matchers[i]->toString();
2205 }
2206 oss << " )";
2207 return oss.str();
2208 }
2209
2210 private:
2211 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2212 };
2213
2214 }
2215
Phil Nash371db8b2012-05-21 18:52:09 +01002216 namespace StdString {
2217
Phil Nash8defc712013-04-24 19:10:02 +01002218 inline std::string makeString( std::string const& str ) { return str; }
Phil Nashd0d4d932013-04-23 08:02:48 +01002219 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
2220
Phil Nash9444bbc2012-10-12 07:58:17 +01002221 struct Equals : MatcherImpl<Equals, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01002222 Equals( std::string const& str ) : m_str( str ){}
2223 Equals( Equals const& other ) : m_str( other.m_str ){}
Phil Nasha8570df2012-05-24 08:29:41 +01002224
Phil Nash9444bbc2012-10-12 07:58:17 +01002225 virtual ~Equals();
2226
Phil Nash8defc712013-04-24 19:10:02 +01002227 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01002228 return m_str == expr;
2229 }
2230 virtual std::string toString() const {
2231 return "equals: \"" + m_str + "\"";
Phil Nasha8570df2012-05-24 08:29:41 +01002232 }
2233
Phil Nasha8570df2012-05-24 08:29:41 +01002234 std::string m_str;
2235 };
2236
Phil Nash9444bbc2012-10-12 07:58:17 +01002237 struct Contains : MatcherImpl<Contains, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01002238 Contains( std::string const& substr ) : m_substr( substr ){}
2239 Contains( Contains const& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002240
Phil Nash9444bbc2012-10-12 07:58:17 +01002241 virtual ~Contains();
2242
Phil Nash8defc712013-04-24 19:10:02 +01002243 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01002244 return expr.find( m_substr ) != std::string::npos;
2245 }
2246 virtual std::string toString() const {
2247 return "contains: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002248 }
2249
Phil Nash371db8b2012-05-21 18:52:09 +01002250 std::string m_substr;
2251 };
2252
Phil Nash9444bbc2012-10-12 07:58:17 +01002253 struct StartsWith : MatcherImpl<StartsWith, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01002254 StartsWith( std::string const& substr ) : m_substr( substr ){}
2255 StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002256
Phil Nash9444bbc2012-10-12 07:58:17 +01002257 virtual ~StartsWith();
2258
Phil Nash8defc712013-04-24 19:10:02 +01002259 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01002260 return expr.find( m_substr ) == 0;
2261 }
2262 virtual std::string toString() const {
2263 return "starts with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002264 }
2265
Phil Nash371db8b2012-05-21 18:52:09 +01002266 std::string m_substr;
2267 };
2268
Phil Nash9444bbc2012-10-12 07:58:17 +01002269 struct EndsWith : MatcherImpl<EndsWith, std::string> {
Phil Nash8defc712013-04-24 19:10:02 +01002270 EndsWith( std::string const& substr ) : m_substr( substr ){}
2271 EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01002272
Phil Nash9444bbc2012-10-12 07:58:17 +01002273 virtual ~EndsWith();
2274
Phil Nash8defc712013-04-24 19:10:02 +01002275 virtual bool match( std::string const& expr ) const {
Phil Nash9444bbc2012-10-12 07:58:17 +01002276 return expr.find( m_substr ) == expr.size() - m_substr.size();
2277 }
2278 virtual std::string toString() const {
2279 return "ends with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01002280 }
2281
Phil Nash371db8b2012-05-21 18:52:09 +01002282 std::string m_substr;
2283 };
2284 } // namespace StdString
2285 } // namespace Impl
2286
Phil Nash9444bbc2012-10-12 07:58:17 +01002287 // The following functions create the actual matcher objects.
2288 // This allows the types to be inferred
2289 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01002290 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
2291 Impl::Matcher<ExpressionT> const& m2 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01002292 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
2293 }
2294 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01002295 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
2296 Impl::Matcher<ExpressionT> const& m2,
2297 Impl::Matcher<ExpressionT> const& m3 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01002298 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2299 }
2300 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01002301 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
2302 Impl::Matcher<ExpressionT> const& m2 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01002303 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
2304 }
2305 template<typename ExpressionT>
Phil Nash8defc712013-04-24 19:10:02 +01002306 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
2307 Impl::Matcher<ExpressionT> const& m2,
2308 Impl::Matcher<ExpressionT> const& m3 ) {
Phil Nash9444bbc2012-10-12 07:58:17 +01002309 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
2310 }
2311
Phil Nash8defc712013-04-24 19:10:02 +01002312 inline Impl::StdString::Equals Equals( std::string const& str ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01002313 return Impl::StdString::Equals( str );
2314 }
2315 inline Impl::StdString::Equals Equals( const char* str ) {
2316 return Impl::StdString::Equals( Impl::StdString::makeString( str ) );
2317 }
Phil Nash8defc712013-04-24 19:10:02 +01002318 inline Impl::StdString::Contains Contains( std::string const& substr ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01002319 return Impl::StdString::Contains( substr );
2320 }
2321 inline Impl::StdString::Contains Contains( const char* substr ) {
2322 return Impl::StdString::Contains( Impl::StdString::makeString( substr ) );
2323 }
Phil Nash8defc712013-04-24 19:10:02 +01002324 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01002325 return Impl::StdString::StartsWith( substr );
2326 }
2327 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
2328 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
2329 }
Phil Nash8defc712013-04-24 19:10:02 +01002330 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
Phil Nashd0d4d932013-04-23 08:02:48 +01002331 return Impl::StdString::EndsWith( substr );
2332 }
2333 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
2334 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
2335 }
Phil Nash371db8b2012-05-21 18:52:09 +01002336
2337} // namespace Matchers
2338
2339using namespace Matchers;
2340
2341} // namespace Catch
2342
Phil Nash0f9c5512012-06-02 23:12:42 +01002343// These files are included here so the single_include script doesn't put them
2344// in the conditionally compiled sections
Phil Nash3649fdf2013-12-03 18:53:55 +00002345// #included from: internal/catch_test_case_info.h
2346#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01002347
2348#include <string>
Phil Nash3649fdf2013-12-03 18:53:55 +00002349#include <set>
2350
2351#ifdef __clang__
2352#pragma clang diagnostic push
2353#pragma clang diagnostic ignored "-Wpadded"
2354#endif
2355
2356namespace Catch {
2357
2358 struct ITestCase;
2359
2360 struct TestCaseInfo {
2361 TestCaseInfo( std::string const& _name,
2362 std::string const& _className,
2363 std::string const& _description,
2364 std::set<std::string> const& _tags,
2365 bool _isHidden,
2366 SourceLineInfo const& _lineInfo );
2367
2368 TestCaseInfo( TestCaseInfo const& other );
2369
2370 std::string name;
2371 std::string className;
2372 std::string description;
2373 std::set<std::string> tags;
2374 std::string tagsAsString;
2375 SourceLineInfo lineInfo;
2376 bool isHidden;
2377 };
2378
2379 class TestCase : protected TestCaseInfo {
2380 public:
2381
2382 TestCase( ITestCase* testCase, TestCaseInfo const& info );
2383 TestCase( TestCase const& other );
2384
2385 TestCase withName( std::string const& _newName ) const;
2386
2387 void invoke() const;
2388
2389 TestCaseInfo const& getTestCaseInfo() const;
2390
2391 bool isHidden() const;
2392 bool hasTag( std::string const& tag ) const;
2393 bool matchesTags( std::string const& tagPattern ) const;
2394 std::set<std::string> const& getTags() const;
2395
2396 void swap( TestCase& other );
2397 bool operator == ( TestCase const& other ) const;
2398 bool operator < ( TestCase const& other ) const;
2399 TestCase& operator = ( TestCase const& other );
2400
2401 private:
2402 Ptr<ITestCase> test;
2403 };
2404
2405 TestCase makeTestCase( ITestCase* testCase,
2406 std::string const& className,
2407 std::string const& name,
2408 std::string const& description,
2409 SourceLineInfo const& lineInfo );
2410}
2411
2412#ifdef __clang__
2413#pragma clang diagnostic pop
2414#endif
2415
2416// #included from: internal/catch_interfaces_runner.h
2417#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01002418
2419namespace Catch {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002420 class TestCase;
Phil Nash0f9c5512012-06-02 23:12:42 +01002421
2422 struct IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01002423 virtual ~IRunner();
Phil Nash0f9c5512012-06-02 23:12:42 +01002424 };
2425}
2426
2427
Phil Nash371db8b2012-05-21 18:52:09 +01002428#ifdef __OBJC__
2429// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002430#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002431
Phil Nash371db8b2012-05-21 18:52:09 +01002432#import <objc/runtime.h>
2433
2434#include <string>
2435
2436// NB. Any general catch headers included here must be included
2437// in catch.hpp first to make sure they are included by the single
2438// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01002439
Phil Nash83224e62011-08-12 18:53:28 +01002440///////////////////////////////////////////////////////////////////////////////
2441// This protocol is really only here for (self) documenting purposes, since
2442// all its methods are optional.
2443@protocol OcFixture
2444
2445@optional
2446
2447-(void) setUp;
2448-(void) tearDown;
2449
2450@end
2451
Phil Nash89d2a3f2012-05-16 15:09:17 +01002452namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01002453
Phil Nash5bc030d2012-08-16 18:48:50 +01002454 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002455
2456 public:
2457 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2458
2459 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00002460 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01002461
Phil Nash53c990a2012-03-17 18:20:06 +00002462 performOptionalSelector( obj, @selector(setUp) );
2463 performOptionalSelector( obj, m_sel );
2464 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01002465
Phil Nash53c990a2012-03-17 18:20:06 +00002466 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01002467 }
Phil Nash83224e62011-08-12 18:53:28 +01002468 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01002469 virtual ~OcMethod() {}
2470
Phil Nash83224e62011-08-12 18:53:28 +01002471 Class m_cls;
2472 SEL m_sel;
2473 };
2474
Phil Nash89d2a3f2012-05-16 15:09:17 +01002475 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01002476
Phil Nash89d2a3f2012-05-16 15:09:17 +01002477 inline std::string getAnnotation( Class cls,
Phil Nash8defc712013-04-24 19:10:02 +01002478 std::string const& annotationName,
2479 std::string const& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01002480 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2481 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00002482 arcSafeRelease( selStr );
2483 id value = performOptionalSelector( cls, sel );
2484 if( value )
2485 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01002486 return "";
2487 }
2488 }
2489
Phil Nash89d2a3f2012-05-16 15:09:17 +01002490 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01002491 size_t noTestMethods = 0;
2492 int noClasses = objc_getClassList( NULL, 0 );
2493
Phil Nash861a1e72012-04-28 12:29:52 +01002494 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00002495 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01002496
Phil Nash89d2a3f2012-05-16 15:09:17 +01002497 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002498 Class cls = classes[c];
2499 {
2500 u_int count;
2501 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01002502 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002503 SEL selector = method_getName(methods[m]);
2504 std::string methodName = sel_getName(selector);
Phil Nash3649fdf2013-12-03 18:53:55 +00002505 if( startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01002506 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00002507 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2508 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nasha8c65432013-02-19 08:46:09 +00002509 const char* className = class_getName( cls );
Phil Nash83224e62011-08-12 18:53:28 +01002510
Phil Nash5bdae842013-02-19 19:47:18 +00002511 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01002512 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01002513 }
2514 }
2515 free(methods);
2516 }
2517 }
2518 return noTestMethods;
2519 }
Phil Nash78d95a02012-03-04 21:22:36 +00002520
Phil Nash89d2a3f2012-05-16 15:09:17 +01002521 namespace Matchers {
2522 namespace Impl {
2523 namespace NSStringMatchers {
2524
Phil Nasha8c65432013-02-19 08:46:09 +00002525 template<typename MatcherT>
2526 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
Phil Nash78d95a02012-03-04 21:22:36 +00002527 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nasha8c65432013-02-19 08:46:09 +00002528 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01002529 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00002530 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002531 }
2532
2533 NSString* m_substr;
2534 };
2535
Phil Nasha8c65432013-02-19 08:46:09 +00002536 struct Equals : StringHolder<Equals> {
Phil Nash8d18d162012-03-14 20:06:14 +00002537 Equals( NSString* substr ) : StringHolder( substr ){}
2538
Phil Nasha8c65432013-02-19 08:46:09 +00002539 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01002540 return (str != nil || m_substr == nil ) &&
2541 [str isEqualToString:m_substr];
Phil Nash8d18d162012-03-14 20:06:14 +00002542 }
2543
Phil Nasha8c65432013-02-19 08:46:09 +00002544 virtual std::string toString() const {
2545 return "equals string: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash8d18d162012-03-14 20:06:14 +00002546 }
2547 };
2548
Phil Nasha8c65432013-02-19 08:46:09 +00002549 struct Contains : StringHolder<Contains> {
Phil Nash78d95a02012-03-04 21:22:36 +00002550 Contains( NSString* substr ) : StringHolder( substr ){}
2551
Phil Nasha8c65432013-02-19 08:46:09 +00002552 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01002553 return (str != nil || m_substr == nil ) &&
2554 [str rangeOfString:m_substr].location != NSNotFound;
Phil Nash78d95a02012-03-04 21:22:36 +00002555 }
2556
Phil Nasha8c65432013-02-19 08:46:09 +00002557 virtual std::string toString() const {
2558 return "contains string: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00002559 }
2560 };
2561
Phil Nasha8c65432013-02-19 08:46:09 +00002562 struct StartsWith : StringHolder<StartsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00002563 StartsWith( NSString* substr ) : StringHolder( substr ){}
2564
Phil Nasha8c65432013-02-19 08:46:09 +00002565 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01002566 return (str != nil || m_substr == nil ) &&
2567 [str rangeOfString:m_substr].location == 0;
Phil Nash78d95a02012-03-04 21:22:36 +00002568 }
2569
Phil Nasha8c65432013-02-19 08:46:09 +00002570 virtual std::string toString() const {
2571 return "starts with: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00002572 }
2573 };
Phil Nasha8c65432013-02-19 08:46:09 +00002574 struct EndsWith : StringHolder<EndsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00002575 EndsWith( NSString* substr ) : StringHolder( substr ){}
2576
Phil Nasha8c65432013-02-19 08:46:09 +00002577 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01002578 return (str != nil || m_substr == nil ) &&
2579 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
Phil Nash78d95a02012-03-04 21:22:36 +00002580 }
2581
Phil Nasha8c65432013-02-19 08:46:09 +00002582 virtual std::string toString() const {
2583 return "ends with: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00002584 }
2585 };
2586
2587 } // namespace NSStringMatchers
2588 } // namespace Impl
2589
Phil Nash8d18d162012-03-14 20:06:14 +00002590 inline Impl::NSStringMatchers::Equals
2591 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2592
Phil Nash78d95a02012-03-04 21:22:36 +00002593 inline Impl::NSStringMatchers::Contains
2594 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002595
Phil Nash78d95a02012-03-04 21:22:36 +00002596 inline Impl::NSStringMatchers::StartsWith
2597 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002598
Phil Nash78d95a02012-03-04 21:22:36 +00002599 inline Impl::NSStringMatchers::EndsWith
2600 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2601
2602 } // namespace Matchers
2603
2604 using namespace Matchers;
2605
2606} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01002607
2608///////////////////////////////////////////////////////////////////////////////
2609#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00002610+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002611{\
Phil Nash53c990a2012-03-17 18:20:06 +00002612return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01002613}\
Phil Nash53c990a2012-03-17 18:20:06 +00002614+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002615{ \
Phil Nash53c990a2012-03-17 18:20:06 +00002616return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01002617} \
2618-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2619
2620#endif
2621
Phil Nashde49ec42013-12-04 20:25:14 +00002622#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
Phil Nasha695eb92012-08-13 07:46:10 +01002623// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04002624#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01002625
2626// Collect all the implementation files together here
2627// These are the equivalent of what would usually be cpp files
2628
Phil Nash5bc030d2012-08-16 18:48:50 +01002629#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01002630#pragma clang diagnostic push
2631#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01002632#endif
Phil Nasha695eb92012-08-13 07:46:10 +01002633
Phil Nash83224e62011-08-12 18:53:28 +01002634// #included from: catch_runner.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002635#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01002636
Phil Nasha695eb92012-08-13 07:46:10 +01002637// #included from: internal/catch_commandline.hpp
2638#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2639
Phil Nash3649fdf2013-12-03 18:53:55 +00002640// #included from: catch_config.hpp
2641#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2642
2643// #included from: catch_test_spec.h
2644#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
2645
2646// #included from: catch_tags.h
2647#define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED
2648
2649#include <string>
2650#include <set>
2651#include <map>
2652#include <vector>
2653
2654#ifdef __clang__
2655#pragma clang diagnostic ignored "-Wpadded"
2656#endif
2657
2658namespace Catch {
2659 class TagParser {
2660 public:
2661 virtual ~TagParser();
2662
2663 void parse( std::string const& str );
2664
2665 protected:
2666 virtual void acceptTag( std::string const& tag ) = 0;
2667 virtual void acceptChar( char c ) = 0;
2668 virtual void endParse() {}
2669
2670 private:
2671 };
2672
2673 class TagExtracter : public TagParser {
2674 public:
2675
2676 TagExtracter( std::set<std::string>& tags );
2677 virtual ~TagExtracter();
2678
2679 void parse( std::string& description );
2680
2681 private:
2682 virtual void acceptTag( std::string const& tag );
2683 virtual void acceptChar( char c );
2684
2685 TagExtracter& operator=(TagExtracter const&);
2686
2687 std::set<std::string>& m_tags;
2688 std::string m_remainder;
2689 };
2690
2691 class Tag {
2692 public:
2693 Tag();
2694 Tag( std::string const& name, bool isNegated );
2695 std::string getName() const;
2696 bool isNegated() const;
2697 bool operator ! () const;
2698
2699 private:
2700 std::string m_name;
2701 bool m_isNegated;
2702 };
2703
2704 class TagSet {
2705 typedef std::map<std::string, Tag> TagMap;
2706 public:
2707 void add( Tag const& tag );
2708 bool empty() const;
2709 bool matches( std::set<std::string> const& tags ) const;
2710
2711 private:
2712 TagMap m_tags;
2713 };
2714
2715 class TagExpression {
2716 public:
2717 bool matches( std::set<std::string> const& tags ) const;
2718
2719 private:
2720 friend class TagExpressionParser;
2721
2722 std::vector<TagSet> m_tagSets;
2723 };
2724
2725 class TagExpressionParser : public TagParser {
2726 public:
2727 TagExpressionParser( TagExpression& exp );
2728 ~TagExpressionParser();
2729
2730 private:
2731 virtual void acceptTag( std::string const& tag );
2732 virtual void acceptChar( char c );
2733 virtual void endParse();
2734
2735 TagExpressionParser& operator=(TagExpressionParser const&);
2736
2737 bool m_isNegated;
2738 TagSet m_currentTagSet;
2739 TagExpression& m_exp;
2740 };
2741
2742} // end namespace Catch
2743
2744#include <string>
2745#include <vector>
2746
2747namespace Catch {
2748
2749 class TestCase;
2750
2751 struct IfFilterMatches{ enum DoWhat {
2752 AutoDetectBehaviour,
2753 IncludeTests,
2754 ExcludeTests
2755 }; };
2756
2757 class TestCaseFilter {
2758 enum WildcardPosition {
2759 NoWildcard = 0,
2760 WildcardAtStart = 1,
2761 WildcardAtEnd = 2,
2762 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
2763 };
2764
2765 public:
2766 TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour );
2767
2768 IfFilterMatches::DoWhat getFilterType() const;
2769 bool shouldInclude( TestCase const& testCase ) const;
2770
2771 private:
2772 bool isMatch( TestCase const& testCase ) const;
2773
2774 std::string m_stringToMatch;
2775 IfFilterMatches::DoWhat m_filterType;
2776 WildcardPosition m_wildcardPosition;
2777 };
2778
2779 class TestCaseFilters {
2780 public:
2781 TestCaseFilters( std::string const& name );
2782 std::string getName() const;
2783 void addFilter( TestCaseFilter const& filter );
2784 void addTags( std::string const& tagPattern );
2785 bool shouldInclude( TestCase const& testCase ) const;
2786
2787 private:
2788 std::vector<TagExpression> m_tagExpressions;
2789 std::vector<TestCaseFilter> m_inclusionFilters;
2790 std::vector<TestCaseFilter> m_exclusionFilters;
2791 std::string m_name;
2792 };
2793
2794}
2795
2796// #included from: catch_stream.h
2797#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
2798
2799#include <streambuf>
2800
2801#ifdef __clang__
2802#pragma clang diagnostic ignored "-Wpadded"
2803#endif
2804
2805namespace Catch {
2806
2807 class Stream {
2808 public:
2809 Stream();
2810 Stream( std::streambuf* _streamBuf, bool _isOwned );
2811 void release();
2812
2813 std::streambuf* streamBuf;
2814
2815 private:
2816 bool isOwned;
2817 };
2818}
2819
2820#include <memory>
2821#include <vector>
2822#include <string>
2823#include <iostream>
2824
2825#ifndef CATCH_CONFIG_CONSOLE_WIDTH
2826#define CATCH_CONFIG_CONSOLE_WIDTH 80
2827#endif
2828
2829namespace Catch {
2830
2831 struct ConfigData {
2832
2833 ConfigData()
2834 : listTests( false ),
2835 listTags( false ),
2836 listReporters( false ),
2837 listTestNamesOnly( false ),
2838 showSuccessfulTests( false ),
2839 shouldDebugBreak( false ),
2840 noThrow( false ),
2841 showHelp( false ),
2842 abortAfter( -1 ),
2843 verbosity( Verbosity::Normal ),
2844 warnings( WarnAbout::Nothing ),
2845 showDurations( ShowDurations::DefaultForReporter )
2846 {}
2847
2848 bool listTests;
2849 bool listTags;
2850 bool listReporters;
2851 bool listTestNamesOnly;
2852
2853 bool showSuccessfulTests;
2854 bool shouldDebugBreak;
2855 bool noThrow;
2856 bool showHelp;
2857
2858 int abortAfter;
2859
2860 Verbosity::Level verbosity;
2861 WarnAbout::What warnings;
2862 ShowDurations::OrNot showDurations;
2863
2864 std::string reporterName;
2865 std::string outputFilename;
2866 std::string name;
2867 std::string processName;
2868
2869 std::vector<std::string> testsOrTags;
2870 };
2871
2872 class Config : public SharedImpl<IConfig> {
2873 private:
2874 Config( Config const& other );
2875 Config& operator = ( Config const& other );
2876 virtual void dummy();
2877 public:
2878
2879 Config()
2880 : m_os( std::cout.rdbuf() )
2881 {}
2882
2883 Config( ConfigData const& data )
2884 : m_data( data ),
2885 m_os( std::cout.rdbuf() )
2886 {
2887 if( !data.testsOrTags.empty() ) {
2888 std::string groupName;
2889 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
2890 if( i != 0 )
2891 groupName += " ";
2892 groupName += data.testsOrTags[i];
2893 }
2894 TestCaseFilters filters( groupName );
2895 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
2896 std::string filter = data.testsOrTags[i];
2897 if( startsWith( filter, "[" ) || startsWith( filter, "~[" ) )
2898 filters.addTags( filter );
2899 else
2900 filters.addFilter( TestCaseFilter( filter ) );
2901 }
2902 m_filterSets.push_back( filters );
2903 }
2904 }
2905
2906 virtual ~Config() {
2907 m_os.rdbuf( std::cout.rdbuf() );
2908 m_stream.release();
2909 }
2910
2911 void setFilename( std::string const& filename ) {
2912 m_data.outputFilename = filename;
2913 }
2914
2915 std::string const& getFilename() const {
2916 return m_data.outputFilename ;
2917 }
2918
2919 bool listTests() const { return m_data.listTests; }
2920 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
2921 bool listTags() const { return m_data.listTags; }
2922 bool listReporters() const { return m_data.listReporters; }
2923
2924 std::string getProcessName() const {
2925 return m_data.processName;
2926 }
2927
2928 bool shouldDebugBreak() const {
2929 return m_data.shouldDebugBreak;
2930 }
2931
2932 void setStreamBuf( std::streambuf* buf ) {
2933 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2934 }
2935
2936 void useStream( std::string const& streamName ) {
2937 Stream stream = createStream( streamName );
2938 setStreamBuf( stream.streamBuf );
2939 m_stream.release();
2940 m_stream = stream;
2941 }
2942
2943 std::string getReporterName() const { return m_data.reporterName; }
2944
2945 void addTestSpec( std::string const& testSpec ) {
2946 TestCaseFilters filters( testSpec );
2947 filters.addFilter( TestCaseFilter( testSpec ) );
2948 m_filterSets.push_back( filters );
2949 }
2950
2951 int abortAfter() const {
2952 return m_data.abortAfter;
2953 }
2954
2955 std::vector<TestCaseFilters> const& filters() const {
2956 return m_filterSets;
2957 }
2958
2959 bool showHelp() const { return m_data.showHelp; }
2960
2961 // IConfig interface
2962 virtual bool allowThrows() const { return !m_data.noThrow; }
2963 virtual std::ostream& stream() const { return m_os; }
2964 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
2965 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
2966 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
2967 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
2968
2969 private:
2970 ConfigData m_data;
2971
2972 Stream m_stream;
2973 mutable std::ostream m_os;
2974 std::vector<TestCaseFilters> m_filterSets;
2975 };
2976
2977} // end namespace Catch
2978
Phil Nash786959d2013-06-07 19:07:50 +01002979// #included from: clara.h
2980#define TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01002981
Phil Nash19279252013-04-20 21:07:32 +01002982// #included from: catch_text.h
2983#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
Phil Nash38f7eef2013-03-29 13:44:33 +00002984
2985#include <string>
2986#include <vector>
2987
Phil Nash89d1e6c2011-05-24 08:23:02 +01002988namespace Catch {
2989
Phil Nash19279252013-04-20 21:07:32 +01002990 struct TextAttributes {
2991 TextAttributes()
2992 : initialIndent( std::string::npos ),
2993 indent( 0 ),
2994 width( CATCH_CONFIG_CONSOLE_WIDTH-1 ),
2995 tabChar( '\t' )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002996 {}
Phil Nash3b80af72012-08-09 07:47:30 +01002997
Phil Nash19279252013-04-20 21:07:32 +01002998 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
2999 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
3000 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
3001 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
Phil Nash89d2a3f2012-05-16 15:09:17 +01003002
Phil Nash19279252013-04-20 21:07:32 +01003003 std::size_t initialIndent; // indent of first line, or npos
3004 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3005 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3006 char tabChar; // If this char is seen the indent is changed to current pos
Phil Nash89d1e6c2011-05-24 08:23:02 +01003007 };
3008
Phil Nash19279252013-04-20 21:07:32 +01003009 class Text {
Phil Nasha695eb92012-08-13 07:46:10 +01003010 public:
Phil Nash19279252013-04-20 21:07:32 +01003011 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() );
3012 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos );
Phil Nasha695eb92012-08-13 07:46:10 +01003013
Phil Nash38f7eef2013-03-29 13:44:33 +00003014 typedef std::vector<std::string>::const_iterator const_iterator;
Phil Nasha695eb92012-08-13 07:46:10 +01003015
Phil Nash38f7eef2013-03-29 13:44:33 +00003016 const_iterator begin() const { return lines.begin(); }
3017 const_iterator end() const { return lines.end(); }
3018 std::string const& last() const { return lines.back(); }
3019 std::size_t size() const { return lines.size(); }
3020 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
Phil Nash19279252013-04-20 21:07:32 +01003021 std::string toString() const;
Phil Nasha695eb92012-08-13 07:46:10 +01003022
Phil Nash19279252013-04-20 21:07:32 +01003023 friend std::ostream& operator << ( std::ostream& _stream, Text const& _text );
Phil Nasha695eb92012-08-13 07:46:10 +01003024
Phil Nasha695eb92012-08-13 07:46:10 +01003025 private:
Phil Nash19279252013-04-20 21:07:32 +01003026 std::string str;
3027 TextAttributes attr;
Phil Nash38f7eef2013-03-29 13:44:33 +00003028 std::vector<std::string> lines;
3029 };
3030
3031} // end namespace Catch
3032
Phil Nash786959d2013-06-07 19:07:50 +01003033namespace Clara {
3034 namespace Detail {
3035 template<typename T> struct RemoveConstRef{ typedef T type; };
3036 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3037 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3038 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3039
3040 template<typename T> struct IsBool { static const bool value = false; };
3041 template<> struct IsBool<bool> { static const bool value = true; };
Phil Nasha695eb92012-08-13 07:46:10 +01003042
3043 template<typename T>
Phil Nash786959d2013-06-07 19:07:50 +01003044 void convertInto( std::string const& _source, T& _dest ) {
3045 std::stringstream ss;
3046 ss << _source;
3047 ss >> _dest;
3048 if( ss.fail() )
3049 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
Phil Nasha695eb92012-08-13 07:46:10 +01003050 }
Phil Nash786959d2013-06-07 19:07:50 +01003051 inline void convertInto( std::string const& _source, std::string& _dest ) {
3052 _dest = _source;
3053 }
3054 inline void convertInto( std::string const& _source, bool& _dest ) {
3055 std::string sourceLC = _source;
3056 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
Phil Nash46118712013-08-16 19:01:32 +01003057 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
Phil Nash786959d2013-06-07 19:07:50 +01003058 _dest = true;
Phil Nash46118712013-08-16 19:01:32 +01003059 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
Phil Nash786959d2013-06-07 19:07:50 +01003060 _dest = false;
3061 else
Phil Nash46118712013-08-16 19:01:32 +01003062 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
Phil Nash786959d2013-06-07 19:07:50 +01003063 }
3064 inline void convertInto( bool _source, bool& _dest ) {
3065 _dest = _source;
3066 }
3067 template<typename T>
3068 inline void convertInto( bool, T& ) {
3069 throw std::runtime_error( "Invalid conversion" );
3070 }
Phil Nasha695eb92012-08-13 07:46:10 +01003071
Phil Nash786959d2013-06-07 19:07:50 +01003072 template<typename ConfigT>
3073 struct IArgFunction {
3074 virtual ~IArgFunction() {}
3075 virtual void set( ConfigT& config, std::string const& value ) const = 0;
3076 virtual void setFlag( ConfigT& config ) const = 0;
3077 virtual bool takesArg() const = 0;
3078 virtual IArgFunction* clone() const = 0;
3079 };
3080
3081 template<typename ConfigT>
3082 class BoundArgFunction {
3083 public:
3084 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
3085 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj->clone() ) {}
3086 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
3087 IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone();
3088 delete functionObj;
3089 functionObj = newFunctionObj;
3090 return *this;
3091 }
3092 ~BoundArgFunction() { delete functionObj; }
3093
3094 void set( ConfigT& config, std::string const& value ) const {
3095 functionObj->set( config, value );
3096 }
3097 void setFlag( ConfigT& config ) const {
3098 functionObj->setFlag( config );
3099 }
3100 bool takesArg() const { return functionObj->takesArg(); }
3101 private:
3102 IArgFunction<ConfigT>* functionObj;
3103 };
3104
3105 template<typename C>
3106 struct NullBinder : IArgFunction<C>{
3107 virtual void set( C&, std::string const& ) const {}
3108 virtual void setFlag( C& ) const {}
3109 virtual bool takesArg() const { return true; }
3110 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
3111 };
3112
3113 template<typename C, typename M>
3114 struct BoundDataMember : IArgFunction<C>{
3115 BoundDataMember( M C::* _member ) : member( _member ) {}
3116 virtual void set( C& p, std::string const& stringValue ) const {
3117 convertInto( stringValue, p.*member );
3118 }
3119 virtual void setFlag( C& p ) const {
3120 convertInto( true, p.*member );
3121 }
3122 virtual bool takesArg() const { return !IsBool<M>::value; }
3123 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
3124 M C::* member;
3125 };
3126 template<typename C, typename M>
3127 struct BoundUnaryMethod : IArgFunction<C>{
3128 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
3129 virtual void set( C& p, std::string const& stringValue ) const {
3130 typename RemoveConstRef<M>::type value;
3131 convertInto( stringValue, value );
3132 (p.*member)( value );
3133 }
3134 virtual void setFlag( C& p ) const {
3135 typename RemoveConstRef<M>::type value;
3136 convertInto( true, value );
3137 (p.*member)( value );
3138 }
3139 virtual bool takesArg() const { return !IsBool<M>::value; }
3140 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
3141 void (C::*member)( M );
3142 };
3143 template<typename C>
3144 struct BoundNullaryMethod : IArgFunction<C>{
3145 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
3146 virtual void set( C& p, std::string const& stringValue ) const {
3147 bool value;
3148 convertInto( stringValue, value );
3149 if( value )
3150 (p.*member)();
3151 }
3152 virtual void setFlag( C& p ) const {
3153 (p.*member)();
3154 }
3155 virtual bool takesArg() const { return false; }
3156 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
3157 void (C::*member)();
3158 };
3159
3160 template<typename C>
3161 struct BoundUnaryFunction : IArgFunction<C>{
3162 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
3163 virtual void set( C& obj, std::string const& stringValue ) const {
3164 bool value;
3165 convertInto( stringValue, value );
3166 if( value )
3167 function( obj );
3168 }
3169 virtual void setFlag( C& p ) const {
3170 function( p );
3171 }
3172 virtual bool takesArg() const { return false; }
3173 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
3174 void (*function)( C& );
3175 };
3176
3177 template<typename C, typename T>
3178 struct BoundBinaryFunction : IArgFunction<C>{
3179 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
3180 virtual void set( C& obj, std::string const& stringValue ) const {
3181 typename RemoveConstRef<T>::type value;
3182 convertInto( stringValue, value );
3183 function( obj, value );
3184 }
3185 virtual void setFlag( C& obj ) const {
3186 typename RemoveConstRef<T>::type value;
3187 convertInto( true, value );
3188 function( obj, value );
3189 }
3190 virtual bool takesArg() const { return !IsBool<T>::value; }
3191 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
3192 void (*function)( C&, T );
3193 };
3194
3195 template<typename C, typename M>
3196 BoundArgFunction<C> makeBoundField( M C::* _member ) {
3197 return BoundArgFunction<C>( new BoundDataMember<C,M>( _member ) );
3198 }
3199 template<typename C, typename M>
3200 BoundArgFunction<C> makeBoundField( void (C::*_member)( M ) ) {
3201 return BoundArgFunction<C>( new BoundUnaryMethod<C,M>( _member ) );
3202 }
3203 template<typename C>
3204 BoundArgFunction<C> makeBoundField( void (C::*_member)() ) {
3205 return BoundArgFunction<C>( new BoundNullaryMethod<C>( _member ) );
3206 }
3207 template<typename C>
3208 BoundArgFunction<C> makeBoundField( void (*_function)( C& ) ) {
3209 return BoundArgFunction<C>( new BoundUnaryFunction<C>( _function ) );
3210 }
3211 template<typename C, typename T>
3212 BoundArgFunction<C> makeBoundField( void (*_function)( C&, T ) ) {
3213 return BoundArgFunction<C>( new BoundBinaryFunction<C, T>( _function ) );
3214 }
3215 } // namespace Detail
3216
3217 struct Parser {
3218 Parser() : separators( " \t=:" ) {}
3219
3220 struct Token {
3221 enum Type { Positional, ShortOpt, LongOpt };
3222 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
3223 Type type;
3224 std::string data;
3225 };
3226
3227 void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
3228 for( int i = 1; i < argc; ++i )
3229 parseIntoTokens( argv[i] , tokens);
3230 }
3231 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
3232 while( !arg.empty() ) {
3233 Parser::Token token( Parser::Token::Positional, arg );
3234 arg = "";
3235 if( token.data[0] == '-' ) {
3236 if( token.data.size() > 1 && token.data[1] == '-' ) {
3237 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
3238 }
3239 else {
3240 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
3241 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
3242 arg = "-" + token.data.substr( 1 );
3243 token.data = token.data.substr( 0, 1 );
3244 }
3245 }
3246 }
3247 if( token.type != Parser::Token::Positional ) {
3248 std::size_t pos = token.data.find_first_of( separators );
3249 if( pos != std::string::npos ) {
3250 arg = token.data.substr( pos+1 );
3251 token.data = token.data.substr( 0, pos );
3252 }
3253 }
3254 tokens.push_back( token );
3255 }
3256 }
3257 std::string separators;
Phil Nasha695eb92012-08-13 07:46:10 +01003258 };
3259
Phil Nash786959d2013-06-07 19:07:50 +01003260 template<typename ConfigT>
3261 class CommandLine {
3262
3263 struct Arg {
3264 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ), position( -1 ) {}
3265
3266 bool hasShortName( std::string const& shortName ) const {
3267 for( std::vector<std::string>::const_iterator
3268 it = shortNames.begin(), itEnd = shortNames.end();
3269 it != itEnd;
3270 ++it )
3271 if( *it == shortName )
3272 return true;
3273 return false;
3274 }
3275 bool hasLongName( std::string const& _longName ) const {
3276 return _longName == longName;
3277 }
3278 bool takesArg() const {
Phil Nash46118712013-08-16 19:01:32 +01003279 return !hint.empty();
Phil Nash786959d2013-06-07 19:07:50 +01003280 }
3281 bool isFixedPositional() const {
3282 return position != -1;
3283 }
3284 bool isAnyPositional() const {
3285 return position == -1 && shortNames.empty() && longName.empty();
3286 }
3287 std::string dbgName() const {
3288 if( !longName.empty() )
3289 return "--" + longName;
3290 if( !shortNames.empty() )
3291 return "-" + shortNames[0];
3292 return "positional args";
3293 }
3294 void validate() const {
3295 if( boundField.takesArg() && !takesArg() )
3296 throw std::logic_error( dbgName() + " must specify an arg name" );
3297 }
3298 std::string commands() const {
3299 std::ostringstream oss;
3300 bool first = true;
3301 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
3302 for(; it != itEnd; ++it ) {
3303 if( first )
3304 first = false;
3305 else
3306 oss << ", ";
3307 oss << "-" << *it;
3308 }
3309 if( !longName.empty() ) {
3310 if( !first )
3311 oss << ", ";
3312 oss << "--" << longName;
3313 }
Phil Nash46118712013-08-16 19:01:32 +01003314 if( !hint.empty() )
3315 oss << " <" << hint << ">";
Phil Nash786959d2013-06-07 19:07:50 +01003316 return oss.str();
3317 }
3318
3319 Detail::BoundArgFunction<ConfigT> boundField;
3320 std::vector<std::string> shortNames;
3321 std::string longName;
3322 std::string description;
Phil Nash46118712013-08-16 19:01:32 +01003323 std::string hint;
Phil Nash786959d2013-06-07 19:07:50 +01003324 int position;
3325 };
3326
Phil Nash5ecb72b2013-11-26 20:57:45 +00003327 // NOTE: std::auto_ptr is deprecated in c++11/c++0x
3328#if defined(__cplusplus) && __cplusplus > 199711L
3329 typedef std::unique_ptr<Arg> ArgAutoPtr;
3330#else
3331 typedef std::auto_ptr<Arg> ArgAutoPtr;
3332#endif
3333
Phil Nash786959d2013-06-07 19:07:50 +01003334 class ArgBinder {
3335 public:
3336 template<typename F>
3337 ArgBinder( CommandLine* cl, F f )
3338 : m_cl( cl ),
3339 m_arg( Detail::makeBoundField( f ) )
3340 {}
3341 ArgBinder( ArgBinder& other )
3342 : m_cl( other.m_cl ),
3343 m_arg( other.m_arg )
3344 {
3345 other.m_cl = NULL;
3346 }
3347 ~ArgBinder() {
3348 if( m_cl ) {
3349 m_arg.validate();
3350 if( m_arg.isFixedPositional() ) {
3351 m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) );
3352 if( m_arg.position > m_cl->m_highestSpecifiedArgPosition )
3353 m_cl->m_highestSpecifiedArgPosition = m_arg.position;
3354 }
3355 else if( m_arg.isAnyPositional() ) {
3356 if( m_cl->m_arg.get() )
3357 throw std::logic_error( "Only one unpositional argument can be added" );
Phil Nash5ecb72b2013-11-26 20:57:45 +00003358 m_cl->m_arg = ArgAutoPtr( new Arg( m_arg ) );
Phil Nash786959d2013-06-07 19:07:50 +01003359 }
3360 else
3361 m_cl->m_options.push_back( m_arg );
3362 }
3363 }
3364 ArgBinder& shortOpt( std::string const& name ) {
3365 m_arg.shortNames.push_back( name );
3366 return *this;
3367 }
3368 ArgBinder& longOpt( std::string const& name ) {
3369 m_arg.longName = name;
3370 return *this;
3371 }
3372 ArgBinder& describe( std::string const& description ) {
3373 m_arg.description = description;
3374 return *this;
3375 }
Phil Nash46118712013-08-16 19:01:32 +01003376 ArgBinder& hint( std::string const& hint ) {
3377 m_arg.hint = hint;
Phil Nash786959d2013-06-07 19:07:50 +01003378 return *this;
3379 }
3380 ArgBinder& position( int position ) {
3381 m_arg.position = position;
3382 return *this;
3383 }
3384 private:
3385 CommandLine* m_cl;
3386 Arg m_arg;
3387 };
3388
3389 public:
3390
3391 CommandLine()
3392 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
3393 m_highestSpecifiedArgPosition( 0 )
3394 {}
3395 CommandLine( CommandLine const& other )
3396 : m_boundProcessName( other.m_boundProcessName ),
3397 m_options ( other.m_options ),
3398 m_positionalArgs( other.m_positionalArgs ),
3399 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition )
3400 {
3401 if( other.m_arg.get() )
Phil Nash5ecb72b2013-11-26 20:57:45 +00003402 m_arg = ArgAutoPtr( new Arg( *other.m_arg ) );
Phil Nash786959d2013-06-07 19:07:50 +01003403 }
3404
3405 template<typename F>
3406 ArgBinder bind( F f ) {
3407 ArgBinder binder( this, f );
3408 return binder;
3409 }
3410 template<typename F>
3411 void bindProcessName( F f ) {
3412 m_boundProcessName = Detail::makeBoundField( f );
3413 }
3414
3415 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = CATCH_CONFIG_CONSOLE_WIDTH ) const {
3416 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
3417 std::size_t maxWidth = 0;
3418 for( it = itBegin; it != itEnd; ++it )
3419 maxWidth = (std::max)( maxWidth, it->commands().size() );
3420
3421 for( it = itBegin; it != itEnd; ++it ) {
3422 Catch::Text usage( it->commands(), Catch::TextAttributes()
3423 .setWidth( maxWidth+indent )
3424 .setIndent( indent ) );
3425 // !TBD handle longer usage strings
3426 Catch::Text desc( it->description, Catch::TextAttributes()
3427 .setWidth( width - maxWidth -3 ) );
3428
Phil Nashcd688302013-06-29 12:11:32 +01003429 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
Phil Nash786959d2013-06-07 19:07:50 +01003430 std::string usageCol = i < usage.size() ? usage[i] : "";
3431 os << usageCol;
3432
3433 if( i < desc.size() && !desc[i].empty() )
3434 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
3435 << desc[i];
3436 os << "\n";
3437 }
3438 }
3439 }
3440 std::string optUsage() const {
3441 std::ostringstream oss;
3442 optUsage( oss );
3443 return oss.str();
3444 }
3445
3446 void argSynopsis( std::ostream& os ) const {
3447 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
3448 if( i > 1 )
3449 os << " ";
3450 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
3451 if( it != m_positionalArgs.end() )
Phil Nash46118712013-08-16 19:01:32 +01003452 os << "<" << it->second.hint << ">";
Phil Nash786959d2013-06-07 19:07:50 +01003453 else if( m_arg.get() )
Phil Nash46118712013-08-16 19:01:32 +01003454 os << "<" << m_arg->hint << ">";
Phil Nash786959d2013-06-07 19:07:50 +01003455 else
3456 throw std::logic_error( "non consecutive positional arguments with no floating args" );
3457 }
3458 // !TBD No indication of mandatory args
3459 if( m_arg.get() ) {
3460 if( m_highestSpecifiedArgPosition > 1 )
3461 os << " ";
Phil Nash46118712013-08-16 19:01:32 +01003462 os << "[<" << m_arg->hint << "> ...]";
Phil Nash786959d2013-06-07 19:07:50 +01003463 }
3464 }
3465 std::string argSynopsis() const {
3466 std::ostringstream oss;
3467 argSynopsis( oss );
3468 return oss.str();
3469 }
3470
3471 void usage( std::ostream& os, std::string const& procName ) const {
3472 os << "usage:\n " << procName << " ";
3473 argSynopsis( os );
3474 if( !m_options.empty() ) {
3475 os << " [options]\n\nwhere options are: \n";
3476 optUsage( os, 2 );
3477 }
3478 os << "\n";
3479 }
3480 std::string usage( std::string const& procName ) const {
3481 std::ostringstream oss;
3482 usage( oss, procName );
3483 return oss.str();
3484 }
3485
3486 std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
3487 std::string processName = argv[0];
3488 std::size_t lastSlash = processName.find_last_of( "/\\" );
3489 if( lastSlash != std::string::npos )
3490 processName = processName.substr( lastSlash+1 );
3491 m_boundProcessName.set( config, processName );
3492 std::vector<Parser::Token> tokens;
3493 Parser parser;
3494 parser.parseIntoTokens( argc, argv, tokens );
3495 return populate( tokens, config );
3496 }
3497
3498 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3499 if( m_options.empty() && m_positionalArgs.empty() )
3500 throw std::logic_error( "No options or arguments specified" );
3501
3502 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
3503 unusedTokens = populateFixedArgs( unusedTokens, config );
3504 unusedTokens = populateFloatingArgs( unusedTokens, config );
3505 return unusedTokens;
3506 }
3507
3508 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3509 std::vector<Parser::Token> unusedTokens;
3510 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3511 Parser::Token const& token = tokens[i];
3512 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
3513 for(; it != itEnd; ++it ) {
3514 Arg const& arg = *it;
3515
3516 try {
3517 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
3518 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
3519 if( arg.takesArg() ) {
3520 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
3521 throw std::domain_error( "Expected argument to option " + token.data );
3522 arg.boundField.set( config, tokens[++i].data );
3523 }
3524 else {
3525 arg.boundField.setFlag( config );
3526 }
3527 break;
3528 }
3529 }
3530 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01003531 throw std::runtime_error( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
Phil Nash786959d2013-06-07 19:07:50 +01003532 }
3533 }
3534 if( it == itEnd )
3535 unusedTokens.push_back( token );
3536 }
3537 return unusedTokens;
3538 }
3539 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3540 std::vector<Parser::Token> unusedTokens;
3541 int position = 1;
3542 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3543 Parser::Token const& token = tokens[i];
3544 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
3545 if( it != m_positionalArgs.end() )
3546 it->second.boundField.set( config, token.data );
3547 else
3548 unusedTokens.push_back( token );
3549 if( token.type == Parser::Token::Positional )
3550 position++;
3551 }
3552 return unusedTokens;
3553 }
3554 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
3555 if( !m_arg.get() )
3556 return tokens;
3557 std::vector<Parser::Token> unusedTokens;
3558 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3559 Parser::Token const& token = tokens[i];
3560 if( token.type == Parser::Token::Positional )
3561 m_arg->boundField.set( config, token.data );
3562 else
3563 unusedTokens.push_back( token );
3564 }
3565 return unusedTokens;
3566 }
3567
3568 private:
3569 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
3570 std::vector<Arg> m_options;
3571 std::map<int, Arg> m_positionalArgs;
Phil Nash5ecb72b2013-11-26 20:57:45 +00003572 ArgAutoPtr m_arg;
Phil Nash786959d2013-06-07 19:07:50 +01003573 int m_highestSpecifiedArgPosition;
3574 };
3575
3576} // end namespace Clara
3577
Phil Nash5ecb72b2013-11-26 20:57:45 +00003578#include <fstream>
3579
Phil Nash786959d2013-06-07 19:07:50 +01003580namespace Catch {
3581
3582 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
3583 inline void abortAfterX( ConfigData& config, int x ) {
3584 if( x < 1 )
3585 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
3586 config.abortAfter = x;
3587 }
3588 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
3589
3590 inline void addWarning( ConfigData& config, std::string const& _warning ) {
3591 if( _warning == "NoAssertions" )
Phil Nashaa7123b2013-08-15 19:01:00 +01003592 config.warnings = (WarnAbout::What)( config.warnings | WarnAbout::NoAssertions );
Phil Nash786959d2013-06-07 19:07:50 +01003593 else
3594 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
3595
3596 }
3597 inline void setVerbosity( ConfigData& config, int level ) {
3598 // !TBD: accept strings?
Phil Nashaa7123b2013-08-15 19:01:00 +01003599 config.verbosity = (Verbosity::Level)level;
3600 }
3601 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
3602 config.showDurations = _showDurations
3603 ? ShowDurations::Always
3604 : ShowDurations::Never;
Phil Nash786959d2013-06-07 19:07:50 +01003605 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00003606 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
3607 std::ifstream f( _filename.c_str() );
3608 if( !f.is_open() )
3609 throw std::domain_error( "Unable to load input file: " + _filename );
3610
3611 std::string line;
3612 while( std::getline( f, line ) ) {
3613 line = trim(line);
3614 if( !line.empty() && !startsWith( line, "#" ) )
3615 addTestOrTags( config, line );
3616 }
3617 }
Phil Nash786959d2013-06-07 19:07:50 +01003618
3619 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
3620
3621 Clara::CommandLine<ConfigData> cli;
3622
3623 cli.bindProcessName( &ConfigData::processName );
3624
3625 cli.bind( &ConfigData::showHelp )
3626 .describe( "display usage information" )
3627 .shortOpt( "?")
3628 .shortOpt( "h")
3629 .longOpt( "help" );
3630
3631 cli.bind( &ConfigData::listTests )
Phil Nash5ecb72b2013-11-26 20:57:45 +00003632 .describe( "list all/matching test cases" )
Phil Nash786959d2013-06-07 19:07:50 +01003633 .shortOpt( "l")
3634 .longOpt( "list-tests" );
3635
3636 cli.bind( &ConfigData::listTags )
Phil Nash5ecb72b2013-11-26 20:57:45 +00003637 .describe( "list all/matching tags" )
Phil Nash786959d2013-06-07 19:07:50 +01003638 .shortOpt( "t")
3639 .longOpt( "list-tags" );
3640
Phil Nash786959d2013-06-07 19:07:50 +01003641 cli.bind( &ConfigData::showSuccessfulTests )
3642 .describe( "include successful tests in output" )
3643 .shortOpt( "s")
3644 .longOpt( "success" );
3645
3646 cli.bind( &ConfigData::shouldDebugBreak )
3647 .describe( "break into debugger on failure" )
3648 .shortOpt( "b")
3649 .longOpt( "break" );
3650
3651 cli.bind( &ConfigData::noThrow )
Phil Nash7d5f2712013-06-07 21:15:25 +01003652 .describe( "skip exception tests" )
Phil Nash786959d2013-06-07 19:07:50 +01003653 .shortOpt( "e")
3654 .longOpt( "nothrow" );
3655
3656 cli.bind( &ConfigData::outputFilename )
3657 .describe( "output filename" )
3658 .shortOpt( "o")
3659 .longOpt( "out" )
Phil Nash46118712013-08-16 19:01:32 +01003660 .hint( "filename" );
Phil Nash786959d2013-06-07 19:07:50 +01003661
3662 cli.bind( &ConfigData::reporterName )
Phil Nash5ecb72b2013-11-26 20:57:45 +00003663 .describe( "reporter to use (defaults to console)" )
Phil Nash786959d2013-06-07 19:07:50 +01003664 .shortOpt( "r")
3665 .longOpt( "reporter" )
Phil Nash46118712013-08-16 19:01:32 +01003666// .hint( "name[:filename]" );
3667 .hint( "name" );
Phil Nash786959d2013-06-07 19:07:50 +01003668
3669 cli.bind( &ConfigData::name )
3670 .describe( "suite name" )
3671 .shortOpt( "n")
3672 .longOpt( "name" )
Phil Nash46118712013-08-16 19:01:32 +01003673 .hint( "name" );
Phil Nash786959d2013-06-07 19:07:50 +01003674
3675 cli.bind( &abortAfterFirst )
3676 .describe( "abort at first failure" )
3677 .shortOpt( "a")
3678 .longOpt( "abort" );
3679
3680 cli.bind( &abortAfterX )
3681 .describe( "abort after x failures" )
3682 .shortOpt( "x")
3683 .longOpt( "abortx" )
Phil Nash46118712013-08-16 19:01:32 +01003684 .hint( "number of failures" );
Phil Nash786959d2013-06-07 19:07:50 +01003685
3686 cli.bind( &addWarning )
3687 .describe( "enable warnings" )
3688 .shortOpt( "w")
3689 .longOpt( "warn" )
Phil Nash46118712013-08-16 19:01:32 +01003690 .hint( "warning name" );
Phil Nash786959d2013-06-07 19:07:50 +01003691
3692// cli.bind( &setVerbosity )
3693// .describe( "level of verbosity (0=no output)" )
3694// .shortOpt( "v")
3695// .longOpt( "verbosity" )
Phil Nash46118712013-08-16 19:01:32 +01003696// .hint( "level" );
Phil Nash786959d2013-06-07 19:07:50 +01003697
3698 cli.bind( &addTestOrTags )
3699 .describe( "which test or tests to use" )
Phil Nash46118712013-08-16 19:01:32 +01003700 .hint( "test name, pattern or tags" );
Phil Nash786959d2013-06-07 19:07:50 +01003701
Phil Nashaa7123b2013-08-15 19:01:00 +01003702 cli.bind( &setShowDurations )
3703 .describe( "show test durations" )
3704 .shortOpt( "d")
3705 .longOpt( "durations" )
Phil Nash46118712013-08-16 19:01:32 +01003706 .hint( "yes/no" );
Phil Nashaa7123b2013-08-15 19:01:00 +01003707
Phil Nash5ecb72b2013-11-26 20:57:45 +00003708 cli.bind( &loadTestNamesFromFile )
3709 .describe( "load test names to run from a file" )
3710 .shortOpt( "f")
3711 .longOpt( "input-file" )
3712 .hint( "filename" );
3713
3714 // Less common commands which don't have a short form
3715 cli.bind( &ConfigData::listTestNamesOnly )
3716 .describe( "list all/matching test cases names only" )
3717 .longOpt( "list-test-names-only" );
3718
3719 cli.bind( &ConfigData::listReporters )
3720 .describe( "list all reporters" )
3721 .longOpt( "list-reporters" );
3722
Phil Nash786959d2013-06-07 19:07:50 +01003723 return cli;
3724 }
3725
Phil Nasha695eb92012-08-13 07:46:10 +01003726} // end namespace Catch
3727
3728// #included from: internal/catch_list.hpp
3729#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
3730
Phil Nash5c7d3d72013-04-01 11:27:10 +01003731// #included from: catch_console_colour.hpp
3732#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003733
3734namespace Catch {
Phil Nash5c7d3d72013-04-01 11:27:10 +01003735
Phil Nash12c16ff2013-04-05 20:58:01 +01003736 namespace Detail {
3737 struct IColourImpl;
3738 }
Phil Nash5c7d3d72013-04-01 11:27:10 +01003739
Phil Nash12c16ff2013-04-05 20:58:01 +01003740 struct Colour {
3741 enum Code {
3742 None = 0,
Phil Nash5c7d3d72013-04-01 11:27:10 +01003743
Phil Nash12c16ff2013-04-05 20:58:01 +01003744 White,
3745 Red,
3746 Green,
3747 Blue,
3748 Cyan,
3749 Yellow,
3750 Grey,
Phil Nash5c7d3d72013-04-01 11:27:10 +01003751
Phil Nash12c16ff2013-04-05 20:58:01 +01003752 Bright = 0x10,
Phil Nash5c7d3d72013-04-01 11:27:10 +01003753
Phil Nash12c16ff2013-04-05 20:58:01 +01003754 BrightRed = Bright | Red,
3755 BrightGreen = Bright | Green,
3756 LightGrey = Bright | Grey,
3757 BrightWhite = Bright | White,
3758
3759 // By intention
3760 FileName = LightGrey,
3761 ResultError = BrightRed,
3762 ResultSuccess = BrightGreen,
3763
3764 Error = BrightRed,
3765 Success = Green,
3766
3767 OriginalExpression = Cyan,
3768 ReconstructedExpression = Yellow,
3769
3770 SecondaryText = LightGrey,
3771 Headers = White
Phil Nash5c7d3d72013-04-01 11:27:10 +01003772 };
3773
Phil Nash12c16ff2013-04-05 20:58:01 +01003774 // Use constructed object for RAII guard
3775 Colour( Code _colourCode );
3776 ~Colour();
Phil Nash5c7d3d72013-04-01 11:27:10 +01003777
Phil Nash12c16ff2013-04-05 20:58:01 +01003778 // Use static method for one-shot changes
3779 static void use( Code _colourCode );
Phil Nash5c7d3d72013-04-01 11:27:10 +01003780
3781 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01003782 static Detail::IColourImpl* impl;
Phil Nash5c7d3d72013-04-01 11:27:10 +01003783 };
3784
3785} // end namespace Catch
3786
Phil Nash3649fdf2013-12-03 18:53:55 +00003787// #included from: catch_interfaces_reporter.h
3788#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
3789
3790// #included from: catch_option.hpp
3791#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3792
3793namespace Catch {
3794
3795 // An optional type
3796 template<typename T>
3797 class Option {
3798 public:
3799 Option() : nullableValue( NULL ) {}
3800 Option( T const& _value )
3801 : nullableValue( new( storage ) T( _value ) )
3802 {}
3803 Option( Option const& _other )
3804 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
3805 {}
3806
3807 ~Option() {
3808 reset();
3809 }
3810
3811 Option& operator= ( Option const& _other ) {
3812 reset();
3813 if( _other )
3814 nullableValue = new( storage ) T( *_other );
3815 return *this;
3816 }
3817 Option& operator = ( T const& _value ) {
3818 reset();
3819 nullableValue = new( storage ) T( _value );
3820 return *this;
3821 }
3822
3823 void reset() {
3824 if( nullableValue )
3825 nullableValue->~T();
3826 nullableValue = NULL;
3827 }
3828
3829 T& operator*() { return *nullableValue; }
3830 T const& operator*() const { return *nullableValue; }
3831 T* operator->() { return nullableValue; }
3832 const T* operator->() const { return nullableValue; }
3833
3834 T valueOr( T const& defaultValue ) const {
3835 return nullableValue ? *nullableValue : defaultValue;
3836 }
3837
3838 bool some() const { return nullableValue != NULL; }
3839 bool none() const { return nullableValue == NULL; }
3840
3841 bool operator !() const { return nullableValue == NULL; }
3842 operator SafeBool::type() const {
3843 return SafeBool::makeSafe( some() );
3844 }
3845
3846 private:
3847 T* nullableValue;
3848 char storage[sizeof(T)];
3849 };
3850
3851} // end namespace Catch
3852
3853#include <string>
3854#include <ostream>
3855#include <map>
3856#include <assert.h>
3857
3858namespace Catch
3859{
3860 struct ReporterConfig {
3861 explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
3862 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
3863
3864 ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
3865 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
3866
3867 std::ostream& stream() const { return *m_stream; }
3868 Ptr<IConfig> fullConfig() const { return m_fullConfig; }
3869
3870 private:
3871 std::ostream* m_stream;
3872 Ptr<IConfig> m_fullConfig;
3873 };
3874
3875 struct ReporterPreferences {
3876 ReporterPreferences()
3877 : shouldRedirectStdOut( false )
3878 {}
3879
3880 bool shouldRedirectStdOut;
3881 };
3882
3883 template<typename T>
3884 struct LazyStat : Option<T> {
3885 LazyStat() : used( false ) {}
3886 LazyStat& operator=( T const& _value ) {
3887 Option<T>::operator=( _value );
3888 used = false;
3889 return *this;
3890 }
3891 void reset() {
3892 Option<T>::reset();
3893 used = false;
3894 }
3895 bool used;
3896 };
3897
3898 struct TestRunInfo {
3899 TestRunInfo( std::string const& _name ) : name( _name ) {}
3900 std::string name;
3901 };
3902 struct GroupInfo {
3903 GroupInfo( std::string const& _name,
3904 std::size_t _groupIndex,
3905 std::size_t _groupsCount )
3906 : name( _name ),
3907 groupIndex( _groupIndex ),
3908 groupsCounts( _groupsCount )
3909 {}
3910
3911 std::string name;
3912 std::size_t groupIndex;
3913 std::size_t groupsCounts;
3914 };
3915
3916 struct AssertionStats {
3917 AssertionStats( AssertionResult const& _assertionResult,
3918 std::vector<MessageInfo> const& _infoMessages,
3919 Totals const& _totals )
3920 : assertionResult( _assertionResult ),
3921 infoMessages( _infoMessages ),
3922 totals( _totals )
3923 {
3924 if( assertionResult.hasMessage() ) {
3925 // Copy message into messages list.
3926 // !TBD This should have been done earlier, somewhere
3927 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
3928 builder << assertionResult.getMessage();
3929 builder.m_info.message = builder.m_stream.str();
3930
3931 infoMessages.push_back( builder.m_info );
3932 }
3933 }
3934 virtual ~AssertionStats();
3935
3936 AssertionResult assertionResult;
3937 std::vector<MessageInfo> infoMessages;
3938 Totals totals;
3939 };
3940
3941 struct SectionStats {
3942 SectionStats( SectionInfo const& _sectionInfo,
3943 Counts const& _assertions,
3944 double _durationInSeconds,
3945 bool _missingAssertions )
3946 : sectionInfo( _sectionInfo ),
3947 assertions( _assertions ),
3948 durationInSeconds( _durationInSeconds ),
3949 missingAssertions( _missingAssertions )
3950 {}
3951 virtual ~SectionStats();
3952
3953 SectionInfo sectionInfo;
3954 Counts assertions;
3955 double durationInSeconds;
3956 bool missingAssertions;
3957 };
3958
3959 struct TestCaseStats {
3960 TestCaseStats( TestCaseInfo const& _testInfo,
3961 Totals const& _totals,
3962 std::string const& _stdOut,
3963 std::string const& _stdErr,
3964 bool _aborting )
3965 : testInfo( _testInfo ),
3966 totals( _totals ),
3967 stdOut( _stdOut ),
3968 stdErr( _stdErr ),
3969 aborting( _aborting )
3970 {}
3971 virtual ~TestCaseStats();
3972
3973 TestCaseInfo testInfo;
3974 Totals totals;
3975 std::string stdOut;
3976 std::string stdErr;
3977 bool aborting;
3978 };
3979
3980 struct TestGroupStats {
3981 TestGroupStats( GroupInfo const& _groupInfo,
3982 Totals const& _totals,
3983 bool _aborting )
3984 : groupInfo( _groupInfo ),
3985 totals( _totals ),
3986 aborting( _aborting )
3987 {}
3988 TestGroupStats( GroupInfo const& _groupInfo )
3989 : groupInfo( _groupInfo ),
3990 aborting( false )
3991 {}
3992 virtual ~TestGroupStats();
3993
3994 GroupInfo groupInfo;
3995 Totals totals;
3996 bool aborting;
3997 };
3998
3999 struct TestRunStats {
4000 TestRunStats( TestRunInfo const& _runInfo,
4001 Totals const& _totals,
4002 bool _aborting )
4003 : runInfo( _runInfo ),
4004 totals( _totals ),
4005 aborting( _aborting )
4006 {}
4007 TestRunStats( TestRunStats const& _other )
4008 : runInfo( _other.runInfo ),
4009 totals( _other.totals ),
4010 aborting( _other.aborting )
4011 {}
4012 virtual ~TestRunStats();
4013
4014 TestRunInfo runInfo;
4015 Totals totals;
4016 bool aborting;
4017 };
4018
4019 struct IStreamingReporter : IShared {
4020 virtual ~IStreamingReporter();
4021
4022 // Implementing class must also provide the following static method:
4023 // static std::string getDescription();
4024
4025 virtual ReporterPreferences getPreferences() const = 0;
4026
4027 virtual void noMatchingTestCases( std::string const& spec ) = 0;
4028
4029 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
4030 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
4031
4032 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
4033 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
4034
4035 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
4036
4037 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
4038 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
4039 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
4040 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
4041 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
4042 };
4043
4044 struct IReporterFactory {
4045 virtual ~IReporterFactory();
4046 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
4047 virtual std::string getDescription() const = 0;
4048 };
4049
4050 struct IReporterRegistry {
4051 typedef std::map<std::string, IReporterFactory*> FactoryMap;
4052
4053 virtual ~IReporterRegistry();
4054 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
4055 virtual FactoryMap const& getFactories() const = 0;
4056 };
4057
4058}
4059
Phil Nasha695eb92012-08-13 07:46:10 +01004060#include <limits>
Phil Nash38f7eef2013-03-29 13:44:33 +00004061#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01004062
4063namespace Catch {
Phil Nash8defc712013-04-24 19:10:02 +01004064 inline bool matchesFilters( std::vector<TestCaseFilters> const& filters, TestCase const& testCase ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004065 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
4066 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
4067 for(; it != itEnd; ++it )
4068 if( !it->shouldInclude( testCase ) )
4069 return false;
4070 return true;
4071 }
Phil Nasha695eb92012-08-13 07:46:10 +01004072
Phil Nash786959d2013-06-07 19:07:50 +01004073 inline std::size_t listTests( Config const& config ) {
4074 if( config.filters().empty() )
Phil Nash38f7eef2013-03-29 13:44:33 +00004075 std::cout << "All available test cases:\n";
4076 else
4077 std::cout << "Matching test cases:\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00004078
4079 std::size_t matchedTests = 0;
Phil Nash8d44f2d2013-11-13 08:10:45 +00004080 TextAttributes nameAttr, tagsAttr;
4081 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
4082 tagsAttr.setIndent( 6 );
4083
4084 std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
4085 for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4086 it != itEnd;
4087 ++it )
Phil Nash786959d2013-06-07 19:07:50 +01004088 if( matchesFilters( config.filters(), *it ) ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004089 matchedTests++;
Phil Nash8d44f2d2013-11-13 08:10:45 +00004090 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
4091 Colour::Code colour = testCaseInfo.isHidden
4092 ? Colour::SecondaryText
4093 : Colour::None;
4094 Colour colourGuard( colour );
Phil Nash38f7eef2013-03-29 13:44:33 +00004095
Phil Nash8d44f2d2013-11-13 08:10:45 +00004096 std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
4097 if( !testCaseInfo.tags.empty() )
4098 std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
Phil Nasha695eb92012-08-13 07:46:10 +01004099 }
Phil Nash8d44f2d2013-11-13 08:10:45 +00004100
Phil Nash786959d2013-06-07 19:07:50 +01004101 if( config.filters().empty() )
4102 std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
Phil Nash38f7eef2013-03-29 13:44:33 +00004103 else
Phil Nash786959d2013-06-07 19:07:50 +01004104 std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
4105 return matchedTests;
Phil Nash38f7eef2013-03-29 13:44:33 +00004106 }
Phil Nasha695eb92012-08-13 07:46:10 +01004107
Phil Nash5ecb72b2013-11-26 20:57:45 +00004108 inline std::size_t listTestsNamesOnly( Config const& config ) {
4109 std::size_t matchedTests = 0;
4110 std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
4111 for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4112 it != itEnd;
4113 ++it )
4114 if( matchesFilters( config.filters(), *it ) ) {
4115 matchedTests++;
4116 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
4117 std::cout << testCaseInfo.name << std::endl;
4118 }
4119 return matchedTests;
4120 }
4121
Phil Nash786959d2013-06-07 19:07:50 +01004122 inline std::size_t listTags( Config const& config ) {
4123 if( config.filters().empty() )
Phil Nash38f7eef2013-03-29 13:44:33 +00004124 std::cout << "All available tags:\n";
4125 else
4126 std::cout << "Matching tags:\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00004127
4128 std::map<std::string, int> tagCounts;
4129
Phil Nash8d44f2d2013-11-13 08:10:45 +00004130 std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
4131 for( std::vector<TestCase>::const_iterator it = allTests.begin(),
4132 itEnd = allTests.end();
4133 it != itEnd;
4134 ++it ) {
Phil Nash786959d2013-06-07 19:07:50 +01004135 if( matchesFilters( config.filters(), *it ) ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004136 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4137 tagItEnd = it->getTestCaseInfo().tags.end();
4138 tagIt != tagItEnd;
4139 ++tagIt ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01004140 std::string tagName = *tagIt;
Phil Nash38f7eef2013-03-29 13:44:33 +00004141 std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
4142 if( countIt == tagCounts.end() )
4143 tagCounts.insert( std::make_pair( tagName, 1 ) );
4144 else
4145 countIt->second++;
4146 }
4147 }
Phil Nasha695eb92012-08-13 07:46:10 +01004148 }
Phil Nash38f7eef2013-03-29 13:44:33 +00004149
Phil Nash8d44f2d2013-11-13 08:10:45 +00004150 for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(),
4151 countItEnd = tagCounts.end();
Phil Nash38f7eef2013-03-29 13:44:33 +00004152 countIt != countItEnd;
4153 ++countIt ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00004154 std::ostringstream oss;
4155 oss << " " << countIt->second << " ";
Phil Nash19279252013-04-20 21:07:32 +01004156 Text wrapper( "[" + countIt->first + "]", TextAttributes()
Phil Nash8d44f2d2013-11-13 08:10:45 +00004157 .setInitialIndent( 0 )
4158 .setIndent( oss.str().size() )
4159 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
4160 std::cout << oss.str() << wrapper << "\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00004161 }
Phil Nash786959d2013-06-07 19:07:50 +01004162 std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
4163 return tagCounts.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00004164 }
4165
Phil Nash786959d2013-06-07 19:07:50 +01004166 inline std::size_t listReporters( Config const& /*config*/ ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004167 std::cout << "Available reports:\n";
4168 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Phil Nash786959d2013-06-07 19:07:50 +01004169 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
4170 std::size_t maxNameLen = 0;
4171 for(it = itBegin; it != itEnd; ++it )
4172 maxNameLen = (std::max)( maxNameLen, it->first.size() );
4173
4174 for(it = itBegin; it != itEnd; ++it ) {
4175 Text wrapper( it->second->getDescription(), TextAttributes()
4176 .setInitialIndent( 0 )
4177 .setIndent( 7+maxNameLen )
4178 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
4179 std::cout << " "
4180 << it->first
4181 << ":"
4182 << std::string( maxNameLen - it->first.size() + 2, ' ' )
4183 << wrapper << "\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00004184 }
4185 std::cout << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01004186 return factories.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00004187 }
4188
Phil Nash786959d2013-06-07 19:07:50 +01004189 inline Option<std::size_t> list( Config const& config ) {
4190 Option<std::size_t> listedCount;
4191 if( config.listTests() )
4192 listedCount = listedCount.valueOr(0) + listTests( config );
Phil Nash5ecb72b2013-11-26 20:57:45 +00004193 if( config.listTestNamesOnly() )
4194 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
Phil Nash786959d2013-06-07 19:07:50 +01004195 if( config.listTags() )
4196 listedCount = listedCount.valueOr(0) + listTags( config );
4197 if( config.listReporters() )
4198 listedCount = listedCount.valueOr(0) + listReporters( config );
4199 return listedCount;
Phil Nasha695eb92012-08-13 07:46:10 +01004200 }
4201
4202} // end namespace Catch
4203
4204// #included from: internal/catch_runner_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004205#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004206
Phil Nash8a52a392013-07-25 08:12:03 +01004207// #included from: catch_test_case_tracker.hpp
4208#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004209
4210#include <map>
4211#include <string>
Phil Nash8a52a392013-07-25 08:12:03 +01004212#include <assert.h>
Phil Nasha695eb92012-08-13 07:46:10 +01004213
4214namespace Catch {
Phil Nash8a52a392013-07-25 08:12:03 +01004215namespace SectionTracking {
Phil Nasha695eb92012-08-13 07:46:10 +01004216
Phil Nash8a52a392013-07-25 08:12:03 +01004217 class TrackedSection {
4218
4219 typedef std::map<std::string, TrackedSection> TrackedSections;
4220
Phil Nasha695eb92012-08-13 07:46:10 +01004221 public:
Phil Nash8a52a392013-07-25 08:12:03 +01004222 enum RunState {
4223 NotStarted,
4224 Executing,
4225 ExecutingChildren,
4226 Completed
Phil Nasha695eb92012-08-13 07:46:10 +01004227 };
4228
Phil Nash8a52a392013-07-25 08:12:03 +01004229 TrackedSection( std::string const& name, TrackedSection* parent )
4230 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
Phil Nasha695eb92012-08-13 07:46:10 +01004231 {}
4232
Phil Nash8a52a392013-07-25 08:12:03 +01004233 RunState runState() const { return m_runState; }
Phil Nasha695eb92012-08-13 07:46:10 +01004234
Phil Nash8a52a392013-07-25 08:12:03 +01004235 void addChild( std::string const& childName ) {
4236 m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
4237 }
4238 TrackedSection* getChild( std::string const& childName ) {
4239 return &m_children.find( childName )->second;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004240 }
4241
Phil Nash8a52a392013-07-25 08:12:03 +01004242 void enter() {
4243 if( m_runState == NotStarted )
4244 m_runState = Executing;
Phil Nasha695eb92012-08-13 07:46:10 +01004245 }
Phil Nash8a52a392013-07-25 08:12:03 +01004246 void leave() {
4247 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
4248 it != itEnd;
4249 ++it )
4250 if( it->second.runState() != Completed ) {
4251 m_runState = ExecutingChildren;
4252 return;
4253 }
4254 m_runState = Completed;
Phil Nasha695eb92012-08-13 07:46:10 +01004255 }
Phil Nash8a52a392013-07-25 08:12:03 +01004256 TrackedSection* getParent() {
Phil Nasha695eb92012-08-13 07:46:10 +01004257 return m_parent;
4258 }
Phil Nash8a52a392013-07-25 08:12:03 +01004259 bool hasChildren() const {
4260 return !m_children.empty();
Phil Nasha1fbfea2012-12-01 23:57:18 +00004261 }
4262
Phil Nasha695eb92012-08-13 07:46:10 +01004263 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00004264 std::string m_name;
Phil Nash8a52a392013-07-25 08:12:03 +01004265 RunState m_runState;
4266 TrackedSections m_children;
4267 TrackedSection* m_parent;
4268
Phil Nasha695eb92012-08-13 07:46:10 +01004269 };
Phil Nasha695eb92012-08-13 07:46:10 +01004270
Phil Nash8a52a392013-07-25 08:12:03 +01004271 class TestCaseTracker {
Phil Nasha695eb92012-08-13 07:46:10 +01004272 public:
Phil Nash8a52a392013-07-25 08:12:03 +01004273 TestCaseTracker( std::string const& testCaseName )
4274 : m_testCase( testCaseName, NULL ),
4275 m_currentSection( &m_testCase ),
4276 m_completedASectionThisRun( false )
Phil Nasha695eb92012-08-13 07:46:10 +01004277 {}
4278
Phil Nash8a52a392013-07-25 08:12:03 +01004279 bool enterSection( std::string const& name ) {
4280 if( m_completedASectionThisRun )
4281 return false;
4282 if( m_currentSection->runState() == TrackedSection::Executing ) {
4283 m_currentSection->addChild( name );
4284 return false;
4285 }
4286 else {
4287 TrackedSection* child = m_currentSection->getChild( name );
4288 if( child->runState() != TrackedSection::Completed ) {
4289 m_currentSection = child;
4290 m_currentSection->enter();
4291 return true;
4292 }
4293 return false;
Phil Nasha695eb92012-08-13 07:46:10 +01004294 }
4295 }
Phil Nash8a52a392013-07-25 08:12:03 +01004296 void leaveSection() {
4297 m_currentSection->leave();
Phil Nasha695eb92012-08-13 07:46:10 +01004298 m_currentSection = m_currentSection->getParent();
Phil Nash8a52a392013-07-25 08:12:03 +01004299 assert( m_currentSection != NULL );
4300 m_completedASectionThisRun = true;
Phil Nasha695eb92012-08-13 07:46:10 +01004301 }
4302
Phil Nash8a52a392013-07-25 08:12:03 +01004303 bool currentSectionHasChildren() const {
4304 return m_currentSection->hasChildren();
4305 }
4306 bool isCompleted() const {
4307 return m_testCase.runState() == TrackedSection::Completed;
Phil Nasha695eb92012-08-13 07:46:10 +01004308 }
4309
Phil Nash8a52a392013-07-25 08:12:03 +01004310 class Guard {
4311 public:
4312 Guard( TestCaseTracker& tracker )
4313 : m_tracker( tracker )
4314 {
4315 m_tracker.enterTestCase();
4316 }
4317 ~Guard() {
4318 m_tracker.leaveTestCase();
4319 }
4320 private:
Phil Nash801672b2013-07-25 08:18:09 +01004321 Guard( Guard const& );
4322 void operator = ( Guard const& );
Phil Nash8a52a392013-07-25 08:12:03 +01004323 TestCaseTracker& m_tracker;
4324 };
Phil Nasha695eb92012-08-13 07:46:10 +01004325
4326 private:
Phil Nash8a52a392013-07-25 08:12:03 +01004327 void enterTestCase() {
4328 m_currentSection = &m_testCase;
4329 m_completedASectionThisRun = false;
4330 m_testCase.enter();
4331 }
4332 void leaveTestCase() {
4333 m_testCase.leave();
4334 }
Phil Nashdd26e882013-03-25 09:25:31 +00004335
Phil Nash8a52a392013-07-25 08:12:03 +01004336 TrackedSection m_testCase;
4337 TrackedSection* m_currentSection;
4338 bool m_completedASectionThisRun;
Phil Nasha695eb92012-08-13 07:46:10 +01004339 };
Phil Nash8a52a392013-07-25 08:12:03 +01004340
4341} // namespace SectionTracking
4342
4343using SectionTracking::TestCaseTracker;
4344
4345} // namespace Catch
Phil Nasha695eb92012-08-13 07:46:10 +01004346
4347#include <set>
4348#include <string>
4349
4350namespace Catch {
4351
4352 class StreamRedirect {
4353
4354 public:
4355 StreamRedirect( std::ostream& stream, std::string& targetString )
4356 : m_stream( stream ),
4357 m_prevBuf( stream.rdbuf() ),
4358 m_targetString( targetString )
4359 {
4360 stream.rdbuf( m_oss.rdbuf() );
4361 }
4362
4363 ~StreamRedirect() {
4364 m_targetString += m_oss.str();
4365 m_stream.rdbuf( m_prevBuf );
4366 }
4367
4368 private:
4369 std::ostream& m_stream;
4370 std::streambuf* m_prevBuf;
4371 std::ostringstream m_oss;
4372 std::string& m_targetString;
4373 };
4374
4375 ///////////////////////////////////////////////////////////////////////////
4376
Phil Nash786959d2013-06-07 19:07:50 +01004377 class RunContext : public IResultCapture, public IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01004378
Phil Nash786959d2013-06-07 19:07:50 +01004379 RunContext( RunContext const& );
4380 void operator =( RunContext const& );
Phil Nasha695eb92012-08-13 07:46:10 +01004381
4382 public:
4383
Phil Nash786959d2013-06-07 19:07:50 +01004384 explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter )
4385 : m_runInfo( config->name() ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00004386 m_context( getCurrentMutableContext() ),
Phil Nash8a52a392013-07-25 08:12:03 +01004387 m_activeTestCase( NULL ),
Phil Nasha695eb92012-08-13 07:46:10 +01004388 m_config( config ),
4389 m_reporter( reporter ),
4390 m_prevRunner( &m_context.getRunner() ),
4391 m_prevResultCapture( &m_context.getResultCapture() ),
4392 m_prevConfig( m_context.getConfig() )
4393 {
4394 m_context.setRunner( this );
Phil Nash786959d2013-06-07 19:07:50 +01004395 m_context.setConfig( m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01004396 m_context.setResultCapture( this );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004397 m_reporter->testRunStarting( m_runInfo );
Phil Nasha695eb92012-08-13 07:46:10 +01004398 }
4399
Phil Nash786959d2013-06-07 19:07:50 +01004400 virtual ~RunContext() {
Phil Nash2e7d9662013-01-16 09:44:43 +00004401 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004402 m_context.setRunner( m_prevRunner );
4403 m_context.setConfig( NULL );
4404 m_context.setResultCapture( m_prevResultCapture );
4405 m_context.setConfig( m_prevConfig );
4406 }
4407
Phil Nash2e7d9662013-01-16 09:44:43 +00004408 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4409 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004410 }
Phil Nash2e7d9662013-01-16 09:44:43 +00004411 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
4412 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004413 }
Phil Nasha695eb92012-08-13 07:46:10 +01004414
Phil Nash8defc712013-04-24 19:10:02 +01004415 Totals runMatching( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004416
Phil Nasha1fbfea2012-12-01 23:57:18 +00004417 std::vector<TestCase> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01004418
4419 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01004420
Phil Nash2e7d9662013-01-16 09:44:43 +00004421 testGroupStarting( testSpec, groupIndex, groupsCount );
Phil Nash56d5c422012-08-23 20:08:50 +01004422
Phil Nasha1fbfea2012-12-01 23:57:18 +00004423 std::vector<TestCase>::const_iterator it = matchingTests.begin();
4424 std::vector<TestCase>::const_iterator itEnd = matchingTests.end();
Phil Nash56d5c422012-08-23 20:08:50 +01004425 for(; it != itEnd; ++it )
4426 totals += runTest( *it );
Phil Nash56d5c422012-08-23 20:08:50 +01004427
Phil Nash2e7d9662013-01-16 09:44:43 +00004428 testGroupEnded( testSpec, totals, groupIndex, groupsCount );
Phil Nash5bc030d2012-08-16 18:48:50 +01004429 return totals;
4430 }
4431
Phil Nash8defc712013-04-24 19:10:02 +01004432 Totals runTest( TestCase const& testCase ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004433 Totals prevTotals = m_totals;
4434
4435 std::string redirectedCout;
4436 std::string redirectedCerr;
4437
Phil Nasha1fbfea2012-12-01 23:57:18 +00004438 TestCaseInfo testInfo = testCase.getTestCaseInfo();
Phil Nasha695eb92012-08-13 07:46:10 +01004439
Phil Nasha1fbfea2012-12-01 23:57:18 +00004440 m_reporter->testCaseStarting( testInfo );
4441
Phil Nash8a52a392013-07-25 08:12:03 +01004442 m_activeTestCase = &testCase;
4443 m_testCaseTracker = TestCaseTracker( testInfo.name );
Phil Nasha695eb92012-08-13 07:46:10 +01004444
4445 do {
4446 do {
Phil Nasha695eb92012-08-13 07:46:10 +01004447 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01004448 }
Phil Nash8a52a392013-07-25 08:12:03 +01004449 while( !m_testCaseTracker->isCompleted() && !aborting() );
Phil Nasha695eb92012-08-13 07:46:10 +01004450 }
4451 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
4452
Phil Nash28463672012-11-21 18:06:13 +00004453 Totals deltaTotals = m_totals.delta( prevTotals );
Phil Nash28463672012-11-21 18:06:13 +00004454 m_totals.testCases += deltaTotals.testCases;
Phil Nash2e7d9662013-01-16 09:44:43 +00004455 m_reporter->testCaseEnded( TestCaseStats( testInfo,
4456 deltaTotals,
4457 redirectedCout,
4458 redirectedCerr,
Phil Nash2e7d9662013-01-16 09:44:43 +00004459 aborting() ) );
Phil Nash28463672012-11-21 18:06:13 +00004460
Phil Nash8a52a392013-07-25 08:12:03 +01004461 m_activeTestCase = NULL;
4462 m_testCaseTracker.reset();
Phil Nasha695eb92012-08-13 07:46:10 +01004463
Phil Nash5bc030d2012-08-16 18:48:50 +01004464 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01004465 }
4466
Phil Nash786959d2013-06-07 19:07:50 +01004467 Ptr<IConfig const> config() const {
Phil Nasha695eb92012-08-13 07:46:10 +01004468 return m_config;
4469 }
4470
4471 private: // IResultCapture
4472
Phil Nash8defc712013-04-24 19:10:02 +01004473 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) {
Phil Nash90a35942012-11-13 22:04:29 +00004474 m_lastAssertionInfo = assertionInfo;
4475 return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004476 }
4477
Phil Nash8defc712013-04-24 19:10:02 +01004478 virtual void assertionEnded( AssertionResult const& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004479 if( result.getResultType() == ResultWas::Ok ) {
4480 m_totals.assertions.passed++;
4481 }
Phil Nash90a35942012-11-13 22:04:29 +00004482 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004483 m_totals.assertions.failed++;
Phil Nasha695eb92012-08-13 07:46:10 +01004484 }
4485
Phil Nashb5fd5a62013-06-28 17:09:57 +01004486 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
4487 m_messages.clear();
Phil Nasha90a88a2012-11-19 19:59:10 +00004488
Phil Nasha2773812013-02-02 20:37:58 +00004489 // Reset working state
4490 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
Phil Nasha695eb92012-08-13 07:46:10 +01004491 }
4492
4493 virtual bool sectionStarted (
Phil Nasha1fbfea2012-12-01 23:57:18 +00004494 SectionInfo const& sectionInfo,
Phil Nasha695eb92012-08-13 07:46:10 +01004495 Counts& assertions
4496 )
4497 {
4498 std::ostringstream oss;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004499 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01004500
Phil Nash8a52a392013-07-25 08:12:03 +01004501 if( !m_testCaseTracker->enterSection( oss.str() ) )
Phil Nasha695eb92012-08-13 07:46:10 +01004502 return false;
4503
Phil Nasha1fbfea2012-12-01 23:57:18 +00004504 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Phil Nash90a35942012-11-13 22:04:29 +00004505
Phil Nasha1fbfea2012-12-01 23:57:18 +00004506 m_reporter->sectionStarting( sectionInfo );
4507
Phil Nasha695eb92012-08-13 07:46:10 +01004508 assertions = m_totals.assertions;
4509
4510 return true;
4511 }
Phil Nashaa7123b2013-08-15 19:01:00 +01004512 bool testForMissingAssertions( Counts& assertions ) {
4513 if( assertions.total() != 0 ||
4514 !m_config->warnAboutMissingAssertions() ||
4515 m_testCaseTracker->currentSectionHasChildren() )
4516 return false;
4517 m_totals.assertions.failed++;
4518 assertions.failed++;
4519 return true;
4520 }
Phil Nasha695eb92012-08-13 07:46:10 +01004521
Phil Nashaa7123b2013-08-15 19:01:00 +01004522 virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
Phil Nash5bdae842013-02-19 19:47:18 +00004523 if( std::uncaught_exception() ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01004524 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
Phil Nash5bdae842013-02-19 19:47:18 +00004525 return;
4526 }
4527
Phil Nasha70fbe32012-08-31 08:10:36 +01004528 Counts assertions = m_totals.assertions - prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01004529 bool missingAssertions = testForMissingAssertions( assertions );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004530
Phil Nash8a52a392013-07-25 08:12:03 +01004531 m_testCaseTracker->leaveSection();
Phil Nasha1fbfea2012-12-01 23:57:18 +00004532
Phil Nashaa7123b2013-08-15 19:01:00 +01004533 m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
Phil Nasha2773812013-02-02 20:37:58 +00004534 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004535 }
4536
Phil Nashb5fd5a62013-06-28 17:09:57 +01004537 virtual void pushScopedMessage( MessageInfo const& message ) {
4538 m_messages.push_back( message );
Phil Nasha695eb92012-08-13 07:46:10 +01004539 }
4540
Phil Nashb5fd5a62013-06-28 17:09:57 +01004541 virtual void popScopedMessage( MessageInfo const& message ) {
4542 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
Phil Nasha695eb92012-08-13 07:46:10 +01004543 }
4544
4545 virtual bool shouldDebugBreak() const {
Phil Nash786959d2013-06-07 19:07:50 +01004546 return m_config->shouldDebugBreak();
Phil Nasha695eb92012-08-13 07:46:10 +01004547 }
4548
4549 virtual std::string getCurrentTestName() const {
Phil Nash8a52a392013-07-25 08:12:03 +01004550 return m_activeTestCase
4551 ? m_activeTestCase->getTestCaseInfo().name
Phil Nasha695eb92012-08-13 07:46:10 +01004552 : "";
4553 }
4554
Phil Nashce612bf2012-11-01 08:27:09 +00004555 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01004556 return &m_lastResult;
4557 }
4558
Phil Nash56d5c422012-08-23 20:08:50 +01004559 public:
4560 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01004561 bool aborting() const {
Phil Nash786959d2013-06-07 19:07:50 +01004562 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
Phil Nasha695eb92012-08-13 07:46:10 +01004563 }
4564
Phil Nash56d5c422012-08-23 20:08:50 +01004565 private:
4566
Phil Nash8defc712013-04-24 19:10:02 +01004567 ResultAction::Value actOnCurrentResult( AssertionResult const& result ) {
Phil Nash90a35942012-11-13 22:04:29 +00004568 m_lastResult = result;
Phil Nasha2773812013-02-02 20:37:58 +00004569 assertionEnded( m_lastResult );
Phil Nasha695eb92012-08-13 07:46:10 +01004570
Phil Nasha695eb92012-08-13 07:46:10 +01004571 ResultAction::Value action = ResultAction::None;
4572
Phil Nash90a35942012-11-13 22:04:29 +00004573 if( !m_lastResult.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004574 action = ResultAction::Failed;
4575 if( shouldDebugBreak() )
4576 action = (ResultAction::Value)( action | ResultAction::Debug );
4577 if( aborting() )
4578 action = (ResultAction::Value)( action | ResultAction::Abort );
4579 }
4580 return action;
4581 }
4582
4583 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
Phil Nash8a52a392013-07-25 08:12:03 +01004584 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
4585 SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
4586 m_reporter->sectionStarting( testCaseSection );
Phil Nashaa7123b2013-08-15 19:01:00 +01004587 Counts prevAssertions = m_totals.assertions;
4588 double duration = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01004589 try {
Phil Nash8a52a392013-07-25 08:12:03 +01004590 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
4591 TestCaseTracker::Guard guard( *m_testCaseTracker );
Phil Nashd768b1b2013-02-04 00:05:16 +00004592
Phil Nashaa7123b2013-08-15 19:01:00 +01004593 Timer timer;
4594 timer.start();
Phil Nasha1fbfea2012-12-01 23:57:18 +00004595 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004596 StreamRedirect coutRedir( std::cout, redirectedCout );
4597 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
Phil Nash8a52a392013-07-25 08:12:03 +01004598 m_activeTestCase->invoke();
Phil Nasha695eb92012-08-13 07:46:10 +01004599 }
4600 else {
Phil Nash8a52a392013-07-25 08:12:03 +01004601 m_activeTestCase->invoke();
Phil Nasha70fbe32012-08-31 08:10:36 +01004602 }
Phil Nashaa7123b2013-08-15 19:01:00 +01004603 duration = timer.getElapsedSeconds();
Phil Nasha695eb92012-08-13 07:46:10 +01004604 }
4605 catch( TestFailureException& ) {
4606 // This just means the test was aborted due to failure
4607 }
4608 catch(...) {
Phil Nash90a35942012-11-13 22:04:29 +00004609 ExpressionResultBuilder exResult( ResultWas::ThrewException );
4610 exResult << translateActiveException();
4611 actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004612 }
Phil Nash8a52a392013-07-25 08:12:03 +01004613 // If sections ended prematurely due to an exception we stored their
4614 // infos here so we can tear them down outside the unwind process.
Phil Nash5bdae842013-02-19 19:47:18 +00004615 for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
4616 itEnd = m_unfinishedSections.end();
4617 it != itEnd;
4618 ++it )
Phil Nashaa7123b2013-08-15 19:01:00 +01004619 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
Phil Nash5bdae842013-02-19 19:47:18 +00004620 m_unfinishedSections.clear();
Phil Nashd768b1b2013-02-04 00:05:16 +00004621 m_messages.clear();
Phil Nashaa7123b2013-08-15 19:01:00 +01004622
4623 Counts assertions = m_totals.assertions - prevAssertions;
4624 bool missingAssertions = testForMissingAssertions( assertions );
4625
4626 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
Phil Nash8a52a392013-07-25 08:12:03 +01004627 m_reporter->sectionEnded( testCaseSectionStats );
Phil Nasha695eb92012-08-13 07:46:10 +01004628 }
4629
4630 private:
Phil Nash5bdae842013-02-19 19:47:18 +00004631 struct UnfinishedSections {
Phil Nashaa7123b2013-08-15 19:01:00 +01004632 UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
4633 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
Phil Nash5bdae842013-02-19 19:47:18 +00004634 {}
4635
4636 SectionInfo info;
4637 Counts prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01004638 double durationInSeconds;
Phil Nash5bdae842013-02-19 19:47:18 +00004639 };
4640
Phil Nasha1fbfea2012-12-01 23:57:18 +00004641 TestRunInfo m_runInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01004642 IMutableContext& m_context;
Phil Nash8a52a392013-07-25 08:12:03 +01004643 TestCase const* m_activeTestCase;
4644 Option<TestCaseTracker> m_testCaseTracker;
Phil Nashce612bf2012-11-01 08:27:09 +00004645 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01004646
Phil Nash786959d2013-06-07 19:07:50 +01004647 Ptr<IConfig const> m_config;
Phil Nasha695eb92012-08-13 07:46:10 +01004648 Totals m_totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004649 Ptr<IStreamingReporter> m_reporter;
Phil Nasha2773812013-02-02 20:37:58 +00004650 std::vector<MessageInfo> m_messages;
Phil Nasha695eb92012-08-13 07:46:10 +01004651 IRunner* m_prevRunner;
4652 IResultCapture* m_prevResultCapture;
Phil Nash786959d2013-06-07 19:07:50 +01004653 Ptr<IConfig const> m_prevConfig;
Phil Nash90a35942012-11-13 22:04:29 +00004654 AssertionInfo m_lastAssertionInfo;
Phil Nash5bdae842013-02-19 19:47:18 +00004655 std::vector<UnfinishedSections> m_unfinishedSections;
Phil Nasha695eb92012-08-13 07:46:10 +01004656 };
4657
4658} // end namespace Catch
4659
Phil Nash7673a302012-11-15 22:15:41 +00004660// #included from: internal/catch_version.h
4661#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
4662
4663namespace Catch {
4664
4665 // Versioning information
4666 struct Version {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004667 Version( unsigned int _majorVersion,
4668 unsigned int _minorVersion,
4669 unsigned int _buildNumber,
4670 std::string const& _branchName )
4671 : majorVersion( _majorVersion ),
4672 minorVersion( _minorVersion ),
4673 buildNumber( _buildNumber ),
4674 branchName( _branchName )
4675 {}
4676
4677 const unsigned int majorVersion;
4678 const unsigned int minorVersion;
4679 const unsigned int buildNumber;
4680 const std::string branchName;
Phil Nashdd26e882013-03-25 09:25:31 +00004681
Phil Nash503d5d02013-07-03 08:25:11 +01004682 private:
4683 void operator=( Version const& );
Phil Nash7673a302012-11-15 22:15:41 +00004684 };
4685
4686 extern Version libraryVersion;
4687}
4688
Phil Nash89d1e6c2011-05-24 08:23:02 +01004689#include <fstream>
4690#include <stdlib.h>
4691#include <limits>
4692
Phil Nash89d2a3f2012-05-16 15:09:17 +01004693namespace Catch {
4694
Phil Nash786959d2013-06-07 19:07:50 +01004695 class Runner {
Phil Nash163088a2012-05-31 19:40:26 +01004696
Phil Nash56d5c422012-08-23 20:08:50 +01004697 public:
Phil Nash786959d2013-06-07 19:07:50 +01004698 Runner( Ptr<Config> const& config )
4699 : m_config( config )
Phil Nash06e959b2012-05-25 08:52:05 +01004700 {
Phil Nash67ec8702012-09-26 18:38:26 +01004701 openStream();
Phil Nash56d5c422012-08-23 20:08:50 +01004702 makeReporter();
4703 }
Phil Nash06e959b2012-05-25 08:52:05 +01004704
Phil Nash56d5c422012-08-23 20:08:50 +01004705 Totals runTests() {
4706
Phil Nash786959d2013-06-07 19:07:50 +01004707 std::vector<TestCaseFilters> filterGroups = m_config->filters();
Phil Nash56d5c422012-08-23 20:08:50 +01004708 if( filterGroups.empty() ) {
4709 TestCaseFilters filterGroup( "" );
Phil Nash56d5c422012-08-23 20:08:50 +01004710 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004711 }
Phil Nash56d5c422012-08-23 20:08:50 +01004712
Phil Nash786959d2013-06-07 19:07:50 +01004713 RunContext context( m_config.get(), m_reporter );
4714
Phil Nash56d5c422012-08-23 20:08:50 +01004715 Totals totals;
4716
Phil Nash2e7d9662013-01-16 09:44:43 +00004717 for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) {
4718 context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() );
4719 totals += runTestsForGroup( context, filterGroups[i] );
4720 context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() );
Phil Nash56d5c422012-08-23 20:08:50 +01004721 }
4722 return totals;
4723 }
4724
Phil Nash786959d2013-06-07 19:07:50 +01004725 Totals runTestsForGroup( RunContext& context, const TestCaseFilters& filterGroup ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004726 Totals totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004727 std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
4728 std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash56d5c422012-08-23 20:08:50 +01004729 int testsRunForGroup = 0;
4730 for(; it != itEnd; ++it ) {
4731 if( filterGroup.shouldInclude( *it ) ) {
4732 testsRunForGroup++;
4733 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
4734
4735 if( context.aborting() )
4736 break;
4737
4738 totals += context.runTest( *it );
4739 m_testsAlreadyRun.insert( *it );
4740 }
Phil Nash06e959b2012-05-25 08:52:05 +01004741 }
4742 }
Phil Nash5bdae842013-02-19 19:47:18 +00004743 if( testsRunForGroup == 0 && !filterGroup.getName().empty() )
Phil Nash37186a12013-03-13 12:19:30 +00004744 m_reporter->noMatchingTestCases( filterGroup.getName() );
Phil Nash56d5c422012-08-23 20:08:50 +01004745 return totals;
4746
Phil Nash89d1e6c2011-05-24 08:23:02 +01004747 }
Phil Nash56d5c422012-08-23 20:08:50 +01004748
4749 private:
Phil Nash67ec8702012-09-26 18:38:26 +01004750 void openStream() {
Phil Nash56d5c422012-08-23 20:08:50 +01004751 // Open output file, if specified
Phil Nash786959d2013-06-07 19:07:50 +01004752 if( !m_config->getFilename().empty() ) {
4753 m_ofs.open( m_config->getFilename().c_str() );
Phil Nash56d5c422012-08-23 20:08:50 +01004754 if( m_ofs.fail() ) {
4755 std::ostringstream oss;
Phil Nash786959d2013-06-07 19:07:50 +01004756 oss << "Unable to open file: '" << m_config->getFilename() << "'";
Phil Nash56d5c422012-08-23 20:08:50 +01004757 throw std::domain_error( oss.str() );
4758 }
Phil Nash786959d2013-06-07 19:07:50 +01004759 m_config->setStreamBuf( m_ofs.rdbuf() );
Phil Nash56d5c422012-08-23 20:08:50 +01004760 }
4761 }
4762 void makeReporter() {
Phil Nash786959d2013-06-07 19:07:50 +01004763 std::string reporterName = m_config->getReporterName().empty()
4764 ? "console"
4765 : m_config->getReporterName();
Phil Nash56d5c422012-08-23 20:08:50 +01004766
Phil Nash786959d2013-06-07 19:07:50 +01004767 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
Phil Nash56d5c422012-08-23 20:08:50 +01004768 if( !m_reporter ) {
4769 std::ostringstream oss;
4770 oss << "No reporter registered with name: '" << reporterName << "'";
4771 throw std::domain_error( oss.str() );
4772 }
4773 }
4774
4775 private:
Phil Nash786959d2013-06-07 19:07:50 +01004776 Ptr<Config> m_config;
Phil Nash56d5c422012-08-23 20:08:50 +01004777 std::ofstream m_ofs;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004778 Ptr<IStreamingReporter> m_reporter;
4779 std::set<TestCase> m_testsAlreadyRun;
Phil Nash56d5c422012-08-23 20:08:50 +01004780 };
4781
Phil Nash786959d2013-06-07 19:07:50 +01004782 class Session {
4783 static bool alreadyInstantiated;
Phil Nash56d5c422012-08-23 20:08:50 +01004784
Phil Nash786959d2013-06-07 19:07:50 +01004785 public:
Phil Nash56d5c422012-08-23 20:08:50 +01004786
Phil Nash786959d2013-06-07 19:07:50 +01004787 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
4788
4789 Session()
4790 : m_cli( makeCommandLineParser() ) {
4791 if( alreadyInstantiated ) {
4792 std::string msg = "Only one instance of Catch::Session can ever be used";
4793 std::cerr << msg << std::endl;
4794 throw std::logic_error( msg );
Phil Nash56d5c422012-08-23 20:08:50 +01004795 }
Phil Nash786959d2013-06-07 19:07:50 +01004796 alreadyInstantiated = true;
Phil Nash56d5c422012-08-23 20:08:50 +01004797 }
Phil Nash786959d2013-06-07 19:07:50 +01004798 ~Session() {
Phil Nash3b80af72012-08-09 07:47:30 +01004799 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004800 }
4801
Phil Nash786959d2013-06-07 19:07:50 +01004802 void showHelp( std::string const& processName ) {
4803 std::cout << "\nCatch v" << libraryVersion.majorVersion << "."
Phil Nasha1fbfea2012-12-01 23:57:18 +00004804 << libraryVersion.minorVersion << " build "
4805 << libraryVersion.buildNumber;
4806 if( libraryVersion.branchName != "master" )
4807 std::cout << " (" << libraryVersion.branchName << " branch)";
Phil Nash786959d2013-06-07 19:07:50 +01004808 std::cout << "\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01004809
Phil Nash786959d2013-06-07 19:07:50 +01004810 m_cli.usage( std::cout, processName );
4811 std::cout << "For more detail usage please see the project docs\n" << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01004812 }
Phil Nash3b80af72012-08-09 07:47:30 +01004813
Phil Nash786959d2013-06-07 19:07:50 +01004814 int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
4815 try {
4816 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
4817 if( unusedOptionBehaviour == OnUnusedOptions::Fail )
4818 enforceNoUsedTokens();
4819 if( m_configData.showHelp )
4820 showHelp( m_configData.processName );
4821 m_config.reset();
Phil Nash3b80af72012-08-09 07:47:30 +01004822 }
Phil Nash786959d2013-06-07 19:07:50 +01004823 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01004824 {
4825 Colour colourGuard( Colour::Red );
4826 std::cerr << "\nError in input:\n"
4827 << Text( ex.what(), TextAttributes().setIndent(2) )
4828 << "\n\n";
4829 }
Phil Nash786959d2013-06-07 19:07:50 +01004830 m_cli.usage( std::cout, m_configData.processName );
4831 return (std::numeric_limits<int>::max)();
4832 }
4833 return 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004834 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01004835
Phil Nash786959d2013-06-07 19:07:50 +01004836 void useConfigData( ConfigData const& _configData ) {
4837 m_configData = _configData;
4838 m_config.reset();
4839 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004840
Phil Nash786959d2013-06-07 19:07:50 +01004841 void enforceNoUsedTokens() const {
4842 if( !m_unusedTokens.empty() ) {
4843 std::vector<Clara::Parser::Token>::const_iterator
4844 it = m_unusedTokens.begin(),
4845 itEnd = m_unusedTokens.end();
4846 std::string msg;
4847 for(; it != itEnd; ++it )
4848 msg += " unrecognised option: " + it->data + "\n";
4849 throw std::runtime_error( msg.substr( 0, msg.size()-1 ) );
4850 }
4851 }
4852
4853 int run( int argc, char* const argv[] ) {
4854
4855 int returnCode = applyCommandLine( argc, argv );
4856 if( returnCode == 0 )
4857 returnCode = run();
4858 return returnCode;
4859 }
4860
4861 int run() {
4862 if( m_configData.showHelp )
4863 return 0;
4864
4865 try
4866 {
4867 config(); // Force config to be constructed
4868 Runner runner( m_config );
4869
4870 // Handle list request
4871 if( Option<std::size_t> listed = list( config() ) )
4872 return static_cast<int>( *listed );
4873
4874 return static_cast<int>( runner.runTests().assertions.failed );
4875 }
4876 catch( std::exception& ex ) {
4877 std::cerr << ex.what() << std::endl;
4878 return (std::numeric_limits<int>::max)();
4879 }
4880 }
4881
4882 Clara::CommandLine<ConfigData> const& cli() const {
4883 return m_cli;
4884 }
4885 std::vector<Clara::Parser::Token> const& unusedTokens() const {
4886 return m_unusedTokens;
4887 }
4888 ConfigData& configData() {
4889 return m_configData;
4890 }
4891 Config& config() {
4892 if( !m_config )
4893 m_config = new Config( m_configData );
4894 return *m_config;
4895 }
4896
4897 private:
4898 Clara::CommandLine<ConfigData> m_cli;
4899 std::vector<Clara::Parser::Token> m_unusedTokens;
4900 ConfigData m_configData;
4901 Ptr<Config> m_config;
4902 };
4903
4904 bool Session::alreadyInstantiated = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004905
4906} // end namespace Catch
4907
4908// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004909#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01004910
Phil Nash89d1e6c2011-05-24 08:23:02 +01004911// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004912#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01004913
4914#include <vector>
4915#include <set>
Phil Nash3b80af72012-08-09 07:47:30 +01004916#include <sstream>
4917#include <iostream>
4918
4919namespace Catch {
4920
4921 class TestRegistry : public ITestCaseRegistry {
4922 public:
4923 TestRegistry() : m_unnamedCount( 0 ) {}
4924 virtual ~TestRegistry();
4925
Phil Nash8defc712013-04-24 19:10:02 +01004926 virtual void registerTest( TestCase const& testCase ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004927 std::string name = testCase.getTestCaseInfo().name;
4928 if( name == "" ) {
Phil Nash3b80af72012-08-09 07:47:30 +01004929 std::ostringstream oss;
Phil Nash93906752013-03-16 20:21:51 +00004930 oss << "Anonymous test case " << ++m_unnamedCount;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004931 return registerTest( testCase.withName( oss.str() ) );
Phil Nash3b80af72012-08-09 07:47:30 +01004932 }
4933
Phil Nasha1fbfea2012-12-01 23:57:18 +00004934 if( m_functions.find( testCase ) == m_functions.end() ) {
4935 m_functions.insert( testCase );
4936 m_functionsInOrder.push_back( testCase );
4937 if( !testCase.isHidden() )
4938 m_nonHiddenFunctions.push_back( testCase );
Phil Nash3b80af72012-08-09 07:47:30 +01004939 }
4940 else {
Phil Nash8defc712013-04-24 19:10:02 +01004941 TestCase const& prev = *m_functions.find( testCase );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004942 std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
Phil Nash5ecb72b2013-11-26 20:57:45 +00004943 << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
4944 << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01004945 exit(1);
4946 }
4947 }
4948
Phil Nash8defc712013-04-24 19:10:02 +01004949 virtual std::vector<TestCase> const& getAllTests() const {
Phil Nash3b80af72012-08-09 07:47:30 +01004950 return m_functionsInOrder;
4951 }
4952
Phil Nash8defc712013-04-24 19:10:02 +01004953 virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
Phil Nash3b80af72012-08-09 07:47:30 +01004954 return m_nonHiddenFunctions;
4955 }
4956
4957 // !TBD deprecated
Phil Nash8defc712013-04-24 19:10:02 +01004958 virtual std::vector<TestCase> getMatchingTestCases( std::string const& rawTestSpec ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004959 std::vector<TestCase> matchingTests;
Phil Nash3b80af72012-08-09 07:47:30 +01004960 getMatchingTestCases( rawTestSpec, matchingTests );
4961 return matchingTests;
4962 }
4963
4964 // !TBD deprecated
Phil Nash8defc712013-04-24 19:10:02 +01004965 virtual void getMatchingTestCases( std::string const& rawTestSpec, std::vector<TestCase>& matchingTestsOut ) const {
Phil Nash3b80af72012-08-09 07:47:30 +01004966 TestCaseFilter filter( rawTestSpec );
4967
Phil Nasha1fbfea2012-12-01 23:57:18 +00004968 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
4969 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
Phil Nash3b80af72012-08-09 07:47:30 +01004970 for(; it != itEnd; ++it ) {
4971 if( filter.shouldInclude( *it ) ) {
4972 matchingTestsOut.push_back( *it );
4973 }
4974 }
4975 }
Phil Nash8defc712013-04-24 19:10:02 +01004976 virtual void getMatchingTestCases( TestCaseFilters const& filters, std::vector<TestCase>& matchingTestsOut ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004977 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
4978 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
Phil Nash3b80af72012-08-09 07:47:30 +01004979 // !TBD: replace with algorithm
4980 for(; it != itEnd; ++it )
4981 if( filters.shouldInclude( *it ) )
4982 matchingTestsOut.push_back( *it );
4983 }
4984
4985 private:
4986
Phil Nasha1fbfea2012-12-01 23:57:18 +00004987 std::set<TestCase> m_functions;
4988 std::vector<TestCase> m_functionsInOrder;
4989 std::vector<TestCase> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01004990 size_t m_unnamedCount;
4991 };
4992
4993 ///////////////////////////////////////////////////////////////////////////
4994
4995 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
4996 public:
4997
4998 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
4999
5000 virtual void invoke() const {
5001 m_fun();
5002 }
5003
5004 private:
5005 virtual ~FreeFunctionTestCase();
5006
5007 TestFunction m_fun;
5008 };
5009
Phil Nash8defc712013-04-24 19:10:02 +01005010 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
Phil Nash90a35942012-11-13 22:04:29 +00005011 std::string className = classOrQualifiedMethodName;
Phil Nashf7378ee2013-09-07 12:07:38 +01005012 if( startsWith( className, "&" ) )
Phil Nash90a35942012-11-13 22:04:29 +00005013 {
5014 std::size_t lastColons = className.rfind( "::" );
5015 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
5016 if( penultimateColons == std::string::npos )
5017 penultimateColons = 1;
5018 className = className.substr( penultimateColons, lastColons-penultimateColons );
5019 }
5020 return className;
5021 }
5022
Phil Nash3b80af72012-08-09 07:47:30 +01005023 ///////////////////////////////////////////////////////////////////////////
5024
5025 AutoReg::AutoReg( TestFunction function,
Phil Nash93906752013-03-16 20:21:51 +00005026 SourceLineInfo const& lineInfo,
5027 NameAndDesc const& nameAndDesc ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01005028 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01005029 }
5030
5031 AutoReg::~AutoReg() {}
5032
5033 void AutoReg::registerTestCase( ITestCase* testCase,
Phil Nash93906752013-03-16 20:21:51 +00005034 char const* classOrQualifiedMethodName,
5035 NameAndDesc const& nameAndDesc,
5036 SourceLineInfo const& lineInfo ) {
Phil Nash90a35942012-11-13 22:04:29 +00005037
Phil Nash93906752013-03-16 20:21:51 +00005038 getMutableRegistryHub().registerTest
5039 ( makeTestCase( testCase,
5040 extractClassName( classOrQualifiedMethodName ),
5041 nameAndDesc.name,
5042 nameAndDesc.description,
5043 lineInfo ) );
Phil Nash3b80af72012-08-09 07:47:30 +01005044 }
5045
5046} // end namespace Catch
5047
5048// #included from: catch_reporter_registry.hpp
5049#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
5050
5051#include <map>
5052
5053namespace Catch {
5054
5055 class ReporterRegistry : public IReporterRegistry {
5056
5057 public:
5058
5059 virtual ~ReporterRegistry() {
5060 deleteAllValues( m_factories );
5061 }
5062
Phil Nash786959d2013-06-07 19:07:50 +01005063 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
Phil Nash3b80af72012-08-09 07:47:30 +01005064 FactoryMap::const_iterator it = m_factories.find( name );
5065 if( it == m_factories.end() )
5066 return NULL;
Phil Nash786959d2013-06-07 19:07:50 +01005067 return it->second->create( ReporterConfig( config ) );
Phil Nash3b80af72012-08-09 07:47:30 +01005068 }
5069
Phil Nash8defc712013-04-24 19:10:02 +01005070 void registerReporter( std::string const& name, IReporterFactory* factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005071 m_factories.insert( std::make_pair( name, factory ) );
5072 }
5073
Phil Nash8defc712013-04-24 19:10:02 +01005074 FactoryMap const& getFactories() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005075 return m_factories;
5076 }
5077
5078 private:
5079 FactoryMap m_factories;
5080 };
5081}
5082
5083// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005084#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005085
5086#ifdef __OBJC__
5087#import "Foundation/Foundation.h"
5088#endif
5089
5090namespace Catch {
5091
5092 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
5093 public:
5094 ~ExceptionTranslatorRegistry() {
5095 deleteAll( m_translators );
5096 }
5097
5098 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5099 m_translators.push_back( translator );
5100 }
5101
5102 virtual std::string translateActiveException() const {
5103 try {
5104#ifdef __OBJC__
5105 // In Objective-C try objective-c exceptions first
5106 @try {
5107 throw;
5108 }
5109 @catch (NSException *exception) {
5110 return toString( [exception description] );
5111 }
5112#else
5113 throw;
5114#endif
5115 }
5116 catch( std::exception& ex ) {
5117 return ex.what();
5118 }
5119 catch( std::string& msg ) {
5120 return msg;
5121 }
5122 catch( const char* msg ) {
5123 return msg;
5124 }
5125 catch(...) {
5126 return tryTranslators( m_translators.begin() );
5127 }
5128 }
5129
5130 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
5131 if( it == m_translators.end() )
5132 return "Unknown exception";
5133
5134 try {
5135 return (*it)->translate();
5136 }
5137 catch(...) {
5138 return tryTranslators( it+1 );
5139 }
5140 }
5141
5142 private:
5143 std::vector<const IExceptionTranslator*> m_translators;
5144 };
5145}
5146
5147namespace Catch {
5148
5149 namespace {
5150
5151 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
5152
Phil Nash8defc712013-04-24 19:10:02 +01005153 RegistryHub( RegistryHub const& );
5154 void operator=( RegistryHub const& );
Phil Nash3b80af72012-08-09 07:47:30 +01005155
5156 public: // IRegistryHub
5157 RegistryHub() {
5158 }
Phil Nash8defc712013-04-24 19:10:02 +01005159 virtual IReporterRegistry const& getReporterRegistry() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005160 return m_reporterRegistry;
5161 }
Phil Nash8defc712013-04-24 19:10:02 +01005162 virtual ITestCaseRegistry const& getTestCaseRegistry() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005163 return m_testCaseRegistry;
5164 }
5165 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
5166 return m_exceptionTranslatorRegistry;
5167 }
5168
5169 public: // IMutableRegistryHub
Phil Nash8defc712013-04-24 19:10:02 +01005170 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005171 m_reporterRegistry.registerReporter( name, factory );
5172 }
Phil Nash8defc712013-04-24 19:10:02 +01005173 virtual void registerTest( TestCase const& testInfo ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005174 m_testCaseRegistry.registerTest( testInfo );
5175 }
5176 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5177 m_exceptionTranslatorRegistry.registerTranslator( translator );
5178 }
5179
5180 private:
5181 TestRegistry m_testCaseRegistry;
5182 ReporterRegistry m_reporterRegistry;
5183 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5184 };
5185
5186 // Single, global, instance
5187 inline RegistryHub*& getTheRegistryHub() {
5188 static RegistryHub* theRegistryHub = NULL;
5189 if( !theRegistryHub )
5190 theRegistryHub = new RegistryHub();
5191 return theRegistryHub;
5192 }
5193 }
5194
5195 IRegistryHub& getRegistryHub() {
5196 return *getTheRegistryHub();
5197 }
5198 IMutableRegistryHub& getMutableRegistryHub() {
5199 return *getTheRegistryHub();
5200 }
5201 void cleanUp() {
5202 delete getTheRegistryHub();
5203 getTheRegistryHub() = NULL;
5204 cleanUpContext();
5205 }
Phil Nashce612bf2012-11-01 08:27:09 +00005206 std::string translateActiveException() {
5207 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
5208 }
Phil Nash3b80af72012-08-09 07:47:30 +01005209
5210} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04005211
Phil Nash3b80af72012-08-09 07:47:30 +01005212// #included from: catch_notimplemented_exception.hpp
5213#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
5214
5215#include <ostream>
5216
5217namespace Catch {
5218
Phil Nash8defc712013-04-24 19:10:02 +01005219 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
Phil Nash3b80af72012-08-09 07:47:30 +01005220 : m_lineInfo( lineInfo ) {
5221 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +00005222 oss << lineInfo << ": function ";
Phil Nash3b80af72012-08-09 07:47:30 +01005223 oss << "not implemented";
5224 m_what = oss.str();
5225 }
5226
5227 const char* NotImplementedException::what() const throw() {
5228 return m_what.c_str();
5229 }
5230
5231} // end namespace Catch
5232
5233// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005234#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005235
Phil Nash3649fdf2013-12-03 18:53:55 +00005236// #included from: catch_stream.hpp
5237#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
5238
5239// #included from: catch_streambuf.h
5240#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
5241
5242#include <streambuf>
5243
5244namespace Catch {
5245
5246 class StreamBufBase : public std::streambuf {
5247 public:
5248 virtual ~StreamBufBase() throw();
5249 };
5250}
5251
5252#include <stdexcept>
5253#include <cstdio>
5254
5255namespace Catch {
5256
5257 template<typename WriterF, size_t bufferSize=256>
5258 class StreamBufImpl : public StreamBufBase {
5259 char data[bufferSize];
5260 WriterF m_writer;
5261
5262 public:
5263 StreamBufImpl() {
5264 setp( data, data + sizeof(data) );
5265 }
5266
5267 ~StreamBufImpl() throw() {
5268 sync();
5269 }
5270
5271 private:
5272 int overflow( int c ) {
5273 sync();
5274
5275 if( c != EOF ) {
5276 if( pbase() == epptr() )
5277 m_writer( std::string( 1, static_cast<char>( c ) ) );
5278 else
5279 sputc( static_cast<char>( c ) );
5280 }
5281 return 0;
5282 }
5283
5284 int sync() {
5285 if( pbase() != pptr() ) {
5286 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
5287 setp( pbase(), epptr() );
5288 }
5289 return 0;
5290 }
5291 };
5292
5293 ///////////////////////////////////////////////////////////////////////////
5294
5295 struct OutputDebugWriter {
5296
5297 void operator()( std::string const&str ) {
5298 writeToDebugConsole( str );
5299 }
5300 };
5301
5302 Stream::Stream()
5303 : streamBuf( NULL ), isOwned( false )
5304 {}
5305
5306 Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
5307 : streamBuf( _streamBuf ), isOwned( _isOwned )
5308 {}
5309
5310 void Stream::release() {
5311 if( isOwned ) {
5312 delete streamBuf;
5313 streamBuf = NULL;
5314 isOwned = false;
5315 }
5316 }
5317}
5318
Phil Nash3b80af72012-08-09 07:47:30 +01005319namespace Catch {
5320
5321 class Context : public IMutableContext {
5322
Phil Nash93a945c2013-10-23 15:35:07 +01005323 Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
Phil Nash8defc712013-04-24 19:10:02 +01005324 Context( Context const& );
5325 void operator=( Context const& );
Phil Nash3b80af72012-08-09 07:47:30 +01005326
5327 public: // IContext
5328 virtual IResultCapture& getResultCapture() {
5329 return *m_resultCapture;
5330 }
5331 virtual IRunner& getRunner() {
5332 return *m_runner;
5333 }
Phil Nash8defc712013-04-24 19:10:02 +01005334 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005335 return getGeneratorsForCurrentTest()
5336 .getGeneratorInfo( fileInfo, totalSize )
5337 .getCurrentIndex();
5338 }
5339 virtual bool advanceGeneratorsForCurrentTest() {
5340 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5341 return generators && generators->moveNext();
5342 }
5343
Phil Nash786959d2013-06-07 19:07:50 +01005344 virtual Ptr<IConfig const> getConfig() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005345 return m_config;
5346 }
5347
5348 public: // IMutableContext
5349 virtual void setResultCapture( IResultCapture* resultCapture ) {
5350 m_resultCapture = resultCapture;
5351 }
5352 virtual void setRunner( IRunner* runner ) {
5353 m_runner = runner;
5354 }
Phil Nash786959d2013-06-07 19:07:50 +01005355 virtual void setConfig( Ptr<IConfig const> const& config ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005356 m_config = config;
5357 }
5358
5359 friend IMutableContext& getCurrentMutableContext();
5360
5361 private:
5362 IGeneratorsForTest* findGeneratorsForCurrentTest() {
5363 std::string testName = getResultCapture().getCurrentTestName();
5364
5365 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
5366 m_generatorsByTestName.find( testName );
5367 return it != m_generatorsByTestName.end()
Phil Nash8a52a392013-07-25 08:12:03 +01005368 ? it->second
5369 : NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01005370 }
5371
5372 IGeneratorsForTest& getGeneratorsForCurrentTest() {
5373 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5374 if( !generators ) {
5375 std::string testName = getResultCapture().getCurrentTestName();
5376 generators = createGeneratorsForTest();
5377 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
5378 }
5379 return *generators;
5380 }
5381
5382 private:
Phil Nash93a945c2013-10-23 15:35:07 +01005383 Ptr<IConfig const> m_config;
Phil Nash3b80af72012-08-09 07:47:30 +01005384 IRunner* m_runner;
5385 IResultCapture* m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01005386 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
5387 };
5388
5389 namespace {
5390 Context* currentContext = NULL;
5391 }
5392 IMutableContext& getCurrentMutableContext() {
5393 if( !currentContext )
5394 currentContext = new Context();
5395 return *currentContext;
5396 }
5397 IContext& getCurrentContext() {
5398 return getCurrentMutableContext();
5399 }
5400
Phil Nash8defc712013-04-24 19:10:02 +01005401 Stream createStream( std::string const& streamName ) {
Phil Nash67ec8702012-09-26 18:38:26 +01005402 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
5403 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
5404 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
Phil Nash3b80af72012-08-09 07:47:30 +01005405
5406 throw std::domain_error( "Unknown stream: " + streamName );
5407 }
5408
5409 void cleanUpContext() {
5410 delete currentContext;
5411 currentContext = NULL;
5412 }
5413}
Matt Wozniskif29c8982012-09-17 01:42:29 -04005414
Phil Nash3b80af72012-08-09 07:47:30 +01005415// #included from: catch_console_colour_impl.hpp
5416#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
5417
Phil Nash12c16ff2013-04-05 20:58:01 +01005418namespace Catch { namespace Detail {
5419 struct IColourImpl {
5420 virtual ~IColourImpl() {}
5421 virtual void use( Colour::Code _colourCode ) = 0;
5422 };
5423}}
5424
Phil Nash3df6c0d2013-03-11 18:38:29 +00005425#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01005426
Phil Nash4b5e0082013-06-29 20:31:17 +01005427#ifndef NOMINMAX
Phil Nash23520432013-06-28 14:11:28 +01005428#define NOMINMAX
Phil Nash4b5e0082013-06-29 20:31:17 +01005429#endif
Phil Nash39075592013-07-01 19:02:29 +01005430
5431#ifdef __AFXDLL
5432#include <AfxWin.h>
5433#else
Phil Nash3b80af72012-08-09 07:47:30 +01005434#include <windows.h>
Phil Nash39075592013-07-01 19:02:29 +01005435#endif
Phil Nash3b80af72012-08-09 07:47:30 +01005436
5437namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00005438namespace {
Phil Nash3b80af72012-08-09 07:47:30 +01005439
Phil Nash12c16ff2013-04-05 20:58:01 +01005440 class Win32ColourImpl : public Detail::IColourImpl {
Phil Nash3b80af72012-08-09 07:47:30 +01005441 public:
Phil Nash12c16ff2013-04-05 20:58:01 +01005442 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
Phil Nash3b80af72012-08-09 07:47:30 +01005443 {
Phil Nash12c16ff2013-04-05 20:58:01 +01005444 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
5445 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
5446 originalAttributes = csbiInfo.wAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01005447 }
Phil Nash3b80af72012-08-09 07:47:30 +01005448
Phil Nash12c16ff2013-04-05 20:58:01 +01005449 virtual void use( Colour::Code _colourCode ) {
5450 switch( _colourCode ) {
5451 case Colour::None: return setTextAttribute( originalAttributes );
5452 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5453 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
5454 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
5455 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
5456 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
5457 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
5458 case Colour::Grey: return setTextAttribute( 0 );
Phil Nash3b80af72012-08-09 07:47:30 +01005459
Phil Nash12c16ff2013-04-05 20:58:01 +01005460 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
5461 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
5462 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
Phil Nash23520432013-06-28 14:11:28 +01005463 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
Phil Nash3b80af72012-08-09 07:47:30 +01005464
Phil Nash12c16ff2013-04-05 20:58:01 +01005465 case Colour::Bright: throw std::logic_error( "not a colour" );
5466 }
Phil Nash3b80af72012-08-09 07:47:30 +01005467 }
Phil Nash3b80af72012-08-09 07:47:30 +01005468
5469 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01005470 void setTextAttribute( WORD _textAttribute ) {
5471 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
Phil Nash3b80af72012-08-09 07:47:30 +01005472 }
Phil Nash12c16ff2013-04-05 20:58:01 +01005473 HANDLE stdoutHandle;
5474 WORD originalAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01005475 };
5476
Phil Nash3df6c0d2013-03-11 18:38:29 +00005477 inline bool shouldUseColourForPlatform() {
5478 return true;
5479 }
5480
Phil Nash12c16ff2013-04-05 20:58:01 +01005481 Win32ColourImpl platformColourImpl;
Phil Nash3df6c0d2013-03-11 18:38:29 +00005482
5483} // end anon namespace
Phil Nash3b80af72012-08-09 07:47:30 +01005484} // end namespace Catch
5485
Phil Nash3df6c0d2013-03-11 18:38:29 +00005486#else // Not Windows - assumed to be POSIX compatible //////////////////////////
Phil Nashce612bf2012-11-01 08:27:09 +00005487
5488#include <unistd.h>
5489
5490namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00005491namespace {
Phil Nashce612bf2012-11-01 08:27:09 +00005492
5493 // use POSIX/ ANSI console terminal codes
Phil Nash12c16ff2013-04-05 20:58:01 +01005494 // Thanks to Adam Strzelecki for original contribution
5495 // (http://github.com/nanoant)
Phil Nashce612bf2012-11-01 08:27:09 +00005496 // https://github.com/philsquared/Catch/pull/131
Phil Nash12c16ff2013-04-05 20:58:01 +01005497 class PosixColourImpl : public Detail::IColourImpl {
5498 public:
5499 virtual void use( Colour::Code _colourCode ) {
5500 switch( _colourCode ) {
5501 case Colour::None:
5502 case Colour::White: return setColour( "[0m" );
5503 case Colour::Red: return setColour( "[0;31m" );
5504 case Colour::Green: return setColour( "[0;32m" );
5505 case Colour::Blue: return setColour( "[0:34m" );
5506 case Colour::Cyan: return setColour( "[0;36m" );
5507 case Colour::Yellow: return setColour( "[0;33m" );
5508 case Colour::Grey: return setColour( "[1;30m" );
Phil Nashce612bf2012-11-01 08:27:09 +00005509
Phil Nash12c16ff2013-04-05 20:58:01 +01005510 case Colour::LightGrey: return setColour( "[0;37m" );
5511 case Colour::BrightRed: return setColour( "[1;31m" );
Phil Nash243f2d22013-04-12 10:43:06 +01005512 case Colour::BrightGreen: return setColour( "[1;32m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01005513 case Colour::BrightWhite: return setColour( "[1;37m" );
Phil Nashce612bf2012-11-01 08:27:09 +00005514
Phil Nash12c16ff2013-04-05 20:58:01 +01005515 case Colour::Bright: throw std::logic_error( "not a colour" );
Phil Nashce612bf2012-11-01 08:27:09 +00005516 }
5517 }
Phil Nash12c16ff2013-04-05 20:58:01 +01005518 private:
5519 void setColour( const char* _escapeCode ) {
5520 std::cout << '\033' << _escapeCode;
Phil Nash3df6c0d2013-03-11 18:38:29 +00005521 }
5522 };
5523
5524 inline bool shouldUseColourForPlatform() {
Phil Nash3649fdf2013-12-03 18:53:55 +00005525 return isatty(STDOUT_FILENO);
Phil Nashce612bf2012-11-01 08:27:09 +00005526 }
5527
Phil Nash12c16ff2013-04-05 20:58:01 +01005528 PosixColourImpl platformColourImpl;
Phil Nashce612bf2012-11-01 08:27:09 +00005529
Phil Nash12c16ff2013-04-05 20:58:01 +01005530} // end anon namespace
5531} // end namespace Catch
Phil Nash3b80af72012-08-09 07:47:30 +01005532
Phil Nash3df6c0d2013-03-11 18:38:29 +00005533#endif // not Windows
Phil Nash3b80af72012-08-09 07:47:30 +01005534
5535namespace Catch {
5536
5537 namespace {
Phil Nash12c16ff2013-04-05 20:58:01 +01005538 struct NoColourImpl : Detail::IColourImpl {
5539 void use( Colour::Code ) {}
5540 };
5541 NoColourImpl noColourImpl;
5542 static const bool shouldUseColour = shouldUseColourForPlatform() &&
5543 !isDebuggerActive();
Phil Nash3b80af72012-08-09 07:47:30 +01005544 }
5545
Phil Nash12c16ff2013-04-05 20:58:01 +01005546 Colour::Colour( Code _colourCode ){ use( _colourCode ); }
5547 Colour::~Colour(){ use( None ); }
5548 void Colour::use( Code _colourCode ) {
5549 impl->use( _colourCode );
Phil Nash3b80af72012-08-09 07:47:30 +01005550 }
5551
Phil Nash12c16ff2013-04-05 20:58:01 +01005552 Detail::IColourImpl* Colour::impl = shouldUseColour
5553 ? static_cast<Detail::IColourImpl*>( &platformColourImpl )
5554 : static_cast<Detail::IColourImpl*>( &noColourImpl );
Phil Nash3b80af72012-08-09 07:47:30 +01005555
5556} // end namespace Catch
5557
Phil Nash3b80af72012-08-09 07:47:30 +01005558// #included from: catch_generators_impl.hpp
5559#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
5560
5561#include <vector>
5562#include <string>
5563#include <map>
5564
5565namespace Catch {
5566
5567 struct GeneratorInfo : IGeneratorInfo {
5568
5569 GeneratorInfo( std::size_t size )
5570 : m_size( size ),
5571 m_currentIndex( 0 )
5572 {}
5573
5574 bool moveNext() {
5575 if( ++m_currentIndex == m_size ) {
5576 m_currentIndex = 0;
5577 return false;
5578 }
5579 return true;
5580 }
5581
5582 std::size_t getCurrentIndex() const {
5583 return m_currentIndex;
5584 }
5585
5586 std::size_t m_size;
5587 std::size_t m_currentIndex;
5588 };
5589
5590 ///////////////////////////////////////////////////////////////////////////
5591
5592 class GeneratorsForTest : public IGeneratorsForTest {
5593
5594 public:
5595 ~GeneratorsForTest() {
5596 deleteAll( m_generatorsInOrder );
5597 }
5598
Phil Nash8defc712013-04-24 19:10:02 +01005599 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005600 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
5601 if( it == m_generatorsByName.end() ) {
5602 IGeneratorInfo* info = new GeneratorInfo( size );
5603 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
5604 m_generatorsInOrder.push_back( info );
5605 return *info;
5606 }
5607 return *it->second;
5608 }
5609
5610 bool moveNext() {
5611 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
5612 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
5613 for(; it != itEnd; ++it ) {
5614 if( (*it)->moveNext() )
5615 return true;
5616 }
5617 return false;
5618 }
5619
5620 private:
5621 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
5622 std::vector<IGeneratorInfo*> m_generatorsInOrder;
5623 };
5624
5625 IGeneratorsForTest* createGeneratorsForTest()
5626 {
5627 return new GeneratorsForTest();
5628 }
5629
5630} // end namespace Catch
5631
Phil Nashce612bf2012-11-01 08:27:09 +00005632// #included from: catch_assertionresult.hpp
5633#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005634
5635namespace Catch {
5636
Phil Nash8defc712013-04-24 19:10:02 +01005637 AssertionInfo::AssertionInfo( std::string const& _macroName,
5638 SourceLineInfo const& _lineInfo,
5639 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +00005640 ResultDisposition::Flags _resultDisposition )
5641 : macroName( _macroName ),
5642 lineInfo( _lineInfo ),
5643 capturedExpression( _capturedExpression ),
5644 resultDisposition( _resultDisposition )
Phil Nash786959d2013-06-07 19:07:50 +01005645 {}
Phil Nash90a35942012-11-13 22:04:29 +00005646
Phil Nashce612bf2012-11-01 08:27:09 +00005647 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005648
Phil Nash8defc712013-04-24 19:10:02 +01005649 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
Phil Nashce612bf2012-11-01 08:27:09 +00005650 : m_info( info ),
5651 m_resultData( data )
5652 {}
Phil Nash3b80af72012-08-09 07:47:30 +01005653
Phil Nashce612bf2012-11-01 08:27:09 +00005654 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005655
Phil Nash90a35942012-11-13 22:04:29 +00005656 // Result was a success
5657 bool AssertionResult::succeeded() const {
5658 return Catch::isOk( m_resultData.resultType );
5659 }
5660
5661 // Result was a success, or failure is suppressed
5662 bool AssertionResult::isOk() const {
5663 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01005664 }
5665
Phil Nashce612bf2012-11-01 08:27:09 +00005666 ResultWas::OfType AssertionResult::getResultType() const {
5667 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01005668 }
5669
Phil Nashce612bf2012-11-01 08:27:09 +00005670 bool AssertionResult::hasExpression() const {
5671 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005672 }
5673
Phil Nashce612bf2012-11-01 08:27:09 +00005674 bool AssertionResult::hasMessage() const {
5675 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005676 }
5677
Phil Nashce612bf2012-11-01 08:27:09 +00005678 std::string AssertionResult::getExpression() const {
Phil Nash786959d2013-06-07 19:07:50 +01005679 if( shouldNegate( m_info.resultDisposition ) )
5680 return "!" + m_info.capturedExpression;
5681 else
5682 return m_info.capturedExpression;
5683 }
5684 std::string AssertionResult::getExpressionInMacro() const {
5685 if( m_info.macroName.empty() )
5686 return m_info.capturedExpression;
5687 else
5688 return m_info.macroName + "( " + m_info.capturedExpression + " )";
Phil Nash3b80af72012-08-09 07:47:30 +01005689 }
5690
Phil Nashce612bf2012-11-01 08:27:09 +00005691 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005692 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01005693 }
5694
Phil Nashce612bf2012-11-01 08:27:09 +00005695 std::string AssertionResult::getExpandedExpression() const {
5696 return m_resultData.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005697 }
5698
Phil Nashce612bf2012-11-01 08:27:09 +00005699 std::string AssertionResult::getMessage() const {
5700 return m_resultData.message;
5701 }
5702 SourceLineInfo AssertionResult::getSourceInfo() const {
5703 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01005704 }
5705
Phil Nashce612bf2012-11-01 08:27:09 +00005706 std::string AssertionResult::getTestMacroName() const {
5707 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01005708 }
5709
5710} // end namespace Catch
5711
Phil Nashce612bf2012-11-01 08:27:09 +00005712// #included from: catch_expressionresult_builder.hpp
5713#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
5714
5715#include <assert.h>
Phil Nash3b80af72012-08-09 07:47:30 +01005716
5717namespace Catch {
5718
Phil Nashce612bf2012-11-01 08:27:09 +00005719 ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
5720 m_data.resultType = resultType;
Phil Nash67305122012-10-09 11:48:55 +01005721 }
Phil Nash8defc712013-04-24 19:10:02 +01005722 ExpressionResultBuilder::ExpressionResultBuilder( ExpressionResultBuilder const& other )
Phil Nashce612bf2012-11-01 08:27:09 +00005723 : m_data( other.m_data ),
5724 m_exprComponents( other.m_exprComponents )
Phil Nash67305122012-10-09 11:48:55 +01005725 {
Phil Nashce612bf2012-11-01 08:27:09 +00005726 m_stream << other.m_stream.str();
Phil Nash3b80af72012-08-09 07:47:30 +01005727 }
Phil Nash8defc712013-04-24 19:10:02 +01005728 ExpressionResultBuilder& ExpressionResultBuilder::operator=(ExpressionResultBuilder const& other ) {
Phil Nashce612bf2012-11-01 08:27:09 +00005729 m_data = other.m_data;
5730 m_exprComponents = other.m_exprComponents;
5731 m_stream.str("");
5732 m_stream << other.m_stream.str();
5733 return *this;
5734 }
5735 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) {
5736 m_data.resultType = result;
5737 return *this;
5738 }
5739 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) {
5740 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
5741 return *this;
5742 }
Phil Nash90a35942012-11-13 22:04:29 +00005743 ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
5744 m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
Phil Nashce612bf2012-11-01 08:27:09 +00005745 return *this;
5746 }
Phil Nash8defc712013-04-24 19:10:02 +01005747 ExpressionResultBuilder& ExpressionResultBuilder::setLhs( std::string const& lhs ) {
Phil Nashce612bf2012-11-01 08:27:09 +00005748 m_exprComponents.lhs = lhs;
5749 return *this;
5750 }
Phil Nash8defc712013-04-24 19:10:02 +01005751 ExpressionResultBuilder& ExpressionResultBuilder::setRhs( std::string const& rhs ) {
Phil Nashce612bf2012-11-01 08:27:09 +00005752 m_exprComponents.rhs = rhs;
5753 return *this;
5754 }
Phil Nash8defc712013-04-24 19:10:02 +01005755 ExpressionResultBuilder& ExpressionResultBuilder::setOp( std::string const& op ) {
Phil Nashce612bf2012-11-01 08:27:09 +00005756 m_exprComponents.op = op;
5757 return *this;
5758 }
Phil Nash8defc712013-04-24 19:10:02 +01005759 AssertionResult ExpressionResultBuilder::buildResult( AssertionInfo const& info ) const
Phil Nashce612bf2012-11-01 08:27:09 +00005760 {
5761 assert( m_data.resultType != ResultWas::Unknown );
Phil Nash3b80af72012-08-09 07:47:30 +01005762
Phil Nashce612bf2012-11-01 08:27:09 +00005763 AssertionResultData data = m_data;
5764
5765 // Flip bool results if shouldNegate is set
5766 if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok )
5767 data.resultType = ResultWas::ExpressionFailed;
5768 else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed )
5769 data.resultType = ResultWas::Ok;
5770
5771 data.message = m_stream.str();
5772 data.reconstructedExpression = reconstructExpression( info );
5773 if( m_exprComponents.shouldNegate ) {
5774 if( m_exprComponents.op == "" )
5775 data.reconstructedExpression = "!" + data.reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +01005776 else
Phil Nashce612bf2012-11-01 08:27:09 +00005777 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
5778 }
5779 return AssertionResult( info, data );
5780 }
Phil Nash8defc712013-04-24 19:10:02 +01005781 std::string ExpressionResultBuilder::reconstructExpression( AssertionInfo const& info ) const {
Phil Nashce612bf2012-11-01 08:27:09 +00005782 if( m_exprComponents.op == "" )
5783 return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
5784 else if( m_exprComponents.op == "matches" )
5785 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
5786 else if( m_exprComponents.op != "!" ) {
Phil Nashdd26e882013-03-25 09:25:31 +00005787 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
5788 m_exprComponents.lhs.find("\n") == std::string::npos &&
5789 m_exprComponents.rhs.find("\n") == std::string::npos )
Phil Nashce612bf2012-11-01 08:27:09 +00005790 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
Phil Nashce612bf2012-11-01 08:27:09 +00005791 else
Phil Nash767f1582013-03-04 12:19:15 +01005792 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
Phil Nash67305122012-10-09 11:48:55 +01005793 }
5794 else
Phil Nashce612bf2012-11-01 08:27:09 +00005795 return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}";
Phil Nash3b80af72012-08-09 07:47:30 +01005796 }
5797
5798} // end namespace Catch
5799
Phil Nash5bc030d2012-08-16 18:48:50 +01005800// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005801#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01005802
5803namespace Catch {
5804
Phil Nasha1fbfea2012-12-01 23:57:18 +00005805 TestCase makeTestCase( ITestCase* _testCase,
Phil Nash8defc712013-04-24 19:10:02 +01005806 std::string const& _className,
5807 std::string const& _name,
5808 std::string const& _descOrTags,
5809 SourceLineInfo const& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +01005810 {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005811 std::string desc = _descOrTags;
Phil Nash5ecb72b2013-11-26 20:57:45 +00005812 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
Phil Nasha1fbfea2012-12-01 23:57:18 +00005813 std::set<std::string> tags;
5814 TagExtracter( tags ).parse( desc );
Phil Nashb5fd5a62013-06-28 17:09:57 +01005815 if( tags.find( "hide" ) != tags.end() || tags.find( "." ) != tags.end() )
Phil Nasha1fbfea2012-12-01 23:57:18 +00005816 isHidden = true;
5817
Phil Nashde49ec42013-12-04 20:25:14 +00005818 if( isHidden ) {
5819 tags.insert( "hide" );
5820 tags.insert( "." );
5821 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00005822 TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );
5823 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +01005824 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005825
Phil Nash8defc712013-04-24 19:10:02 +01005826 TestCaseInfo::TestCaseInfo( std::string const& _name,
5827 std::string const& _className,
5828 std::string const& _description,
5829 std::set<std::string> const& _tags,
Phil Nasha1fbfea2012-12-01 23:57:18 +00005830 bool _isHidden,
Phil Nash8defc712013-04-24 19:10:02 +01005831 SourceLineInfo const& _lineInfo )
Phil Nasha1fbfea2012-12-01 23:57:18 +00005832 : name( _name ),
5833 className( _className ),
5834 description( _description ),
5835 tags( _tags ),
Phil Nashff03cdf2012-12-06 08:44:51 +00005836 lineInfo( _lineInfo ),
5837 isHidden( _isHidden )
Phil Nash38f7eef2013-03-29 13:44:33 +00005838 {
5839 std::ostringstream oss;
5840 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it )
5841 oss << "[" << *it << "]";
5842 tagsAsString = oss.str();
5843 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005844
Phil Nash8defc712013-04-24 19:10:02 +01005845 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00005846 : name( other.name ),
5847 className( other.className ),
5848 description( other.description ),
5849 tags( other.tags ),
Phil Nash38f7eef2013-03-29 13:44:33 +00005850 tagsAsString( other.tagsAsString ),
Phil Nashff03cdf2012-12-06 08:44:51 +00005851 lineInfo( other.lineInfo ),
5852 isHidden( other.isHidden )
Phil Nash5bc030d2012-08-16 18:48:50 +01005853 {}
5854
Phil Nash8defc712013-04-24 19:10:02 +01005855 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00005856
Phil Nash8defc712013-04-24 19:10:02 +01005857 TestCase::TestCase( TestCase const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00005858 : TestCaseInfo( other ),
5859 test( other.test )
Phil Nash5bc030d2012-08-16 18:48:50 +01005860 {}
5861
Phil Nash8defc712013-04-24 19:10:02 +01005862 TestCase TestCase::withName( std::string const& _newName ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005863 TestCase other( *this );
5864 other.name = _newName;
5865 return other;
Phil Nash5bc030d2012-08-16 18:48:50 +01005866 }
5867
Phil Nasha1fbfea2012-12-01 23:57:18 +00005868 void TestCase::invoke() const {
5869 test->invoke();
Phil Nash5bc030d2012-08-16 18:48:50 +01005870 }
5871
Phil Nasha1fbfea2012-12-01 23:57:18 +00005872 bool TestCase::isHidden() const {
5873 return TestCaseInfo::isHidden;
Phil Nashfc1baac2012-09-15 17:53:27 +01005874 }
5875
Phil Nash8defc712013-04-24 19:10:02 +01005876 bool TestCase::hasTag( std::string const& tag ) const {
Phil Nashdd26e882013-03-25 09:25:31 +00005877 return tags.find( toLower( tag ) ) != tags.end();
Phil Nashfc1baac2012-09-15 17:53:27 +01005878 }
Phil Nash8defc712013-04-24 19:10:02 +01005879 bool TestCase::matchesTags( std::string const& tagPattern ) const {
Phil Nash799ecf92012-09-24 08:30:13 +01005880 TagExpression exp;
5881 TagExpressionParser( exp ).parse( tagPattern );
Phil Nasha1fbfea2012-12-01 23:57:18 +00005882 return exp.matches( tags );
Phil Nash799ecf92012-09-24 08:30:13 +01005883 }
Phil Nash8defc712013-04-24 19:10:02 +01005884 std::set<std::string> const& TestCase::getTags() const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005885 return tags;
Phil Nash5bc030d2012-08-16 18:48:50 +01005886 }
5887
Phil Nasha1fbfea2012-12-01 23:57:18 +00005888 void TestCase::swap( TestCase& other ) {
5889 test.swap( other.test );
5890 className.swap( other.className );
5891 name.swap( other.name );
5892 description.swap( other.description );
5893 std::swap( lineInfo, other.lineInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01005894 }
5895
Phil Nash8defc712013-04-24 19:10:02 +01005896 bool TestCase::operator == ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005897 return test.get() == other.test.get() &&
5898 name == other.name &&
5899 className == other.className;
Phil Nash5bc030d2012-08-16 18:48:50 +01005900 }
5901
Phil Nash8defc712013-04-24 19:10:02 +01005902 bool TestCase::operator < ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005903 return name < other.name;
Phil Nash5bc030d2012-08-16 18:48:50 +01005904 }
Phil Nash8defc712013-04-24 19:10:02 +01005905 TestCase& TestCase::operator = ( TestCase const& other ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005906 TestCase temp( other );
Phil Nashd2ec8492012-08-23 19:48:57 +01005907 swap( temp );
5908 return *this;
5909 }
Phil Nash799ecf92012-09-24 08:30:13 +01005910
Phil Nash8defc712013-04-24 19:10:02 +01005911 TestCaseInfo const& TestCase::getTestCaseInfo() const
Phil Nasha1fbfea2012-12-01 23:57:18 +00005912 {
5913 return *this;
5914 }
5915
Phil Nash799ecf92012-09-24 08:30:13 +01005916} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01005917
Phil Nash3649fdf2013-12-03 18:53:55 +00005918// #included from: catch_tags.hpp
5919#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
5920
5921namespace Catch {
5922 TagParser::~TagParser() {}
5923
5924 void TagParser::parse( std::string const& str ) {
5925 std::size_t pos = 0;
5926 while( pos < str.size() ) {
5927 char c = str[pos];
5928 if( c == '[' ) {
5929 std::size_t end = str.find_first_of( ']', pos );
5930 if( end != std::string::npos ) {
5931 acceptTag( str.substr( pos+1, end-pos-1 ) );
5932 pos = end+1;
5933 }
5934 else {
5935 acceptChar( c );
5936 pos++;
5937 }
5938 }
5939 else {
5940 acceptChar( c );
5941 pos++;
5942 }
5943 }
5944 endParse();
5945 }
5946
5947 TagExtracter::TagExtracter( std::set<std::string>& tags )
5948 : m_tags( tags )
5949 {}
5950
5951 TagExtracter::~TagExtracter() {}
5952
5953 void TagExtracter::parse( std::string& description ) {
5954 TagParser::parse( description );
5955 description = m_remainder;
5956 }
5957
5958 void TagExtracter::acceptTag( std::string const& tag ) {
5959 m_tags.insert( toLower( tag ) );
5960 }
5961 void TagExtracter::acceptChar( char c ) {
5962 m_remainder += c;
5963 }
5964
5965 Tag::Tag() : m_isNegated( false ) {}
5966 Tag::Tag( std::string const& name, bool isNegated )
5967 : m_name( name ),
5968 m_isNegated( isNegated )
5969 {}
5970
5971 std::string Tag::getName() const {
5972 return m_name;
5973 }
5974 bool Tag::isNegated() const {
5975 return m_isNegated;
5976 }
5977
5978 bool Tag::operator ! () const {
5979 return m_name.empty();
5980 }
5981
5982 void TagSet::add( Tag const& tag ) {
5983 m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) );
5984 }
5985
5986 bool TagSet::empty() const {
5987 return m_tags.empty();
5988 }
5989
5990 bool TagSet::matches( std::set<std::string> const& tags ) const {
5991 for( TagMap::const_iterator
5992 it = m_tags.begin(), itEnd = m_tags.end();
5993 it != itEnd;
5994 ++it ) {
5995 bool found = tags.find( it->first ) != tags.end();
5996 if( found == it->second.isNegated() )
5997 return false;
5998 }
5999 return true;
6000 }
6001
6002 bool TagExpression::matches( std::set<std::string> const& tags ) const {
6003 for( std::vector<TagSet>::const_iterator
6004 it = m_tagSets.begin(), itEnd = m_tagSets.end();
6005 it != itEnd;
6006 ++it )
6007 if( it->matches( tags ) )
6008 return true;
6009 return false;
6010 }
6011
6012 TagExpressionParser::TagExpressionParser( TagExpression& exp )
6013 : m_isNegated( false ),
6014 m_exp( exp )
6015 {}
6016
6017 TagExpressionParser::~TagExpressionParser() {}
6018
6019 void TagExpressionParser::acceptTag( std::string const& tag ) {
6020 m_currentTagSet.add( Tag( tag, m_isNegated ) );
6021 m_isNegated = false;
6022 }
6023
6024 void TagExpressionParser::acceptChar( char c ) {
6025 switch( c ) {
6026 case '~':
6027 m_isNegated = true;
6028 break;
6029 case ',':
6030 m_exp.m_tagSets.push_back( m_currentTagSet );
6031 m_currentTagSet = TagSet();
6032 break;
6033 }
6034 }
6035
6036 void TagExpressionParser::endParse() {
6037 if( !m_currentTagSet.empty() )
6038 m_exp.m_tagSets.push_back( m_currentTagSet );
6039 }
6040
6041} // end namespace Catch
6042
6043// #included from: catch_test_spec.hpp
6044#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
6045
6046namespace Catch {
6047
6048 TestCaseFilter::TestCaseFilter( std::string const& testSpec, IfFilterMatches::DoWhat matchBehaviour )
6049 : m_stringToMatch( toLower( testSpec ) ),
6050 m_filterType( matchBehaviour ),
6051 m_wildcardPosition( NoWildcard )
6052 {
6053 if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
6054 if( startsWith( m_stringToMatch, "exclude:" ) ) {
6055 m_stringToMatch = m_stringToMatch.substr( 8 );
6056 m_filterType = IfFilterMatches::ExcludeTests;
6057 }
6058 else if( startsWith( m_stringToMatch, "~" ) ) {
6059 m_stringToMatch = m_stringToMatch.substr( 1 );
6060 m_filterType = IfFilterMatches::ExcludeTests;
6061 }
6062 else {
6063 m_filterType = IfFilterMatches::IncludeTests;
6064 }
6065 }
6066
6067 if( startsWith( m_stringToMatch, "*" ) ) {
6068 m_stringToMatch = m_stringToMatch.substr( 1 );
6069 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
6070 }
6071 if( endsWith( m_stringToMatch, "*" ) ) {
6072 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
6073 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
6074 }
6075 }
6076
6077 IfFilterMatches::DoWhat TestCaseFilter::getFilterType() const {
6078 return m_filterType;
6079 }
6080
6081 bool TestCaseFilter::shouldInclude( TestCase const& testCase ) const {
6082 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
6083 }
6084
6085#ifdef __clang__
6086#pragma clang diagnostic push
6087#pragma clang diagnostic ignored "-Wunreachable-code"
6088#endif
6089
6090 bool TestCaseFilter::isMatch( TestCase const& testCase ) const {
6091 std::string name = testCase.getTestCaseInfo().name;
6092 toLowerInPlace( name );
6093
6094 switch( m_wildcardPosition ) {
6095 case NoWildcard:
6096 return m_stringToMatch == name;
6097 case WildcardAtStart:
6098 return endsWith( name, m_stringToMatch );
6099 case WildcardAtEnd:
6100 return startsWith( name, m_stringToMatch );
6101 case WildcardAtBothEnds:
6102 return contains( name, m_stringToMatch );
6103 }
6104 throw std::logic_error( "Unhandled wildcard type" );
6105 }
6106
6107#ifdef __clang__
6108#pragma clang diagnostic pop
6109#endif
6110
6111 TestCaseFilters::TestCaseFilters( std::string const& name ) : m_name( name ) {}
6112
6113 std::string TestCaseFilters::getName() const {
6114 return m_name;
6115 }
6116
6117 void TestCaseFilters::addFilter( TestCaseFilter const& filter ) {
6118 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
6119 m_exclusionFilters.push_back( filter );
6120 else
6121 m_inclusionFilters.push_back( filter );
6122 }
6123
6124 void TestCaseFilters::addTags( std::string const& tagPattern ) {
6125 TagExpression exp;
6126 TagExpressionParser( exp ).parse( tagPattern );
6127
6128 m_tagExpressions.push_back( exp );
6129 }
6130
6131 bool TestCaseFilters::shouldInclude( TestCase const& testCase ) const {
6132 if( !m_tagExpressions.empty() ) {
6133 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
6134 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
6135 for(; it != itEnd; ++it )
6136 if( it->matches( testCase.getTags() ) )
6137 break;
6138 if( it == itEnd )
6139 return false;
6140 }
6141
6142 if( !m_inclusionFilters.empty() ) {
6143 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
6144 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
6145 for(; it != itEnd; ++it )
6146 if( it->shouldInclude( testCase ) )
6147 break;
6148 if( it == itEnd )
6149 return false;
6150 }
6151 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
6152 return !testCase.isHidden();
6153 }
6154
6155 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
6156 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
6157 for(; it != itEnd; ++it )
6158 if( !it->shouldInclude( testCase ) )
6159 return false;
6160 return true;
6161 }
6162}
6163
Phil Nash7673a302012-11-15 22:15:41 +00006164// #included from: catch_version.hpp
6165#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
6166
6167namespace Catch {
6168
6169 // These numbers are maintained by a script
Phil Nash859760a2013-12-14 14:34:05 +00006170 Version libraryVersion( 1, 0, 18, "master" );
Phil Nash7673a302012-11-15 22:15:41 +00006171}
6172
Phil Nash19279252013-04-20 21:07:32 +01006173// #included from: catch_text.hpp
6174#define TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED
6175
6176#include <string>
6177#include <vector>
Phil Nash2e7d9662013-01-16 09:44:43 +00006178
6179namespace Catch {
6180
Phil Nash19279252013-04-20 21:07:32 +01006181 Text::Text( std::string const& _str, TextAttributes const& _attr )
6182 : attr( _attr )
6183 {
6184 std::string wrappableChars = " [({.,/|\\-";
6185 std::size_t indent = _attr.initialIndent != std::string::npos
6186 ? _attr.initialIndent
6187 : _attr.indent;
6188 std::string remainder = _str;
Phil Nash2e7d9662013-01-16 09:44:43 +00006189
Phil Nash19279252013-04-20 21:07:32 +01006190 while( !remainder.empty() ) {
Phil Nash380f98e2013-10-17 22:45:21 +01006191 if( lines.size() >= 1000 ) {
6192 lines.push_back( "... message truncated due to excessive size" );
6193 return;
6194 }
Phil Nash19279252013-04-20 21:07:32 +01006195 std::size_t tabPos = std::string::npos;
6196 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
6197 std::size_t pos = remainder.find_first_of( '\n' );
6198 if( pos <= width ) {
6199 width = pos;
Phil Nash2e7d9662013-01-16 09:44:43 +00006200 }
Phil Nash19279252013-04-20 21:07:32 +01006201 pos = remainder.find_last_of( _attr.tabChar, width );
6202 if( pos != std::string::npos ) {
6203 tabPos = pos;
6204 if( remainder[width] == '\n' )
6205 width--;
6206 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
6207 }
6208
6209 if( width == remainder.size() ) {
6210 spliceLine( indent, remainder, width );
6211 }
6212 else if( remainder[width] == '\n' ) {
6213 spliceLine( indent, remainder, width );
6214 if( width <= 1 || remainder.size() != 1 )
6215 remainder = remainder.substr( 1 );
6216 indent = _attr.indent;
6217 }
6218 else {
6219 pos = remainder.find_last_of( wrappableChars, width );
6220 if( pos != std::string::npos && pos > 0 ) {
6221 spliceLine( indent, remainder, pos );
6222 if( remainder[0] == ' ' )
6223 remainder = remainder.substr( 1 );
Phil Nash38f7eef2013-03-29 13:44:33 +00006224 }
6225 else {
Phil Nash19279252013-04-20 21:07:32 +01006226 spliceLine( indent, remainder, width-1 );
6227 lines.back() += "-";
Phil Nash38f7eef2013-03-29 13:44:33 +00006228 }
Phil Nash19279252013-04-20 21:07:32 +01006229 if( lines.size() == 1 )
6230 indent = _attr.indent;
6231 if( tabPos != std::string::npos )
6232 indent += tabPos;
Phil Nash38f7eef2013-03-29 13:44:33 +00006233 }
Phil Nash2e7d9662013-01-16 09:44:43 +00006234 }
6235 }
6236
Phil Nash19279252013-04-20 21:07:32 +01006237 void Text::spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
6238 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
6239 _remainder = _remainder.substr( _pos );
Phil Nash2e7d9662013-01-16 09:44:43 +00006240 }
Phil Nash19279252013-04-20 21:07:32 +01006241
6242 std::string Text::toString() const {
Phil Nash2e7d9662013-01-16 09:44:43 +00006243 std::ostringstream oss;
Phil Nash38f7eef2013-03-29 13:44:33 +00006244 oss << *this;
Phil Nash2e7d9662013-01-16 09:44:43 +00006245 return oss.str();
6246 }
6247
Phil Nash19279252013-04-20 21:07:32 +01006248 std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
6249 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
6250 it != itEnd; ++it ) {
6251 if( it != _text.begin() )
6252 _stream << "\n";
6253 _stream << *it;
6254 }
6255 return _stream;
Phil Nash12c16ff2013-04-05 20:58:01 +01006256 }
6257
Phil Nash2e7d9662013-01-16 09:44:43 +00006258} // end namespace Catch
6259
Phil Nasha2773812013-02-02 20:37:58 +00006260// #included from: catch_message.hpp
6261#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
6262
6263namespace Catch {
6264
6265 MessageInfo::MessageInfo( std::string const& _macroName,
6266 SourceLineInfo const& _lineInfo,
6267 ResultWas::OfType _type )
6268 : macroName( _macroName ),
6269 lineInfo( _lineInfo ),
6270 type( _type ),
6271 sequence( ++globalCount )
6272 {}
6273
6274 // This may need protecting if threading support is added
6275 unsigned int MessageInfo::globalCount = 0;
6276
6277 ////////////////////////////////////////////////////////////////////////////
6278
Phil Nashb5fd5a62013-06-28 17:09:57 +01006279 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
6280 : m_info( builder.m_info )
6281 {
6282 m_info.message = builder.m_stream.str();
6283 getResultCapture().pushScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00006284 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01006285 ScopedMessage::~ScopedMessage() {
6286 getResultCapture().popScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00006287 }
6288
6289} // end namespace Catch
6290
Phil Nash243f2d22013-04-12 10:43:06 +01006291// #included from: catch_legacy_reporter_adapter.hpp
Phil Nash87641772013-04-08 11:50:41 +01006292#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
6293
6294// #included from: catch_legacy_reporter_adapter.h
6295#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
6296
6297namespace Catch
6298{
Phil Nash3649fdf2013-12-03 18:53:55 +00006299 // Deprecated
6300 struct IReporter : IShared {
6301 virtual ~IReporter();
6302
6303 virtual bool shouldRedirectStdout() const = 0;
6304
6305 virtual void StartTesting() = 0;
6306 virtual void EndTesting( Totals const& totals ) = 0;
6307 virtual void StartGroup( std::string const& groupName ) = 0;
6308 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
6309 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
6310 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
6311 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
6312 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
6313 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
6314 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
6315 virtual void Aborted() = 0;
6316 virtual void Result( AssertionResult const& result ) = 0;
6317 };
6318
Phil Nash87641772013-04-08 11:50:41 +01006319 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
6320 {
6321 public:
Phil Nash786959d2013-06-07 19:07:50 +01006322 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
Phil Nash87641772013-04-08 11:50:41 +01006323 virtual ~LegacyReporterAdapter();
6324
6325 virtual ReporterPreferences getPreferences() const;
6326 virtual void noMatchingTestCases( std::string const& );
6327 virtual void testRunStarting( TestRunInfo const& );
6328 virtual void testGroupStarting( GroupInfo const& groupInfo );
6329 virtual void testCaseStarting( TestCaseInfo const& testInfo );
6330 virtual void sectionStarting( SectionInfo const& sectionInfo );
6331 virtual void assertionStarting( AssertionInfo const& );
Phil Nashb5fd5a62013-06-28 17:09:57 +01006332 virtual bool assertionEnded( AssertionStats const& assertionStats );
Phil Nash87641772013-04-08 11:50:41 +01006333 virtual void sectionEnded( SectionStats const& sectionStats );
6334 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
6335 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
6336 virtual void testRunEnded( TestRunStats const& testRunStats );
6337
6338 private:
6339 Ptr<IReporter> m_legacyReporter;
Phil Nash87641772013-04-08 11:50:41 +01006340 };
6341}
6342
6343namespace Catch
6344{
Phil Nash786959d2013-06-07 19:07:50 +01006345 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
6346 : m_legacyReporter( legacyReporter )
Phil Nash87641772013-04-08 11:50:41 +01006347 {}
6348 LegacyReporterAdapter::~LegacyReporterAdapter() {}
6349
6350 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
6351 ReporterPreferences prefs;
6352 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
6353 return prefs;
6354 }
6355
6356 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
6357 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
6358 m_legacyReporter->StartTesting();
6359 }
6360 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
6361 m_legacyReporter->StartGroup( groupInfo.name );
6362 }
6363 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
6364 m_legacyReporter->StartTestCase( testInfo );
6365 }
6366 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
6367 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
6368 }
6369 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
6370 // Not on legacy interface
6371 }
6372
Phil Nashb5fd5a62013-06-28 17:09:57 +01006373 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
Phil Nash87641772013-04-08 11:50:41 +01006374 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
6375 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
6376 it != itEnd;
6377 ++it ) {
6378 if( it->type == ResultWas::Info ) {
6379 ExpressionResultBuilder expressionBuilder( it->type );
6380 expressionBuilder << it->message;
6381 AssertionInfo info( it->macroName, it->lineInfo, "", ResultDisposition::Normal );
6382 AssertionResult result = expressionBuilder.buildResult( info );
6383 m_legacyReporter->Result( result );
6384 }
6385 }
6386 }
6387 m_legacyReporter->Result( assertionStats.assertionResult );
Phil Nashb5fd5a62013-06-28 17:09:57 +01006388 return true;
Phil Nash87641772013-04-08 11:50:41 +01006389 }
6390 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
6391 if( sectionStats.missingAssertions )
6392 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
6393 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
6394 }
6395 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
Phil Nash87641772013-04-08 11:50:41 +01006396 m_legacyReporter->EndTestCase
6397 ( testCaseStats.testInfo,
6398 testCaseStats.totals,
6399 testCaseStats.stdOut,
6400 testCaseStats.stdErr );
6401 }
6402 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
6403 if( testGroupStats.aborting )
6404 m_legacyReporter->Aborted();
6405 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
6406 }
6407 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
6408 m_legacyReporter->EndTesting( testRunStats.totals );
6409 }
6410}
6411
Phil Nashaa7123b2013-08-15 19:01:00 +01006412// #included from: catch_timer.hpp
6413
6414#ifdef __clang__
6415#pragma clang diagnostic push
6416#pragma clang diagnostic ignored "-Wc++11-long-long"
6417#endif
6418
Phil Nash04a33642013-08-16 19:09:09 +01006419#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01006420#include <windows.h>
6421#else
6422#include <sys/time.h>
6423#endif
6424
6425namespace Catch {
6426
6427 namespace {
Phil Nash04a33642013-08-16 19:09:09 +01006428#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01006429 uint64_t getCurrentTicks() {
6430 static uint64_t hz=0, hzo=0;
6431 if (!hz) {
6432 QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
6433 QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
6434 }
6435 uint64_t t;
6436 QueryPerformanceCounter((LARGE_INTEGER*)&t);
6437 return ((t-hzo)*1000000)/hz;
6438 }
6439#else
6440 uint64_t getCurrentTicks() {
6441 timeval t;
6442 gettimeofday(&t,NULL);
6443 return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec;
6444 }
6445#endif
6446 }
6447
6448 void Timer::start() {
6449 m_ticks = getCurrentTicks();
6450 }
6451 unsigned int Timer::getElapsedNanoseconds() const {
6452 return (unsigned int)(getCurrentTicks() - m_ticks);
6453 }
6454 unsigned int Timer::getElapsedMilliseconds() const {
6455 return (unsigned int)((getCurrentTicks() - m_ticks)/1000);
6456 }
6457 double Timer::getElapsedSeconds() const {
6458 return (getCurrentTicks() - m_ticks)/1000000.0;
6459 }
6460
6461} // namespace Catch
6462
6463#ifdef __clang__
6464#pragma clang diagnostic pop
6465#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00006466// #included from: catch_common.hpp
6467#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
6468
6469namespace Catch {
6470
6471 bool startsWith( std::string const& s, std::string const& prefix ) {
6472 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
6473 }
6474 bool endsWith( std::string const& s, std::string const& suffix ) {
6475 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
6476 }
6477 bool contains( std::string const& s, std::string const& infix ) {
6478 return s.find( infix ) != std::string::npos;
6479 }
6480 void toLowerInPlace( std::string& s ) {
6481 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
6482 }
6483 std::string toLower( std::string const& s ) {
6484 std::string lc = s;
6485 toLowerInPlace( lc );
6486 return lc;
6487 }
6488 std::string trim( std::string const& str ) {
6489 static char const* whitespaceChars = "\n\r\t ";
6490 std::string::size_type start = str.find_first_not_of( whitespaceChars );
6491 std::string::size_type end = str.find_last_not_of( whitespaceChars );
6492
6493 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
6494 }
6495
6496 pluralise::pluralise( std::size_t count, std::string const& label )
6497 : m_count( count ),
6498 m_label( label )
6499 {}
6500
6501 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
6502 os << pluraliser.m_count << " " << pluraliser.m_label;
6503 if( pluraliser.m_count != 1 )
6504 os << "s";
6505 return os;
6506 }
6507
6508 SourceLineInfo::SourceLineInfo() : line( 0 ){}
Phil Nashde49ec42013-12-04 20:25:14 +00006509 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
Phil Nash3649fdf2013-12-03 18:53:55 +00006510 : file( _file ),
6511 line( _line )
6512 {}
6513 SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
6514 : file( other.file ),
6515 line( other.line )
6516 {}
6517 bool SourceLineInfo::empty() const {
6518 return file.empty();
6519 }
6520 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
6521 return line == other.line && file == other.file;
6522 }
6523
6524 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
6525#ifndef __GNUG__
6526 os << info.file << "(" << info.line << ")";
6527#else
6528 os << info.file << ":" << info.line;
6529#endif
6530 return os;
6531 }
6532
6533 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
6534 std::ostringstream oss;
6535 oss << locationInfo << ": Internal Catch error: '" << message << "'";
6536 if( isTrue( true ))
6537 throw std::logic_error( oss.str() );
6538 }
6539}
6540
6541// #included from: catch_section.hpp
6542#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
6543
6544namespace Catch {
6545
6546 Section::Section( SourceLineInfo const& lineInfo,
6547 std::string const& name,
6548 std::string const& description )
6549 : m_info( name, description, lineInfo ),
6550 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) )
6551 {
6552 m_timer.start();
6553 }
6554
6555 Section::~Section() {
6556 if( m_sectionIncluded )
6557 getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
6558 }
6559
6560 // This indicates whether the section should be executed or not
6561 Section::operator bool() {
6562 return m_sectionIncluded;
6563 }
6564
6565} // end namespace Catch
6566
6567// #included from: catch_debugger.hpp
6568#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
6569
6570#include <iostream>
6571
6572#ifdef CATCH_PLATFORM_MAC
6573
6574 #include <assert.h>
6575 #include <stdbool.h>
6576 #include <sys/types.h>
6577 #include <unistd.h>
6578 #include <sys/sysctl.h>
6579
6580 namespace Catch{
6581
6582 // The following function is taken directly from the following technical note:
6583 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
6584
6585 // Returns true if the current process is being debugged (either
6586 // running under the debugger or has a debugger attached post facto).
6587 bool isDebuggerActive(){
6588
6589 int junk;
6590 int mib[4];
6591 struct kinfo_proc info;
6592 size_t size;
6593
6594 // Initialize the flags so that, if sysctl fails for some bizarre
6595 // reason, we get a predictable result.
6596
6597 info.kp_proc.p_flag = 0;
6598
6599 // Initialize mib, which tells sysctl the info we want, in this case
6600 // we're looking for information about a specific process ID.
6601
6602 mib[0] = CTL_KERN;
6603 mib[1] = KERN_PROC;
6604 mib[2] = KERN_PROC_PID;
6605 mib[3] = getpid();
6606
6607 // Call sysctl.
6608
6609 size = sizeof(info);
6610 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
6611 assert(junk == 0);
6612
6613 // We're being debugged if the P_TRACED flag is set.
6614
6615 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
6616 }
6617 } // namespace Catch
6618
6619#elif defined(_MSC_VER)
6620 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
6621 namespace Catch {
6622 bool isDebuggerActive() {
6623 return IsDebuggerPresent() != 0;
6624 }
6625 }
6626#elif defined(__MINGW32__)
6627 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
6628 namespace Catch {
6629 bool isDebuggerActive() {
6630 return IsDebuggerPresent() != 0;
6631 }
6632 }
6633#else
6634 namespace Catch {
6635 inline bool isDebuggerActive() { return false; }
6636 }
6637#endif // Platform
6638
6639#ifdef CATCH_PLATFORM_WINDOWS
6640 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
6641 namespace Catch {
6642 void writeToDebugConsole( std::string const& text ) {
6643 ::OutputDebugStringA( text.c_str() );
6644 }
6645 }
6646#else
6647 namespace Catch {
6648 void writeToDebugConsole( std::string const& text ) {
6649 // !TBD: Need a version for Mac/ XCode and other IDEs
6650 std::cout << text;
6651 }
6652 }
6653#endif // Platform
6654
Phil Nash3faa4122013-08-15 19:09:07 +01006655// #included from: ../reporters/catch_reporter_xml.hpp
6656#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
Phil Nash56d5c422012-08-23 20:08:50 +01006657
Phil Nash3649fdf2013-12-03 18:53:55 +00006658// #included from: catch_reporter_bases.hpp
6659#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
6660
6661namespace Catch {
6662
6663 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
6664
6665 StreamingReporterBase( ReporterConfig const& _config )
6666 : m_config( _config.fullConfig() ),
6667 stream( _config.stream() )
6668 {}
6669
6670 virtual ~StreamingReporterBase();
6671
6672 virtual void noMatchingTestCases( std::string const& ) {}
6673
6674 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
6675 currentTestRunInfo = _testRunInfo;
6676 }
6677 virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
6678 currentGroupInfo = _groupInfo;
6679 }
6680
6681 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
6682 currentTestCaseInfo = _testInfo;
6683 }
6684 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
6685 m_sectionStack.push_back( _sectionInfo );
6686 }
6687
6688 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
6689 m_sectionStack.pop_back();
6690 }
6691 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
6692 currentTestCaseInfo.reset();
6693 assert( m_sectionStack.empty() );
6694 }
6695 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
6696 currentGroupInfo.reset();
6697 }
6698 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
6699 currentTestCaseInfo.reset();
6700 currentGroupInfo.reset();
6701 currentTestRunInfo.reset();
6702 }
6703
6704 Ptr<IConfig> m_config;
6705 std::ostream& stream;
6706
6707 LazyStat<TestRunInfo> currentTestRunInfo;
6708 LazyStat<GroupInfo> currentGroupInfo;
6709 LazyStat<TestCaseInfo> currentTestCaseInfo;
6710
6711 std::vector<SectionInfo> m_sectionStack;
6712 };
6713
6714 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
6715 template<typename T, typename ChildNodeT>
6716 struct Node : SharedImpl<> {
6717 explicit Node( T const& _value ) : value( _value ) {}
6718 virtual ~Node() {}
6719
6720 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
6721 T value;
6722 ChildNodes children;
6723 };
6724 struct SectionNode : SharedImpl<> {
6725 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
6726 virtual ~SectionNode();
6727
6728 bool operator == ( SectionNode const& other ) const {
6729 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
6730 }
6731 bool operator == ( Ptr<SectionNode> const& other ) const {
6732 return operator==( *other );
6733 }
6734
6735 SectionStats stats;
6736 typedef std::vector<Ptr<SectionNode> > ChildSections;
6737 typedef std::vector<AssertionStats> Assertions;
6738 ChildSections childSections;
6739 Assertions assertions;
6740 std::string stdOut;
6741 std::string stdErr;
6742 };
6743 friend bool operator == ( Ptr<SectionNode> const& node, SectionInfo const& other ) {
6744 return node->stats.sectionInfo.lineInfo == other.lineInfo;
6745 }
6746
6747 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
6748 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
6749 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
6750
6751 CumulativeReporterBase( ReporterConfig const& _config )
6752 : m_config( _config.fullConfig() ),
6753 stream( _config.stream() )
6754 {}
6755 ~CumulativeReporterBase();
6756
6757 virtual void testRunStarting( TestRunInfo const& ) {}
6758 virtual void testGroupStarting( GroupInfo const& ) {}
6759
6760 virtual void testCaseStarting( TestCaseInfo const& ) {}
6761
6762 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
6763 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
6764 Ptr<SectionNode> node;
6765 if( m_sectionStack.empty() ) {
6766 if( !m_rootSection )
6767 m_rootSection = new SectionNode( incompleteStats );
6768 node = m_rootSection;
6769 }
6770 else {
6771 SectionNode& parentNode = *m_sectionStack.back();
6772 SectionNode::ChildSections::const_iterator it =
6773 std::find( parentNode.childSections.begin(), parentNode.childSections.end(), sectionInfo );
6774 if( it == parentNode.childSections.end() ) {
6775 node = new SectionNode( incompleteStats );
6776 parentNode.childSections.push_back( node );
6777 }
6778 else
6779 node = *it;
6780 }
6781 m_sectionStack.push_back( node );
6782 m_deepestSection = node;
6783 }
6784
6785 virtual void assertionStarting( AssertionInfo const& ) {}
6786
6787 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
6788 assert( !m_sectionStack.empty() );
6789 SectionNode& sectionNode = *m_sectionStack.back();
6790 sectionNode.assertions.push_back( assertionStats );
6791 return true;
6792 }
6793 virtual void sectionEnded( SectionStats const& sectionStats ) {
6794 assert( !m_sectionStack.empty() );
6795 SectionNode& node = *m_sectionStack.back();
6796 node.stats = sectionStats;
6797 m_sectionStack.pop_back();
6798 }
6799 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
6800 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
6801 assert( m_sectionStack.size() == 0 );
6802 node->children.push_back( m_rootSection );
6803 m_testCases.push_back( node );
6804 m_rootSection.reset();
6805
6806 assert( m_deepestSection );
6807 m_deepestSection->stdOut = testCaseStats.stdOut;
6808 m_deepestSection->stdErr = testCaseStats.stdErr;
6809 }
6810 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
6811 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
6812 node->children.swap( m_testCases );
6813 m_testGroups.push_back( node );
6814 }
6815 virtual void testRunEnded( TestRunStats const& testRunStats ) {
6816 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
6817 node->children.swap( m_testGroups );
6818 m_testRuns.push_back( node );
Phil Nasha6d74bd2013-12-11 08:28:15 +00006819 testRunEndedCumulative();
Phil Nash3649fdf2013-12-03 18:53:55 +00006820 }
Phil Nasha6d74bd2013-12-11 08:28:15 +00006821 virtual void testRunEndedCumulative() = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00006822
6823 Ptr<IConfig> m_config;
6824 std::ostream& stream;
6825 std::vector<AssertionStats> m_assertions;
6826 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
6827 std::vector<Ptr<TestCaseNode> > m_testCases;
6828 std::vector<Ptr<TestGroupNode> > m_testGroups;
6829
6830 std::vector<Ptr<TestRunNode> > m_testRuns;
6831
6832 Ptr<SectionNode> m_rootSection;
6833 Ptr<SectionNode> m_deepestSection;
6834 std::vector<Ptr<SectionNode> > m_sectionStack;
6835
6836 };
6837
6838} // end namespace Catch
6839
Phil Nash56d5c422012-08-23 20:08:50 +01006840// #included from: ../internal/catch_reporter_registrars.hpp
6841#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
6842
6843namespace Catch {
6844
6845 template<typename T>
Phil Nasha1fbfea2012-12-01 23:57:18 +00006846 class LegacyReporterRegistrar {
6847
6848 class ReporterFactory : public IReporterFactory {
Phil Nash8defc712013-04-24 19:10:02 +01006849 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash786959d2013-06-07 19:07:50 +01006850 return new LegacyReporterAdapter( new T( config ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006851 }
6852
6853 virtual std::string getDescription() const {
6854 return T::getDescription();
6855 }
6856 };
6857
6858 public:
6859
Phil Nash8defc712013-04-24 19:10:02 +01006860 LegacyReporterRegistrar( std::string const& name ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006861 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
6862 }
6863 };
6864
6865 template<typename T>
Phil Nash56d5c422012-08-23 20:08:50 +01006866 class ReporterRegistrar {
6867
6868 class ReporterFactory : public IReporterFactory {
6869
Phil Nasha1fbfea2012-12-01 23:57:18 +00006870 // *** Please Note ***:
6871 // - If you end up here looking at a compiler error because it's trying to register
6872 // your custom reporter class be aware that the native reporter interface has changed
6873 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
6874 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
6875 // However please consider updating to the new interface as the old one is now
6876 // deprecated and will probably be removed quite soon!
6877 // Please contact me via github if you have any questions at all about this.
6878 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
6879 // no idea who is actually using custom reporters at all (possibly no-one!).
6880 // The new interface is designed to minimise exposure to interface changes in the future.
Phil Nash8defc712013-04-24 19:10:02 +01006881 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01006882 return new T( config );
6883 }
6884
6885 virtual std::string getDescription() const {
6886 return T::getDescription();
6887 }
6888 };
6889
6890 public:
6891
Phil Nash8defc712013-04-24 19:10:02 +01006892 ReporterRegistrar( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006893 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
6894 }
6895 };
6896}
6897
Phil Nasha1fbfea2012-12-01 23:57:18 +00006898#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01006899 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nash56d5c422012-08-23 20:08:50 +01006900#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01006901 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nash56d5c422012-08-23 20:08:50 +01006902
Phil Nash56d5c422012-08-23 20:08:50 +01006903// #included from: ../internal/catch_xmlwriter.hpp
6904#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
6905
6906#include <sstream>
Phil Nash9e7e63c2012-09-29 20:54:03 +01006907#include <iostream>
Phil Nash56d5c422012-08-23 20:08:50 +01006908#include <string>
6909#include <vector>
6910
6911namespace Catch {
6912
6913 class XmlWriter {
6914 public:
6915
6916 class ScopedElement {
6917 public:
6918 ScopedElement( XmlWriter* writer )
6919 : m_writer( writer )
6920 {}
6921
Phil Nash8defc712013-04-24 19:10:02 +01006922 ScopedElement( ScopedElement const& other )
Phil Nash56d5c422012-08-23 20:08:50 +01006923 : m_writer( other.m_writer ){
6924 other.m_writer = NULL;
6925 }
6926
6927 ~ScopedElement() {
6928 if( m_writer )
6929 m_writer->endElement();
6930 }
6931
Phil Nash8defc712013-04-24 19:10:02 +01006932 ScopedElement& writeText( std::string const& text, bool indent = true ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006933 m_writer->writeText( text, indent );
Phil Nash56d5c422012-08-23 20:08:50 +01006934 return *this;
6935 }
6936
6937 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01006938 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006939 m_writer->writeAttribute( name, attribute );
6940 return *this;
6941 }
6942
6943 private:
6944 mutable XmlWriter* m_writer;
6945 };
6946
6947 XmlWriter()
6948 : m_tagIsOpen( false ),
6949 m_needsNewline( false ),
6950 m_os( &std::cout )
6951 {}
6952
6953 XmlWriter( std::ostream& os )
6954 : m_tagIsOpen( false ),
6955 m_needsNewline( false ),
6956 m_os( &os )
6957 {}
6958
6959 ~XmlWriter() {
6960 while( !m_tags.empty() )
6961 endElement();
6962 }
6963
Phil Nash8defc712013-04-24 19:10:02 +01006964 XmlWriter& operator = ( XmlWriter const& other ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006965 XmlWriter temp( other );
6966 swap( temp );
6967 return *this;
6968 }
6969
6970 void swap( XmlWriter& other ) {
6971 std::swap( m_tagIsOpen, other.m_tagIsOpen );
6972 std::swap( m_needsNewline, other.m_needsNewline );
6973 std::swap( m_tags, other.m_tags );
6974 std::swap( m_indent, other.m_indent );
6975 std::swap( m_os, other.m_os );
6976 }
6977
Phil Nash8defc712013-04-24 19:10:02 +01006978 XmlWriter& startElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006979 ensureTagClosed();
6980 newlineIfNecessary();
6981 stream() << m_indent << "<" << name;
6982 m_tags.push_back( name );
6983 m_indent += " ";
6984 m_tagIsOpen = true;
6985 return *this;
6986 }
6987
Phil Nash8defc712013-04-24 19:10:02 +01006988 ScopedElement scopedElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006989 ScopedElement scoped( this );
6990 startElement( name );
6991 return scoped;
6992 }
6993
6994 XmlWriter& endElement() {
6995 newlineIfNecessary();
6996 m_indent = m_indent.substr( 0, m_indent.size()-2 );
6997 if( m_tagIsOpen ) {
6998 stream() << "/>\n";
6999 m_tagIsOpen = false;
7000 }
7001 else {
7002 stream() << m_indent << "</" << m_tags.back() << ">\n";
7003 }
7004 m_tags.pop_back();
7005 return *this;
7006 }
7007
Phil Nash8defc712013-04-24 19:10:02 +01007008 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007009 if( !name.empty() && !attribute.empty() ) {
7010 stream() << " " << name << "=\"";
7011 writeEncodedText( attribute );
7012 stream() << "\"";
7013 }
7014 return *this;
7015 }
7016
Phil Nash8defc712013-04-24 19:10:02 +01007017 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007018 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
7019 return *this;
7020 }
7021
7022 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01007023 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007024 if( !name.empty() )
7025 stream() << " " << name << "=\"" << attribute << "\"";
7026 return *this;
7027 }
7028
Phil Nash8defc712013-04-24 19:10:02 +01007029 XmlWriter& writeText( std::string const& text, bool indent = true ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007030 if( !text.empty() ){
7031 bool tagWasOpen = m_tagIsOpen;
7032 ensureTagClosed();
Phil Nasha1fbfea2012-12-01 23:57:18 +00007033 if( tagWasOpen && indent )
Phil Nash56d5c422012-08-23 20:08:50 +01007034 stream() << m_indent;
7035 writeEncodedText( text );
7036 m_needsNewline = true;
7037 }
7038 return *this;
7039 }
7040
Phil Nash8defc712013-04-24 19:10:02 +01007041 XmlWriter& writeComment( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007042 ensureTagClosed();
7043 stream() << m_indent << "<!--" << text << "-->";
7044 m_needsNewline = true;
7045 return *this;
7046 }
7047
7048 XmlWriter& writeBlankLine() {
7049 ensureTagClosed();
7050 stream() << "\n";
7051 return *this;
7052 }
7053
7054 private:
7055
7056 std::ostream& stream() {
7057 return *m_os;
7058 }
7059
7060 void ensureTagClosed() {
7061 if( m_tagIsOpen ) {
7062 stream() << ">\n";
7063 m_tagIsOpen = false;
7064 }
7065 }
7066
7067 void newlineIfNecessary() {
7068 if( m_needsNewline ) {
7069 stream() << "\n";
7070 m_needsNewline = false;
7071 }
7072 }
7073
Phil Nash8defc712013-04-24 19:10:02 +01007074 void writeEncodedText( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007075 static const char* charsToEncode = "<&\"";
7076 std::string mtext = text;
7077 std::string::size_type pos = mtext.find_first_of( charsToEncode );
7078 while( pos != std::string::npos ) {
7079 stream() << mtext.substr( 0, pos );
7080
7081 switch( mtext[pos] ) {
7082 case '<':
7083 stream() << "&lt;";
7084 break;
7085 case '&':
7086 stream() << "&amp;";
7087 break;
7088 case '\"':
7089 stream() << "&quot;";
7090 break;
7091 }
7092 mtext = mtext.substr( pos+1 );
7093 pos = mtext.find_first_of( charsToEncode );
7094 }
7095 stream() << mtext;
7096 }
7097
7098 bool m_tagIsOpen;
7099 bool m_needsNewline;
7100 std::vector<std::string> m_tags;
7101 std::string m_indent;
7102 std::ostream* m_os;
7103 };
7104
7105}
7106namespace Catch {
7107 class XmlReporter : public SharedImpl<IReporter> {
7108 public:
Phil Nash8a52a392013-07-25 08:12:03 +01007109 XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01007110
7111 static std::string getDescription() {
7112 return "Reports test results as an XML document";
7113 }
7114 virtual ~XmlReporter();
7115
7116 private: // IReporter
7117
7118 virtual bool shouldRedirectStdout() const {
7119 return true;
7120 }
7121
7122 virtual void StartTesting() {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007123 m_xml = XmlWriter( m_config.stream() );
Phil Nash56d5c422012-08-23 20:08:50 +01007124 m_xml.startElement( "Catch" );
Phil Nash786959d2013-06-07 19:07:50 +01007125 if( !m_config.fullConfig()->name().empty() )
7126 m_xml.writeAttribute( "name", m_config.fullConfig()->name() );
Phil Nash56d5c422012-08-23 20:08:50 +01007127 }
7128
7129 virtual void EndTesting( const Totals& totals ) {
7130 m_xml.scopedElement( "OverallResults" )
7131 .writeAttribute( "successes", totals.assertions.passed )
7132 .writeAttribute( "failures", totals.assertions.failed );
7133 m_xml.endElement();
7134 }
7135
7136 virtual void StartGroup( const std::string& groupName ) {
7137 m_xml.startElement( "Group" )
7138 .writeAttribute( "name", groupName );
7139 }
7140
7141 virtual void EndGroup( const std::string&, const Totals& totals ) {
7142 m_xml.scopedElement( "OverallResults" )
7143 .writeAttribute( "successes", totals.assertions.passed )
7144 .writeAttribute( "failures", totals.assertions.failed );
7145 m_xml.endElement();
7146 }
7147
7148 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
Phil Nash8a52a392013-07-25 08:12:03 +01007149 if( m_sectionDepth++ > 0 ) {
7150 m_xml.startElement( "Section" )
Phil Nasha6d74bd2013-12-11 08:28:15 +00007151 .writeAttribute( "name", trim( sectionName ) )
Phil Nash8a52a392013-07-25 08:12:03 +01007152 .writeAttribute( "description", description );
7153 }
Phil Nash56d5c422012-08-23 20:08:50 +01007154 }
Phil Nasha70fbe32012-08-31 08:10:36 +01007155 virtual void NoAssertionsInSection( const std::string& ) {}
7156 virtual void NoAssertionsInTestCase( const std::string& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01007157
7158 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
Phil Nash8a52a392013-07-25 08:12:03 +01007159 if( --m_sectionDepth > 0 ) {
7160 m_xml.scopedElement( "OverallResults" )
7161 .writeAttribute( "successes", assertions.passed )
7162 .writeAttribute( "failures", assertions.failed );
7163 m_xml.endElement();
7164 }
Phil Nash56d5c422012-08-23 20:08:50 +01007165 }
7166
7167 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
Phil Nasha6d74bd2013-12-11 08:28:15 +00007168 m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
Phil Nash56d5c422012-08-23 20:08:50 +01007169 m_currentTestSuccess = true;
7170 }
7171
Phil Nashce612bf2012-11-01 08:27:09 +00007172 virtual void Result( const Catch::AssertionResult& assertionResult ) {
Phil Nash786959d2013-06-07 19:07:50 +01007173 if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01007174 return;
7175
Phil Nashce612bf2012-11-01 08:27:09 +00007176 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007177 m_xml.startElement( "Expression" )
Phil Nash90a35942012-11-13 22:04:29 +00007178 .writeAttribute( "success", assertionResult.succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00007179 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
7180 .writeAttribute( "line", assertionResult.getSourceInfo().line );
Phil Nash56d5c422012-08-23 20:08:50 +01007181
7182 m_xml.scopedElement( "Original" )
Phil Nashce612bf2012-11-01 08:27:09 +00007183 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01007184 m_xml.scopedElement( "Expanded" )
Phil Nashce612bf2012-11-01 08:27:09 +00007185 .writeText( assertionResult.getExpandedExpression() );
Phil Nash90a35942012-11-13 22:04:29 +00007186 m_currentTestSuccess &= assertionResult.succeeded();
Phil Nash56d5c422012-08-23 20:08:50 +01007187 }
7188
Phil Nashce612bf2012-11-01 08:27:09 +00007189 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007190 case ResultWas::ThrewException:
7191 m_xml.scopedElement( "Exception" )
Phil Nashce612bf2012-11-01 08:27:09 +00007192 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
7193 .writeAttribute( "line", assertionResult.getSourceInfo().line )
7194 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01007195 m_currentTestSuccess = false;
7196 break;
7197 case ResultWas::Info:
7198 m_xml.scopedElement( "Info" )
Phil Nashce612bf2012-11-01 08:27:09 +00007199 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01007200 break;
7201 case ResultWas::Warning:
7202 m_xml.scopedElement( "Warning" )
Phil Nashce612bf2012-11-01 08:27:09 +00007203 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01007204 break;
7205 case ResultWas::ExplicitFailure:
7206 m_xml.scopedElement( "Failure" )
Phil Nashce612bf2012-11-01 08:27:09 +00007207 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01007208 m_currentTestSuccess = false;
7209 break;
7210 case ResultWas::Unknown:
7211 case ResultWas::Ok:
7212 case ResultWas::FailureBit:
7213 case ResultWas::ExpressionFailed:
7214 case ResultWas::Exception:
7215 case ResultWas::DidntThrowException:
7216 break;
7217 }
Phil Nashce612bf2012-11-01 08:27:09 +00007218 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01007219 m_xml.endElement();
7220 }
7221
7222 virtual void Aborted() {
7223 // !TBD
7224 }
7225
7226 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
7227 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
7228 m_xml.endElement();
7229 }
7230
7231 private:
7232 ReporterConfig m_config;
7233 bool m_currentTestSuccess;
7234 XmlWriter m_xml;
Phil Nash8a52a392013-07-25 08:12:03 +01007235 int m_sectionDepth;
Phil Nash56d5c422012-08-23 20:08:50 +01007236 };
7237
7238} // end namespace Catch
7239
7240// #included from: ../reporters/catch_reporter_junit.hpp
7241#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
7242
Phil Nashf276a052012-12-02 00:05:51 +00007243#include <assert.h>
7244
Phil Nash56d5c422012-08-23 20:08:50 +01007245namespace Catch {
7246
Phil Nashaa7123b2013-08-15 19:01:00 +01007247 class JunitReporter : public CumulativeReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +01007248 public:
Phil Nashaa7123b2013-08-15 19:01:00 +01007249 JunitReporter( ReporterConfig const& _config )
7250 : CumulativeReporterBase( _config ),
7251 xml( _config.stream() )
Phil Nash56d5c422012-08-23 20:08:50 +01007252 {}
Phil Nashaa7123b2013-08-15 19:01:00 +01007253
7254 ~JunitReporter();
Phil Nash56d5c422012-08-23 20:08:50 +01007255
7256 static std::string getDescription() {
7257 return "Reports test results in an XML format that looks like Ant's junitreport target";
7258 }
7259
Phil Nashaa7123b2013-08-15 19:01:00 +01007260 virtual void noMatchingTestCases( std::string const& /*spec*/ ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01007261
Phil Nashaa7123b2013-08-15 19:01:00 +01007262 virtual ReporterPreferences getPreferences() const {
7263 ReporterPreferences prefs;
7264 prefs.shouldRedirectStdOut = true;
7265 return prefs;
Phil Nash56d5c422012-08-23 20:08:50 +01007266 }
7267
Phil Nashaa7123b2013-08-15 19:01:00 +01007268 virtual void testRunStarting( TestRunInfo const& runInfo ) {
7269 CumulativeReporterBase::testRunStarting( runInfo );
7270 xml.startElement( "testsuites" );
7271 }
Phil Nash56d5c422012-08-23 20:08:50 +01007272
Phil Nashaa7123b2013-08-15 19:01:00 +01007273 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
7274 suiteTimer.start();
7275 stdOutForSuite.str("");
7276 stdErrForSuite.str("");
7277 unexpectedExceptions = 0;
7278 CumulativeReporterBase::testGroupStarting( groupInfo );
7279 }
7280
7281 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
7282 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
7283 unexpectedExceptions++;
7284 return CumulativeReporterBase::assertionEnded( assertionStats );
7285 }
7286
7287 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
7288 stdOutForSuite << testCaseStats.stdOut;
7289 stdErrForSuite << testCaseStats.stdErr;
7290 CumulativeReporterBase::testCaseEnded( testCaseStats );
7291 }
7292
7293 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
7294 double suiteTime = suiteTimer.getElapsedSeconds();
7295 CumulativeReporterBase::testGroupEnded( testGroupStats );
7296 writeGroup( *m_testGroups.back(), suiteTime );
7297 }
7298
Phil Nasha6d74bd2013-12-11 08:28:15 +00007299 virtual void testRunEndedCumulative() {
Phil Nashaa7123b2013-08-15 19:01:00 +01007300 xml.endElement();
7301 }
7302
7303 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
7304 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
7305 TestGroupStats const& stats = groupNode.value;
7306 xml.writeAttribute( "name", stats.groupInfo.name );
7307 xml.writeAttribute( "errors", unexpectedExceptions );
7308 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
7309 xml.writeAttribute( "tests", stats.totals.assertions.total() );
7310 xml.writeAttribute( "hostname", "tbd" ); // !TBD
7311 if( m_config->showDurations() == ShowDurations::Never )
7312 xml.writeAttribute( "time", "" );
Phil Nashef60d542012-11-16 08:47:03 +00007313 else
Phil Nashaa7123b2013-08-15 19:01:00 +01007314 xml.writeAttribute( "time", suiteTime );
7315 xml.writeAttribute( "timestamp", "tbd" ); // !TBD
7316
7317 // Write test cases
7318 for( TestGroupNode::ChildNodes::const_iterator
7319 it = groupNode.children.begin(), itEnd = groupNode.children.end();
7320 it != itEnd;
7321 ++it )
7322 writeTestCase( **it );
7323
7324 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
7325 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
Phil Nash56d5c422012-08-23 20:08:50 +01007326 }
7327
Phil Nashaa7123b2013-08-15 19:01:00 +01007328 void writeTestCase( TestCaseNode const& testCaseNode ) {
7329 TestCaseStats const& stats = testCaseNode.value;
7330
7331 // All test cases have exactly one section - which represents the
7332 // test case itself. That section may have 0-n nested sections
7333 assert( testCaseNode.children.size() == 1 );
7334 SectionNode const& rootSection = *testCaseNode.children.front();
7335
7336 std::string className = stats.testInfo.className;
7337
7338 if( className.empty() ) {
7339 if( rootSection.childSections.empty() )
7340 className = "global";
7341 }
7342 writeSection( className, "", rootSection );
Phil Nash56d5c422012-08-23 20:08:50 +01007343 }
7344
Phil Nashaa7123b2013-08-15 19:01:00 +01007345 void writeSection( std::string const& className,
7346 std::string const& rootName,
7347 SectionNode const& sectionNode ) {
7348 std::string name = trim( sectionNode.stats.sectionInfo.name );
7349 if( !rootName.empty() )
7350 name = rootName + "/" + name;
Phil Nash56d5c422012-08-23 20:08:50 +01007351
Phil Nashaa7123b2013-08-15 19:01:00 +01007352 if( !sectionNode.assertions.empty() ||
7353 !sectionNode.stdOut.empty() ||
7354 !sectionNode.stdErr.empty() ) {
7355 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
7356 if( className.empty() ) {
7357 xml.writeAttribute( "classname", name );
7358 xml.writeAttribute( "name", "root" );
7359 }
7360 else {
7361 xml.writeAttribute( "classname", className );
7362 xml.writeAttribute( "name", name );
7363 }
7364 xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) );
Phil Nasha70fbe32012-08-31 08:10:36 +01007365
Phil Nashaa7123b2013-08-15 19:01:00 +01007366 writeAssertions( sectionNode );
Phil Nash56d5c422012-08-23 20:08:50 +01007367
Phil Nashaa7123b2013-08-15 19:01:00 +01007368 if( !sectionNode.stdOut.empty() )
7369 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
7370 if( !sectionNode.stdErr.empty() )
7371 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
7372 }
7373 for( SectionNode::ChildSections::const_iterator
7374 it = sectionNode.childSections.begin(),
7375 itEnd = sectionNode.childSections.end();
7376 it != itEnd;
7377 ++it )
7378 if( className.empty() )
7379 writeSection( name, "", **it );
7380 else
7381 writeSection( className, name, **it );
Phil Nash56d5c422012-08-23 20:08:50 +01007382 }
7383
Phil Nashaa7123b2013-08-15 19:01:00 +01007384 void writeAssertions( SectionNode const& sectionNode ) {
7385 for( SectionNode::Assertions::const_iterator
7386 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
7387 it != itEnd;
7388 ++it )
7389 writeAssertion( *it );
7390 }
7391 void writeAssertion( AssertionStats const& stats ) {
7392 AssertionResult const& result = stats.assertionResult;
7393 if( !result.isOk() ) {
7394 std::string elementName;
7395 switch( result.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007396 case ResultWas::ThrewException:
Phil Nashaa7123b2013-08-15 19:01:00 +01007397 elementName = "error";
Phil Nash56d5c422012-08-23 20:08:50 +01007398 break;
7399 case ResultWas::ExplicitFailure:
Phil Nashaa7123b2013-08-15 19:01:00 +01007400 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +01007401 break;
7402 case ResultWas::ExpressionFailed:
Phil Nashaa7123b2013-08-15 19:01:00 +01007403 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +01007404 break;
Phil Nash243f2d22013-04-12 10:43:06 +01007405 case ResultWas::DidntThrowException:
Phil Nashaa7123b2013-08-15 19:01:00 +01007406 elementName = "failure";
Phil Nash243f2d22013-04-12 10:43:06 +01007407 break;
Phil Nashaa7123b2013-08-15 19:01:00 +01007408
7409 // We should never see these here:
7410 case ResultWas::Info:
7411 case ResultWas::Warning:
7412 case ResultWas::Ok:
Phil Nash56d5c422012-08-23 20:08:50 +01007413 case ResultWas::Unknown:
7414 case ResultWas::FailureBit:
7415 case ResultWas::Exception:
Phil Nashaa7123b2013-08-15 19:01:00 +01007416 elementName = "internalError";
Phil Nash56d5c422012-08-23 20:08:50 +01007417 break;
7418 }
Phil Nashaa7123b2013-08-15 19:01:00 +01007419
7420 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
7421
7422 xml.writeAttribute( "message", result.getExpandedExpression() );
7423 xml.writeAttribute( "type", result.getTestMacroName() );
7424
7425 std::ostringstream oss;
7426 if( !result.getMessage().empty() )
7427 oss << result.getMessage() << "\n";
7428 for( std::vector<MessageInfo>::const_iterator
7429 it = stats.infoMessages.begin(),
7430 itEnd = stats.infoMessages.end();
7431 it != itEnd;
7432 ++it )
7433 if( it->type == ResultWas::Info )
7434 oss << it->message << "\n";
7435
7436 oss << "at " << result.getSourceInfo();
7437 xml.writeText( oss.str(), false );
Phil Nash56d5c422012-08-23 20:08:50 +01007438 }
7439 }
7440
Phil Nashaa7123b2013-08-15 19:01:00 +01007441 XmlWriter xml;
7442 Timer suiteTimer;
7443 std::ostringstream stdOutForSuite;
7444 std::ostringstream stdErrForSuite;
7445 unsigned int unexpectedExceptions;
Phil Nash56d5c422012-08-23 20:08:50 +01007446 };
7447
Phil Nashaa7123b2013-08-15 19:01:00 +01007448 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
7449
Phil Nash56d5c422012-08-23 20:08:50 +01007450} // end namespace Catch
7451
Phil Nashff03cdf2012-12-06 08:44:51 +00007452// #included from: ../reporters/catch_reporter_console.hpp
7453#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
7454
7455namespace Catch {
7456
Phil Nash2e7d9662013-01-16 09:44:43 +00007457 struct ConsoleReporter : StreamingReporterBase {
Phil Nashff03cdf2012-12-06 08:44:51 +00007458 ConsoleReporter( ReporterConfig const& _config )
Phil Nash2e7d9662013-01-16 09:44:43 +00007459 : StreamingReporterBase( _config ),
Phil Nasha04981b2013-03-08 09:30:25 +00007460 m_headerPrinted( false ),
Phil Nashcf5ced52012-12-14 07:50:08 +00007461 m_atLeastOneTestCasePrinted( false )
Phil Nashff03cdf2012-12-06 08:44:51 +00007462 {}
7463
7464 virtual ~ConsoleReporter();
7465 static std::string getDescription() {
7466 return "Reports test results as plain lines of text";
7467 }
7468 virtual ReporterPreferences getPreferences() const {
7469 ReporterPreferences prefs;
7470 prefs.shouldRedirectStdOut = false;
7471 return prefs;
Phil Nashff03cdf2012-12-06 08:44:51 +00007472 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007473
Phil Nash37186a12013-03-13 12:19:30 +00007474 virtual void noMatchingTestCases( std::string const& spec ) {
7475 stream << "No test cases matched '" << spec << "'" << std::endl;
7476 }
7477
Phil Nashbcad0932012-12-10 08:54:57 +00007478 virtual void assertionStarting( AssertionInfo const& ) {
Phil Nashff03cdf2012-12-06 08:44:51 +00007479 }
Phil Nashbcad0932012-12-10 08:54:57 +00007480
Phil Nashb5fd5a62013-06-28 17:09:57 +01007481 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00007482 AssertionResult const& result = _assertionStats.assertionResult;
Phil Nashbcad0932012-12-10 08:54:57 +00007483
Phil Nash8d44f2d2013-11-13 08:10:45 +00007484 bool printInfoMessages = true;
7485
Phil Nashbcad0932012-12-10 08:54:57 +00007486 // Drop out if result was successful and we're not printing those
Phil Nash8d44f2d2013-11-13 08:10:45 +00007487 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
7488 if( result.getResultType() != ResultWas::Warning )
7489 return false;
7490 printInfoMessages = false;
7491 }
Phil Nashbcad0932012-12-10 08:54:57 +00007492
7493 lazyPrint();
7494
Phil Nash8d44f2d2013-11-13 08:10:45 +00007495 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
Phil Nashe4756452013-01-26 20:18:30 +00007496 printer.print();
Phil Nash2e7d9662013-01-16 09:44:43 +00007497 stream << std::endl;
Phil Nashb5fd5a62013-06-28 17:09:57 +01007498 return true;
Phil Nash2e7d9662013-01-16 09:44:43 +00007499 }
7500
Phil Nashe4756452013-01-26 20:18:30 +00007501 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
Phil Nasha04981b2013-03-08 09:30:25 +00007502 m_headerPrinted = false;
Phil Nashe4756452013-01-26 20:18:30 +00007503 StreamingReporterBase::sectionStarting( _sectionInfo );
Phil Nash2e7d9662013-01-16 09:44:43 +00007504 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007505 virtual void sectionEnded( SectionStats const& _sectionStats ) {
7506 if( _sectionStats.missingAssertions ) {
7507 lazyPrint();
Phil Nash12c16ff2013-04-05 20:58:01 +01007508 Colour colour( Colour::ResultError );
Phil Nashaa7123b2013-08-15 19:01:00 +01007509 if( m_sectionStack.size() > 1 )
7510 stream << "\nNo assertions in section";
7511 else
7512 stream << "\nNo assertions in test case";
7513 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00007514 }
Phil Nash46118712013-08-16 19:01:32 +01007515 if( m_headerPrinted ) {
7516 if( m_config->showDurations() == ShowDurations::Always )
7517 stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
7518 m_headerPrinted = false;
7519 }
Phil Nashf7378ee2013-09-07 12:07:38 +01007520 else {
7521 if( m_config->showDurations() == ShowDurations::Always )
7522 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
7523 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007524 StreamingReporterBase::sectionEnded( _sectionStats );
7525 }
7526
7527 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00007528 StreamingReporterBase::testCaseEnded( _testCaseStats );
Phil Nasha04981b2013-03-08 09:30:25 +00007529 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +00007530 }
7531 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01007532 if( currentGroupInfo.used ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00007533 printSummaryDivider();
7534 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
7535 printTotals( _testGroupStats.totals );
7536 stream << "\n" << std::endl;
7537 }
7538 StreamingReporterBase::testGroupEnded( _testGroupStats );
7539 }
7540 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
7541 if( m_atLeastOneTestCasePrinted )
7542 printTotalsDivider();
7543 printTotals( _testRunStats.totals );
7544 stream << "\n" << std::endl;
7545 StreamingReporterBase::testRunEnded( _testRunStats );
7546 }
7547
7548 private:
Phil Nashe4756452013-01-26 20:18:30 +00007549
7550 class AssertionPrinter {
Phil Nash503d5d02013-07-03 08:25:11 +01007551 void operator= ( AssertionPrinter const& );
Phil Nashe4756452013-01-26 20:18:30 +00007552 public:
Phil Nash8d44f2d2013-11-13 08:10:45 +00007553 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +00007554 : stream( _stream ),
7555 stats( _stats ),
7556 result( _stats.assertionResult ),
Phil Nash12c16ff2013-04-05 20:58:01 +01007557 colour( Colour::None ),
Phil Nasha2773812013-02-02 20:37:58 +00007558 message( result.getMessage() ),
Phil Nash8d44f2d2013-11-13 08:10:45 +00007559 messages( _stats.infoMessages ),
7560 printInfoMessages( _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +00007561 {
7562 switch( result.getResultType() ) {
7563 case ResultWas::Ok:
Phil Nash12c16ff2013-04-05 20:58:01 +01007564 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +00007565 passOrFail = "PASSED";
Phil Nasha2773812013-02-02 20:37:58 +00007566 //if( result.hasMessage() )
7567 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00007568 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00007569 if( _stats.infoMessages.size() > 1 )
7570 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007571 break;
7572 case ResultWas::ExpressionFailed:
7573 if( result.isOk() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007574 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +00007575 passOrFail = "FAILED - but was ok";
7576 }
7577 else {
Phil Nash12c16ff2013-04-05 20:58:01 +01007578 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007579 passOrFail = "FAILED";
7580 }
Phil Nasha2773812013-02-02 20:37:58 +00007581 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00007582 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00007583 if( _stats.infoMessages.size() > 1 )
7584 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007585 break;
7586 case ResultWas::ThrewException:
Phil Nash12c16ff2013-04-05 20:58:01 +01007587 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007588 passOrFail = "FAILED";
7589 messageLabel = "due to unexpected exception with message";
7590 break;
7591 case ResultWas::DidntThrowException:
Phil Nash12c16ff2013-04-05 20:58:01 +01007592 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007593 passOrFail = "FAILED";
7594 messageLabel = "because no exception was thrown where one was expected";
7595 break;
7596 case ResultWas::Info:
7597 messageLabel = "info";
7598 break;
7599 case ResultWas::Warning:
7600 messageLabel = "warning";
7601 break;
7602 case ResultWas::ExplicitFailure:
7603 passOrFail = "FAILED";
Phil Nash12c16ff2013-04-05 20:58:01 +01007604 colour = Colour::Error;
Phil Nasha2773812013-02-02 20:37:58 +00007605 if( _stats.infoMessages.size() == 1 )
7606 messageLabel = "explicitly with message";
7607 if( _stats.infoMessages.size() > 1 )
7608 messageLabel = "explicitly with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007609 break;
Phil Nashe4756452013-01-26 20:18:30 +00007610 // These cases are here to prevent compiler warnings
7611 case ResultWas::Unknown:
7612 case ResultWas::FailureBit:
Phil Nash243f2d22013-04-12 10:43:06 +01007613 case ResultWas::Exception:
Phil Nashe4756452013-01-26 20:18:30 +00007614 passOrFail = "** internal error **";
Phil Nash12c16ff2013-04-05 20:58:01 +01007615 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00007616 break;
7617 }
7618 }
7619
7620 void print() const {
Phil Nash767f1582013-03-04 12:19:15 +01007621 printSourceInfo();
Phil Nashe4756452013-01-26 20:18:30 +00007622 if( stats.totals.assertions.total() > 0 ) {
Phil Nash767f1582013-03-04 12:19:15 +01007623 if( result.isOk() )
7624 stream << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00007625 printResultType();
7626 printOriginalExpression();
7627 printReconstructedExpression();
7628 }
Phil Nash767f1582013-03-04 12:19:15 +01007629 else {
7630 stream << "\n";
7631 }
Phil Nashe4756452013-01-26 20:18:30 +00007632 printMessage();
Phil Nashe4756452013-01-26 20:18:30 +00007633 }
7634
7635 private:
7636 void printResultType() const {
7637 if( !passOrFail.empty() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007638 Colour colourGuard( colour );
Phil Nashe4756452013-01-26 20:18:30 +00007639 stream << passOrFail << ":\n";
7640 }
7641 }
7642 void printOriginalExpression() const {
7643 if( result.hasExpression() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007644 Colour colourGuard( Colour::OriginalExpression );
Phil Nashe4756452013-01-26 20:18:30 +00007645 stream << " ";
Phil Nash786959d2013-06-07 19:07:50 +01007646 stream << result.getExpressionInMacro();
Phil Nashe4756452013-01-26 20:18:30 +00007647 stream << "\n";
7648 }
7649 }
7650 void printReconstructedExpression() const {
7651 if( result.hasExpandedExpression() ) {
7652 stream << "with expansion:\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01007653 Colour colourGuard( Colour::ReconstructedExpression );
Phil Nash19279252013-04-20 21:07:32 +01007654 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00007655 }
7656 }
7657 void printMessage() const {
7658 if( !messageLabel.empty() )
7659 stream << messageLabel << ":" << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00007660 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
7661 it != itEnd;
7662 ++it ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00007663 // If this assertion is a warning ignore any INFO messages
7664 if( printInfoMessages || it->type != ResultWas::Info )
7665 stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00007666 }
Phil Nashe4756452013-01-26 20:18:30 +00007667 }
7668 void printSourceInfo() const {
Phil Nash12c16ff2013-04-05 20:58:01 +01007669 Colour colourGuard( Colour::FileName );
Phil Nash767f1582013-03-04 12:19:15 +01007670 stream << result.getSourceInfo() << ": ";
Phil Nashe4756452013-01-26 20:18:30 +00007671 }
7672
Phil Nashe4756452013-01-26 20:18:30 +00007673 std::ostream& stream;
7674 AssertionStats const& stats;
7675 AssertionResult const& result;
Phil Nash12c16ff2013-04-05 20:58:01 +01007676 Colour::Code colour;
Phil Nashe4756452013-01-26 20:18:30 +00007677 std::string passOrFail;
7678 std::string messageLabel;
7679 std::string message;
Phil Nasha2773812013-02-02 20:37:58 +00007680 std::vector<MessageInfo> messages;
Phil Nash8d44f2d2013-11-13 08:10:45 +00007681 bool printInfoMessages;
Phil Nashe4756452013-01-26 20:18:30 +00007682 };
Phil Nash2e7d9662013-01-16 09:44:43 +00007683
7684 void lazyPrint() {
7685
Phil Nashaa7123b2013-08-15 19:01:00 +01007686 if( !currentTestRunInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +00007687 lazyPrintRunInfo();
Phil Nashaa7123b2013-08-15 19:01:00 +01007688 if( !currentGroupInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +00007689 lazyPrintGroupInfo();
Phil Nash2e7d9662013-01-16 09:44:43 +00007690
Phil Nasha04981b2013-03-08 09:30:25 +00007691 if( !m_headerPrinted ) {
7692 printTestCaseAndSectionHeader();
7693 m_headerPrinted = true;
7694 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007695 m_atLeastOneTestCasePrinted = true;
7696 }
7697 void lazyPrintRunInfo() {
Phil Nash93906752013-03-16 20:21:51 +00007698 stream << "\n" << getTildes() << "\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01007699 Colour colour( Colour::SecondaryText );
Phil Nashaa7123b2013-08-15 19:01:00 +01007700 stream << currentTestRunInfo->name
Phil Nash786959d2013-06-07 19:07:50 +01007701 << " is a Catch v" << libraryVersion.majorVersion << "."
Phil Nash2e7d9662013-01-16 09:44:43 +00007702 << libraryVersion.minorVersion << " b"
7703 << libraryVersion.buildNumber;
7704 if( libraryVersion.branchName != "master" )
7705 stream << " (" << libraryVersion.branchName << ")";
7706 stream << " host application.\n"
7707 << "Run with -? for options\n\n";
7708
Phil Nashaa7123b2013-08-15 19:01:00 +01007709 currentTestRunInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +00007710 }
7711 void lazyPrintGroupInfo() {
Phil Nashaa7123b2013-08-15 19:01:00 +01007712 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
7713 printClosedHeader( "Group: " + currentGroupInfo->name );
7714 currentGroupInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +00007715 }
7716 }
Phil Nasha04981b2013-03-08 09:30:25 +00007717 void printTestCaseAndSectionHeader() {
Phil Nashaa7123b2013-08-15 19:01:00 +01007718 assert( !m_sectionStack.empty() );
7719 printOpenHeader( currentTestCaseInfo->name );
Phil Nash2e7d9662013-01-16 09:44:43 +00007720
Phil Nashaa7123b2013-08-15 19:01:00 +01007721 if( m_sectionStack.size() > 1 ) {
7722 Colour colourGuard( Colour::Headers );
7723
7724 std::vector<SectionInfo>::const_iterator
7725 it = m_sectionStack.begin()+1, // Skip first section (test case)
7726 itEnd = m_sectionStack.end();
7727 for( ; it != itEnd; ++it )
7728 printHeaderString( it->name, 2 );
Phil Nash2e7d9662013-01-16 09:44:43 +00007729 }
Phil Nashaa7123b2013-08-15 19:01:00 +01007730
7731 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
Phil Nash19279252013-04-20 21:07:32 +01007732
7733 if( !lineInfo.empty() ){
7734 stream << getDashes() << "\n";
7735 Colour colourGuard( Colour::FileName );
7736 stream << lineInfo << "\n";
7737 }
Phil Nasha04981b2013-03-08 09:30:25 +00007738 stream << getDots() << "\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00007739 }
7740
Phil Nasha04981b2013-03-08 09:30:25 +00007741 void printClosedHeader( std::string const& _name ) {
7742 printOpenHeader( _name );
7743 stream << getDots() << "\n";
7744 }
Phil Nash19279252013-04-20 21:07:32 +01007745 void printOpenHeader( std::string const& _name ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01007746 stream << getDashes() << "\n";
Phil Nash5c7d3d72013-04-01 11:27:10 +01007747 {
Phil Nash12c16ff2013-04-05 20:58:01 +01007748 Colour colourGuard( Colour::Headers );
Phil Nash19279252013-04-20 21:07:32 +01007749 printHeaderString( _name );
Phil Nash5c7d3d72013-04-01 11:27:10 +01007750 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007751 }
7752
Phil Nash12c16ff2013-04-05 20:58:01 +01007753 // if string has a : in first line will set indent to follow it on
7754 // subsequent lines
Phil Nash19279252013-04-20 21:07:32 +01007755 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007756 std::size_t i = _string.find( ": " );
7757 if( i != std::string::npos )
7758 i+=2;
7759 else
7760 i = 0;
Phil Nash19279252013-04-20 21:07:32 +01007761 stream << Text( _string, TextAttributes()
7762 .setIndent( indent+i)
7763 .setInitialIndent( indent ) ) << "\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01007764 }
7765
Phil Nash2e7d9662013-01-16 09:44:43 +00007766 void printTotals( const Totals& totals ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00007767 if( totals.testCases.total() == 0 ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00007768 stream << "No tests ran";
7769 }
Phil Nash8d44f2d2013-11-13 08:10:45 +00007770 else if( totals.assertions.total() == 0 ) {
7771 Colour colour( Colour::Yellow );
7772 printCounts( "test case", totals.testCases );
7773 stream << " (no assertions)";
7774 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007775 else if( totals.assertions.failed ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01007776 Colour colour( Colour::ResultError );
Phil Nash2e7d9662013-01-16 09:44:43 +00007777 printCounts( "test case", totals.testCases );
7778 if( totals.testCases.failed > 0 ) {
7779 stream << " (";
7780 printCounts( "assertion", totals.assertions );
7781 stream << ")";
7782 }
Phil Nashbcad0932012-12-10 08:54:57 +00007783 }
7784 else {
Phil Nash12c16ff2013-04-05 20:58:01 +01007785 Colour colour( Colour::ResultSuccess );
Phil Nash2e7d9662013-01-16 09:44:43 +00007786 stream << "All tests passed ("
7787 << pluralise( totals.assertions.passed, "assertion" ) << " in "
7788 << pluralise( totals.testCases.passed, "test case" ) << ")";
Phil Nashbcad0932012-12-10 08:54:57 +00007789 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007790 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007791 void printCounts( std::string const& label, Counts const& counts ) {
Phil Nashf1178122012-12-11 09:03:14 +00007792 if( counts.total() == 1 ) {
7793 stream << "1 " << label << " - ";
7794 if( counts.failed )
7795 stream << "failed";
7796 else
7797 stream << "passed";
7798 }
7799 else {
7800 stream << counts.total() << " " << label << "s ";
7801 if( counts.passed ) {
7802 if( counts.failed )
7803 stream << "- " << counts.failed << " failed";
7804 else if( counts.passed == 2 )
7805 stream << "- both passed";
7806 else
7807 stream << "- all passed";
7808 }
7809 else {
7810 if( counts.failed == 2 )
7811 stream << "- both failed";
7812 else
7813 stream << "- all failed";
7814 }
7815 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007816 }
7817
Phil Nash2e7d9662013-01-16 09:44:43 +00007818 void printTotalsDivider() {
7819 stream << getDoubleDashes() << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00007820 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007821 void printSummaryDivider() {
7822 stream << getDashes() << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00007823 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007824 static std::string const& getDashes() {
Phil Nashe4756452013-01-26 20:18:30 +00007825 static const std::string dashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '-' );
Phil Nash2e7d9662013-01-16 09:44:43 +00007826 return dashes;
Phil Nashff03cdf2012-12-06 08:44:51 +00007827 }
Phil Nash3ce320d2013-01-18 08:09:28 +00007828 static std::string const& getDots() {
Phil Nashe4756452013-01-26 20:18:30 +00007829 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '.' );
Phil Nash3ce320d2013-01-18 08:09:28 +00007830 return dots;
7831 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007832 static std::string const& getDoubleDashes() {
Phil Nashe4756452013-01-26 20:18:30 +00007833 static const std::string doubleDashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
Phil Nash2e7d9662013-01-16 09:44:43 +00007834 return doubleDashes;
Phil Nashff03cdf2012-12-06 08:44:51 +00007835 }
Phil Nash93906752013-03-16 20:21:51 +00007836 static std::string const& getTildes() {
7837 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '~' );
7838 return dots;
7839 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007840
Phil Nashcf5ced52012-12-14 07:50:08 +00007841 private:
Phil Nasha04981b2013-03-08 09:30:25 +00007842 bool m_headerPrinted;
Phil Nashcf5ced52012-12-14 07:50:08 +00007843 bool m_atLeastOneTestCasePrinted;
Phil Nashff03cdf2012-12-06 08:44:51 +00007844 };
7845
7846 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
7847
7848} // end namespace Catch
7849
Phil Nasha695eb92012-08-13 07:46:10 +01007850namespace Catch {
7851 NonCopyable::~NonCopyable() {}
7852 IShared::~IShared() {}
Phil Nashad7445d2013-07-02 08:49:29 +01007853 StreamBufBase::~StreamBufBase() throw() {}
Phil Nasha695eb92012-08-13 07:46:10 +01007854 IContext::~IContext() {}
7855 IResultCapture::~IResultCapture() {}
7856 ITestCase::~ITestCase() {}
7857 ITestCaseRegistry::~ITestCaseRegistry() {}
7858 IRegistryHub::~IRegistryHub() {}
7859 IMutableRegistryHub::~IMutableRegistryHub() {}
7860 IExceptionTranslator::~IExceptionTranslator() {}
7861 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
7862 IReporter::~IReporter() {}
7863 IReporterFactory::~IReporterFactory() {}
7864 IReporterRegistry::~IReporterRegistry() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007865 IStreamingReporter::~IStreamingReporter() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007866 AssertionStats::~AssertionStats() {}
7867 SectionStats::~SectionStats() {}
7868 TestCaseStats::~TestCaseStats() {}
7869 TestGroupStats::~TestGroupStats() {}
7870 TestRunStats::~TestRunStats() {}
Phil Nashaa7123b2013-08-15 19:01:00 +01007871 CumulativeReporterBase::SectionNode::~SectionNode() {}
7872 CumulativeReporterBase::~CumulativeReporterBase() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007873
Phil Nash2e7d9662013-01-16 09:44:43 +00007874 StreamingReporterBase::~StreamingReporterBase() {}
Phil Nashff03cdf2012-12-06 08:44:51 +00007875 ConsoleReporter::~ConsoleReporter() {}
Phil Nasha695eb92012-08-13 07:46:10 +01007876 IRunner::~IRunner() {}
7877 IMutableContext::~IMutableContext() {}
7878 IConfig::~IConfig() {}
7879 XmlReporter::~XmlReporter() {}
7880 JunitReporter::~JunitReporter() {}
7881 TestRegistry::~TestRegistry() {}
7882 FreeFunctionTestCase::~FreeFunctionTestCase() {}
7883 IGeneratorInfo::~IGeneratorInfo() {}
7884 IGeneratorsForTest::~IGeneratorsForTest() {}
7885
Phil Nash9444bbc2012-10-12 07:58:17 +01007886 Matchers::Impl::StdString::Equals::~Equals() {}
7887 Matchers::Impl::StdString::Contains::~Contains() {}
7888 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
7889 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
7890
Phil Nasha695eb92012-08-13 07:46:10 +01007891 void Config::dummy() {}
7892
Phil Nasha1fbfea2012-12-01 23:57:18 +00007893 INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
Phil Nasha695eb92012-08-13 07:46:10 +01007894}
7895
Phil Nash5bc030d2012-08-16 18:48:50 +01007896#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01007897#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01007898#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -04007899
Phil Nash3649fdf2013-12-03 18:53:55 +00007900#endif // CATCH_CONFIG_MAIN || CATCH_CONFIG_RUNNER
Phil Nash89d1e6c2011-05-24 08:23:02 +01007901
Phil Nashde49ec42013-12-04 20:25:14 +00007902#ifdef CATCH_CONFIG_MAIN
Phil Nash89d1e6c2011-05-24 08:23:02 +01007903// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01007904#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007905
Phil Nash176eb812012-05-11 08:17:16 +01007906#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01007907
Phil Nash176eb812012-05-11 08:17:16 +01007908// Standard C/C++ main entry point
7909int main (int argc, char * const argv[]) {
Phil Nash786959d2013-06-07 19:07:50 +01007910 return Catch::Session().run( argc, argv );
Phil Nash176eb812012-05-11 08:17:16 +01007911}
7912
7913#else // __OBJC__
7914
7915// Objective-C entry point
7916int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00007917#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007918 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00007919#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007920
7921 Catch::registerTestMethods();
Phil Nash786959d2013-06-07 19:07:50 +01007922 int result = Catch::Session().run( argc, (char* const*)argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01007923
Phil Nash53c990a2012-03-17 18:20:06 +00007924#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007925 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00007926#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007927
Phil Nashdd5b9c22012-02-18 09:58:30 +00007928 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01007929}
7930
Phil Nash176eb812012-05-11 08:17:16 +01007931#endif // __OBJC__
7932
Phil Nash3649fdf2013-12-03 18:53:55 +00007933#endif // CATCH_CONFIG_MAIN
Phil Nash89d1e6c2011-05-24 08:23:02 +01007934
Phil Nash89d1e6c2011-05-24 08:23:02 +01007935//////
7936
Phil Nash46bcd4b2012-07-20 18:43:48 +01007937// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
7938#ifdef CATCH_CONFIG_PREFIX_ALL
7939
Phil Nash90a35942012-11-13 22:04:29 +00007940#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
7941#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007942
Phil Nash90a35942012-11-13 22:04:29 +00007943#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
7944#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
7945#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007946
Phil Nash90a35942012-11-13 22:04:29 +00007947#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
7948#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" )
7949#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
7950#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
7951#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007952
Phil Nash90a35942012-11-13 22:04:29 +00007953#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
7954#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
7955#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007956
Phil Nash90a35942012-11-13 22:04:29 +00007957#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
7958#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007959
Phil Nasha2773812013-02-02 20:37:58 +00007960#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nash859760a2013-12-14 14:34:05 +00007961#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
7962#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +01007963#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nasha2773812013-02-02 20:37:58 +00007964#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +01007965#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007966
Phil Nash93906752013-03-16 20:21:51 +00007967#ifdef CATCH_CONFIG_VARIADIC_MACROS
7968 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +01007969 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +00007970 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
7971 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +00007972 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +00007973#else
7974 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +01007975 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +00007976 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
7977 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +00007978 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
Phil Nash93906752013-03-16 20:21:51 +00007979#endif
7980#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007981
7982#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007983#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007984
7985#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
7986
Phil Nash37186a12013-03-13 12:19:30 +00007987// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +00007988#ifdef CATCH_CONFIG_VARIADIC_MACROS
7989#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
7990#else
Phil Nash37186a12013-03-13 12:19:30 +00007991#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +00007992#endif
Phil Nash37186a12013-03-13 12:19:30 +00007993#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
7994#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
7995#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
7996#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
7997#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
7998
Phil Nash46bcd4b2012-07-20 18:43:48 +01007999// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
8000#else
8001
Phil Nash90a35942012-11-13 22:04:29 +00008002#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
8003#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008004
Phil Nash90a35942012-11-13 22:04:29 +00008005#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
8006#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
8007#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008008
Phil Nash90a35942012-11-13 22:04:29 +00008009#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
8010#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" )
8011#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
8012#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
8013#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008014
Phil Nash90a35942012-11-13 22:04:29 +00008015#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
8016#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
8017#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008018
Phil Nash90a35942012-11-13 22:04:29 +00008019#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
8020#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +00008021
Phil Nasha2773812013-02-02 20:37:58 +00008022#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nash859760a2013-12-14 14:34:05 +00008023#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
8024#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +01008025#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nasha2773812013-02-02 20:37:58 +00008026#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +01008027#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008028
Phil Nash93906752013-03-16 20:21:51 +00008029#ifdef CATCH_CONFIG_VARIADIC_MACROS
8030 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +01008031 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +00008032 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
8033 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +00008034 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +00008035#else
8036 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +01008037 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +00008038 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
8039 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +00008040 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
Phil Nash93906752013-03-16 20:21:51 +00008041#endif
8042#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008043
8044#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +00008045#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008046
8047#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
8048
Phil Nash46bcd4b2012-07-20 18:43:48 +01008049#endif
8050
8051#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01008052
Phil Nash37186a12013-03-13 12:19:30 +00008053// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +00008054#ifdef CATCH_CONFIG_VARIADIC_MACROS
8055#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
8056#else
Phil Nash37186a12013-03-13 12:19:30 +00008057#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +00008058#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00008059#define GIVEN( desc ) SECTION( " Given: " desc, "" )
8060#define WHEN( desc ) SECTION( " When: " desc, "" )
8061#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
8062#define THEN( desc ) SECTION( " Then: " desc, "" )
8063#define AND_THEN( desc ) SECTION( " And: " desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +00008064
Phil Nash89d1e6c2011-05-24 08:23:02 +01008065using Catch::Detail::Approx;
8066
Phil Nash5bc030d2012-08-16 18:48:50 +01008067#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01008068#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01008069#endif
Phil Nasha695eb92012-08-13 07:46:10 +01008070
Phil Nashaec1e5e2012-05-09 19:37:51 +01008071#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01008072