blob: 240d77d15c7483be856921b91bbfe8b81a9f0061 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nash5c7d3d72013-04-01 11:27:10 +01002 * CATCH v0.9 build 30 (integration branch)
3 * Generated: 2013-04-01 11:26:11.785709
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 Nash778f9c42012-10-30 09:09:30 +000017#pragma clang diagnostic ignored "-Wglobal-constructors"
Phil Nash93906752013-03-16 20:21:51 +000018#pragma clang diagnostic ignored "-Wvariadic-macros"
Phil Nash5bc030d2012-08-16 18:48:50 +010019
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 Nash93906752013-03-16 20:21:51 +000024// Use variadic macros if the compiler supports them
25#if ( defined _MSC_VER && _MSC_VER >= 1400 && !defined __EDGE__) || \
26 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
27 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
28 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
29 #define CATCH_CONFIG_VARIADIC_MACROS
30#endif
31
Phil Nash3b80af72012-08-09 07:47:30 +010032// #included from: internal/catch_notimplemented_exception.h
33#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010034
Phil Nash89d1e6c2011-05-24 08:23:02 +010035// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010036#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010037
Phil Nash89d1e6c2011-05-24 08:23:02 +010038#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
39#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
40#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
41
42#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
43#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
44
45#ifdef __GNUC__
Phil Nasha695eb92012-08-13 07:46:10 +010046#define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
Phil Nash89d1e6c2011-05-24 08:23:02 +010047#else
Phil Nasha695eb92012-08-13 07:46:10 +010048#define CATCH_ATTRIBUTE_NORETURN
Phil Nash89d1e6c2011-05-24 08:23:02 +010049#endif
50
51#include <sstream>
52#include <stdexcept>
53#include <algorithm>
54
Phil Nash89d2a3f2012-05-16 15:09:17 +010055namespace Catch {
56
Phil Nasha04981b2013-03-08 09:30:25 +000057 class NonCopyable {
58 NonCopyable( const NonCopyable& );
59 void operator = ( const NonCopyable& );
60 protected:
61 NonCopyable() {}
62 virtual ~NonCopyable();
63 };
Phil Nash89d1e6c2011-05-24 08:23:02 +010064
Phil Nash163088a2012-05-31 19:40:26 +010065 class SafeBool {
66 public:
67 typedef void (SafeBool::*type)() const;
68
69 static type makeSafe( bool value ) {
70 return value ? &SafeBool::trueValue : 0;
71 }
72 private:
73 void trueValue() const {}
74 };
75
Phil Nash89d1e6c2011-05-24 08:23:02 +010076 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010077 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010078 typename ContainerT::const_iterator it = container.begin();
79 typename ContainerT::const_iterator itEnd = container.end();
80 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +010081 delete *it;
Phil Nash89d1e6c2011-05-24 08:23:02 +010082 }
83 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010084 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010085 typename AssociativeContainerT::const_iterator it = container.begin();
86 typename AssociativeContainerT::const_iterator itEnd = container.end();
87 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +010088 delete it->second;
Phil Nash89d1e6c2011-05-24 08:23:02 +010089 }
90
91 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010092 inline void forEach( ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010093 std::for_each( container.begin(), container.end(), function );
94 }
95
96 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010097 inline void forEach( const ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010098 std::for_each( container.begin(), container.end(), function );
99 }
100
Phil Nash56d5c422012-08-23 20:08:50 +0100101 inline bool startsWith( const std::string& s, const std::string& prefix ) {
102 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
103 }
Phil Nash4c97fc52012-08-24 08:23:50 +0100104 inline bool endsWith( const std::string& s, const std::string& suffix ) {
105 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
106 }
107 inline bool contains( const std::string& s, const std::string& infix ) {
108 return s.find( infix ) != std::string::npos;
109 }
Phil Nashdd26e882013-03-25 09:25:31 +0000110 inline void toLowerInPlace( std::string& s ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000111 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
112 }
Phil Nashdd26e882013-03-25 09:25:31 +0000113 inline std::string toLower( std::string const& s ) {
114 std::string lc = s;
115 toLowerInPlace( lc );
116 return lc;
117 }
Phil Nash4c97fc52012-08-24 08:23:50 +0100118
119 struct pluralise {
120 pluralise( std::size_t count, const std::string& label )
121 : m_count( count ),
122 m_label( label )
123 {}
124
125 friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) {
126 os << pluraliser.m_count << " " << pluraliser.m_label;
127 if( pluraliser.m_count != 1 )
Phil Nash88b70822012-11-04 21:39:38 +0000128 os << "s";
Phil Nash4c97fc52012-08-24 08:23:50 +0100129 return os;
130 }
131
132 std::size_t m_count;
133 std::string m_label;
134 };
Phil Nash56d5c422012-08-23 20:08:50 +0100135
Phil Nash89d2a3f2012-05-16 15:09:17 +0100136 struct SourceLineInfo {
137
Phil Nashd31737f2012-05-09 19:04:00 +0100138 SourceLineInfo() : line( 0 ){}
Phil Nash62179662012-05-11 19:06:43 +0100139 SourceLineInfo( const std::string& _file, std::size_t _line )
140 : file( _file ),
141 line( _line )
Phil Nash6e0f58d2012-02-15 18:37:21 +0000142 {}
Phil Nashd31737f2012-05-09 19:04:00 +0100143 SourceLineInfo( const SourceLineInfo& other )
144 : file( other.file ),
145 line( other.line )
146 {}
Phil Nash82acc2c2012-10-28 12:07:17 +0000147 bool empty() const {
148 return file.empty();
149 }
Phil Nash6e0f58d2012-02-15 18:37:21 +0000150
151 std::string file;
152 std::size_t line;
153 };
154
Phil Nashd31737f2012-05-09 19:04:00 +0100155 inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) {
Phil Nash6e0f58d2012-02-15 18:37:21 +0000156#ifndef __GNUG__
Phil Nash5c7d3d72013-04-01 11:27:10 +0100157 os << info.file << "(" << info.line << ")";
Phil Nash6e0f58d2012-02-15 18:37:21 +0000158#else
Phil Nash2e7d9662013-01-16 09:44:43 +0000159 os << info.file << ":" << info.line;
Phil Nash6e0f58d2012-02-15 18:37:21 +0000160#endif
161 return os;
162 }
163
Phil Nasha695eb92012-08-13 07:46:10 +0100164 CATCH_ATTRIBUTE_NORETURN
165 inline void throwLogicError( const std::string& message, const SourceLineInfo& locationInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100166 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +0000167 oss << locationInfo << ": Internal Catch error: '" << message << "'";
Phil Nash89d1e6c2011-05-24 08:23:02 +0100168 throw std::logic_error( oss.str() );
169 }
170}
171
Phil Nasha695eb92012-08-13 07:46:10 +0100172#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
173#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100174
Phil Nash3b80af72012-08-09 07:47:30 +0100175#include <ostream>
176
177namespace Catch {
178
179 class NotImplementedException : public std::exception
180 {
181 public:
182 NotImplementedException( const SourceLineInfo& lineInfo );
183
184 virtual ~NotImplementedException() throw() {}
185
186 virtual const char* what() const throw();
187
188 private:
189 std::string m_what;
190 SourceLineInfo m_lineInfo;
191 };
192
193} // end namespace Catch
194
195///////////////////////////////////////////////////////////////////////////////
196#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
197
198// #included from: internal/catch_context.h
199#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
200
Phil Nasha70fbe32012-08-31 08:10:36 +0100201// #included from: catch_interfaces_generators.h
202#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100203
Phil Nasha70fbe32012-08-31 08:10:36 +0100204#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000205
Phil Nash89d2a3f2012-05-16 15:09:17 +0100206namespace Catch {
207
Phil Nasha70fbe32012-08-31 08:10:36 +0100208 struct IGeneratorInfo {
209 virtual ~IGeneratorInfo();
210 virtual bool moveNext() = 0;
211 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000212 };
213
Phil Nasha70fbe32012-08-31 08:10:36 +0100214 struct IGeneratorsForTest {
215 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100216
Phil Nasha70fbe32012-08-31 08:10:36 +0100217 virtual IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) = 0;
218 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000219 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100220
221 IGeneratorsForTest* createGeneratorsForTest();
222
223} // end namespace Catch
224
225#include <memory>
226#include <vector>
227#include <stdlib.h>
228
229namespace Catch {
230
Phil Nasha1fbfea2012-12-01 23:57:18 +0000231 class TestCase;
Phil Nash67ec8702012-09-26 18:38:26 +0100232 class Stream;
Phil Nasha70fbe32012-08-31 08:10:36 +0100233 struct IResultCapture;
234 struct IRunner;
235 struct IGeneratorsForTest;
236 struct IConfig;
237
Phil Nasha70fbe32012-08-31 08:10:36 +0100238 struct IContext
239 {
240 virtual ~IContext();
241
242 virtual IResultCapture& getResultCapture() = 0;
243 virtual IRunner& getRunner() = 0;
244 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0;
245 virtual bool advanceGeneratorsForCurrentTest() = 0;
246 virtual const IConfig* getConfig() const = 0;
247 };
248
249 struct IMutableContext : IContext
250 {
251 virtual ~IMutableContext();
252 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
253 virtual void setRunner( IRunner* runner ) = 0;
254 virtual void setConfig( const IConfig* config ) = 0;
255 };
256
257 IContext& getCurrentContext();
258 IMutableContext& getCurrentMutableContext();
259 void cleanUpContext();
Phil Nash67ec8702012-09-26 18:38:26 +0100260 Stream createStream( const std::string& streamName );
Phil Nasha70fbe32012-08-31 08:10:36 +0100261
Phil Nashf7299fc2012-02-25 09:39:45 +0000262}
263
Phil Nasha70fbe32012-08-31 08:10:36 +0100264// #included from: internal/catch_test_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -0400265#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +0100266
267// #included from: catch_interfaces_testcase.h
268#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
269
Phil Nash49e6d532012-05-05 19:35:35 +0100270// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100271#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100272
Phil Nash37186a12013-03-13 12:19:30 +0000273#ifdef __clang__
274#pragma clang diagnostic push
275#pragma clang diagnostic ignored "-Wpadded"
276#endif
277
Phil Nash89d2a3f2012-05-16 15:09:17 +0100278namespace Catch {
279
Phil Nash49e6d532012-05-05 19:35:35 +0100280 // An intrusive reference counting smart pointer.
281 // T must implement addRef() and release() methods
282 // typically implementing the IShared interface
283 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100284 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100285 public:
286 Ptr() : m_p( NULL ){}
287 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100288 if( m_p )
289 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100290 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000291 Ptr( Ptr const& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100292 if( m_p )
293 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100294 }
295 ~Ptr(){
296 if( m_p )
297 m_p->release();
298 }
Phil Nashff03cdf2012-12-06 08:44:51 +0000299 void reset() {
300 if( m_p )
301 m_p->release();
302 m_p = NULL;
303 }
Phil Nash49e6d532012-05-05 19:35:35 +0100304 Ptr& operator = ( T* p ){
305 Ptr temp( p );
306 swap( temp );
307 return *this;
308 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000309 Ptr& operator = ( Ptr const& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100310 Ptr temp( other );
311 swap( temp );
312 return *this;
313 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000314 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
315 T* get() { return m_p; }
316 const T* get() const{ return m_p; }
317 T& operator*() const { return *m_p; }
318 T* operator->() const { return m_p; }
319 bool operator !() const { return m_p == NULL; }
Phil Nashff03cdf2012-12-06 08:44:51 +0000320 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
Phil Nash49e6d532012-05-05 19:35:35 +0100321
322 private:
323 T* m_p;
324 };
325
326 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100327 virtual ~IShared();
Phil Nasha1fbfea2012-12-01 23:57:18 +0000328 virtual void addRef() const = 0;
329 virtual void release() const = 0;
Phil Nash49e6d532012-05-05 19:35:35 +0100330 };
331
Phil Nasha1fbfea2012-12-01 23:57:18 +0000332 template<typename T = IShared>
Phil Nash49e6d532012-05-05 19:35:35 +0100333 struct SharedImpl : T {
334
335 SharedImpl() : m_rc( 0 ){}
336
Phil Nasha1fbfea2012-12-01 23:57:18 +0000337 virtual void addRef() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100338 ++m_rc;
339 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000340 virtual void release() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100341 if( --m_rc == 0 )
342 delete this;
343 }
344
Phil Nasha1fbfea2012-12-01 23:57:18 +0000345 mutable unsigned int m_rc;
Phil Nash49e6d532012-05-05 19:35:35 +0100346 };
347
348} // end namespace Catch
349
Phil Nash37186a12013-03-13 12:19:30 +0000350#ifdef __clang__
351#pragma clang diagnostic pop
352#endif
353
Phil Nash0f9c5512012-06-02 23:12:42 +0100354#include <vector>
355
356namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100357
358 class TestCaseFilters;
359
Phil Nash5bc030d2012-08-16 18:48:50 +0100360 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100361 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100362 protected:
363 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100364 };
365
Phil Nasha1fbfea2012-12-01 23:57:18 +0000366 class TestCase;
Phil Nash0f9c5512012-06-02 23:12:42 +0100367
368 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100369 virtual ~ITestCaseRegistry();
Phil Nasha1fbfea2012-12-01 23:57:18 +0000370 virtual const std::vector<TestCase>& getAllTests() const = 0;
371 virtual std::vector<TestCase> getMatchingTestCases( const std::string& rawTestSpec ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100372 };
373}
374
Phil Nash89d2a3f2012-05-16 15:09:17 +0100375namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100376
377template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100378class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100379
Phil Nash176eb812012-05-11 08:17:16 +0100380public:
381 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100382
Phil Nash176eb812012-05-11 08:17:16 +0100383 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100384 C obj;
385 (obj.*m_method)();
386 }
387
Phil Nash89d1e6c2011-05-24 08:23:02 +0100388private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100389 virtual ~MethodTestCase() {}
390
Phil Nash89d1e6c2011-05-24 08:23:02 +0100391 void (C::*m_method)();
392};
393
394typedef void(*TestFunction)();
395
Phil Nash93906752013-03-16 20:21:51 +0000396struct NameAndDesc {
397 NameAndDesc( const char* _name = "", const char* _description= "" )
398 : name( _name ), description( _description )
399 {}
400
401 const char* name;
402 const char* description;
403};
404
Phil Nash89d2a3f2012-05-16 15:09:17 +0100405struct AutoReg {
406
Phil Nash176eb812012-05-11 08:17:16 +0100407 AutoReg( TestFunction function,
Phil Nash93906752013-03-16 20:21:51 +0000408 SourceLineInfo const& lineInfo,
409 NameAndDesc const& nameAndDesc );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100410
Phil Nash89d1e6c2011-05-24 08:23:02 +0100411 template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100412 AutoReg( void (C::*method)(),
Phil Nash93906752013-03-16 20:21:51 +0000413 char const* className,
414 NameAndDesc const& nameAndDesc,
415 SourceLineInfo const& lineInfo ) {
416 registerTestCase( new MethodTestCase<C>( method ),
417 className,
418 nameAndDesc,
419 lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100420 }
421
Phil Nash176eb812012-05-11 08:17:16 +0100422 void registerTestCase( ITestCase* testCase,
Phil Nash93906752013-03-16 20:21:51 +0000423 char const* className,
424 NameAndDesc const& nameAndDesc,
425 SourceLineInfo const& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100426
Phil Nash176eb812012-05-11 08:17:16 +0100427 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100428
429private:
Phil Nash176eb812012-05-11 08:17:16 +0100430 AutoReg( const AutoReg& );
431 void operator= ( const AutoReg& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100432};
433
434} // end namespace Catch
435
Phil Nash93906752013-03-16 20:21:51 +0000436#ifdef CATCH_CONFIG_VARIADIC_MACROS
437 ///////////////////////////////////////////////////////////////////////////////
438 #define INTERNAL_CATCH_TESTCASE( ... ) \
439 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \
440 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
441 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100442
Phil Nash93906752013-03-16 20:21:51 +0000443 ///////////////////////////////////////////////////////////////////////////////
444 #define INTERNAL_CATCH_TESTCASE_NORETURN( ... ) \
445 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \
446 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
447 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100448
Phil Nash93906752013-03-16 20:21:51 +0000449 ///////////////////////////////////////////////////////////////////////////////
450 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
451 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100452
Phil Nash93906752013-03-16 20:21:51 +0000453 ///////////////////////////////////////////////////////////////////////////////
454 #define TEST_CASE_METHOD( ClassName, ... )\
455 namespace{ \
456 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
457 void test(); \
458 }; \
459 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
460 } \
461 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
462
463#else
464 ///////////////////////////////////////////////////////////////////////////////
465 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
466 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \
467 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
468 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
469
470 ///////////////////////////////////////////////////////////////////////////////
471 #define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
472 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \
473 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
474 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
475
476 ///////////////////////////////////////////////////////////////////////////////
477 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
478 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
479
480 ///////////////////////////////////////////////////////////////////////////////
481 #define TEST_CASE_METHOD( ClassName, TestName, Desc )\
482 namespace{ \
483 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
484 void test(); \
485 }; \
486 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
487 } \
488 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
489
490#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100491
492// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100493#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100494
Phil Nash82acc2c2012-10-28 12:07:17 +0000495// #included from: catch_expression_decomposer.hpp
496#define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100497
Phil Nash82acc2c2012-10-28 12:07:17 +0000498// #included from: catch_expression_lhs.hpp
499#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
Phil Nash176eb812012-05-11 08:17:16 +0100500
Phil Nash82acc2c2012-10-28 12:07:17 +0000501// #included from: catch_expressionresult_builder.h
502#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100503
Phil Nashd31737f2012-05-09 19:04:00 +0100504// #included from: catch_tostring.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100505#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100506
Phil Nashd31737f2012-05-09 19:04:00 +0100507#include <sstream>
Phil Nash767f1582013-03-04 12:19:15 +0100508#include <iomanip>
509#include <limits>
Phil Nashd31737f2012-05-09 19:04:00 +0100510
Phil Nash0dc9e432012-08-01 08:17:07 +0100511#ifdef __OBJC__
512// #included from: catch_objc_arc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100513#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
Phil Nash0dc9e432012-08-01 08:17:07 +0100514
515#import <Foundation/Foundation.h>
516
517#ifdef __has_feature
518#define CATCH_ARC_ENABLED __has_feature(objc_arc)
519#else
520#define CATCH_ARC_ENABLED 0
521#endif
522
523void arcSafeRelease( NSObject* obj );
524id performOptionalSelector( id obj, SEL sel );
525
526#if !CATCH_ARC_ENABLED
527inline void arcSafeRelease( NSObject* obj ) {
528 [obj release];
529}
530inline id performOptionalSelector( id obj, SEL sel ) {
531 if( [obj respondsToSelector: sel] )
532 return [obj performSelector: sel];
533 return nil;
534}
535#define CATCH_UNSAFE_UNRETAINED
536#define CATCH_ARC_STRONG
537#else
538inline void arcSafeRelease( NSObject* ){}
539inline id performOptionalSelector( id obj, SEL sel ) {
Phil Nash5bc030d2012-08-16 18:48:50 +0100540#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100541#pragma clang diagnostic push
542#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
Phil Nash5bc030d2012-08-16 18:48:50 +0100543#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100544 if( [obj respondsToSelector: sel] )
545 return [obj performSelector: sel];
Phil Nash5bc030d2012-08-16 18:48:50 +0100546#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100547#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +0100548#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100549 return nil;
550}
551#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
552#define CATCH_ARC_STRONG __strong
553#endif
554
555#endif
556
Phil Nash89d2a3f2012-05-16 15:09:17 +0100557namespace Catch {
558namespace Detail {
559
Phil Nashd31737f2012-05-09 19:04:00 +0100560 struct NonStreamable {
561 template<typename T> NonStreamable( const T& ){}
562 };
563
Phil Nash767f1582013-03-04 12:19:15 +0100564} // end namespace Detail
Phil Nashd31737f2012-05-09 19:04:00 +0100565
Phil Nash767f1582013-03-04 12:19:15 +0100566// If the type does not have its own << overload for ostream then
567// this one will be used instead
568inline std::ostream& operator << ( std::ostream& ss, Detail::NonStreamable ){
569 return ss << "{?}";
570}
571
572template<typename T>
573struct StringMaker {
574 static std::string convert( T const& value ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100575 std::ostringstream oss;
576 oss << value;
577 return oss.str();
578 }
Phil Nash767f1582013-03-04 12:19:15 +0100579};
580template<typename T>
581struct StringMaker<T*> {
582 static std::string convert( T const* p ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100583 if( !p )
584 return INTERNAL_CATCH_STRINGIFY( NULL );
585 std::ostringstream oss;
586 oss << p;
587 return oss.str();
588 }
Phil Nash767f1582013-03-04 12:19:15 +0100589};
Phil Nashd31737f2012-05-09 19:04:00 +0100590
Phil Nash767f1582013-03-04 12:19:15 +0100591template<typename T>
592struct StringMaker<std::vector<T> > {
593 static std::string convert( std::vector<T> const& v ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100594 std::ostringstream oss;
Phil Nash767f1582013-03-04 12:19:15 +0100595 oss << "{ ";
596 for( std::size_t i = 0; i < v.size(); ++ i ) {
597 oss << v[i];
598 if( i < v.size() - 1 )
599 oss << ", ";
600 }
601 oss << " }";
Phil Nashd31737f2012-05-09 19:04:00 +0100602 return oss.str();
603 }
Phil Nash767f1582013-03-04 12:19:15 +0100604};
Phil Nashd31737f2012-05-09 19:04:00 +0100605
Phil Nash767f1582013-03-04 12:19:15 +0100606namespace Detail {
607 template<typename T>
608 inline std::string makeString( const T& value ) {
609 return StringMaker<T>::convert( value );
610 }
Phil Nashd31737f2012-05-09 19:04:00 +0100611} // end namespace Detail
612
613/// \brief converts any type to a string
614///
615/// The default template forwards on to ostringstream - except when an
616/// ostringstream overload does not exist - in which case it attempts to detect
617/// that and writes {?}.
618/// Overload (not specialise) this template for custom typs that you don't want
619/// to provide an ostream overload for.
620template<typename T>
621std::string toString( const T& value ) {
Phil Nash767f1582013-03-04 12:19:15 +0100622 return StringMaker<T>::convert( value );
623// return Detail::makeString( value );
Phil Nashd31737f2012-05-09 19:04:00 +0100624}
625
626// Built in overloads
627
628inline std::string toString( const std::string& value ) {
629 return "\"" + value + "\"";
630}
631
632inline std::string toString( const std::wstring& value ) {
633 std::ostringstream oss;
634 oss << "\"";
635 for(size_t i = 0; i < value.size(); ++i )
636 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
637 oss << "\"";
638 return oss.str();
639}
640
641inline std::string toString( const char* const value ) {
642 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
643}
644
645inline std::string toString( char* const value ) {
646 return Catch::toString( static_cast<const char*>( value ) );
647}
648
649inline std::string toString( int value ) {
650 std::ostringstream oss;
651 oss << value;
652 return oss.str();
653}
654
655inline std::string toString( unsigned long value ) {
656 std::ostringstream oss;
657 if( value > 8192 )
658 oss << "0x" << std::hex << value;
659 else
660 oss << value;
661 return oss.str();
662}
663
664inline std::string toString( unsigned int value ) {
Phil Nash62179662012-05-11 19:06:43 +0100665 return toString( static_cast<unsigned long>( value ) );
Phil Nashd31737f2012-05-09 19:04:00 +0100666}
667
668inline std::string toString( const double value ) {
669 std::ostringstream oss;
Phil Nash767f1582013-03-04 12:19:15 +0100670 oss << std::setprecision (std::numeric_limits<double>::digits10 + 1)
671 << value;
Phil Nashd31737f2012-05-09 19:04:00 +0100672 return oss.str();
673}
674
675inline std::string toString( bool value ) {
676 return value ? "true" : "false";
677}
678
Phil Nash78372d02012-06-06 08:06:40 +0100679inline std::string toString( char value ) {
680 return value < ' '
Phil Nashcf5ced52012-12-14 07:50:08 +0000681 ? toString( static_cast<unsigned int>( value ) )
Phil Nash78372d02012-06-06 08:06:40 +0100682 : Detail::makeString( value );
683}
684
685inline std::string toString( signed char value ) {
686 return toString( static_cast<char>( value ) );
687}
688
Phil Nashcf5ced52012-12-14 07:50:08 +0000689inline std::string toString( unsigned char value ) {
690 return toString( static_cast<char>( value ) );
691}
692
Phil Nash176eb812012-05-11 08:17:16 +0100693#ifdef CATCH_CONFIG_CPP11_NULLPTR
Phil Nash06e959b2012-05-25 08:52:05 +0100694inline std::string toString( std::nullptr_t ) {
Phil Nash176eb812012-05-11 08:17:16 +0100695 return "nullptr";
696}
697#endif
698
Phil Nash0dc9e432012-08-01 08:17:07 +0100699#ifdef __OBJC__
Phil Nash0dc9e432012-08-01 08:17:07 +0100700 inline std::string toString( NSString const * const& nsstring ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000701 if( !nsstring )
702 return "nil";
Phil Nash0dc9e432012-08-01 08:17:07 +0100703 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
704 }
705 inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
Phil Nash6d56d712013-03-12 18:49:37 +0000706 if( !nsstring )
707 return "nil";
Phil Nash0dc9e432012-08-01 08:17:07 +0100708 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
709 }
710 inline std::string toString( NSObject* const& nsObject ) {
711 return toString( [nsObject description] );
712 }
713#endif
714
Phil Nashd31737f2012-05-09 19:04:00 +0100715} // end namespace Catch
716
Phil Nash82acc2c2012-10-28 12:07:17 +0000717// #included from: catch_assertionresult.h
718#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100719
Phil Nash89d1e6c2011-05-24 08:23:02 +0100720#include <string>
721// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100722#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100723
Phil Nash89d2a3f2012-05-16 15:09:17 +0100724namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100725
Phil Nash70c5ef92012-11-13 21:46:01 +0000726 // ResultWas::OfType enum
Phil Nashaf1a3212012-11-10 18:46:39 +0000727 struct ResultWas { enum OfType {
728 Unknown = -1,
729 Ok = 0,
730 Info = 1,
731 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100732
Phil Nashaf1a3212012-11-10 18:46:39 +0000733 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100734
Phil Nashaf1a3212012-11-10 18:46:39 +0000735 ExpressionFailed = FailureBit | 1,
736 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100737
Phil Nashaf1a3212012-11-10 18:46:39 +0000738 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100739
Phil Nashaf1a3212012-11-10 18:46:39 +0000740 ThrewException = Exception | 1,
741 DidntThrowException = Exception | 2
Phil Nash89d1e6c2011-05-24 08:23:02 +0100742
Phil Nashaf1a3212012-11-10 18:46:39 +0000743 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100744
Phil Nashaf1a3212012-11-10 18:46:39 +0000745 inline bool isOk( ResultWas::OfType resultType ) {
746 return ( resultType & ResultWas::FailureBit ) == 0;
747 }
Phil Nasha2773812013-02-02 20:37:58 +0000748 inline bool isJustInfo( int flags ) {
749 return flags == ResultWas::Info;
750 }
Phil Nash67305122012-10-09 11:48:55 +0100751
Phil Nash70c5ef92012-11-13 21:46:01 +0000752 // ResultAction::Value enum
Phil Nashaf1a3212012-11-10 18:46:39 +0000753 struct ResultAction { enum Value {
754 None,
755 Failed = 1, // Failure - but no debug break if Debug bit not set
756 Debug = 2, // If this bit is set, invoke the debugger
757 Abort = 4 // Test run should abort
758 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100759
Phil Nash70c5ef92012-11-13 21:46:01 +0000760 // ResultDisposition::Flags enum
761 struct ResultDisposition { enum Flags {
Phil Nashaf1a3212012-11-10 18:46:39 +0000762 Normal = 0x00,
763
Phil Nash70c5ef92012-11-13 21:46:01 +0000764 ContinueOnFailure = 0x01, // Failures fail test, but execution continues
765 NegateResult = 0x02, // Prefix expressiom with !
766 SuppressFail = 0x04 // Failures are reported but do not fail the test
767 }; };
768
Phil Nashaf1a3212012-11-10 18:46:39 +0000769 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
770 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
771 }
772
Phil Nash3e2e3182012-11-17 10:49:24 +0000773 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
774 inline bool shouldNegate( int flags ) { return ( flags & ResultDisposition::NegateResult ) != 0; }
775 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nashaf1a3212012-11-10 18:46:39 +0000776
777} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100778
779
Phil Nash89d2a3f2012-05-16 15:09:17 +0100780namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100781
Phil Nash82acc2c2012-10-28 12:07:17 +0000782 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100783 {
Phil Nash82acc2c2012-10-28 12:07:17 +0000784 AssertionInfo() {}
Phil Nashd539da92012-11-13 09:44:52 +0000785 AssertionInfo( const std::string& _macroName,
786 const SourceLineInfo& _lineInfo,
787 const std::string& _capturedExpression,
788 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100789
790 std::string macroName;
791 SourceLineInfo lineInfo;
792 std::string capturedExpression;
Phil Nashd539da92012-11-13 09:44:52 +0000793 ResultDisposition::Flags resultDisposition;
Phil Nash82acc2c2012-10-28 12:07:17 +0000794 };
795
796 struct AssertionResultData
797 {
798 AssertionResultData() : resultType( ResultWas::Unknown ) {}
799
Phil Nash67305122012-10-09 11:48:55 +0100800 std::string reconstructedExpression;
801 std::string message;
802 ResultWas::OfType resultType;
803 };
804
Phil Nash82acc2c2012-10-28 12:07:17 +0000805 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100806 public:
Phil Nash82acc2c2012-10-28 12:07:17 +0000807 AssertionResult();
808 AssertionResult( const AssertionInfo& info, const AssertionResultData& data );
809 ~AssertionResult();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100810
Phil Nashd539da92012-11-13 09:44:52 +0000811 bool isOk() const;
812 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100813 ResultWas::OfType getResultType() const;
814 bool hasExpression() const;
815 bool hasMessage() const;
816 std::string getExpression() const;
817 bool hasExpandedExpression() const;
818 std::string getExpandedExpression() const;
819 std::string getMessage() const;
Phil Nash82acc2c2012-10-28 12:07:17 +0000820 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100821 std::string getTestMacroName() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100822
823 protected:
Phil Nash82acc2c2012-10-28 12:07:17 +0000824 AssertionInfo m_info;
825 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100826 };
827
828} // end namespace Catch
829
Phil Nash89d1e6c2011-05-24 08:23:02 +0100830// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100831#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100832
Phil Nashdd26e882013-03-25 09:25:31 +0000833#ifdef _MSC_VER
834#pragma warning(push)
835#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
836#endif
837
Phil Nash89d2a3f2012-05-16 15:09:17 +0100838namespace Catch {
839namespace Internal {
840
841 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100842 IsEqualTo,
843 IsNotEqualTo,
844 IsLessThan,
845 IsGreaterThan,
846 IsLessThanOrEqualTo,
847 IsGreaterThanOrEqualTo
848 };
849
Phil Nash371db8b2012-05-21 18:52:09 +0100850 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
851 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
852 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
853 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
854 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
855 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
856 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100857
858 // So the compare overloads can be operator agnostic we convey the operator as a template
859 // enum, which is used to specialise an Evaluator for doing the comparison.
860 template<typename T1, typename T2, Operator Op>
861 class Evaluator{};
862
863 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100864 struct Evaluator<T1, T2, IsEqualTo> {
865 static bool evaluate( const T1& lhs, const T2& rhs) {
Phil Nashd31737f2012-05-09 19:04:00 +0100866 return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100867 }
868 };
869 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100870 struct Evaluator<T1, T2, IsNotEqualTo> {
871 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100872 return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
873 }
874 };
875 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100876 struct Evaluator<T1, T2, IsLessThan> {
877 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100878 return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
879 }
880 };
881 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100882 struct Evaluator<T1, T2, IsGreaterThan> {
883 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100884 return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
885 }
886 };
887 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100888 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
889 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100890 return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
891 }
892 };
893 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100894 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
895 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100896 return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
897 }
898 };
899
900 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100901 bool applyEvaluator( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100902 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
903 }
904
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000905 // This level of indirection allows us to specialise for integer types
906 // to avoid signed/ unsigned warnings
907
Phil Nash89d1e6c2011-05-24 08:23:02 +0100908 // "base" overload
909 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100910 bool compare( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100911 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
912 }
913
914 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +0100915 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100916 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
917 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100918 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100919 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
920 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100921 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100922 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
923 }
924
925 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +0100926 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100927 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
928 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100929 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100930 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
931 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100932 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100933 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
934 }
935
936 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100937 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100938 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
939 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100940 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100941 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
942 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100943 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100944 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
945 }
946
947 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100948 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300949 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100950 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100951 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300952 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100953 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100954 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300955 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100956 }
957
Phil Nash06e959b2012-05-25 08:52:05 +0100958 // pointer to long (when comparing against NULL)
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000959 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100960 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +0100961 }
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000962 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100963 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100964 }
965
Phil Nash06e959b2012-05-25 08:52:05 +0100966 // pointer to int (when comparing against NULL)
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000967 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +0100968 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
969 }
Phil Nashb5b1b1e2012-11-06 19:13:25 +0000970 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +0100971 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
972 }
973
Phil Nash89d1e6c2011-05-24 08:23:02 +0100974} // end of namespace Internal
975} // end of namespace Catch
976
Phil Nashdd26e882013-03-25 09:25:31 +0000977#ifdef _MSC_VER
978#pragma warning(pop)
979#endif
980
Phil Nash89d2a3f2012-05-16 15:09:17 +0100981namespace Catch {
Phil Nashf51d3162011-12-28 10:37:31 +0000982
Phil Nash82acc2c2012-10-28 12:07:17 +0000983// Wraps the (stringised versions of) the lhs, operator and rhs of an expression - as well as
984// the result of evaluating it. This is used to build an AssertionResult object
985class ExpressionResultBuilder {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100986public:
987
Phil Nash82acc2c2012-10-28 12:07:17 +0000988 ExpressionResultBuilder( ResultWas::OfType resultType = ResultWas::Unknown );
989 ExpressionResultBuilder( const ExpressionResultBuilder& other );
990 ExpressionResultBuilder& operator=(const ExpressionResultBuilder& other );
Phil Nashd31737f2012-05-09 19:04:00 +0100991
Phil Nash82acc2c2012-10-28 12:07:17 +0000992 ExpressionResultBuilder& setResultType( ResultWas::OfType result );
993 ExpressionResultBuilder& setResultType( bool result );
994 ExpressionResultBuilder& setLhs( const std::string& lhs );
995 ExpressionResultBuilder& setRhs( const std::string& rhs );
996 ExpressionResultBuilder& setOp( const std::string& op );
Phil Nash78d95a02012-03-04 21:22:36 +0000997
Phil Nashaf1a3212012-11-10 18:46:39 +0000998 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100999
Phil Nash82acc2c2012-10-28 12:07:17 +00001000 template<typename T>
1001 ExpressionResultBuilder& operator << ( const T& value ) {
1002 m_stream << value;
1003 return *this;
Phil Nash67305122012-10-09 11:48:55 +01001004 }
1005
Phil Nash82acc2c2012-10-28 12:07:17 +00001006 std::string reconstructExpression( const AssertionInfo& info ) const;
1007
1008 AssertionResult buildResult( const AssertionInfo& info ) const;
1009
Phil Nash89d1e6c2011-05-24 08:23:02 +01001010private:
Phil Nash82acc2c2012-10-28 12:07:17 +00001011 AssertionResultData m_data;
1012 struct ExprComponents {
1013 ExprComponents() : shouldNegate( false ) {}
1014 bool shouldNegate;
1015 std::string lhs, rhs, op;
1016 } m_exprComponents;
1017 std::ostringstream m_stream;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001018};
1019
Phil Nashd31737f2012-05-09 19:04:00 +01001020} // end namespace Catch
1021
Phil Nash89d2a3f2012-05-16 15:09:17 +01001022namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001023
Phil Nash134e45b2012-10-28 20:57:21 +00001024struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
Phil Nash82acc2c2012-10-28 12:07:17 +00001025
1026// Wraps the LHS of an expression and captures the operator and RHS (if any) - wrapping them all
1027// in an ExpressionResultBuilder object
Phil Nash176eb812012-05-11 08:17:16 +01001028template<typename T>
Phil Nash82acc2c2012-10-28 12:07:17 +00001029class ExpressionLhs {
Phil Nasha04981b2013-03-08 09:30:25 +00001030 void operator = ( const ExpressionLhs& );
Phil Nash176eb812012-05-11 08:17:16 +01001031
1032public:
Wichert Akkermanfec10532012-11-16 10:47:33 +01001033 ExpressionLhs( T lhs ) : m_lhs( lhs ) {}
Phil Nash176eb812012-05-11 08:17:16 +01001034
1035 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +00001036 ExpressionResultBuilder& operator == ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001037 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001038 }
1039
1040 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +00001041 ExpressionResultBuilder& operator != ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001042 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001043 }
1044
1045 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +00001046 ExpressionResultBuilder& operator < ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001047 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001048 }
1049
1050 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +00001051 ExpressionResultBuilder& operator > ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001052 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001053 }
1054
1055 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +00001056 ExpressionResultBuilder& operator <= ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001057 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001058 }
1059
1060 template<typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +00001061 ExpressionResultBuilder& operator >= ( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001062 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001063 }
1064
Phil Nash82acc2c2012-10-28 12:07:17 +00001065 ExpressionResultBuilder& operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001066 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001067 }
1068
Phil Nash82acc2c2012-10-28 12:07:17 +00001069 ExpressionResultBuilder& operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001070 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001071 }
1072
Phil Nashaf1a3212012-11-10 18:46:39 +00001073 ExpressionResultBuilder& endExpression( ResultDisposition::Flags resultDisposition ) {
Phil Nash134e45b2012-10-28 20:57:21 +00001074 bool value = m_lhs ? true : false;
1075 return m_result
1076 .setLhs( Catch::toString( value ) )
1077 .setResultType( value )
Phil Nashaf1a3212012-11-10 18:46:39 +00001078 .endExpression( resultDisposition );
Phil Nash176eb812012-05-11 08:17:16 +01001079 }
1080
Phil Nash82acc2c2012-10-28 12:07:17 +00001081 // Only simple binary expressions are allowed on the LHS.
1082 // If more complex compositions are required then place the sub expression in parentheses
1083 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& );
1084 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& );
1085 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( const RhsT& );
1086 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( const RhsT& );
Phil Nash176eb812012-05-11 08:17:16 +01001087
1088private:
Phil Nash9902ac92012-10-09 20:58:33 +01001089 template<Internal::Operator Op, typename RhsT>
Phil Nash82acc2c2012-10-28 12:07:17 +00001090 ExpressionResultBuilder& captureExpression( const RhsT& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001091 return m_result
Phil Nash82acc2c2012-10-28 12:07:17 +00001092 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
Phil Nash134e45b2012-10-28 20:57:21 +00001093 .setLhs( Catch::toString( m_lhs ) )
Phil Nash9902ac92012-10-09 20:58:33 +01001094 .setRhs( Catch::toString( rhs ) )
1095 .setOp( Internal::OperatorTraits<Op>::getName() );
1096 }
1097
1098private:
Phil Nash82acc2c2012-10-28 12:07:17 +00001099 ExpressionResultBuilder m_result;
Phil Nash176eb812012-05-11 08:17:16 +01001100 T m_lhs;
1101};
1102
Phil Nash176eb812012-05-11 08:17:16 +01001103} // end namespace Catch
1104
Phil Nash89d2a3f2012-05-16 15:09:17 +01001105namespace Catch {
1106
Phil Nash82acc2c2012-10-28 12:07:17 +00001107// Captures the LHS of the expression and wraps it in an Expression Lhs object
1108class ExpressionDecomposer {
Phil Nash89d2a3f2012-05-16 15:09:17 +01001109public:
1110
Phil Nash89d2a3f2012-05-16 15:09:17 +01001111 template<typename T>
Phil Nash82acc2c2012-10-28 12:07:17 +00001112 ExpressionLhs<const T&> operator->* ( const T & operand ) {
1113 return ExpressionLhs<const T&>( operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001114 }
1115
Phil Nash82acc2c2012-10-28 12:07:17 +00001116 ExpressionLhs<bool> operator->* ( bool value ) {
1117 return ExpressionLhs<bool>( value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001118 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001119};
1120
1121} // end namespace Catch
1122
Phil Nasha2773812013-02-02 20:37:58 +00001123// #included from: catch_message.h
1124#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1125
1126#include <string>
1127
1128namespace Catch {
1129
1130 struct MessageInfo {
1131 MessageInfo( std::string const& _macroName,
1132 SourceLineInfo const& _lineInfo,
1133 ResultWas::OfType _type );
1134
1135 std::string macroName;
1136 SourceLineInfo lineInfo;
1137 ResultWas::OfType type;
1138 std::string message;
1139 unsigned int sequence;
1140
1141 bool operator == ( MessageInfo const& other ) const {
1142 return sequence == other.sequence;
1143 }
1144 bool operator < ( MessageInfo const& other ) const {
1145 return sequence < other.sequence;
1146 }
1147 private:
1148 static unsigned int globalCount;
1149 };
1150
1151 class MessageBuilder : public MessageInfo {
1152 public:
1153 MessageBuilder( std::string const& _macroName,
1154 SourceLineInfo const& _lineInfo,
1155 ResultWas::OfType _type );
1156
1157 MessageInfo build() const;
1158
1159 template<typename T>
1160 MessageBuilder& operator << ( T const& _value ) {
1161 stream << _value;
1162 return *this;
1163 }
1164 private:
1165 std::ostringstream stream;
1166 };
1167
1168 class ScopedMessageBuilder : public MessageBuilder {
1169 public:
1170 ScopedMessageBuilder( std::string const& _macroName,
1171 SourceLineInfo const& _lineInfo,
1172 ResultWas::OfType _type );
1173 ~ScopedMessageBuilder();
1174 };
1175
1176} // end namespace Catch
1177
Phil Nashd31737f2012-05-09 19:04:00 +01001178// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001179#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001180
Phil Nashd31737f2012-05-09 19:04:00 +01001181#include <string>
Phil Nasha70fbe32012-08-31 08:10:36 +01001182// #included from: catch_totals.hpp
1183#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1184
Phil Nash9e7e63c2012-09-29 20:54:03 +01001185#include <cstddef>
1186
Phil Nasha70fbe32012-08-31 08:10:36 +01001187namespace Catch {
1188
1189 struct Counts {
Phil Nasha2773812013-02-02 20:37:58 +00001190 Counts() : passed( 0 ), failed( 0 ) {}
Phil Nasha70fbe32012-08-31 08:10:36 +01001191
1192 Counts operator - ( const Counts& other ) const {
1193 Counts diff;
1194 diff.passed = passed - other.passed;
1195 diff.failed = failed - other.failed;
1196 return diff;
1197 }
1198 Counts& operator += ( const Counts& other ) {
1199 passed += other.passed;
1200 failed += other.failed;
1201 return *this;
1202 }
1203
1204 std::size_t total() const {
1205 return passed + failed;
1206 }
1207
1208 std::size_t passed;
1209 std::size_t failed;
1210 };
1211
1212 struct Totals {
1213
1214 Totals operator - ( const Totals& other ) const {
1215 Totals diff;
1216 diff.assertions = assertions - other.assertions;
1217 diff.testCases = testCases - other.testCases;
1218 return diff;
1219 }
1220
1221 Totals delta( const Totals& prevTotals ) const {
1222 Totals diff = *this - prevTotals;
1223 if( diff.assertions.failed > 0 )
1224 ++diff.testCases.failed;
1225 else
1226 ++diff.testCases.passed;
1227 return diff;
1228 }
1229
1230 Totals& operator += ( const Totals& other ) {
1231 assertions += other.assertions;
1232 testCases += other.testCases;
1233 return *this;
1234 }
1235
1236 Counts assertions;
1237 Counts testCases;
1238 };
1239}
1240
Phil Nashd31737f2012-05-09 19:04:00 +01001241
Phil Nash89d2a3f2012-05-16 15:09:17 +01001242namespace Catch {
1243
Phil Nasha1fbfea2012-12-01 23:57:18 +00001244 class TestCase;
Phil Nash82acc2c2012-10-28 12:07:17 +00001245 class ExpressionResultBuilder;
1246 class AssertionResult;
1247 struct AssertionInfo;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001248 struct SectionInfo;
Phil Nasha2773812013-02-02 20:37:58 +00001249 class MessageBuilder;
1250 class ScopedMessageBuilder;
Phil Nashd31737f2012-05-09 19:04:00 +01001251
Phil Nash89d2a3f2012-05-16 15:09:17 +01001252 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001253
Phil Nasha695eb92012-08-13 07:46:10 +01001254 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001255
Phil Nasha2773812013-02-02 20:37:58 +00001256 virtual void assertionEnded( AssertionResult const& result ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001257 virtual bool sectionStarted( SectionInfo const& sectionInfo,
Phil Nash89d2a3f2012-05-16 15:09:17 +01001258 Counts& assertions ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001259 virtual void sectionEnded( SectionInfo const& name, Counts const& assertions ) = 0;
Phil Nasha2773812013-02-02 20:37:58 +00001260 virtual void pushScopedMessage( ScopedMessageBuilder const& _builder ) = 0;
1261 virtual void popScopedMessage( ScopedMessageBuilder const& _builder ) = 0;
1262
Phil Nash89d2a3f2012-05-16 15:09:17 +01001263 virtual bool shouldDebugBreak() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001264
Phil Nasha2773812013-02-02 20:37:58 +00001265 virtual void acceptMessage( const MessageBuilder& messageBuilder ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001266 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001267
Phil Nash89d2a3f2012-05-16 15:09:17 +01001268 virtual std::string getCurrentTestName() const = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00001269 virtual const AssertionResult* getLastResult() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001270 };
1271}
1272
1273// #included from: catch_debugger.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001274#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001275
Phil Nashd31737f2012-05-09 19:04:00 +01001276#include <iostream>
1277
1278#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1279#define CATCH_PLATFORM_MAC
1280#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1281#define CATCH_PLATFORM_IPHONE
1282#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1283#define CATCH_PLATFORM_WINDOWS
1284#endif
1285
1286#ifdef CATCH_PLATFORM_MAC
1287
1288 #include <assert.h>
1289 #include <stdbool.h>
1290 #include <sys/types.h>
1291 #include <unistd.h>
1292 #include <sys/sysctl.h>
1293
Phil Nash89d2a3f2012-05-16 15:09:17 +01001294 namespace Catch{
1295
Phil Nashd31737f2012-05-09 19:04:00 +01001296 // The following function is taken directly from the following technical note:
1297 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1298
Phil Nashd31737f2012-05-09 19:04:00 +01001299 // Returns true if the current process is being debugged (either
1300 // running under the debugger or has a debugger attached post facto).
Phil Nash89d2a3f2012-05-16 15:09:17 +01001301 inline bool isDebuggerActive(){
1302
Phil Nashd31737f2012-05-09 19:04:00 +01001303 int junk;
1304 int mib[4];
1305 struct kinfo_proc info;
1306 size_t size;
1307
1308 // Initialize the flags so that, if sysctl fails for some bizarre
1309 // reason, we get a predictable result.
1310
1311 info.kp_proc.p_flag = 0;
1312
1313 // Initialize mib, which tells sysctl the info we want, in this case
1314 // we're looking for information about a specific process ID.
1315
1316 mib[0] = CTL_KERN;
1317 mib[1] = KERN_PROC;
1318 mib[2] = KERN_PROC_PID;
1319 mib[3] = getpid();
1320
1321 // Call sysctl.
1322
1323 size = sizeof(info);
1324 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1325 assert(junk == 0);
1326
1327 // We're being debugged if the P_TRACED flag is set.
1328
1329 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1330 }
1331 }
1332
1333 // The following code snippet taken from:
1334 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1335 #ifdef DEBUG
1336 #if defined(__ppc64__) || defined(__ppc__)
1337 #define BreakIntoDebugger() \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001338 if( Catch::isDebuggerActive() ) { \
Phil Nashd31737f2012-05-09 19:04:00 +01001339 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1340 : : : "memory","r0","r3","r4" ); \
1341 }
1342 #else
1343 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1344 #endif
1345 #else
1346 inline void BreakIntoDebugger(){}
1347 #endif
1348
1349#elif defined(_MSC_VER)
1350 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1351 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001352 inline bool isDebuggerActive() {
Phil Nashd31737f2012-05-09 19:04:00 +01001353 return IsDebuggerPresent() != 0;
1354 }
Phil Nash176eb812012-05-11 08:17:16 +01001355#elif defined(__MINGW32__)
1356 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1357 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1358 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001359 inline bool isDebuggerActive() {
Phil Nash176eb812012-05-11 08:17:16 +01001360 return IsDebuggerPresent() != 0;
1361 }
Phil Nashd31737f2012-05-09 19:04:00 +01001362#else
Phil Nasha04981b2013-03-08 09:30:25 +00001363 inline void BreakIntoDebugger(){}
1364 inline bool isDebuggerActive() { return false; }
Phil Nashd31737f2012-05-09 19:04:00 +01001365#endif
1366
1367#ifdef CATCH_PLATFORM_WINDOWS
1368extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001369inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001370 ::OutputDebugStringA( text.c_str() );
1371}
1372#else
Phil Nash89d2a3f2012-05-16 15:09:17 +01001373inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001374 // !TBD: Need a version for Mac/ XCode and other IDEs
1375 std::cout << text;
1376}
1377#endif // CATCH_PLATFORM_WINDOWS
1378
Phil Nash3b80af72012-08-09 07:47:30 +01001379// #included from: catch_interfaces_registry_hub.h
1380#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1381
Phil Nasha70fbe32012-08-31 08:10:36 +01001382// #included from: catch_interfaces_reporter.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001383#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001384
1385// #included from: catch_config.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04001386#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001387
1388// #included from: catch_test_spec.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001389#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001390
1391// #included from: catch_test_case_info.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001392#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001393
1394#include <string>
Phil Nashfc1baac2012-09-15 17:53:27 +01001395#include <set>
Phil Nasha70fbe32012-08-31 08:10:36 +01001396
Phil Nash37186a12013-03-13 12:19:30 +00001397#ifdef __clang__
1398#pragma clang diagnostic push
1399#pragma clang diagnostic ignored "-Wpadded"
1400#endif
1401
Phil Nasha70fbe32012-08-31 08:10:36 +01001402namespace Catch {
1403
1404 struct ITestCase;
1405
Phil Nasha1fbfea2012-12-01 23:57:18 +00001406 struct TestCaseInfo {
1407 TestCaseInfo( const std::string& _name,
1408 const std::string& _className,
1409 const std::string& _description,
1410 const std::set<std::string>& _tags,
1411 bool _isHidden,
1412 const SourceLineInfo& _lineInfo );
Phil Nasha70fbe32012-08-31 08:10:36 +01001413
Phil Nasha70fbe32012-08-31 08:10:36 +01001414 TestCaseInfo( const TestCaseInfo& other );
1415
Phil Nasha1fbfea2012-12-01 23:57:18 +00001416 std::string name;
1417 std::string className;
1418 std::string description;
1419 std::set<std::string> tags;
Phil Nash38f7eef2013-03-29 13:44:33 +00001420 std::string tagsAsString;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001421 SourceLineInfo lineInfo;
Phil Nashff03cdf2012-12-06 08:44:51 +00001422 bool isHidden;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001423 };
1424
1425 class TestCase : protected TestCaseInfo {
1426 public:
1427
1428 TestCase( ITestCase* testCase, const TestCaseInfo& info );
1429 TestCase( const TestCase& other );
1430
1431 TestCase withName( const std::string& _newName ) const;
1432
Phil Nasha70fbe32012-08-31 08:10:36 +01001433 void invoke() const;
Phil Nash88b70822012-11-04 21:39:38 +00001434
Phil Nasha1fbfea2012-12-01 23:57:18 +00001435 const TestCaseInfo& getTestCaseInfo() const;
1436
Phil Nasha70fbe32012-08-31 08:10:36 +01001437 bool isHidden() const;
Phil Nashfc1baac2012-09-15 17:53:27 +01001438 bool hasTag( const std::string& tag ) const;
Phil Nash799ecf92012-09-24 08:30:13 +01001439 bool matchesTags( const std::string& tagPattern ) const;
Phil Nash67ec8702012-09-26 18:38:26 +01001440 const std::set<std::string>& getTags() const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001441
Phil Nasha1fbfea2012-12-01 23:57:18 +00001442 void swap( TestCase& other );
1443 bool operator == ( const TestCase& other ) const;
1444 bool operator < ( const TestCase& other ) const;
1445 TestCase& operator = ( const TestCase& other );
Phil Nasha70fbe32012-08-31 08:10:36 +01001446
1447 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00001448 Ptr<ITestCase> test;
Phil Nasha70fbe32012-08-31 08:10:36 +01001449 };
Phil Nasha1fbfea2012-12-01 23:57:18 +00001450
1451 TestCase makeTestCase( ITestCase* testCase,
1452 const std::string& className,
1453 const std::string& name,
1454 const std::string& description,
1455 const SourceLineInfo& lineInfo );
Phil Nasha70fbe32012-08-31 08:10:36 +01001456}
1457
Phil Nash37186a12013-03-13 12:19:30 +00001458#ifdef __clang__
1459#pragma clang diagnostic pop
1460#endif
1461
Phil Nash67ec8702012-09-26 18:38:26 +01001462// #included from: catch_tags.hpp
1463#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
1464
1465#include <string>
1466#include <set>
1467#include <map>
1468#include <vector>
1469
1470#ifdef __clang__
1471#pragma clang diagnostic ignored "-Wpadded"
1472#endif
1473
1474namespace Catch {
1475 class TagParser {
1476 public:
1477 virtual ~TagParser();
1478
1479 void parse( const std::string& str ) {
1480 std::size_t pos = 0;
1481 while( pos < str.size() ) {
1482 char c = str[pos];
1483 if( c == '[' ) {
1484 std::size_t end = str.find_first_of( ']', pos );
1485 if( end != std::string::npos ) {
1486 acceptTag( str.substr( pos+1, end-pos-1 ) );
1487 pos = end+1;
1488 }
1489 else {
1490 acceptChar( c );
1491 pos++;
1492 }
1493 }
1494 else {
1495 acceptChar( c );
1496 pos++;
1497 }
1498 }
1499 endParse();
1500 }
1501
1502 protected:
1503 virtual void acceptTag( const std::string& tag ) = 0;
1504 virtual void acceptChar( char c ) = 0;
1505 virtual void endParse() {}
1506
1507 private:
1508 };
1509
1510 class TagExtracter : public TagParser {
1511 public:
1512
1513 TagExtracter( std::set<std::string>& tags )
1514 : m_tags( tags )
1515 {}
1516 virtual ~TagExtracter();
1517
1518 void parse( std::string& description ) {
1519 TagParser::parse( description );
1520 description = m_remainder;
1521 }
1522
1523 private:
1524 virtual void acceptTag( const std::string& tag ) {
Phil Nashdd26e882013-03-25 09:25:31 +00001525 m_tags.insert( toLower( tag ) );
Phil Nash67ec8702012-09-26 18:38:26 +01001526 }
1527 virtual void acceptChar( char c ) {
1528 m_remainder += c;
1529 }
1530
Phil Nash88b70822012-11-04 21:39:38 +00001531 TagExtracter& operator=(const TagExtracter&);
1532
Phil Nash67ec8702012-09-26 18:38:26 +01001533 std::set<std::string>& m_tags;
1534 std::string m_remainder;
1535 };
1536
1537 class Tag {
1538 public:
1539 Tag()
Phil Nasha1dc7e32012-11-06 19:34:35 +00001540 : m_isNegated( false )
Phil Nash67ec8702012-09-26 18:38:26 +01001541 {}
1542
1543 Tag( const std::string& name, bool isNegated )
1544 : m_name( name ),
Phil Nasha1dc7e32012-11-06 19:34:35 +00001545 m_isNegated( isNegated )
Phil Nash67ec8702012-09-26 18:38:26 +01001546 {}
1547
1548 std::string getName() const {
1549 return m_name;
1550 }
1551 bool isNegated() const {
1552 return m_isNegated;
1553 }
1554
1555 bool operator ! () const {
1556 return m_name.empty();
1557 }
1558
1559 private:
1560 std::string m_name;
1561 bool m_isNegated;
1562 };
1563
1564 class TagSet {
1565 typedef std::map<std::string, Tag> TagMap;
1566 public:
1567 void add( const Tag& tag ) {
Phil Nashdd26e882013-03-25 09:25:31 +00001568 m_tags.insert( std::make_pair( toLower( tag.getName() ), tag ) );
Phil Nash67ec8702012-09-26 18:38:26 +01001569 }
1570
Phil Nash67ec8702012-09-26 18:38:26 +01001571 bool empty() const {
1572 return m_tags.empty();
1573 }
1574
1575 bool matches( const std::set<std::string>& tags ) const {
1576 TagMap::const_iterator it = m_tags.begin();
1577 TagMap::const_iterator itEnd = m_tags.end();
1578 for(; it != itEnd; ++it ) {
1579 bool found = tags.find( it->first ) != tags.end();
1580 if( found == it->second.isNegated() )
1581 return false;
1582 }
1583 return true;
1584 }
1585
1586 private:
1587 TagMap m_tags;
1588 };
1589
1590 class TagExpression {
1591 public:
1592 bool matches( const std::set<std::string>& tags ) const {
1593 std::vector<TagSet>::const_iterator it = m_tagSets.begin();
1594 std::vector<TagSet>::const_iterator itEnd = m_tagSets.end();
1595 for(; it != itEnd; ++it )
1596 if( it->matches( tags ) )
1597 return true;
1598 return false;
1599 }
1600
1601 private:
1602 friend class TagExpressionParser;
1603
1604 std::vector<TagSet> m_tagSets;
1605 };
1606
1607 class TagExpressionParser : public TagParser {
1608 public:
1609 TagExpressionParser( TagExpression& exp )
1610 : m_isNegated( false ),
1611 m_exp( exp )
1612 {}
1613
1614 ~TagExpressionParser();
1615
1616 private:
1617 virtual void acceptTag( const std::string& tag ) {
1618 m_currentTagSet.add( Tag( tag, m_isNegated ) );
1619 m_isNegated = false;
1620 }
1621 virtual void acceptChar( char c ) {
1622 switch( c ) {
1623 case '~':
1624 m_isNegated = true;
1625 break;
1626 case ',':
1627 m_exp.m_tagSets.push_back( m_currentTagSet );
1628 break;
1629 }
1630 }
1631 virtual void endParse() {
1632 if( !m_currentTagSet.empty() )
1633 m_exp.m_tagSets.push_back( m_currentTagSet );
1634 }
1635
Phil Nash88b70822012-11-04 21:39:38 +00001636 TagExpressionParser& operator=(const TagExpressionParser&);
1637
Phil Nash67ec8702012-09-26 18:38:26 +01001638 bool m_isNegated;
1639 TagSet m_currentTagSet;
1640 TagExpression& m_exp;
1641 };
1642
1643} // end namespace Catch
1644
Phil Nasha70fbe32012-08-31 08:10:36 +01001645#include <string>
1646#include <vector>
1647
1648namespace Catch {
1649
1650 struct IfFilterMatches{ enum DoWhat {
Phil Nashe2d215e2012-09-07 17:52:35 +01001651 AutoDetectBehaviour,
Phil Nasha70fbe32012-08-31 08:10:36 +01001652 IncludeTests,
1653 ExcludeTests
1654 }; };
1655
1656 class TestCaseFilter {
1657 enum WildcardPosition {
1658 NoWildcard = 0,
1659 WildcardAtStart = 1,
1660 WildcardAtEnd = 2,
1661 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
1662 };
1663
1664 public:
Phil Nashe2d215e2012-09-07 17:52:35 +01001665 TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour )
Phil Nashdd26e882013-03-25 09:25:31 +00001666 : m_stringToMatch( toLower( testSpec ) ),
Phil Nasha70fbe32012-08-31 08:10:36 +01001667 m_filterType( matchBehaviour ),
1668 m_wildcardPosition( NoWildcard )
1669 {
Phil Nashe2d215e2012-09-07 17:52:35 +01001670 if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
1671 if( startsWith( m_stringToMatch, "exclude:" ) ) {
1672 m_stringToMatch = m_stringToMatch.substr( 8 );
1673 m_filterType = IfFilterMatches::ExcludeTests;
1674 }
1675 else if( startsWith( m_stringToMatch, "~" ) ) {
1676 m_stringToMatch = m_stringToMatch.substr( 1 );
1677 m_filterType = IfFilterMatches::ExcludeTests;
1678 }
1679 else {
1680 m_filterType = IfFilterMatches::IncludeTests;
1681 }
1682 }
1683
Phil Nashbd7f7972013-03-21 09:00:24 +00001684 if( startsWith( m_stringToMatch, "*" ) ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01001685 m_stringToMatch = m_stringToMatch.substr( 1 );
1686 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
1687 }
Phil Nashbd7f7972013-03-21 09:00:24 +00001688 if( endsWith( m_stringToMatch, "*" ) ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01001689 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
1690 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
1691 }
1692 }
1693
1694 IfFilterMatches::DoWhat getFilterType() const {
1695 return m_filterType;
1696 }
1697
Phil Nasha1fbfea2012-12-01 23:57:18 +00001698 bool shouldInclude( const TestCase& testCase ) const {
Phil Nasha70fbe32012-08-31 08:10:36 +01001699 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
1700 }
1701 private:
1702
1703#ifdef __clang__
1704#pragma clang diagnostic push
1705#pragma clang diagnostic ignored "-Wunreachable-code"
1706#endif
1707
Phil Nasha1fbfea2012-12-01 23:57:18 +00001708 bool isMatch( const TestCase& testCase ) const {
Phil Nash6d56d712013-03-12 18:49:37 +00001709 std::string name = testCase.getTestCaseInfo().name;
Phil Nashdd26e882013-03-25 09:25:31 +00001710 toLowerInPlace( name );
Phil Nasha70fbe32012-08-31 08:10:36 +01001711
1712 switch( m_wildcardPosition ) {
1713 case NoWildcard:
1714 return m_stringToMatch == name;
1715 case WildcardAtStart:
1716 return endsWith( name, m_stringToMatch );
1717 case WildcardAtEnd:
1718 return startsWith( name, m_stringToMatch );
1719 case WildcardAtBothEnds:
1720 return contains( name, m_stringToMatch );
1721 }
1722 throw std::logic_error( "Unhandled wildcard type" );
1723 }
1724
1725#ifdef __clang__
1726#pragma clang diagnostic pop
1727#endif
1728
1729 std::string m_stringToMatch;
1730 IfFilterMatches::DoWhat m_filterType;
1731 WildcardPosition m_wildcardPosition;
1732 };
1733
1734 class TestCaseFilters {
1735 public:
1736 TestCaseFilters( const std::string& name ) : m_name( name ) {}
1737
1738 std::string getName() const {
1739 return m_name;
1740 }
1741
1742 void addFilter( const TestCaseFilter& filter ) {
1743 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
1744 m_exclusionFilters.push_back( filter );
1745 else
1746 m_inclusionFilters.push_back( filter );
1747 }
1748
Phil Nash67ec8702012-09-26 18:38:26 +01001749 void addTags( const std::string& tagPattern ) {
1750 TagExpression exp;
1751 TagExpressionParser( exp ).parse( tagPattern );
1752
1753 m_tagExpressions.push_back( exp );
1754 }
1755
Phil Nasha1fbfea2012-12-01 23:57:18 +00001756 bool shouldInclude( const TestCase& testCase ) const {
Phil Nash67ec8702012-09-26 18:38:26 +01001757 if( !m_tagExpressions.empty() ) {
1758 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
1759 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
1760 for(; it != itEnd; ++it )
1761 if( it->matches( testCase.getTags() ) )
1762 break;
1763 if( it == itEnd )
1764 return false;
1765 }
1766
Phil Nasha70fbe32012-08-31 08:10:36 +01001767 if( !m_inclusionFilters.empty() ) {
1768 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
1769 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
1770 for(; it != itEnd; ++it )
1771 if( it->shouldInclude( testCase ) )
1772 break;
1773 if( it == itEnd )
1774 return false;
1775 }
Phil Nash67ec8702012-09-26 18:38:26 +01001776 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
Phil Nashfc1baac2012-09-15 17:53:27 +01001777 return !testCase.isHidden();
1778 }
1779
Phil Nasha70fbe32012-08-31 08:10:36 +01001780 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
1781 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
1782 for(; it != itEnd; ++it )
1783 if( !it->shouldInclude( testCase ) )
1784 return false;
1785 return true;
1786 }
1787 private:
Phil Nash67ec8702012-09-26 18:38:26 +01001788 std::vector<TagExpression> m_tagExpressions;
Phil Nasha70fbe32012-08-31 08:10:36 +01001789 std::vector<TestCaseFilter> m_inclusionFilters;
1790 std::vector<TestCaseFilter> m_exclusionFilters;
1791 std::string m_name;
1792 };
1793
1794}
1795
1796// #included from: catch_interfaces_config.h
1797#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
1798
1799namespace Catch {
1800
1801 struct IConfig {
1802
1803 virtual ~IConfig();
1804
1805 virtual bool allowThrows() const = 0;
1806 };
1807}
1808
Phil Nash67ec8702012-09-26 18:38:26 +01001809// #included from: catch_stream.hpp
1810#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
1811
Phil Nash9e7e63c2012-09-29 20:54:03 +01001812// #included from: catch_streambuf.h
1813#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
1814
1815#include <streambuf>
1816
1817namespace Catch {
1818
1819 class StreamBufBase : public std::streambuf {
1820 public:
1821 virtual ~StreamBufBase();
1822 };
1823}
1824
Phil Nash67ec8702012-09-26 18:38:26 +01001825#include <stdexcept>
1826#include <cstdio>
1827
1828namespace Catch {
1829
1830 template<typename WriterF, size_t bufferSize=256>
1831 class StreamBufImpl : public StreamBufBase {
1832 char data[bufferSize];
1833 WriterF m_writer;
1834
1835 public:
1836 StreamBufImpl() {
1837 setp( data, data + sizeof(data) );
1838 }
1839
1840 ~StreamBufImpl() {
1841 sync();
1842 }
1843
1844 private:
Phil Nasha04981b2013-03-08 09:30:25 +00001845 int overflow( int c ) {
Phil Nash67ec8702012-09-26 18:38:26 +01001846 sync();
1847
1848 if( c != EOF ) {
1849 if( pbase() == epptr() )
1850 m_writer( std::string( 1, static_cast<char>( c ) ) );
1851 else
1852 sputc( static_cast<char>( c ) );
1853 }
1854 return 0;
1855 }
1856
Phil Nasha04981b2013-03-08 09:30:25 +00001857 int sync() {
Phil Nash67ec8702012-09-26 18:38:26 +01001858 if( pbase() != pptr() ) {
1859 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
1860 setp( pbase(), epptr() );
1861 }
1862 return 0;
1863 }
1864 };
1865
1866 ///////////////////////////////////////////////////////////////////////////
1867
1868 struct OutputDebugWriter {
1869
1870 void operator()( const std::string &str ) {
1871 writeToDebugConsole( str );
1872 }
1873 };
1874
1875 class Stream {
1876 public:
1877 Stream()
1878 : streamBuf( NULL ), isOwned( false )
1879 {}
1880
1881 Stream( std::streambuf* _streamBuf, bool _isOwned )
1882 : streamBuf( _streamBuf ), isOwned( _isOwned )
1883 {}
1884
1885 void release() {
1886 if( isOwned ) {
1887 delete streamBuf;
1888 streamBuf = NULL;
1889 isOwned = false;
1890 }
1891 }
1892
1893 std::streambuf* streamBuf;
1894
1895 private:
1896 bool isOwned;
1897 };
1898}
1899
Phil Nasha70fbe32012-08-31 08:10:36 +01001900#include <memory>
1901#include <vector>
1902#include <string>
1903#include <iostream>
1904
Phil Nashe4756452013-01-26 20:18:30 +00001905#ifndef CATCH_CONFIG_CONSOLE_WIDTH
1906#define CATCH_CONFIG_CONSOLE_WIDTH 80
1907#endif
1908
Phil Nasha70fbe32012-08-31 08:10:36 +01001909namespace Catch {
1910
1911 struct Include { enum WhichResults {
1912 FailedOnly,
1913 SuccessfulResults
1914 }; };
1915
1916 struct List{ enum What {
1917 None = 0,
1918
1919 Reports = 1,
1920 Tests = 2,
Phil Nash38f7eef2013-03-29 13:44:33 +00001921 Tags = 4,
1922 All = Reports | Tests | Tags,
Phil Nasha70fbe32012-08-31 08:10:36 +01001923
1924 WhatMask = 0xf,
1925
1926 AsText = 0x10,
1927 AsXml = 0x20,
1928
1929 AsMask = 0xf0
1930 }; };
1931
1932 struct ConfigData {
1933
1934 struct WarnAbout { enum What {
1935 Nothing = 0x00,
1936 NoAssertions = 0x01
1937 }; };
1938
1939 ConfigData()
1940 : listSpec( List::None ),
1941 shouldDebugBreak( false ),
1942 includeWhichResults( Include::FailedOnly ),
1943 cutoff( -1 ),
1944 allowThrows( true ),
1945 warnings( WarnAbout::Nothing )
1946 {}
1947
1948 std::string reporter;
1949 std::string outputFilename;
1950 List::What listSpec;
1951 std::vector<TestCaseFilters> filters;
1952 bool shouldDebugBreak;
1953 std::string stream;
1954 Include::WhichResults includeWhichResults;
1955 std::string name;
1956 int cutoff;
1957 bool allowThrows;
1958 WarnAbout::What warnings;
1959 };
1960
1961 class Config : public IConfig {
1962 private:
1963 Config( const Config& other );
1964 Config& operator = ( const Config& other );
1965 virtual void dummy();
1966 public:
1967
1968 Config()
Phil Nash67ec8702012-09-26 18:38:26 +01001969 : m_os( std::cout.rdbuf() )
Phil Nasha70fbe32012-08-31 08:10:36 +01001970 {}
1971
1972 Config( const ConfigData& data )
1973 : m_data( data ),
Phil Nasha70fbe32012-08-31 08:10:36 +01001974 m_os( std::cout.rdbuf() )
1975 {}
1976
1977 virtual ~Config() {
1978 m_os.rdbuf( std::cout.rdbuf() );
Phil Nash67ec8702012-09-26 18:38:26 +01001979 m_stream.release();
Phil Nasha70fbe32012-08-31 08:10:36 +01001980 }
1981
1982 void setFilename( const std::string& filename ) {
1983 m_data.outputFilename = filename;
1984 }
1985
1986 List::What getListSpec( void ) const {
1987 return m_data.listSpec;
1988 }
1989
1990 const std::string& getFilename() const {
1991 return m_data.outputFilename ;
1992 }
1993
1994 List::What listWhat() const {
1995 return static_cast<List::What>( m_data.listSpec & List::WhatMask );
1996 }
1997
1998 List::What listAs() const {
1999 return static_cast<List::What>( m_data.listSpec & List::AsMask );
2000 }
2001
2002 std::string getName() const {
2003 return m_data.name;
2004 }
2005
2006 bool shouldDebugBreak() const {
2007 return m_data.shouldDebugBreak;
2008 }
2009
2010 virtual std::ostream& stream() const {
2011 return m_os;
2012 }
2013
2014 void setStreamBuf( std::streambuf* buf ) {
2015 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2016 }
2017
2018 void useStream( const std::string& streamName ) {
Phil Nash67ec8702012-09-26 18:38:26 +01002019 Stream stream = createStream( streamName );
2020 setStreamBuf( stream.streamBuf );
2021 m_stream.release();
2022 m_stream = stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002023 }
2024
Phil Nashe2d215e2012-09-07 17:52:35 +01002025 void addTestSpec( const std::string& testSpec ) {
2026 TestCaseFilters filters( testSpec );
2027 filters.addFilter( TestCaseFilter( testSpec ) );
2028 m_data.filters.push_back( filters );
2029 }
2030
Phil Nasha70fbe32012-08-31 08:10:36 +01002031 virtual bool includeSuccessfulResults() const {
2032 return m_data.includeWhichResults == Include::SuccessfulResults;
2033 }
2034
2035 int getCutoff() const {
2036 return m_data.cutoff;
2037 }
2038
2039 virtual bool allowThrows() const {
2040 return m_data.allowThrows;
2041 }
2042
2043 const ConfigData& data() const {
2044 return m_data;
2045 }
2046 ConfigData& data() {
2047 return m_data;
2048 }
2049
2050 private:
2051 ConfigData m_data;
2052
2053 // !TBD Move these out of here
Phil Nash67ec8702012-09-26 18:38:26 +01002054 Stream m_stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002055 mutable std::ostream m_os;
2056 };
2057
2058} // end namespace Catch
2059
Phil Nashff03cdf2012-12-06 08:44:51 +00002060// #included from: catch_option.hpp
2061#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2062
2063namespace Catch {
2064
2065 // An optional type
2066 template<typename T>
2067 class Option {
2068 public:
2069 Option() : nullableValue( NULL ) {}
2070 Option( T const& _value )
2071 : nullableValue( new( storage ) T( _value ) )
2072 {}
2073 Option( Option const& _other )
2074 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
2075 {}
2076
2077 ~Option() {
2078 reset();
2079 }
2080
2081 Option& operator= ( Option const& _other ) {
2082 reset();
2083 if( _other )
2084 nullableValue = new( storage ) T( *_other );
2085 return *this;
2086 }
2087
2088 void reset() {
2089 if( nullableValue )
2090 nullableValue->~T();
2091 nullableValue = NULL;
2092 }
2093 T& operator*() { return *nullableValue; }
2094 const T& operator*() const { return *nullableValue; }
2095 T* operator->() { return nullableValue; }
2096 const T* operator->() const { return nullableValue; }
2097
2098 bool some() const { return nullableValue != NULL; }
2099 bool none() const { return nullableValue == NULL; }
2100
2101 bool operator !() const { return nullableValue == NULL; }
2102 operator SafeBool::type() const {
2103 return SafeBool::makeSafe( some() );
2104 }
2105
2106 private:
2107 T* nullableValue;
2108 char storage[sizeof(T)];
2109 };
2110
2111} // end namespace Catch
2112
Phil Nasha70fbe32012-08-31 08:10:36 +01002113#include <string>
2114#include <ostream>
2115#include <map>
2116
2117namespace Catch
2118{
Phil Nasha1fbfea2012-12-01 23:57:18 +00002119 struct ReporterConfig {
2120 ReporterConfig( std::ostream& _stream, ConfigData const& _fullConfig )
2121 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
2122
Phil Nashff03cdf2012-12-06 08:44:51 +00002123 std::ostream& stream() const { return *m_stream; }
Phil Nasha1fbfea2012-12-01 23:57:18 +00002124 std::string name() const { return m_fullConfig.name; }
2125 bool includeSuccessfulResults() const { return m_fullConfig.includeWhichResults == Include::SuccessfulResults; }
2126 bool warnAboutMissingAssertions() const { return m_fullConfig.warnings & ConfigData::WarnAbout::NoAssertions; }
2127
2128 private:
2129 std::ostream* m_stream;
2130 ConfigData m_fullConfig;
2131 };
2132
2133 struct ReporterPreferences {
2134 ReporterPreferences()
2135 : shouldRedirectStdOut( false )
Phil Nasha70fbe32012-08-31 08:10:36 +01002136 {}
2137
Phil Nasha1fbfea2012-12-01 23:57:18 +00002138 bool shouldRedirectStdOut;
2139 };
2140
2141 struct TestRunInfo {
2142 TestRunInfo( std::string const& _name ) : name( _name ) {}
2143 std::string name;
2144 };
2145 struct GroupInfo {
Phil Nash2e7d9662013-01-16 09:44:43 +00002146 GroupInfo( std::string const& _name,
2147 std::size_t _groupIndex,
2148 std::size_t _groupsCount )
2149 : name( _name ),
2150 groupIndex( _groupIndex ),
2151 groupsCounts( _groupsCount )
2152 {}
2153
Phil Nasha1fbfea2012-12-01 23:57:18 +00002154 std::string name;
Phil Nash2e7d9662013-01-16 09:44:43 +00002155 std::size_t groupIndex;
2156 std::size_t groupsCounts;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002157 };
2158
2159 struct SectionInfo {
2160 SectionInfo( std::string const& _name,
2161 std::string const& _description,
2162 SourceLineInfo const& _lineInfo )
2163 : name( _name ),
2164 description( _description ),
2165 lineInfo( _lineInfo )
Phil Nash799ecf92012-09-24 08:30:13 +01002166 {}
2167
Phil Nasha70fbe32012-08-31 08:10:36 +01002168 std::string name;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002169 std::string description;
2170 SourceLineInfo lineInfo;
Phil Nasha70fbe32012-08-31 08:10:36 +01002171 };
2172
Phil Nashff03cdf2012-12-06 08:44:51 +00002173 struct ThreadedSectionInfo : SectionInfo, SharedImpl<> {
Phil Nashe4756452013-01-26 20:18:30 +00002174 ThreadedSectionInfo( SectionInfo const& _sectionInfo, ThreadedSectionInfo* _parent = NULL )
Phil Nashff03cdf2012-12-06 08:44:51 +00002175 : SectionInfo( _sectionInfo ),
Phil Nash2e7d9662013-01-16 09:44:43 +00002176 parent( _parent )
Phil Nashff03cdf2012-12-06 08:44:51 +00002177 {}
2178 virtual ~ThreadedSectionInfo();
2179
2180 std::vector<Ptr<ThreadedSectionInfo> > children;
Phil Nashe4756452013-01-26 20:18:30 +00002181 ThreadedSectionInfo* parent;
Phil Nashff03cdf2012-12-06 08:44:51 +00002182 };
2183
Phil Nash2e7d9662013-01-16 09:44:43 +00002184 struct AssertionStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002185 AssertionStats( AssertionResult const& _assertionResult,
Phil Nasha2773812013-02-02 20:37:58 +00002186 std::vector<MessageInfo> const& _infoMessages,
Phil Nasha1fbfea2012-12-01 23:57:18 +00002187 Totals const& _totals )
2188 : assertionResult( _assertionResult ),
Phil Nasha2773812013-02-02 20:37:58 +00002189 infoMessages( _infoMessages ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00002190 totals( _totals )
Phil Nasha2773812013-02-02 20:37:58 +00002191 {
2192 if( assertionResult.hasMessage() ) {
2193 // Copy message into messages list.
2194 // !TBD This should have been done earlier, somewhere
2195 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
2196 builder << assertionResult.getMessage();
2197 infoMessages.push_back( builder.build() );
2198 }
2199 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00002200 virtual ~AssertionStats();
Phil Nasha70fbe32012-08-31 08:10:36 +01002201
Phil Nasha1fbfea2012-12-01 23:57:18 +00002202 AssertionResult assertionResult;
Phil Nasha2773812013-02-02 20:37:58 +00002203 std::vector<MessageInfo> infoMessages;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002204 Totals totals;
2205 };
2206
Phil Nash2e7d9662013-01-16 09:44:43 +00002207 struct SectionStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002208 SectionStats( SectionInfo const& _sectionInfo,
2209 Counts const& _assertions,
2210 bool _missingAssertions )
2211 : sectionInfo( _sectionInfo ),
2212 assertions( _assertions ),
2213 missingAssertions( _missingAssertions )
2214 {}
2215 virtual ~SectionStats();
2216
2217 SectionInfo sectionInfo;
2218 Counts assertions;
2219 bool missingAssertions;
2220 };
2221
Phil Nash2e7d9662013-01-16 09:44:43 +00002222 struct TestCaseStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002223 TestCaseStats( TestCaseInfo const& _testInfo,
2224 Totals const& _totals,
2225 std::string const& _stdOut,
2226 std::string const& _stdErr,
2227 bool _missingAssertions,
2228 bool _aborting )
2229 : testInfo( _testInfo ),
2230 totals( _totals ),
2231 stdOut( _stdOut ),
2232 stdErr( _stdErr ),
2233 missingAssertions( _missingAssertions ),
2234 aborting( _aborting )
2235 {}
2236 virtual ~TestCaseStats();
2237
2238 TestCaseInfo testInfo;
2239 Totals totals;
2240 std::string stdOut;
2241 std::string stdErr;
2242 bool missingAssertions;
2243 bool aborting;
2244 };
2245
Phil Nash2e7d9662013-01-16 09:44:43 +00002246 struct TestGroupStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002247 TestGroupStats( GroupInfo const& _groupInfo,
2248 Totals const& _totals,
2249 bool _aborting )
2250 : groupInfo( _groupInfo ),
2251 totals( _totals ),
2252 aborting( _aborting )
2253 {}
Phil Nash2e7d9662013-01-16 09:44:43 +00002254 TestGroupStats( GroupInfo const& _groupInfo )
2255 : groupInfo( _groupInfo ),
2256 aborting( false )
2257 {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00002258 virtual ~TestGroupStats();
2259
2260 GroupInfo groupInfo;
2261 Totals totals;
2262 bool aborting;
2263 };
2264
Phil Nash2e7d9662013-01-16 09:44:43 +00002265 struct TestRunStats {
Phil Nasha1fbfea2012-12-01 23:57:18 +00002266 TestRunStats( TestRunInfo const& _runInfo,
2267 Totals const& _totals,
2268 bool _aborting )
2269 : runInfo( _runInfo ),
2270 totals( _totals ),
2271 aborting( _aborting )
2272 {}
Phil Nash2e7d9662013-01-16 09:44:43 +00002273 TestRunStats( TestRunStats const& _other )
2274 : runInfo( _other.runInfo ),
2275 totals( _other.totals ),
2276 aborting( _other.aborting )
2277 {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00002278 virtual ~TestRunStats();
2279
2280 TestRunInfo runInfo;
2281 Totals totals;
2282 bool aborting;
2283 };
2284
2285 // !Work In progress
2286 struct IStreamingReporter : IShared {
2287 virtual ~IStreamingReporter();
Phil Nashff03cdf2012-12-06 08:44:51 +00002288
Phil Nash2e7d9662013-01-16 09:44:43 +00002289 // Implementing class must also provide the following static method:
Phil Nashff03cdf2012-12-06 08:44:51 +00002290 // static std::string getDescription();
2291
Phil Nasha1fbfea2012-12-01 23:57:18 +00002292 virtual ReporterPreferences getPreferences() const = 0;
2293
Phil Nash37186a12013-03-13 12:19:30 +00002294 virtual void noMatchingTestCases( std::string const& spec ) = 0;
2295
Phil Nasha1fbfea2012-12-01 23:57:18 +00002296 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
2297 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
2298
2299 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
2300 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
2301
2302 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
2303
Phil Nash2e7d9662013-01-16 09:44:43 +00002304 virtual void assertionEnded( AssertionStats const& assertionStats ) = 0;
2305 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
2306 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
2307 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
2308 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002309 };
Phil Nashff03cdf2012-12-06 08:44:51 +00002310
Phil Nash2e7d9662013-01-16 09:44:43 +00002311 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
2312
2313 StreamingReporterBase( ReporterConfig const& _config )
Phil Nashbcad0932012-12-10 08:54:57 +00002314 : m_config( _config ),
2315 stream( _config.stream() )
Phil Nashff03cdf2012-12-06 08:44:51 +00002316 {}
2317
Phil Nash2e7d9662013-01-16 09:44:43 +00002318 virtual ~StreamingReporterBase();
Phil Nashff03cdf2012-12-06 08:44:51 +00002319
Phil Nash37186a12013-03-13 12:19:30 +00002320 virtual void noMatchingTestCases( std::string const& ) {}
2321
Phil Nashff03cdf2012-12-06 08:44:51 +00002322 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
2323 testRunInfo = _testRunInfo;
2324 }
2325 virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
2326 unusedGroupInfo = _groupInfo;
2327 }
2328
2329 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
2330 unusedTestCaseInfo = _testInfo;
2331 }
2332 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
2333 Ptr<ThreadedSectionInfo> sectionInfo = new ThreadedSectionInfo( _sectionInfo );
Phil Nashff03cdf2012-12-06 08:44:51 +00002334 if( !currentSectionInfo ) {
2335 currentSectionInfo = sectionInfo;
Phil Nashe4756452013-01-26 20:18:30 +00002336 m_rootSections.push_back( currentSectionInfo );
Phil Nashff03cdf2012-12-06 08:44:51 +00002337 }
2338 else {
2339 currentSectionInfo->children.push_back( sectionInfo );
Phil Nashe4756452013-01-26 20:18:30 +00002340 sectionInfo->parent = currentSectionInfo.get();
Phil Nashff03cdf2012-12-06 08:44:51 +00002341 currentSectionInfo = sectionInfo;
2342 }
2343 }
2344
Phil Nash2e7d9662013-01-16 09:44:43 +00002345 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
Phil Nashff03cdf2012-12-06 08:44:51 +00002346 currentSectionInfo = currentSectionInfo->parent;
Phil Nashff03cdf2012-12-06 08:44:51 +00002347 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002348 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
Phil Nashff03cdf2012-12-06 08:44:51 +00002349 unusedTestCaseInfo.reset();
2350 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002351 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
Phil Nashff03cdf2012-12-06 08:44:51 +00002352 unusedGroupInfo.reset();
2353 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002354 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
2355 currentSectionInfo.reset();
Phil Nash2e7d9662013-01-16 09:44:43 +00002356 unusedTestCaseInfo.reset();
2357 unusedGroupInfo.reset();
2358 testRunInfo.reset();
Phil Nashff03cdf2012-12-06 08:44:51 +00002359 }
2360
Phil Nashbcad0932012-12-10 08:54:57 +00002361 ReporterConfig m_config;
Phil Nashff03cdf2012-12-06 08:44:51 +00002362 Option<TestRunInfo> testRunInfo;
2363 Option<GroupInfo> unusedGroupInfo;
2364 Option<TestCaseInfo> unusedTestCaseInfo;
Phil Nashff03cdf2012-12-06 08:44:51 +00002365 Ptr<ThreadedSectionInfo> currentSectionInfo;
Phil Nash2e7d9662013-01-16 09:44:43 +00002366 std::ostream& stream;
Phil Nashe4756452013-01-26 20:18:30 +00002367
2368 // !TBD: This should really go in the TestCaseStats class
2369 std::vector<Ptr<ThreadedSectionInfo> > m_rootSections;
Phil Nash2e7d9662013-01-16 09:44:43 +00002370 };
2371
2372 struct TestGroupNode : TestGroupStats {
2373 TestGroupNode( TestGroupStats const& _stats ) : TestGroupStats( _stats ) {}
2374// TestGroupNode( GroupInfo const& _info ) : TestGroupStats( _stats ) {}
2375 ~TestGroupNode();
2376
2377 };
2378
2379 struct TestRunNode : TestRunStats {
2380
2381 TestRunNode( TestRunStats const& _stats ) : TestRunStats( _stats ) {}
2382 ~TestRunNode();
2383
2384 std::vector<TestGroupNode> groups;
2385 };
2386
Phil Nasha1fbfea2012-12-01 23:57:18 +00002387 // Deprecated
Phil Nasha70fbe32012-08-31 08:10:36 +01002388 struct IReporter : IShared {
2389 virtual ~IReporter();
Phil Nash82acc2c2012-10-28 12:07:17 +00002390
Phil Nasha70fbe32012-08-31 08:10:36 +01002391 virtual bool shouldRedirectStdout() const = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00002392
Phil Nasha70fbe32012-08-31 08:10:36 +01002393 virtual void StartTesting() = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002394 virtual void EndTesting( Totals const& totals ) = 0;
2395 virtual void StartGroup( std::string const& groupName ) = 0;
2396 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
2397 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
2398 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
2399 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
2400 virtual void EndSection( std::string const& sectionName, const Counts& assertions ) = 0;
2401 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
2402 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002403 virtual void Aborted() = 0;
Phil Nash82acc2c2012-10-28 12:07:17 +00002404 virtual void Result( const AssertionResult& result ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002405 };
2406
Phil Nasha1fbfea2012-12-01 23:57:18 +00002407 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
2408 {
2409 public:
2410 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter, ReporterConfig const& config )
2411 : m_legacyReporter( legacyReporter ),
2412 m_config( config )
2413 {}
2414 virtual ~LegacyReporterAdapter();
2415
2416 virtual ReporterPreferences getPreferences() const {
2417 ReporterPreferences prefs;
2418 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
2419 return prefs;
2420 }
2421
Phil Nash37186a12013-03-13 12:19:30 +00002422 virtual void noMatchingTestCases( std::string const& ) {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00002423 virtual void testRunStarting( TestRunInfo const& ) {
2424 m_legacyReporter->StartTesting();
2425 }
2426 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
2427 m_legacyReporter->StartGroup( groupInfo.name );
2428 }
2429 virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
2430 m_legacyReporter->StartTestCase( testInfo );
2431 }
2432 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
2433 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
2434 }
2435 virtual void assertionStarting( AssertionInfo const& ) {
2436 // Not on legacy interface
2437 }
2438
Phil Nash2e7d9662013-01-16 09:44:43 +00002439 virtual void assertionEnded( AssertionStats const& assertionStats ) {
2440 m_legacyReporter->Result( assertionStats.assertionResult );
Phil Nasha1fbfea2012-12-01 23:57:18 +00002441 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002442 virtual void sectionEnded( SectionStats const& sectionStats ) {
2443 if( sectionStats.missingAssertions )
2444 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
2445 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
Phil Nasha1fbfea2012-12-01 23:57:18 +00002446 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002447 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
2448 if( testCaseStats.missingAssertions )
2449 m_legacyReporter->NoAssertionsInTestCase( testCaseStats.testInfo.name );
Phil Nasha1fbfea2012-12-01 23:57:18 +00002450 m_legacyReporter->EndTestCase
Phil Nash2e7d9662013-01-16 09:44:43 +00002451 ( testCaseStats.testInfo,
2452 testCaseStats.totals,
2453 testCaseStats.stdOut,
2454 testCaseStats.stdErr );
Phil Nasha1fbfea2012-12-01 23:57:18 +00002455 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002456 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
2457 if( testGroupStats.aborting )
Phil Nasha1fbfea2012-12-01 23:57:18 +00002458 m_legacyReporter->Aborted();
Phil Nash2e7d9662013-01-16 09:44:43 +00002459 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
Phil Nasha1fbfea2012-12-01 23:57:18 +00002460 }
Phil Nash2e7d9662013-01-16 09:44:43 +00002461 virtual void testRunEnded( TestRunStats const& testRunStats ) {
2462 m_legacyReporter->EndTesting( testRunStats.totals );
Phil Nasha1fbfea2012-12-01 23:57:18 +00002463 }
2464
2465 private:
2466 Ptr<IReporter> m_legacyReporter;
2467 ReporterConfig m_config;
2468 };
2469
Phil Nasha70fbe32012-08-31 08:10:36 +01002470 struct IReporterFactory {
2471 virtual ~IReporterFactory();
Phil Nasha1fbfea2012-12-01 23:57:18 +00002472 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002473 virtual std::string getDescription() const = 0;
2474 };
2475
2476 struct IReporterRegistry {
2477 typedef std::map<std::string, IReporterFactory*> FactoryMap;
2478
2479 virtual ~IReporterRegistry();
Phil Nasha1fbfea2012-12-01 23:57:18 +00002480 virtual IStreamingReporter* create( std::string const& name, ReporterConfig const& config ) const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002481 virtual const FactoryMap& getFactories() const = 0;
2482 };
2483
Phil Nasha1fbfea2012-12-01 23:57:18 +00002484 inline std::string trim( std::string const& str ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01002485 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
2486 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
2487
2488 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
2489 }
2490}
2491
Phil Nash3b80af72012-08-09 07:47:30 +01002492#include <vector>
Phil Nash3b80af72012-08-09 07:47:30 +01002493
2494namespace Catch {
2495
Phil Nasha1fbfea2012-12-01 23:57:18 +00002496 class TestCase;
Phil Nash3b80af72012-08-09 07:47:30 +01002497 struct ITestCaseRegistry;
2498 struct IExceptionTranslatorRegistry;
2499 struct IExceptionTranslator;
2500
2501 struct IRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002502 virtual ~IRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01002503
2504 virtual const IReporterRegistry& getReporterRegistry() const = 0;
2505 virtual const ITestCaseRegistry& getTestCaseRegistry() const = 0;
2506 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2507 };
2508
2509 struct IMutableRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002510 virtual ~IMutableRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01002511 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002512 virtual void registerTest( const TestCase& testInfo ) = 0;
Phil Nash3b80af72012-08-09 07:47:30 +01002513 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2514 };
2515
2516 IRegistryHub& getRegistryHub();
2517 IMutableRegistryHub& getMutableRegistryHub();
2518 void cleanUp();
Phil Nash82acc2c2012-10-28 12:07:17 +00002519 std::string translateActiveException();
2520
Phil Nash3b80af72012-08-09 07:47:30 +01002521}
2522
Phil Nash82acc2c2012-10-28 12:07:17 +00002523#include <ostream>
2524
2525namespace Catch {
2526
2527 inline IResultCapture& getResultCapture() {
2528 return getCurrentContext().getResultCapture();
2529 }
2530
2531 template<typename MatcherT>
2532 ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher,
2533 const std::string& matcherCallAsString ) {
2534 std::string matcherAsString = matcher.toString();
2535 if( matcherAsString == "{?}" )
2536 matcherAsString = matcherCallAsString;
2537 return ExpressionResultBuilder()
2538 .setRhs( matcherAsString )
2539 .setOp( "matches" );
2540 }
2541
2542 template<typename MatcherT, typename ArgT>
2543 ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher,
2544 const ArgT& arg,
2545 const std::string& matcherCallAsString ) {
2546 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
2547 .setLhs( Catch::toString( arg ) )
2548 .setResultType( matcher.match( arg ) );
2549 }
2550
2551 template<typename MatcherT, typename ArgT>
2552 ExpressionResultBuilder expressionResultBuilderFromMatcher( const MatcherT& matcher,
2553 ArgT* arg,
2554 const std::string& matcherCallAsString ) {
2555 return expressionResultBuilderFromMatcher( matcher, matcherCallAsString )
2556 .setLhs( Catch::toString( arg ) )
2557 .setResultType( matcher.match( arg ) );
2558 }
2559
2560struct TestFailureException{};
2561
Phil Nash82acc2c2012-10-28 12:07:17 +00002562// This is just here to avoid compiler warnings with macro constants and boolean literals
2563inline bool isTrue( bool value ){ return value; }
2564
2565} // end namespace Catch
2566
2567///////////////////////////////////////////////////////////////////////////////
Phil Nash5efa4bc2012-10-29 20:49:22 +00002568#define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
2569
2570///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002571#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002572 if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
Phil Nash82acc2c2012-10-28 12:07:17 +00002573 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
2574 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
Phil Nashaf1a3212012-11-10 18:46:39 +00002575 if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
Phil Nash3df6c0d2013-03-11 18:38:29 +00002576 Catch::isTrue( false && originalExpr ); \
Phil Nash82acc2c2012-10-28 12:07:17 +00002577 }
2578
2579///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002580#define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
Phil Nashd539da92012-11-13 09:44:52 +00002581 Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition );
Phil Nash82acc2c2012-10-28 12:07:17 +00002582
2583///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002584#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002585 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002586 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002587 try { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002588 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002589 } catch( Catch::TestFailureException& ) { \
2590 throw; \
2591 } catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002592 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
2593 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002594 throw; \
2595 } \
2596 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002597
2598///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002599#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2600 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
Phil Nashd539da92012-11-13 09:44:52 +00002601 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nash82acc2c2012-10-28 12:07:17 +00002602
2603///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002604#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2605 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
Phil Nashd539da92012-11-13 09:44:52 +00002606 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nash82acc2c2012-10-28 12:07:17 +00002607
2608///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002609#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002610 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002611 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002612 try { \
2613 expr; \
Phil Nashaf1a3212012-11-10 18:46:39 +00002614 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002615 } \
2616 catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002617 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002618 } \
2619} while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002620
2621///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002622#define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nash82acc2c2012-10-28 12:07:17 +00002623 try { \
Phil Nash82acc2c2012-10-28 12:07:17 +00002624 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
2625 expr; \
Phil Nashaf1a3212012-11-10 18:46:39 +00002626 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
Phil Nash82acc2c2012-10-28 12:07:17 +00002627 } \
2628 } \
2629 catch( Catch::TestFailureException& ) { \
2630 throw; \
2631 } \
2632 catch( exceptionType ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002633 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
Phil Nash82acc2c2012-10-28 12:07:17 +00002634 }
2635
2636///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002637#define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002638 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002639 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2640 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002641 } while( Catch::isTrue( false ) )
2642
2643///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002644#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002645 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002646 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
2647 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002648 catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002649 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
2650 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002651 } \
2652 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002653
2654///////////////////////////////////////////////////////////////////////////////
Phil Nasha2773812013-02-02 20:37:58 +00002655#define INTERNAL_CATCH_INFO( log, macroName ) \
2656 do { \
2657 Catch::getResultCapture().acceptMessage( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); \
2658 } while( Catch::isTrue( false ) )
2659
2660///////////////////////////////////////////////////////////////////////////////
2661#define INTERNAL_CATCH_MSG( log, messageType, resultDisposition, macroName ) \
Phil Nashec5956f2012-11-06 07:52:28 +00002662 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002663 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
Phil Nasha2773812013-02-02 20:37:58 +00002664 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
Phil Nashec5956f2012-11-06 07:52:28 +00002665 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002666
2667///////////////////////////////////////////////////////////////////////////////
2668#define INTERNAL_CATCH_SCOPED_INFO( log, macroName ) \
Phil Nasha2773812013-02-02 20:37:58 +00002669 Catch::ScopedMessageBuilder INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ); \
2670 INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) << log; \
2671 Catch::getResultCapture().pushScopedMessage( INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002672
2673///////////////////////////////////////////////////////////////////////////////
Phil Nashaf1a3212012-11-10 18:46:39 +00002674#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002675 do { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002676 INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002677 try { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002678 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002679 } catch( Catch::TestFailureException& ) { \
2680 throw; \
2681 } catch( ... ) { \
Phil Nashaf1a3212012-11-10 18:46:39 +00002682 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
2683 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
Phil Nash5efa4bc2012-10-29 20:49:22 +00002684 throw; \
2685 } \
2686 } while( Catch::isTrue( false ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002687
2688// #included from: internal/catch_section.hpp
2689#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
2690
2691#include <string>
2692
2693namespace Catch {
2694
2695 class Section {
2696 public:
Phil Nash93906752013-03-16 20:21:51 +00002697 Section( const SourceLineInfo& lineInfo,
2698 const std::string& name,
2699 const std::string& description = "" )
Phil Nasha1fbfea2012-12-01 23:57:18 +00002700 : m_info( name, description, lineInfo ),
2701 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( m_info, m_assertions ) )
Phil Nash82acc2c2012-10-28 12:07:17 +00002702 {}
2703
2704 ~Section() {
2705 if( m_sectionIncluded )
Phil Nasha1fbfea2012-12-01 23:57:18 +00002706 getCurrentContext().getResultCapture().sectionEnded( m_info, m_assertions );
Phil Nash82acc2c2012-10-28 12:07:17 +00002707 }
2708
2709 // This indicates whether the section should be executed or not
2710 operator bool() {
2711 return m_sectionIncluded;
2712 }
2713
2714 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00002715 SectionInfo m_info;
Phil Nash82acc2c2012-10-28 12:07:17 +00002716
2717 std::string m_name;
2718 Counts m_assertions;
2719 bool m_sectionIncluded;
2720 };
2721
2722} // end namespace Catch
2723
Phil Nash93906752013-03-16 20:21:51 +00002724#ifdef CATCH_CONFIG_VARIADIC_MACROS
2725 #define INTERNAL_CATCH_SECTION( ... ) \
2726 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2727#else
2728 #define INTERNAL_CATCH_SECTION( name, desc ) \
2729 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
2730#endif
Phil Nash82acc2c2012-10-28 12:07:17 +00002731
2732// #included from: internal/catch_generators.hpp
2733#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2734
2735#include <iterator>
2736#include <vector>
2737#include <string>
2738#include <stdlib.h>
2739
2740namespace Catch {
2741
2742template<typename T>
2743struct IGenerator {
2744 virtual ~IGenerator() {}
2745 virtual T getValue( std::size_t index ) const = 0;
2746 virtual std::size_t size () const = 0;
2747};
2748
2749template<typename T>
2750class BetweenGenerator : public IGenerator<T> {
2751public:
2752 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2753
2754 virtual T getValue( std::size_t index ) const {
Phil Nash2e7d9662013-01-16 09:44:43 +00002755 return m_from+static_cast<int>( index );
Phil Nash82acc2c2012-10-28 12:07:17 +00002756 }
2757
2758 virtual std::size_t size() const {
2759 return static_cast<std::size_t>( 1+m_to-m_from );
2760 }
2761
2762private:
2763
2764 T m_from;
2765 T m_to;
2766};
2767
2768template<typename T>
2769class ValuesGenerator : public IGenerator<T> {
2770public:
2771 ValuesGenerator(){}
2772
2773 void add( T value ) {
2774 m_values.push_back( value );
2775 }
2776
2777 virtual T getValue( std::size_t index ) const {
2778 return m_values[index];
2779 }
2780
2781 virtual std::size_t size() const {
2782 return m_values.size();
2783 }
2784
2785private:
2786 std::vector<T> m_values;
2787};
2788
2789template<typename T>
2790class CompositeGenerator {
2791public:
2792 CompositeGenerator() : m_totalSize( 0 ) {}
2793
Phil Nasha04981b2013-03-08 09:30:25 +00002794 // *** Move semantics, similar to auto_ptr ***
Phil Nash82acc2c2012-10-28 12:07:17 +00002795 CompositeGenerator( CompositeGenerator& other )
2796 : m_fileInfo( other.m_fileInfo ),
2797 m_totalSize( 0 )
2798 {
Phil Nasha04981b2013-03-08 09:30:25 +00002799 move( other );
Phil Nash82acc2c2012-10-28 12:07:17 +00002800 }
2801
2802 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2803 m_fileInfo = fileInfo;
2804 return *this;
2805 }
2806
2807 ~CompositeGenerator() {
2808 deleteAll( m_composed );
2809 }
2810
2811 operator T () const {
2812 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2813
2814 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2815 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2816 for( size_t index = 0; it != itEnd; ++it )
2817 {
2818 const IGenerator<T>* generator = *it;
2819 if( overallIndex >= index && overallIndex < index + generator->size() )
2820 {
2821 return generator->getValue( overallIndex-index );
2822 }
2823 index += generator->size();
2824 }
2825 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
Phil Nasha04981b2013-03-08 09:30:25 +00002826 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 Nash82acc2c2012-10-28 12:07:17 +00002827 }
2828
2829 void add( const IGenerator<T>* generator ) {
2830 m_totalSize += generator->size();
2831 m_composed.push_back( generator );
2832 }
2833
2834 CompositeGenerator& then( CompositeGenerator& other ) {
2835 move( other );
2836 return *this;
2837 }
2838
2839 CompositeGenerator& then( T value ) {
2840 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2841 valuesGen->add( value );
2842 add( valuesGen );
2843 return *this;
2844 }
2845
2846private:
2847
2848 void move( CompositeGenerator& other ) {
2849 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2850 m_totalSize += other.m_totalSize;
2851 other.m_composed.clear();
2852 }
2853
2854 std::vector<const IGenerator<T>*> m_composed;
2855 std::string m_fileInfo;
2856 size_t m_totalSize;
2857};
2858
2859namespace Generators
2860{
2861 template<typename T>
2862 CompositeGenerator<T> between( T from, T to ) {
2863 CompositeGenerator<T> generators;
2864 generators.add( new BetweenGenerator<T>( from, to ) );
2865 return generators;
2866 }
2867
2868 template<typename T>
2869 CompositeGenerator<T> values( T val1, T val2 ) {
2870 CompositeGenerator<T> generators;
2871 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2872 valuesGen->add( val1 );
2873 valuesGen->add( val2 );
2874 generators.add( valuesGen );
2875 return generators;
2876 }
2877
2878 template<typename T>
2879 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2880 CompositeGenerator<T> generators;
2881 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2882 valuesGen->add( val1 );
2883 valuesGen->add( val2 );
2884 valuesGen->add( val3 );
2885 generators.add( valuesGen );
2886 return generators;
2887 }
2888
2889 template<typename T>
2890 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2891 CompositeGenerator<T> generators;
2892 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2893 valuesGen->add( val1 );
2894 valuesGen->add( val2 );
2895 valuesGen->add( val3 );
2896 valuesGen->add( val4 );
2897 generators.add( valuesGen );
2898 return generators;
2899 }
2900
2901} // end namespace Generators
2902
2903using namespace Generators;
2904
2905} // end namespace Catch
2906
2907#define INTERNAL_CATCH_LINESTR2( line ) #line
2908#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2909
2910#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2911
2912// #included from: internal/catch_interfaces_exception.h
2913#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2914
2915#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +01002916
Phil Nash89d2a3f2012-05-16 15:09:17 +01002917namespace Catch {
2918
Phil Nash89d1e6c2011-05-24 08:23:02 +01002919 typedef std::string(*exceptionTranslateFunction)();
2920
Phil Nash89d2a3f2012-05-16 15:09:17 +01002921 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002922 virtual ~IExceptionTranslator();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002923 virtual std::string translate() const = 0;
2924 };
2925
Phil Nash89d2a3f2012-05-16 15:09:17 +01002926 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002927 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002928
Phil Nash89d2a3f2012-05-16 15:09:17 +01002929 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002930 };
2931
Phil Nash89d2a3f2012-05-16 15:09:17 +01002932 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002933 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002934 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002935 public:
2936
Phil Nash89d2a3f2012-05-16 15:09:17 +01002937 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002938 : m_translateFunction( translateFunction )
2939 {}
2940
Phil Nash89d2a3f2012-05-16 15:09:17 +01002941 virtual std::string translate() const {
2942 try {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002943 throw;
2944 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002945 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002946 return m_translateFunction( ex );
2947 }
2948 }
2949
2950 protected:
2951 std::string(*m_translateFunction)( T& );
2952 };
2953
2954 public:
2955 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002956 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002957 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002958 ( new ExceptionTranslator<T>( translateFunction ) );
2959 }
2960 };
2961}
2962
2963///////////////////////////////////////////////////////////////////////////////
2964#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2965 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2966 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2967 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2968
2969// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002970#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002971
Phil Nash89d1e6c2011-05-24 08:23:02 +01002972#include <cmath>
2973#include <limits>
2974
Phil Nash89d2a3f2012-05-16 15:09:17 +01002975namespace Catch {
2976namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002977
Phil Nash89d2a3f2012-05-16 15:09:17 +01002978 class Approx {
2979 public:
2980 explicit Approx ( double value )
2981 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2982 m_scale( 1.0 ),
2983 m_value( value )
2984 {}
Phil Nashf721a962011-06-07 14:13:57 +01002985
Phil Nash89d2a3f2012-05-16 15:09:17 +01002986 Approx( const Approx& other )
2987 : m_epsilon( other.m_epsilon ),
2988 m_scale( other.m_scale ),
2989 m_value( other.m_value )
2990 {}
Phil Nashf721a962011-06-07 14:13:57 +01002991
Phil Nash89d2a3f2012-05-16 15:09:17 +01002992 static Approx custom() {
2993 return Approx( 0 );
2994 }
Phil Nashf721a962011-06-07 14:13:57 +01002995
Phil Nash89d2a3f2012-05-16 15:09:17 +01002996 Approx operator()( double value ) {
2997 Approx approx( value );
2998 approx.epsilon( m_epsilon );
2999 approx.scale( m_scale );
3000 return approx;
3001 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003002
Phil Nash89d2a3f2012-05-16 15:09:17 +01003003 friend bool operator == ( double lhs, const Approx& rhs ) {
3004 // Thanks to Richard Harris for his help refining this formula
3005 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
3006 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003007
Phil Nash89d2a3f2012-05-16 15:09:17 +01003008 friend bool operator == ( const Approx& lhs, double rhs ) {
3009 return operator==( rhs, lhs );
3010 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003011
Phil Nash89d2a3f2012-05-16 15:09:17 +01003012 friend bool operator != ( double lhs, const Approx& rhs ) {
3013 return !operator==( lhs, rhs );
3014 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003015
Phil Nash89d2a3f2012-05-16 15:09:17 +01003016 friend bool operator != ( const Approx& lhs, double rhs ) {
3017 return !operator==( rhs, lhs );
3018 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003019
Phil Nash89d2a3f2012-05-16 15:09:17 +01003020 Approx& epsilon( double newEpsilon ) {
3021 m_epsilon = newEpsilon;
3022 return *this;
3023 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003024
Phil Nash89d2a3f2012-05-16 15:09:17 +01003025 Approx& scale( double newScale ) {
3026 m_scale = newScale;
3027 return *this;
3028 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003029
Phil Nash89d2a3f2012-05-16 15:09:17 +01003030 std::string toString() const {
3031 std::ostringstream oss;
Phil Nash67305122012-10-09 11:48:55 +01003032 oss << "Approx( " << m_value << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01003033 return oss.str();
3034 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003035
Phil Nash89d2a3f2012-05-16 15:09:17 +01003036 private:
3037 double m_epsilon;
3038 double m_scale;
3039 double m_value;
3040 };
3041}
3042
3043template<>
3044inline std::string toString<Detail::Approx>( const Detail::Approx& value ) {
3045 return value.toString();
3046}
Phil Nash89d1e6c2011-05-24 08:23:02 +01003047
3048} // end namespace Catch
3049
Phil Nash371db8b2012-05-21 18:52:09 +01003050// #included from: internal/catch_matchers.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003051#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01003052
3053namespace Catch {
3054namespace Matchers {
3055 namespace Impl {
Phil Nash9444bbc2012-10-12 07:58:17 +01003056
3057 template<typename ExpressionT>
3058 struct Matcher : SharedImpl<IShared>
3059 {
Phil Nashff03cdf2012-12-06 08:44:51 +00003060 typedef ExpressionT ExpressionType;
3061
Phil Nash9444bbc2012-10-12 07:58:17 +01003062 virtual ~Matcher() {}
3063 virtual Ptr<Matcher> clone() const = 0;
Phil Nashff03cdf2012-12-06 08:44:51 +00003064 virtual bool match( ExpressionT const& expr ) const = 0;
Phil Nash9444bbc2012-10-12 07:58:17 +01003065 virtual std::string toString() const = 0;
3066 };
3067
3068 template<typename DerivedT, typename ExpressionT>
3069 struct MatcherImpl : Matcher<ExpressionT> {
3070
3071 virtual Ptr<Matcher<ExpressionT> > clone() const {
3072 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<const DerivedT&>( *this ) ) );
3073 }
3074 };
3075
3076 namespace Generic {
3077
3078 template<typename ExpressionT>
3079 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
3080 public:
3081
3082 AllOf() {}
3083 AllOf( const AllOf& other ) : m_matchers( other.m_matchers ) {}
3084
3085 AllOf& add( const Matcher<ExpressionT>& matcher ) {
3086 m_matchers.push_back( matcher.clone() );
3087 return *this;
3088 }
3089 virtual bool match( const ExpressionT& expr ) const
3090 {
3091 for( std::size_t i = 0; i < m_matchers.size(); ++i )
3092 if( !m_matchers[i]->match( expr ) )
3093 return false;
3094 return true;
3095 }
3096 virtual std::string toString() const {
3097 std::ostringstream oss;
3098 oss << "( ";
3099 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
3100 if( i != 0 )
3101 oss << " and ";
3102 oss << m_matchers[i]->toString();
3103 }
3104 oss << " )";
3105 return oss.str();
3106 }
3107
3108 private:
3109 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
3110 };
3111
3112 template<typename ExpressionT>
3113 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
3114 public:
3115
3116 AnyOf() {}
3117 AnyOf( const AnyOf& other ) : m_matchers( other.m_matchers ) {}
3118
3119 AnyOf& add( const Matcher<ExpressionT>& matcher ) {
3120 m_matchers.push_back( matcher.clone() );
3121 return *this;
3122 }
3123 virtual bool match( const ExpressionT& expr ) const
3124 {
3125 for( std::size_t i = 0; i < m_matchers.size(); ++i )
3126 if( m_matchers[i]->match( expr ) )
3127 return true;
3128 return false;
3129 }
3130 virtual std::string toString() const {
3131 std::ostringstream oss;
3132 oss << "( ";
3133 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
3134 if( i != 0 )
3135 oss << " or ";
3136 oss << m_matchers[i]->toString();
3137 }
3138 oss << " )";
3139 return oss.str();
3140 }
3141
3142 private:
3143 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
3144 };
3145
3146 }
3147
Phil Nash371db8b2012-05-21 18:52:09 +01003148 namespace StdString {
3149
Phil Nash9444bbc2012-10-12 07:58:17 +01003150 struct Equals : MatcherImpl<Equals, std::string> {
Phil Nasha8570df2012-05-24 08:29:41 +01003151 Equals( const std::string& str ) : m_str( str ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01003152 Equals( const Equals& other ) : m_str( other.m_str ){}
Phil Nasha8570df2012-05-24 08:29:41 +01003153
Phil Nash9444bbc2012-10-12 07:58:17 +01003154 virtual ~Equals();
3155
3156 virtual bool match( const std::string& expr ) const {
3157 return m_str == expr;
3158 }
3159 virtual std::string toString() const {
3160 return "equals: \"" + m_str + "\"";
Phil Nasha8570df2012-05-24 08:29:41 +01003161 }
3162
Phil Nasha8570df2012-05-24 08:29:41 +01003163 std::string m_str;
3164 };
3165
Phil Nash9444bbc2012-10-12 07:58:17 +01003166 struct Contains : MatcherImpl<Contains, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01003167 Contains( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01003168 Contains( const Contains& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01003169
Phil Nash9444bbc2012-10-12 07:58:17 +01003170 virtual ~Contains();
3171
3172 virtual bool match( const std::string& expr ) const {
3173 return expr.find( m_substr ) != std::string::npos;
3174 }
3175 virtual std::string toString() const {
3176 return "contains: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01003177 }
3178
Phil Nash371db8b2012-05-21 18:52:09 +01003179 std::string m_substr;
3180 };
3181
Phil Nash9444bbc2012-10-12 07:58:17 +01003182 struct StartsWith : MatcherImpl<StartsWith, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01003183 StartsWith( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01003184 StartsWith( const StartsWith& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01003185
Phil Nash9444bbc2012-10-12 07:58:17 +01003186 virtual ~StartsWith();
3187
3188 virtual bool match( const std::string& expr ) const {
3189 return expr.find( m_substr ) == 0;
3190 }
3191 virtual std::string toString() const {
3192 return "starts with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01003193 }
3194
Phil Nash371db8b2012-05-21 18:52:09 +01003195 std::string m_substr;
3196 };
3197
Phil Nash9444bbc2012-10-12 07:58:17 +01003198 struct EndsWith : MatcherImpl<EndsWith, std::string> {
Phil Nash371db8b2012-05-21 18:52:09 +01003199 EndsWith( const std::string& substr ) : m_substr( substr ){}
Phil Nash9444bbc2012-10-12 07:58:17 +01003200 EndsWith( const EndsWith& other ) : m_substr( other.m_substr ){}
Phil Nash371db8b2012-05-21 18:52:09 +01003201
Phil Nash9444bbc2012-10-12 07:58:17 +01003202 virtual ~EndsWith();
3203
3204 virtual bool match( const std::string& expr ) const {
3205 return expr.find( m_substr ) == expr.size() - m_substr.size();
3206 }
3207 virtual std::string toString() const {
3208 return "ends with: \"" + m_substr + "\"";
Phil Nash371db8b2012-05-21 18:52:09 +01003209 }
3210
Phil Nash371db8b2012-05-21 18:52:09 +01003211 std::string m_substr;
3212 };
3213 } // namespace StdString
3214 } // namespace Impl
3215
Phil Nash9444bbc2012-10-12 07:58:17 +01003216 // The following functions create the actual matcher objects.
3217 // This allows the types to be inferred
3218 template<typename ExpressionT>
3219 inline Impl::Generic::AllOf<ExpressionT> AllOf( const Impl::Matcher<ExpressionT>& m1,
3220 const Impl::Matcher<ExpressionT>& m2 ) {
3221 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
3222 }
3223 template<typename ExpressionT>
3224 inline Impl::Generic::AllOf<ExpressionT> AllOf( const Impl::Matcher<ExpressionT>& m1,
3225 const Impl::Matcher<ExpressionT>& m2,
3226 const Impl::Matcher<ExpressionT>& m3 ) {
3227 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
3228 }
3229 template<typename ExpressionT>
3230 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( const Impl::Matcher<ExpressionT>& m1,
3231 const Impl::Matcher<ExpressionT>& m2 ) {
3232 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
3233 }
3234 template<typename ExpressionT>
3235 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( const Impl::Matcher<ExpressionT>& m1,
3236 const Impl::Matcher<ExpressionT>& m2,
3237 const Impl::Matcher<ExpressionT>& m3 ) {
3238 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
3239 }
3240
Phil Nasha8570df2012-05-24 08:29:41 +01003241 inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); }
Phil Nash371db8b2012-05-21 18:52:09 +01003242 inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); }
3243 inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); }
3244 inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); }
3245
3246} // namespace Matchers
3247
3248using namespace Matchers;
3249
3250} // namespace Catch
3251
Phil Nash0f9c5512012-06-02 23:12:42 +01003252// These files are included here so the single_include script doesn't put them
3253// in the conditionally compiled sections
Phil Nash0f9c5512012-06-02 23:12:42 +01003254// #included from: internal/catch_interfaces_runner.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04003255#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01003256
3257#include <string>
3258
3259namespace Catch {
Phil Nasha1fbfea2012-12-01 23:57:18 +00003260 class TestCase;
Phil Nash0f9c5512012-06-02 23:12:42 +01003261
3262 struct IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01003263 virtual ~IRunner();
Phil Nash0f9c5512012-06-02 23:12:42 +01003264 };
3265}
3266
3267
Phil Nash371db8b2012-05-21 18:52:09 +01003268#ifdef __OBJC__
3269// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003270#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01003271
Phil Nash371db8b2012-05-21 18:52:09 +01003272#import <objc/runtime.h>
3273
3274#include <string>
3275
3276// NB. Any general catch headers included here must be included
3277// in catch.hpp first to make sure they are included by the single
3278// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01003279
Phil Nash83224e62011-08-12 18:53:28 +01003280///////////////////////////////////////////////////////////////////////////////
3281// This protocol is really only here for (self) documenting purposes, since
3282// all its methods are optional.
3283@protocol OcFixture
3284
3285@optional
3286
3287-(void) setUp;
3288-(void) tearDown;
3289
3290@end
3291
Phil Nash89d2a3f2012-05-16 15:09:17 +01003292namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01003293
Phil Nash5bc030d2012-08-16 18:48:50 +01003294 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003295
3296 public:
3297 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3298
3299 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00003300 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01003301
Phil Nash53c990a2012-03-17 18:20:06 +00003302 performOptionalSelector( obj, @selector(setUp) );
3303 performOptionalSelector( obj, m_sel );
3304 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01003305
Phil Nash53c990a2012-03-17 18:20:06 +00003306 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01003307 }
Phil Nash83224e62011-08-12 18:53:28 +01003308 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01003309 virtual ~OcMethod() {}
3310
Phil Nash83224e62011-08-12 18:53:28 +01003311 Class m_cls;
3312 SEL m_sel;
3313 };
3314
Phil Nash89d2a3f2012-05-16 15:09:17 +01003315 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01003316
Phil Nash89d2a3f2012-05-16 15:09:17 +01003317 inline bool startsWith( const std::string& str, const std::string& sub ) {
Phil Nash83224e62011-08-12 18:53:28 +01003318 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
3319 }
3320
Phil Nash89d2a3f2012-05-16 15:09:17 +01003321 inline std::string getAnnotation( Class cls,
3322 const std::string& annotationName,
3323 const std::string& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01003324 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3325 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00003326 arcSafeRelease( selStr );
3327 id value = performOptionalSelector( cls, sel );
3328 if( value )
3329 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01003330 return "";
3331 }
3332 }
3333
Phil Nash89d2a3f2012-05-16 15:09:17 +01003334 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01003335 size_t noTestMethods = 0;
3336 int noClasses = objc_getClassList( NULL, 0 );
3337
Phil Nash861a1e72012-04-28 12:29:52 +01003338 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00003339 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01003340
Phil Nash89d2a3f2012-05-16 15:09:17 +01003341 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003342 Class cls = classes[c];
3343 {
3344 u_int count;
3345 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01003346 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003347 SEL selector = method_getName(methods[m]);
3348 std::string methodName = sel_getName(selector);
Phil Nash89d2a3f2012-05-16 15:09:17 +01003349 if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01003350 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00003351 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3352 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nash5bdae842013-02-19 19:47:18 +00003353 const char* className = class_getName( cls );
Phil Nash83224e62011-08-12 18:53:28 +01003354
Phil Nash5bdae842013-02-19 19:47:18 +00003355 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01003356 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01003357 }
3358 }
3359 free(methods);
3360 }
3361 }
3362 return noTestMethods;
3363 }
Phil Nash78d95a02012-03-04 21:22:36 +00003364
Phil Nash89d2a3f2012-05-16 15:09:17 +01003365 namespace Matchers {
3366 namespace Impl {
3367 namespace NSStringMatchers {
3368
Phil Nashff03cdf2012-12-06 08:44:51 +00003369 template<typename MatcherT>
3370 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
Phil Nash78d95a02012-03-04 21:22:36 +00003371 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nashff03cdf2012-12-06 08:44:51 +00003372 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01003373 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00003374 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003375 }
3376
3377 NSString* m_substr;
3378 };
3379
Phil Nashff03cdf2012-12-06 08:44:51 +00003380 struct Equals : StringHolder<Equals> {
Phil Nash8d18d162012-03-14 20:06:14 +00003381 Equals( NSString* substr ) : StringHolder( substr ){}
3382
Phil Nashff03cdf2012-12-06 08:44:51 +00003383 virtual bool match( ExpressionType const& str ) const {
Phil Nash8d18d162012-03-14 20:06:14 +00003384 return [str isEqualToString:m_substr];
3385 }
3386
Phil Nashff03cdf2012-12-06 08:44:51 +00003387 virtual std::string toString() const {
3388 return "equals string: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash8d18d162012-03-14 20:06:14 +00003389 }
3390 };
3391
Phil Nashff03cdf2012-12-06 08:44:51 +00003392 struct Contains : StringHolder<Contains> {
Phil Nash78d95a02012-03-04 21:22:36 +00003393 Contains( NSString* substr ) : StringHolder( substr ){}
3394
Phil Nashff03cdf2012-12-06 08:44:51 +00003395 virtual bool match( ExpressionType const& str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00003396 return [str rangeOfString:m_substr].location != NSNotFound;
3397 }
3398
Phil Nashff03cdf2012-12-06 08:44:51 +00003399 virtual std::string toString() const {
3400 return "contains string: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00003401 }
3402 };
3403
Phil Nashff03cdf2012-12-06 08:44:51 +00003404 struct StartsWith : StringHolder<StartsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003405 StartsWith( NSString* substr ) : StringHolder( substr ){}
3406
Phil Nashff03cdf2012-12-06 08:44:51 +00003407 virtual bool match( ExpressionType const& str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00003408 return [str rangeOfString:m_substr].location == 0;
3409 }
3410
Phil Nashff03cdf2012-12-06 08:44:51 +00003411 virtual std::string toString() const {
3412 return "starts with: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00003413 }
3414 };
Phil Nashff03cdf2012-12-06 08:44:51 +00003415 struct EndsWith : StringHolder<EndsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003416 EndsWith( NSString* substr ) : StringHolder( substr ){}
3417
Phil Nashff03cdf2012-12-06 08:44:51 +00003418 virtual bool match( ExpressionType const& str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00003419 return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3420 }
3421
Phil Nashff03cdf2012-12-06 08:44:51 +00003422 virtual std::string toString() const {
3423 return "ends with: \"" + Catch::toString( m_substr ) + "\"";
Phil Nash78d95a02012-03-04 21:22:36 +00003424 }
3425 };
3426
3427 } // namespace NSStringMatchers
3428 } // namespace Impl
3429
Phil Nash8d18d162012-03-14 20:06:14 +00003430 inline Impl::NSStringMatchers::Equals
3431 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3432
Phil Nash78d95a02012-03-04 21:22:36 +00003433 inline Impl::NSStringMatchers::Contains
3434 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003435
Phil Nash78d95a02012-03-04 21:22:36 +00003436 inline Impl::NSStringMatchers::StartsWith
3437 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003438
Phil Nash78d95a02012-03-04 21:22:36 +00003439 inline Impl::NSStringMatchers::EndsWith
3440 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3441
3442 } // namespace Matchers
3443
3444 using namespace Matchers;
3445
3446} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01003447
3448///////////////////////////////////////////////////////////////////////////////
3449#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00003450+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003451{\
Phil Nash53c990a2012-03-17 18:20:06 +00003452return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01003453}\
Phil Nash53c990a2012-03-17 18:20:06 +00003454+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003455{ \
Phil Nash53c990a2012-03-17 18:20:06 +00003456return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01003457} \
3458-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3459
3460#endif
3461
3462#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
Phil Nasha695eb92012-08-13 07:46:10 +01003463// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003464#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003465
3466// Collect all the implementation files together here
3467// These are the equivalent of what would usually be cpp files
3468
Phil Nash5bc030d2012-08-16 18:48:50 +01003469#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01003470#pragma clang diagnostic push
3471#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01003472#endif
Phil Nasha695eb92012-08-13 07:46:10 +01003473
Phil Nash83224e62011-08-12 18:53:28 +01003474// #included from: catch_runner.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003475#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01003476
Phil Nasha695eb92012-08-13 07:46:10 +01003477// #included from: internal/catch_commandline.hpp
3478#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3479
Phil Nasha695eb92012-08-13 07:46:10 +01003480namespace Catch {
3481
3482 class Command {
3483 public:
3484 Command(){}
3485
Phil Nashecf934b2012-08-27 21:42:55 +01003486 explicit Command( const std::string& name ) : m_name( name ) {
3487 }
Phil Nasha695eb92012-08-13 07:46:10 +01003488
3489 Command& operator += ( const std::string& arg ) {
3490 m_args.push_back( arg );
3491 return *this;
3492 }
3493 Command& operator += ( const Command& other ) {
3494 std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
3495 if( m_name.empty() )
3496 m_name = other.m_name;
3497 return *this;
3498 }
3499 Command operator + ( const Command& other ) {
3500 Command newCommand( *this );
3501 newCommand += other;
3502 return newCommand;
3503 }
3504
3505 operator SafeBool::type() const {
Phil Nashe571e6f2012-08-24 18:54:56 +01003506 return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() );
Phil Nasha695eb92012-08-13 07:46:10 +01003507 }
3508
3509 std::string name() const { return m_name; }
3510 std::string operator[]( std::size_t i ) const { return m_args[i]; }
3511 std::size_t argsCount() const { return m_args.size(); }
3512
3513 CATCH_ATTRIBUTE_NORETURN
3514 void raiseError( const std::string& message ) const {
3515 std::ostringstream oss;
Phil Nashecf934b2012-08-27 21:42:55 +01003516 if( m_name.empty() )
3517 oss << "Error while parsing " << m_name << ". " << message << ".";
3518 else
3519 oss << "Error while parsing arguments. " << message << ".";
3520
Phil Nasha695eb92012-08-13 07:46:10 +01003521 if( m_args.size() > 0 )
Phil Nashecf934b2012-08-27 21:42:55 +01003522 oss << " Arguments were:";
Phil Nasha695eb92012-08-13 07:46:10 +01003523 for( std::size_t i = 0; i < m_args.size(); ++i )
3524 oss << " " << m_args[i];
3525 throw std::domain_error( oss.str() );
3526 }
3527
3528 private:
3529
3530 std::string m_name;
3531 std::vector<std::string> m_args;
3532 };
3533
3534 class CommandParser {
3535 public:
3536 CommandParser( int argc, char const * const * argv ) : m_argc( static_cast<std::size_t>( argc ) ), m_argv( argv ) {}
3537
Phil Nashe2d215e2012-09-07 17:52:35 +01003538 std::string exeName() const {
Phil Nasha90a88a2012-11-19 19:59:10 +00003539 std::string exeName = m_argv[0];
3540 std::string::size_type pos = exeName.find_last_of( "/\\" );
3541 if( pos != std::string::npos )
3542 exeName = exeName.substr( pos+1 );
3543 return exeName;
Phil Nashe2d215e2012-09-07 17:52:35 +01003544 }
Phil Nasha695eb92012-08-13 07:46:10 +01003545 Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
3546 return find( arg1 ) + find( arg2 ) + find( arg3 );
3547 }
3548
3549 Command find( const std::string& shortArg, const std::string& longArg ) const {
3550 return find( shortArg ) + find( longArg );
3551 }
3552 Command find( const std::string& arg ) const {
Phil Nashecf934b2012-08-27 21:42:55 +01003553 if( arg.empty() )
3554 return getArgs( "", 1 );
3555 else
3556 for( std::size_t i = 1; i < m_argc; ++i )
3557 if( m_argv[i] == arg )
3558 return getArgs( m_argv[i], i+1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003559 return Command();
3560 }
Phil Nashe571e6f2012-08-24 18:54:56 +01003561 Command getDefaultArgs() const {
3562 return getArgs( "", 1 );
3563 }
Phil Nasha695eb92012-08-13 07:46:10 +01003564
3565 private:
Phil Nashe571e6f2012-08-24 18:54:56 +01003566 Command getArgs( const std::string& cmdName, std::size_t from ) const {
3567 Command command( cmdName );
3568 for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i )
Phil Nasha695eb92012-08-13 07:46:10 +01003569 command += m_argv[i];
3570 return command;
3571 }
3572
3573 std::size_t m_argc;
3574 char const * const * m_argv;
3575 };
3576
Phil Nashecf934b2012-08-27 21:42:55 +01003577 class OptionParser : public SharedImpl<IShared> {
3578 public:
3579 OptionParser( int minArgs = 0, int maxArgs = 0 )
3580 : m_minArgs( minArgs ), m_maxArgs( maxArgs )
3581 {}
Phil Nasha695eb92012-08-13 07:46:10 +01003582
Phil Nashecf934b2012-08-27 21:42:55 +01003583 virtual ~OptionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01003584
Phil Nashecf934b2012-08-27 21:42:55 +01003585 Command find( const CommandParser& parser ) const {
3586 Command cmd;
3587 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3588 it != m_optionNames.end();
3589 ++it )
3590 cmd += parser.find( *it );
3591 return cmd;
3592 }
3593
3594 void validateArgs( const Command& args ) const {
3595 if( tooFewArgs( args ) || tooManyArgs( args ) ) {
3596 std::ostringstream oss;
3597 if( m_maxArgs == -1 )
3598 oss <<"Expected at least " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
3599 else if( m_minArgs == m_maxArgs )
3600 oss <<"Expected " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
Phil Nasha695eb92012-08-13 07:46:10 +01003601 else
Phil Nashecf934b2012-08-27 21:42:55 +01003602 oss <<"Expected between " << m_minArgs << " and " << m_maxArgs << " argument";
3603 args.raiseError( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003604 }
Phil Nashecf934b2012-08-27 21:42:55 +01003605 }
3606
3607 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
3608 if( Command cmd = find( parser ) ) {
3609 validateArgs( cmd );
3610 parseIntoConfig( cmd, config );
3611 }
3612 }
3613
3614 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0;
3615 virtual std::string argsSynopsis() const = 0;
3616 virtual std::string optionSummary() const = 0;
Phil Nasha2773812013-02-02 20:37:58 +00003617 virtual std::string optionDescription() const { return ""; }
Phil Nashecf934b2012-08-27 21:42:55 +01003618
3619 std::string optionNames() const {
3620 std::string names;
3621 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
3622 it != m_optionNames.end();
3623 ++it ) {
3624 if( !it->empty() ) {
3625 if( !names.empty() )
3626 names += ", ";
3627 names += *it;
3628 }
3629 else {
3630 names = "[" + names;
3631 }
3632 }
3633 if( names[0] == '[' )
3634 names += "]";
3635 return names;
3636 }
3637
3638 protected:
3639
3640 bool tooFewArgs( const Command& args ) const {
3641 return args.argsCount() < static_cast<std::size_t>( m_minArgs );
3642 }
3643 bool tooManyArgs( const Command& args ) const {
3644 return m_maxArgs >= 0 && args.argsCount() > static_cast<std::size_t>( m_maxArgs );
3645 }
3646 std::vector<std::string> m_optionNames;
3647 int m_minArgs;
3648 int m_maxArgs;
3649 };
3650
3651 namespace Options {
3652
3653 class HelpOptionParser : public OptionParser {
3654 public:
3655 HelpOptionParser() {
3656 m_optionNames.push_back( "-?" );
3657 m_optionNames.push_back( "-h" );
3658 m_optionNames.push_back( "--help" );
3659 }
3660 virtual std::string argsSynopsis() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003661 return "[<option for help on> ...]";
Phil Nashecf934b2012-08-27 21:42:55 +01003662 }
3663 virtual std::string optionSummary() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003664 return "Shows this usage summary, or help on a specific option, or options, if supplied";
Phil Nashe2d215e2012-09-07 17:52:35 +01003665 }
3666 virtual std::string optionDescription() const {
3667 return "";
Phil Nashecf934b2012-08-27 21:42:55 +01003668 }
3669
3670 virtual void parseIntoConfig( const Command&, ConfigData& ) {
3671 // Does not affect config
3672 }
3673 };
3674
3675 class TestCaseOptionParser : public OptionParser {
3676 public:
3677 TestCaseOptionParser() : OptionParser( 1, -1 ) {
3678 m_optionNames.push_back( "-t" );
3679 m_optionNames.push_back( "--test" );
3680 m_optionNames.push_back( "" ); // default option
3681 }
3682 virtual std::string argsSynopsis() const {
3683 return "<testspec> [<testspec>...]";
3684 }
3685 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003686 return "Specifies which test case or cases to run";
3687 }
3688
3689 // Lines are split at the nearest prior space char to the 80 char column.
3690 // Tab chars are removed from the output but their positions are used to align
3691 // subsequently wrapped lines
3692 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003693 return
3694 "This option allows one ore more test specs to be supplied. Each spec either fully "
3695 "specifies a test case or is a pattern containing wildcards to match a set of test "
3696 "cases. If this option is not provided then all test cases, except those prefixed "
3697 "by './' are run\n"
3698 "\n"
3699 "Specs must be enclosed in \"quotes\" if they contain spaces. If they do not "
3700 "contain spaces the quotes are optional.\n"
3701 "\n"
3702 "Wildcards consist of the * character at the beginning, end, or both and can substitute for "
3703 "any number of any characters (including none)\n"
3704 "\n"
3705 "If spec is prefixed with exclude: or the ~ character then the pattern matches an exclusion. "
3706 "This means that tests matching the pattern are excluded from the set - even if a prior "
Phil Nash799ecf92012-09-24 08:30:13 +01003707 "inclusion spec included them. Subsequent inclusion specs will take precedence, however. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003708 "Inclusions and exclusions are evaluated in left-to-right order.\n"
3709 "\n"
3710 "Examples:\n"
3711 "\n"
3712 " -t thisTestOnly \tMatches the test case called, 'thisTestOnly'\n"
3713 " -t \"this test only\" \tMatches the test case called, 'this test only'\n"
3714 " -t these/* \tMatches all cases starting with 'these/'\n"
3715 " -t exclude:notThis \tMatches all tests except, 'notThis'\n"
3716 " -t ~notThis \tMatches all tests except, 'notThis'\n"
3717 " -t ~*private* \tMatches all tests except those that contain 'private'\n"
3718 " -t a/* ~a/b/* a/b/c \tMatches all tests that start with 'a/', except those "
3719 "that start with 'a/b/', except 'a/b/c', which is included";
Phil Nashecf934b2012-08-27 21:42:55 +01003720 }
3721
3722 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3723 std::string groupName;
3724 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3725 if( i != 0 )
3726 groupName += " ";
3727 groupName += cmd[i];
3728 }
3729 TestCaseFilters filters( groupName );
Phil Nashbd7f7972013-03-21 09:00:24 +00003730 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3731 if( startsWith( cmd[i], "[" ) || startsWith( cmd[i], "~[" ) )
3732 filters.addTags( cmd[i] );
3733 else
3734 filters.addFilter( TestCaseFilter( cmd[i] ) );
3735 }
Phil Nashecf934b2012-08-27 21:42:55 +01003736 config.filters.push_back( filters );
3737 }
3738 };
3739
Phil Nash799ecf92012-09-24 08:30:13 +01003740 class TagOptionParser : public OptionParser {
3741 public:
3742 TagOptionParser() : OptionParser( 1, -1 ) {
3743 m_optionNames.push_back( "-g" );
3744 m_optionNames.push_back( "--tag" );
3745 }
3746 virtual std::string argsSynopsis() const {
3747 return "<tagspec> [,<tagspec>...]";
3748 }
3749 virtual std::string optionSummary() const {
3750 return "Matches test cases against tags or tag patterns";
3751 }
3752
3753 // Lines are split at the nearest prior space char to the 80 char column.
3754 // Tab chars are removed from the output but their positions are used to align
3755 // subsequently wrapped lines
3756 virtual std::string optionDescription() const {
3757 return
Phil Nasha1dc7e32012-11-06 19:34:35 +00003758 "This option allows one or more tags or tag patterns to be specified.\n"
3759 "Each tag is enclosed in square brackets. A series of tags form an AND expression "
3760 "wheras a comma seperated sequence forms an OR expression. e.g.:\n\n"
3761 " -g [one][two],[three]\n\n"
3762 "This matches all tests tagged [one] and [two], as well as all tests tagged [three].\n\n"
3763 "Tags can be negated with the ~ character. This removes matching tests from the set. e.g.:\n\n"
3764 " -g [one]~[two]\n\n"
3765 "matches all tests tagged [one], except those also tagged [two]";
Phil Nash799ecf92012-09-24 08:30:13 +01003766 }
3767
3768 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
Phil Nash67ec8702012-09-26 18:38:26 +01003769 std::string groupName;
3770 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3771 if( i != 0 )
3772 groupName += " ";
3773 groupName += cmd[i];
3774 }
3775 TestCaseFilters filters( groupName );
3776 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3777 filters.addTags( cmd[i] );
3778 config.filters.push_back( filters );
Phil Nash799ecf92012-09-24 08:30:13 +01003779 }
3780 };
3781
Phil Nashecf934b2012-08-27 21:42:55 +01003782 class ListOptionParser : public OptionParser {
3783 public:
3784 ListOptionParser() : OptionParser( 0, 2 ) {
3785 m_optionNames.push_back( "-l" );
3786 m_optionNames.push_back( "--list" );
3787 }
3788 virtual std::string argsSynopsis() const {
Phil Nash38f7eef2013-03-29 13:44:33 +00003789// return "[all | tests | reporters | tags [xml]]";
3790 return "[all | tests | reporters | tags]";
Phil Nashecf934b2012-08-27 21:42:55 +01003791 }
3792 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003793 return "Lists available tests or reporters";
3794 }
3795
3796 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003797 return
3798 "With no arguments this option will list all registered tests - one per line.\n"
Phil Nash38f7eef2013-03-29 13:44:33 +00003799// "Supplying the xml argument formats the list as an xml document (which may be useful for "
3800// "consumption by other tools).\n"
Phil Nashf7418eb2012-09-09 11:44:30 +01003801 "Supplying the tests or reporters lists tests or reporters respectively - with descriptions.\n"
3802 "\n"
3803 "Examples:\n"
3804 "\n"
3805 " -l\n"
3806 " -l tests\n"
Phil Nash38f7eef2013-03-29 13:44:33 +00003807 " -l tags\n"
Phil Nashf7418eb2012-09-09 11:44:30 +01003808 " -l reporters xml\n"
Phil Nash38f7eef2013-03-29 13:44:33 +00003809 ;//" -l xml";
Phil Nashecf934b2012-08-27 21:42:55 +01003810 }
3811
3812 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00003813 config.listSpec = List::Tests;
Phil Nashecf934b2012-08-27 21:42:55 +01003814 if( cmd.argsCount() >= 1 ) {
3815 if( cmd[0] == "all" )
3816 config.listSpec = List::All;
3817 else if( cmd[0] == "tests" )
3818 config.listSpec = List::Tests;
Phil Nash38f7eef2013-03-29 13:44:33 +00003819 else if( cmd[0] == "tags" )
3820 config.listSpec = List::Tags;
Phil Nashecf934b2012-08-27 21:42:55 +01003821 else if( cmd[0] == "reporters" )
3822 config.listSpec = List::Reports;
3823 else
Phil Nash38f7eef2013-03-29 13:44:33 +00003824 cmd.raiseError( "Expected tests, reporters or tags" );
Phil Nashecf934b2012-08-27 21:42:55 +01003825 }
3826 if( cmd.argsCount() >= 2 ) {
3827 if( cmd[1] == "xml" )
3828 config.listSpec = static_cast<List::What>( config.listSpec | List::AsXml );
3829 else if( cmd[1] == "text" )
3830 config.listSpec = static_cast<List::What>( config.listSpec | List::AsText );
3831 else
Phil Nash38f7eef2013-03-29 13:44:33 +00003832 cmd.raiseError( "Expected xml or text" );
Phil Nashecf934b2012-08-27 21:42:55 +01003833 }
3834 }
3835 };
3836
3837 class ReporterOptionParser : public OptionParser {
3838 public:
3839 ReporterOptionParser() : OptionParser( 1, 1 ) {
3840 m_optionNames.push_back( "-r" );
3841 m_optionNames.push_back( "--reporter" );
3842 }
3843 virtual std::string argsSynopsis() const {
3844 return "<reporter name>";
3845 }
3846 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003847 return "Specifies type of reporter";
3848 }
3849
3850 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003851 return
3852 "A reporter is an object that formats and structures the output of running "
Phil Nash2e7d9662013-01-16 09:44:43 +00003853 "tests, and potentially summarises the results. By default the console reporter "
3854 "is used which writes IDE friendly results. CATCH comes bundled with some "
Phil Nashf7418eb2012-09-09 11:44:30 +01003855 "alternative reporters, but more can be added in client code.\n"
3856 "\n"
3857 "The bundled reporters are:\n"
Phil Nash2e7d9662013-01-16 09:44:43 +00003858 " -r console\n"
Phil Nashf7418eb2012-09-09 11:44:30 +01003859 " -r xml\n"
3860 " -r junit\n"
3861 "\n"
3862 "The JUnit reporter is an xml format that follows the structure of the JUnit "
3863 "XML Report ANT task, as consumed by a number of third-party tools, "
3864 "including Continuous Integration servers such as Jenkins.\n"
3865 "If not otherwise needed, the standard XML reporter is preferred as this is "
3866 "a streaming reporter, whereas the Junit reporter needs to hold all its "
3867 "results until the end so it can write the overall results into attributes "
3868 "of the root node.";
Phil Nashecf934b2012-08-27 21:42:55 +01003869 }
3870
3871 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3872 config.reporter = cmd[0];
3873 }
3874 };
3875
3876 class OutputOptionParser : public OptionParser {
3877 public:
3878 OutputOptionParser() : OptionParser( 1, 1 ) {
3879 m_optionNames.push_back( "-o" );
3880 m_optionNames.push_back( "--out" );
3881 }
3882 virtual std::string argsSynopsis() const {
3883 return "<file name>|<%stream name>";
3884 }
3885 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003886 return "Sends output to a file or stream";
Phil Nashecf934b2012-08-27 21:42:55 +01003887 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003888 virtual std::string optionDescription() const {
3889 return
3890 "Use this option to send all output to a file or a stream. By default output is "
Phil Nash799ecf92012-09-24 08:30:13 +01003891 "sent to stdout (note that uses of stdout and stderr from within test cases are "
Phil Nashf7418eb2012-09-09 11:44:30 +01003892 "redirected and included in the report - so even stderr will effectively end up "
Phil Nash799ecf92012-09-24 08:30:13 +01003893 "on stdout). If the name begins with % it is interpreted as a stream. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003894 "Otherwise it is treated as a filename.\n"
3895 "\n"
3896 "Examples are:\n"
3897 "\n"
3898 " -o filename.txt\n"
3899 " -o \"long filename.txt\"\n"
3900 " -o %stdout\n"
3901 " -o %stderr\n"
3902 " -o %debug \t(The IDE's debug output window - currently only Windows' "
3903 "OutputDebugString is supported).";
3904 }
Phil Nashecf934b2012-08-27 21:42:55 +01003905 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3906 if( cmd[0][0] == '%' )
3907 config.stream = cmd[0].substr( 1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003908 else
Phil Nashecf934b2012-08-27 21:42:55 +01003909 config.outputFilename = cmd[0];
Phil Nasha695eb92012-08-13 07:46:10 +01003910 }
Phil Nashecf934b2012-08-27 21:42:55 +01003911 };
Phil Nasha695eb92012-08-13 07:46:10 +01003912
Phil Nashf7418eb2012-09-09 11:44:30 +01003913 class SuccessOptionParser : public OptionParser {
Phil Nashecf934b2012-08-27 21:42:55 +01003914 public:
Phil Nashf7418eb2012-09-09 11:44:30 +01003915 SuccessOptionParser() {
Phil Nashecf934b2012-08-27 21:42:55 +01003916 m_optionNames.push_back( "-s" );
3917 m_optionNames.push_back( "--success" );
Phil Nash56d5c422012-08-23 20:08:50 +01003918 }
Phil Nashecf934b2012-08-27 21:42:55 +01003919 virtual std::string argsSynopsis() const {
3920 return "";
Phil Nash56d5c422012-08-23 20:08:50 +01003921 }
Phil Nashecf934b2012-08-27 21:42:55 +01003922 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003923 return "Shows results for successful tests";
Phil Nasha695eb92012-08-13 07:46:10 +01003924 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003925 virtual std::string optionDescription() const {
3926 return
3927 "Usually you only want to see reporting for failed tests. Sometimes it's useful "
3928 "to see all the output (especially when you don't trust that that test you just "
Phil Nash799ecf92012-09-24 08:30:13 +01003929 "added worked first time!). To see successful, as well as failing, test results "
Phil Nashf7418eb2012-09-09 11:44:30 +01003930 "just pass this option.";
3931 }
Phil Nash78c92e62012-08-27 21:48:15 +01003932 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003933 config.includeWhichResults = Include::SuccessfulResults;
3934 }
3935 };
Phil Nasha695eb92012-08-13 07:46:10 +01003936
Phil Nashecf934b2012-08-27 21:42:55 +01003937 class DebugBreakOptionParser : public OptionParser {
3938 public:
3939 DebugBreakOptionParser() {
3940 m_optionNames.push_back( "-b" );
3941 m_optionNames.push_back( "--break" );
3942 }
3943 virtual std::string argsSynopsis() const {
3944 return "";
3945 }
3946 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003947 return "Breaks into the debugger on failure";
Phil Nashecf934b2012-08-27 21:42:55 +01003948 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003949 virtual std::string optionDescription() const {
3950 return
3951 "In some IDEs (currently XCode and Visual Studio) it is possible for CATCH to "
3952 "break into the debugger on a test failure. This can be very helpful during "
3953 "debug sessions - especially when there is more than one path through a "
3954 "particular test. In addition to the command line option, ensure you have "
3955 "built your code with the DEBUG preprocessor symbol";
3956 }
Phil Nashecf934b2012-08-27 21:42:55 +01003957
Phil Nash78c92e62012-08-27 21:48:15 +01003958 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003959 config.shouldDebugBreak = true;
3960 }
3961 };
3962
3963 class NameOptionParser : public OptionParser {
3964 public:
3965 NameOptionParser() : OptionParser( 1, 1 ) {
3966 m_optionNames.push_back( "-n" );
3967 m_optionNames.push_back( "--name" );
3968 }
3969 virtual std::string argsSynopsis() const {
3970 return "<name>";
3971 }
3972 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003973 return "Names a test run";
Phil Nashecf934b2012-08-27 21:42:55 +01003974 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003975 virtual std::string optionDescription() const {
3976 return
3977 "If a name is supplied it will be used by the reporter to provide an overall "
3978 "name for the test run. This can be useful if you are sending to a file, for "
3979 "example, and need to distinguish different test runs - either from different "
3980 "Catch executables or runs of the same executable with different options.\n"
3981 "\n"
3982 "Examples:\n"
3983 "\n"
3984 " -n testRun\n"
3985 " -n \"tests of the widget component\"";
3986 }
Phil Nashecf934b2012-08-27 21:42:55 +01003987
3988 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3989 config.name = cmd[0];
3990 }
3991 };
3992
3993 class AbortOptionParser : public OptionParser {
3994 public:
3995 AbortOptionParser() : OptionParser( 0, 1 ) {
3996 m_optionNames.push_back( "-a" );
3997 m_optionNames.push_back( "--abort" );
3998 }
3999 virtual std::string argsSynopsis() const {
4000 return "[#]";
4001 }
4002 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01004003 return "Aborts after a certain number of failures";
Phil Nashecf934b2012-08-27 21:42:55 +01004004 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004005 virtual std::string optionDescription() const {
4006 return
4007 "If a REQUIRE assertion fails the test case aborts, but subsequent test cases "
4008 "are still run. If a CHECK assertion fails even the current test case is not "
4009 "aborted.\n"
4010 "\n"
4011 "Sometimes this results in a flood of failure messages and you'd rather just "
4012 "see the first few. Specifying -a or --abort on its own will abort the whole "
4013 "test run on the first failed assertion of any kind. Following it with a "
4014 "number causes it to abort after that number of assertion failures.";
4015 }
Phil Nashecf934b2012-08-27 21:42:55 +01004016
4017 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
4018 int threshold = 1;
4019 if( cmd.argsCount() == 1 ) {
4020 std::stringstream ss;
4021 ss << cmd[0];
4022 ss >> threshold;
4023 if( ss.fail() || threshold <= 0 )
4024 cmd.raiseError( "threshold must be a number greater than zero" );
4025 }
4026 config.cutoff = threshold;
4027 }
4028 };
4029
4030 class NoThrowOptionParser : public OptionParser {
4031 public:
4032 NoThrowOptionParser() {
4033 m_optionNames.push_back( "-nt" );
4034 m_optionNames.push_back( "--nothrow" );
4035 }
4036 virtual std::string argsSynopsis() const {
4037 return "";
4038 }
4039 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01004040 return "Elides assertions expected to throw";
Phil Nashecf934b2012-08-27 21:42:55 +01004041 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004042 virtual std::string optionDescription() const {
4043 return
4044 "Skips all assertions that test that an exception is thrown, "
4045 "e.g. REQUIRE_THROWS.\n"
4046 "\n"
4047 "These can be a nuisance in certain debugging environments that may break when "
4048 "exceptions are thrown (while this is usually optional for handled exceptions, "
4049 "it can be useful to have enabled if you are trying to track down something "
4050 "unexpected).\n"
4051 "\n"
4052 "When running with this option the throw checking assertions are skipped so "
4053 "as not to contribute additional noise.";
4054 }
Phil Nashecf934b2012-08-27 21:42:55 +01004055
Phil Nash78c92e62012-08-27 21:48:15 +01004056 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01004057 config.allowThrows = false;
4058 }
4059 };
Phil Nasha70fbe32012-08-31 08:10:36 +01004060
4061 class WarningsOptionParser : public OptionParser {
4062 public:
4063 WarningsOptionParser() : OptionParser( 1, -1 ) {
4064 m_optionNames.push_back( "-w" );
4065 m_optionNames.push_back( "--warnings" );
4066 }
4067 virtual std::string argsSynopsis() const {
4068 return "<warning>";
4069 }
4070 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01004071 return "Enable warnings";
Phil Nasha70fbe32012-08-31 08:10:36 +01004072 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004073 virtual std::string optionDescription() const {
4074 return
4075 "Enables the named warnings. If the warnings are violated the test case is "
4076 "failed.\n"
4077 "\n"
4078 "At present only one warning has been provided: NoAssertions. If this warning "
4079 "is enabled then any test case that completes without an assertions (CHECK, "
4080 "REQUIRE etc) being encountered violates the warning.\n"
4081 "\n"
4082 "e.g.:\n"
4083 "\n"
4084 " -w NoAssertions";
4085 }
Phil Nasha70fbe32012-08-31 08:10:36 +01004086
4087 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
4088 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
4089 if( cmd[i] == "NoAssertions" )
4090 config.warnings = (ConfigData::WarnAbout::What)( config.warnings | ConfigData::WarnAbout::NoAssertions );
4091 else
4092 cmd.raiseError( "Unrecognised warning: " + cmd[i] );
4093 }
4094 }
4095 };
Phil Nasha695eb92012-08-13 07:46:10 +01004096 }
4097
Phil Nashecf934b2012-08-27 21:42:55 +01004098 class AllOptions
4099 {
4100 public:
4101 typedef std::vector<Ptr<OptionParser> > Parsers;
4102 typedef Parsers::const_iterator const_iterator;
4103 typedef Parsers::const_iterator iterator;
4104
4105 AllOptions() {
Phil Nasha70fbe32012-08-31 08:10:36 +01004106 add<Options::TestCaseOptionParser>(); // Keep this one first
4107
Phil Nash67ec8702012-09-26 18:38:26 +01004108 add<Options::TagOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01004109 add<Options::ListOptionParser>();
4110 add<Options::ReporterOptionParser>();
4111 add<Options::OutputOptionParser>();
Phil Nashf7418eb2012-09-09 11:44:30 +01004112 add<Options::SuccessOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01004113 add<Options::DebugBreakOptionParser>();
4114 add<Options::NameOptionParser>();
4115 add<Options::AbortOptionParser>();
4116 add<Options::NoThrowOptionParser>();
Phil Nasha70fbe32012-08-31 08:10:36 +01004117 add<Options::WarningsOptionParser>();
4118
4119 add<Options::HelpOptionParser>(); // Keep this one last
Phil Nashecf934b2012-08-27 21:42:55 +01004120 }
4121
4122 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
Phil Nasha90a88a2012-11-19 19:59:10 +00004123 config.name = parser.exeName();
4124 if( endsWith( config.name, ".exe" ) )
4125 config.name = config.name.substr( 0, config.name.size()-4 );
Phil Nashecf934b2012-08-27 21:42:55 +01004126 for( const_iterator it = m_parsers.begin(); it != m_parsers.end(); ++it )
4127 (*it)->parseIntoConfig( parser, config );
4128 }
4129
4130 const_iterator begin() const {
4131 return m_parsers.begin();
4132 }
4133 const_iterator end() const {
4134 return m_parsers.end();
4135 }
4136 private:
4137
4138 template<typename T>
4139 void add() {
4140 m_parsers.push_back( new T() );
4141 }
4142 Parsers m_parsers;
4143
4144 };
4145
Phil Nasha695eb92012-08-13 07:46:10 +01004146} // end namespace Catch
4147
4148// #included from: internal/catch_list.hpp
4149#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4150
Phil Nash38f7eef2013-03-29 13:44:33 +00004151// #included from: catch_line_wrap.h
4152#define TWOBLUECUBES_CATCH_LINE_WRAP_H_INCLUDED
4153
4154#include <string>
4155#include <vector>
4156
4157namespace Catch {
4158
4159 class LineWrapper {
4160 public:
4161 LineWrapper();
4162
4163 LineWrapper& setIndent( std::size_t _indent );
4164 LineWrapper& setRight( std::size_t _right );
4165
4166 LineWrapper& wrap( std::string const& _str );
4167
4168 std::string toString() const;
4169
4170 typedef std::vector<std::string>::const_iterator const_iterator;
4171
4172 const_iterator begin() const { return lines.begin(); }
4173 const_iterator end() const { return lines.end(); }
4174 std::string const& last() const { return lines.back(); }
4175 std::size_t size() const { return lines.size(); }
4176 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
4177
4178 friend std::ostream& operator << ( std::ostream& _stream, LineWrapper const& _lineWrapper );
4179
4180 private:
4181 void wrapInternal( std::string const& _str );
4182 void addLine( const std::string& _line );
4183 bool isWrapPoint( char c );
4184
4185 std::string indent;
4186 std::size_t right;
4187 std::size_t nextTab;
4188 std::size_t tab;
4189 std::string wrappableChars;
4190 int recursionCount;
4191 std::vector<std::string> lines;
4192 };
4193
4194} // end namespace Catch
4195
Phil Nash5c7d3d72013-04-01 11:27:10 +01004196// #included from: catch_console_colour.hpp
4197#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4198
4199namespace Catch {
4200
4201 struct IConsoleColourCodes : NonCopyable {
4202 enum Colours {
4203 None,
4204
4205 FileName,
4206 ResultError,
4207 ResultSuccess,
4208
4209 Error,
4210 Success,
4211
4212 OriginalExpression,
4213 ReconstructedExpression,
4214
4215 SecondaryText,
4216 Headers
4217 };
4218
4219 virtual void set( Colours colour ) = 0;
4220 };
4221
4222 class TextColour : public IConsoleColourCodes {
4223 public:
4224 TextColour( Colours colour = None );
4225 void set( Colours colour );
4226 ~TextColour();
4227
4228 private:
4229 IConsoleColourCodes* m_impl;
4230 };
4231
4232} // end namespace Catch
4233
Phil Nasha695eb92012-08-13 07:46:10 +01004234#include <limits>
Phil Nash38f7eef2013-03-29 13:44:33 +00004235#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01004236
4237namespace Catch {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004238 inline bool matchesFilters( const std::vector<TestCaseFilters>& filters, const TestCase& testCase ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004239 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
4240 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
4241 for(; it != itEnd; ++it )
4242 if( !it->shouldInclude( testCase ) )
4243 return false;
4244 return true;
4245 }
Phil Nasha695eb92012-08-13 07:46:10 +01004246
Phil Nash38f7eef2013-03-29 13:44:33 +00004247 inline void listTests( const ConfigData& config ) {
4248 if( config.filters.empty() )
4249 std::cout << "All available test cases:\n";
4250 else
4251 std::cout << "Matching test cases:\n";
4252 std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
4253 std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4254
4255 // First pass - get max tags
4256 std::size_t maxTagLen = 0;
4257 std::size_t maxNameLen = 0;
4258 for(; it != itEnd; ++it ) {
4259 if( matchesFilters( config.filters, *it ) ) {
4260 maxTagLen = (std::max)( it->getTestCaseInfo().tagsAsString.size(), maxTagLen );
4261 maxNameLen = (std::max)( it->getTestCaseInfo().name.size(), maxNameLen );
Phil Nasha695eb92012-08-13 07:46:10 +01004262 }
Phil Nasha695eb92012-08-13 07:46:10 +01004263 }
4264
Phil Nash38f7eef2013-03-29 13:44:33 +00004265 // Try to fit everything in. If not shrink tag column first, down to 30
4266 // then shrink name column until it all fits (strings will be wrapped within column)
4267 while( maxTagLen + maxNameLen > CATCH_CONFIG_CONSOLE_WIDTH-5 ) {
4268 if( maxTagLen > 30 )
4269 --maxTagLen;
Phil Nash56d5c422012-08-23 20:08:50 +01004270 else
Phil Nash38f7eef2013-03-29 13:44:33 +00004271 --maxNameLen;
4272 }
4273
4274 std::size_t matchedTests = 0;
4275 for( it = allTests.begin(); it != itEnd; ++it ) {
4276 if( matchesFilters( config.filters, *it ) ) {
4277 matchedTests++;
4278 // !TBD: consider listAs()
4279 LineWrapper nameWrapper;
4280 nameWrapper.setRight( maxNameLen ).setIndent( 2 ).wrap( it->getTestCaseInfo().name );
4281
4282 LineWrapper tagsWrapper;
4283 tagsWrapper.setRight( maxTagLen ).wrap( it->getTestCaseInfo().tagsAsString );
4284
4285 for( std::size_t i = 0; i < std::max( nameWrapper.size(), tagsWrapper.size() ); ++i ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01004286 TextColour::Colours colour = TextColour::None;
4287 if( it->getTestCaseInfo().isHidden )
4288 colour = TextColour::SecondaryText;
Phil Nash38f7eef2013-03-29 13:44:33 +00004289 std::string nameCol;
Phil Nash5c7d3d72013-04-01 11:27:10 +01004290 if( i < nameWrapper.size() ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00004291 nameCol = nameWrapper[i];
Phil Nash5c7d3d72013-04-01 11:27:10 +01004292 }
4293 else {
Phil Nash38f7eef2013-03-29 13:44:33 +00004294 nameCol = " ...";
Phil Nash5c7d3d72013-04-01 11:27:10 +01004295 colour = TextColour::SecondaryText;
4296 }
4297
4298 {
4299 TextColour colourGuard( colour );
4300 std::cout << nameCol;
4301 }
Phil Nash38f7eef2013-03-29 13:44:33 +00004302 if( i < tagsWrapper.size() && !tagsWrapper[i].empty() ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01004303 if( i == 0 ) {
4304 TextColour colourGuard( TextColour::SecondaryText );
4305 std::cout << " " << std::string( maxNameLen - nameCol.size(), '.' ) << " ";
4306 }
4307 else {
4308 std::cout << std::string( maxNameLen - nameCol.size(), ' ' ) << " ";
4309 }
4310 std::cout << tagsWrapper[i];
Phil Nash38f7eef2013-03-29 13:44:33 +00004311 }
4312 std::cout << "\n";
Phil Nash56d5c422012-08-23 20:08:50 +01004313 }
Phil Nasha695eb92012-08-13 07:46:10 +01004314 }
Phil Nasha695eb92012-08-13 07:46:10 +01004315 }
Phil Nash38f7eef2013-03-29 13:44:33 +00004316 if( config.filters.empty() )
4317 std::cout << pluralise( matchedTests, "test case" ) << std::endl;
4318 else
4319 std::cout << pluralise( matchedTests, "matching test case" ) << std::endl;
4320 }
Phil Nasha695eb92012-08-13 07:46:10 +01004321
Phil Nash38f7eef2013-03-29 13:44:33 +00004322 inline void listTags( const ConfigData& config ) {
4323 if( config.filters.empty() )
4324 std::cout << "All available tags:\n";
4325 else
4326 std::cout << "Matching tags:\n";
4327 std::vector<TestCase> const& allTests = getRegistryHub().getTestCaseRegistry().getAllTests();
4328 std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4329
4330 std::map<std::string, int> tagCounts;
4331
4332 std::size_t maxTagLen = 0;
4333
4334 for(; it != itEnd; ++it ) {
4335 if( matchesFilters( config.filters, *it ) ) {
4336 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4337 tagItEnd = it->getTestCaseInfo().tags.end();
4338 tagIt != tagItEnd;
4339 ++tagIt ) {
4340 std::string tagName = "[" + *tagIt + "]";
4341 maxTagLen = (std::max)( maxTagLen, tagName.size() );
4342 std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
4343 if( countIt == tagCounts.end() )
4344 tagCounts.insert( std::make_pair( tagName, 1 ) );
4345 else
4346 countIt->second++;
4347 }
4348 }
Phil Nasha695eb92012-08-13 07:46:10 +01004349 }
Phil Nash38f7eef2013-03-29 13:44:33 +00004350 maxTagLen +=2;
4351 if( maxTagLen > CATCH_CONFIG_CONSOLE_WIDTH-10 )
4352 maxTagLen = CATCH_CONFIG_CONSOLE_WIDTH-10;
4353
4354 for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(), countItEnd = tagCounts.end();
4355 countIt != countItEnd;
4356 ++countIt ) {
4357 LineWrapper wrapper;
4358 wrapper.setIndent(2).setRight( maxTagLen ).wrap( countIt->first );
4359
4360 std::cout << wrapper;
Phil Nash5c7d3d72013-04-01 11:27:10 +01004361 std::size_t dots = 2;
Phil Nash38f7eef2013-03-29 13:44:33 +00004362 if( maxTagLen > wrapper.last().size() )
Phil Nash5c7d3d72013-04-01 11:27:10 +01004363 dots += maxTagLen - wrapper.last().size();
4364 {
4365 TextColour colourGuard( TextColour::SecondaryText );
4366 std::cout << std::string( dots, '.' );
4367 }
4368 std::cout << countIt->second
Phil Nash38f7eef2013-03-29 13:44:33 +00004369 << "\n";
4370 }
4371 std::cout << pluralise( tagCounts.size(), "tag" ) << std::endl;
4372 }
4373
4374 inline void listReporters( const ConfigData& /*config*/ ) {
4375 std::cout << "Available reports:\n";
4376 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
4377 IReporterRegistry::FactoryMap::const_iterator it = factories.begin(), itEnd = factories.end();
4378 for(; it != itEnd; ++it ) {
4379 // !TBD: consider listAs()
4380 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
4381 }
4382 std::cout << std::endl;
4383 }
4384
4385 inline void list( const ConfigData& config ) {
4386 if( config.listSpec & List::Tests )
4387 listTests( config );
4388 if( config.listSpec & List::Tags )
4389 listTags( config );
4390 if( config.listSpec & List::Reports )
4391 listReporters( config );
4392 if( ( config.listSpec & List::All ) == 0 )
4393 throw std::logic_error( "Unknown list type" );
Phil Nasha695eb92012-08-13 07:46:10 +01004394 }
4395
4396} // end namespace Catch
4397
4398// #included from: internal/catch_runner_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004399#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004400
4401// #included from: catch_running_test.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004402#define TWOBLUECUBES_CATCH_RUNNING_TEST_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004403
4404// #included from: catch_section_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004405#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004406
4407#include <map>
4408#include <string>
4409
4410namespace Catch {
4411
Phil Nasha1fbfea2012-12-01 23:57:18 +00004412 class RunningSection {
Phil Nasha695eb92012-08-13 07:46:10 +01004413 public:
4414
Phil Nasha1fbfea2012-12-01 23:57:18 +00004415 typedef std::vector<RunningSection*> SubSections;
4416
4417 enum State {
Phil Nasha695eb92012-08-13 07:46:10 +01004418 Root,
4419 Unknown,
4420 Branch,
4421 TestedBranch,
4422 TestedLeaf
4423 };
4424
Phil Nasha1fbfea2012-12-01 23:57:18 +00004425 RunningSection( RunningSection* parent, const std::string& name )
4426 : m_state( Unknown ),
4427 m_parent( parent ),
4428 m_name( name )
Phil Nasha695eb92012-08-13 07:46:10 +01004429 {}
4430
Phil Nasha1fbfea2012-12-01 23:57:18 +00004431 RunningSection( const std::string& name )
4432 : m_state( Root ),
4433 m_parent( NULL ),
4434 m_name( name )
Phil Nasha695eb92012-08-13 07:46:10 +01004435 {}
4436
Phil Nasha1fbfea2012-12-01 23:57:18 +00004437 ~RunningSection() {
4438 deleteAll( m_subSections );
4439 }
4440
4441 std::string getName() const {
4442 return m_name;
Phil Nasha695eb92012-08-13 07:46:10 +01004443 }
4444
4445 bool shouldRun() const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004446 return m_state < TestedBranch;
Phil Nasha695eb92012-08-13 07:46:10 +01004447 }
4448
Phil Nasha70fbe32012-08-31 08:10:36 +01004449 bool isBranch() const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004450 return m_state == Branch;
Phil Nasha70fbe32012-08-31 08:10:36 +01004451 }
4452
Phil Nasha1fbfea2012-12-01 23:57:18 +00004453 const RunningSection* getParent() const {
Phil Nasha695eb92012-08-13 07:46:10 +01004454 return m_parent;
4455 }
4456
4457 bool hasUntestedSections() const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004458 if( m_state == Unknown )
Phil Nasha695eb92012-08-13 07:46:10 +01004459 return true;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004460 for( SubSections::const_iterator it = m_subSections.begin();
4461 it != m_subSections.end();
4462 ++it)
4463 if( (*it)->hasUntestedSections() )
Phil Nasha695eb92012-08-13 07:46:10 +01004464 return true;
Phil Nasha695eb92012-08-13 07:46:10 +01004465 return false;
4466 }
4467
Phil Nasha1fbfea2012-12-01 23:57:18 +00004468 // Mutable methods:
4469
4470 RunningSection* getParent() {
4471 return m_parent;
4472 }
4473
4474 RunningSection* findOrAddSubSection( const std::string& name, bool& changed ) {
4475 for( SubSections::const_iterator it = m_subSections.begin();
4476 it != m_subSections.end();
4477 ++it)
4478 if( (*it)->getName() == name )
4479 return *it;
4480 RunningSection* subSection = new RunningSection( this, name );
4481 m_subSections.push_back( subSection );
4482 m_state = Branch;
4483 changed = true;
4484 return subSection;
4485 }
4486
4487 bool ran() {
4488 if( m_state >= Branch )
4489 return false;
4490 m_state = TestedLeaf;
4491 return true;
4492 }
4493
4494 void ranToCompletion() {
4495 if( m_state == Branch && !hasUntestedSections() )
4496 m_state = TestedBranch;
4497 }
4498
Phil Nasha695eb92012-08-13 07:46:10 +01004499 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00004500 State m_state;
4501 RunningSection* m_parent;
4502 std::string m_name;
4503 SubSections m_subSections;
Phil Nasha695eb92012-08-13 07:46:10 +01004504 };
4505}
4506
4507namespace Catch {
4508
4509 class RunningTest {
4510
4511 enum RunStatus {
4512 NothingRun,
4513 EncounteredASection,
4514 RanAtLeastOneSection,
4515 RanToCompletionWithSections,
4516 RanToCompletionWithNoSections
4517 };
4518
4519 public:
Phil Nasha1fbfea2012-12-01 23:57:18 +00004520 explicit RunningTest( const TestCase& info )
Phil Nasha695eb92012-08-13 07:46:10 +01004521 : m_info( info ),
4522 m_runStatus( RanAtLeastOneSection ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00004523 m_rootSection( info.getTestCaseInfo().name ),
Phil Nasha695eb92012-08-13 07:46:10 +01004524 m_currentSection( &m_rootSection ),
4525 m_changed( false )
4526 {}
4527
4528 bool wasSectionSeen() const {
4529 return m_runStatus == RanAtLeastOneSection ||
4530 m_runStatus == RanToCompletionWithSections;
4531 }
4532
Phil Nasha70fbe32012-08-31 08:10:36 +01004533 bool isBranchSection() const {
4534 return m_currentSection &&
4535 m_currentSection->isBranch();
4536 }
4537
4538 bool hasSections() const {
4539 return m_runStatus == RanAtLeastOneSection ||
4540 m_runStatus == RanToCompletionWithSections ||
4541 m_runStatus == EncounteredASection;
4542 }
4543
Phil Nasha695eb92012-08-13 07:46:10 +01004544 void reset() {
4545 m_runStatus = NothingRun;
4546 m_changed = false;
4547 m_lastSectionToRun = NULL;
4548 }
4549
4550 void ranToCompletion() {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004551 if( m_runStatus != RanAtLeastOneSection && m_runStatus != EncounteredASection )
Phil Nasha695eb92012-08-13 07:46:10 +01004552 m_runStatus = RanToCompletionWithNoSections;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004553 m_runStatus = RanToCompletionWithSections;
4554 if( m_lastSectionToRun ) {
4555 m_lastSectionToRun->ranToCompletion();
4556 m_changed = true;
Phil Nasha695eb92012-08-13 07:46:10 +01004557 }
4558 }
4559
4560 bool addSection( const std::string& name ) {
4561 if( m_runStatus == NothingRun )
4562 m_runStatus = EncounteredASection;
4563
Phil Nasha1fbfea2012-12-01 23:57:18 +00004564 RunningSection* thisSection = m_currentSection->findOrAddSubSection( name, m_changed );
Phil Nasha695eb92012-08-13 07:46:10 +01004565
4566 if( !wasSectionSeen() && thisSection->shouldRun() ) {
4567 m_currentSection = thisSection;
4568 m_lastSectionToRun = NULL;
4569 return true;
4570 }
4571 return false;
4572 }
4573
Phil Nash767f1582013-03-04 12:19:15 +01004574 void endSection( const std::string&, bool stealth ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004575 if( m_currentSection->ran() ) {
Phil Nash767f1582013-03-04 12:19:15 +01004576 if( !stealth )
4577 m_runStatus = RanAtLeastOneSection;
Phil Nasha695eb92012-08-13 07:46:10 +01004578 m_changed = true;
4579 }
4580 else if( m_runStatus == EncounteredASection ) {
Phil Nash767f1582013-03-04 12:19:15 +01004581 if( !stealth )
4582 m_runStatus = RanAtLeastOneSection;
Phil Nasha695eb92012-08-13 07:46:10 +01004583 m_lastSectionToRun = m_currentSection;
4584 }
4585 m_currentSection = m_currentSection->getParent();
4586 }
4587
Phil Nasha1fbfea2012-12-01 23:57:18 +00004588 const TestCase& getTestCase() const {
4589 return m_info;
Phil Nasha695eb92012-08-13 07:46:10 +01004590 }
4591
4592 bool hasUntestedSections() const {
4593 return m_runStatus == RanAtLeastOneSection ||
4594 ( m_rootSection.hasUntestedSections() && m_changed );
4595 }
4596
4597 private:
Phil Nashdd26e882013-03-25 09:25:31 +00004598 RunningTest( RunningTest const& );
4599 void operator=( RunningTest const& );
4600
Phil Nasha1fbfea2012-12-01 23:57:18 +00004601 const TestCase& m_info;
Phil Nasha695eb92012-08-13 07:46:10 +01004602 RunStatus m_runStatus;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004603 RunningSection m_rootSection;
4604 RunningSection* m_currentSection;
4605 RunningSection* m_lastSectionToRun;
Phil Nasha695eb92012-08-13 07:46:10 +01004606 bool m_changed;
4607 };
4608}
4609
4610#include <set>
4611#include <string>
4612
4613namespace Catch {
4614
4615 class StreamRedirect {
4616
4617 public:
4618 StreamRedirect( std::ostream& stream, std::string& targetString )
4619 : m_stream( stream ),
4620 m_prevBuf( stream.rdbuf() ),
4621 m_targetString( targetString )
4622 {
4623 stream.rdbuf( m_oss.rdbuf() );
4624 }
4625
4626 ~StreamRedirect() {
4627 m_targetString += m_oss.str();
4628 m_stream.rdbuf( m_prevBuf );
4629 }
4630
4631 private:
4632 std::ostream& m_stream;
4633 std::streambuf* m_prevBuf;
4634 std::ostringstream m_oss;
4635 std::string& m_targetString;
4636 };
4637
4638 ///////////////////////////////////////////////////////////////////////////
4639
4640 class Runner : public IResultCapture, public IRunner {
4641
4642 Runner( const Runner& );
4643 void operator =( const Runner& );
4644
4645 public:
4646
Phil Nasha1fbfea2012-12-01 23:57:18 +00004647 explicit Runner( const Config& config, const Ptr<IStreamingReporter>& reporter )
4648 : m_runInfo( config.data().name ),
4649 m_context( getCurrentMutableContext() ),
Phil Nasha695eb92012-08-13 07:46:10 +01004650 m_runningTest( NULL ),
4651 m_config( config ),
4652 m_reporter( reporter ),
4653 m_prevRunner( &m_context.getRunner() ),
4654 m_prevResultCapture( &m_context.getResultCapture() ),
4655 m_prevConfig( m_context.getConfig() )
4656 {
4657 m_context.setRunner( this );
4658 m_context.setConfig( &m_config );
4659 m_context.setResultCapture( this );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004660 m_reporter->testRunStarting( m_runInfo );
Phil Nasha695eb92012-08-13 07:46:10 +01004661 }
4662
4663 virtual ~Runner() {
Phil Nash2e7d9662013-01-16 09:44:43 +00004664 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004665 m_context.setRunner( m_prevRunner );
4666 m_context.setConfig( NULL );
4667 m_context.setResultCapture( m_prevResultCapture );
4668 m_context.setConfig( m_prevConfig );
4669 }
4670
Phil Nash2e7d9662013-01-16 09:44:43 +00004671 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4672 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004673 }
Phil Nash2e7d9662013-01-16 09:44:43 +00004674 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
4675 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004676 }
4677
Phil Nash2e7d9662013-01-16 09:44:43 +00004678 Totals runMatching( const std::string& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004679
Phil Nasha1fbfea2012-12-01 23:57:18 +00004680 std::vector<TestCase> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01004681
4682 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01004683
Phil Nash2e7d9662013-01-16 09:44:43 +00004684 testGroupStarting( testSpec, groupIndex, groupsCount );
Phil Nash56d5c422012-08-23 20:08:50 +01004685
Phil Nasha1fbfea2012-12-01 23:57:18 +00004686 std::vector<TestCase>::const_iterator it = matchingTests.begin();
4687 std::vector<TestCase>::const_iterator itEnd = matchingTests.end();
Phil Nash56d5c422012-08-23 20:08:50 +01004688 for(; it != itEnd; ++it )
4689 totals += runTest( *it );
Phil Nash56d5c422012-08-23 20:08:50 +01004690
Phil Nash2e7d9662013-01-16 09:44:43 +00004691 testGroupEnded( testSpec, totals, groupIndex, groupsCount );
Phil Nash5bc030d2012-08-16 18:48:50 +01004692 return totals;
4693 }
4694
Phil Nasha1fbfea2012-12-01 23:57:18 +00004695 Totals runTest( const TestCase& testCase ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004696 Totals prevTotals = m_totals;
4697
4698 std::string redirectedCout;
4699 std::string redirectedCerr;
4700
Phil Nasha1fbfea2012-12-01 23:57:18 +00004701 TestCaseInfo testInfo = testCase.getTestCaseInfo();
Phil Nasha695eb92012-08-13 07:46:10 +01004702
Phil Nasha1fbfea2012-12-01 23:57:18 +00004703 m_reporter->testCaseStarting( testInfo );
4704
4705 m_runningTest = new RunningTest( testCase );
Phil Nasha695eb92012-08-13 07:46:10 +01004706
4707 do {
4708 do {
Phil Nasha695eb92012-08-13 07:46:10 +01004709 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01004710 }
4711 while( m_runningTest->hasUntestedSections() && !aborting() );
4712 }
4713 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
4714
Phil Nash28463672012-11-21 18:06:13 +00004715 Totals deltaTotals = m_totals.delta( prevTotals );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004716 bool missingAssertions = false;
Phil Nash28463672012-11-21 18:06:13 +00004717 if( deltaTotals.assertions.total() == 0 &&
4718 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) ) {
4719 m_totals.assertions.failed++;
4720 deltaTotals = m_totals.delta( prevTotals );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004721 missingAssertions = true;
Phil Nash28463672012-11-21 18:06:13 +00004722 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00004723
Phil Nash28463672012-11-21 18:06:13 +00004724 m_totals.testCases += deltaTotals.testCases;
4725
Phil Nash2e7d9662013-01-16 09:44:43 +00004726 m_reporter->testCaseEnded( TestCaseStats( testInfo,
4727 deltaTotals,
4728 redirectedCout,
4729 redirectedCerr,
4730 missingAssertions,
4731 aborting() ) );
Phil Nash28463672012-11-21 18:06:13 +00004732
Phil Nasha695eb92012-08-13 07:46:10 +01004733 delete m_runningTest;
4734 m_runningTest = NULL;
4735
Phil Nash5bc030d2012-08-16 18:48:50 +01004736 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01004737 }
4738
4739 const Config& config() const {
4740 return m_config;
4741 }
4742
4743 private: // IResultCapture
4744
Phil Nasha2773812013-02-02 20:37:58 +00004745 virtual void acceptMessage( const MessageBuilder& messageBuilder ) {
4746 m_messages.push_back( messageBuilder.build() );
4747 }
4748
Phil Nash5efa4bc2012-10-29 20:49:22 +00004749 virtual ResultAction::Value acceptExpression( const ExpressionResultBuilder& assertionResult, const AssertionInfo& assertionInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00004750 m_lastAssertionInfo = assertionInfo;
4751 return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004752 }
4753
Phil Nasha2773812013-02-02 20:37:58 +00004754 virtual void assertionEnded( const AssertionResult& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004755 if( result.getResultType() == ResultWas::Ok ) {
4756 m_totals.assertions.passed++;
4757 }
Phil Nashd539da92012-11-13 09:44:52 +00004758 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004759 m_totals.assertions.failed++;
Phil Nasha695eb92012-08-13 07:46:10 +01004760 }
4761
Phil Nasha2773812013-02-02 20:37:58 +00004762 m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) );
Phil Nasha90a88a2012-11-19 19:59:10 +00004763
Phil Nasha2773812013-02-02 20:37:58 +00004764 // Reset working state
4765 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
4766 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004767 }
4768
4769 virtual bool sectionStarted (
Phil Nasha1fbfea2012-12-01 23:57:18 +00004770 SectionInfo const& sectionInfo,
Phil Nasha695eb92012-08-13 07:46:10 +01004771 Counts& assertions
4772 )
4773 {
4774 std::ostringstream oss;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004775 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01004776
4777 if( !m_runningTest->addSection( oss.str() ) )
4778 return false;
4779
Phil Nasha1fbfea2012-12-01 23:57:18 +00004780 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Phil Nash88b70822012-11-04 21:39:38 +00004781
Phil Nasha1fbfea2012-12-01 23:57:18 +00004782 m_reporter->sectionStarting( sectionInfo );
4783
Phil Nasha695eb92012-08-13 07:46:10 +01004784 assertions = m_totals.assertions;
4785
4786 return true;
4787 }
4788
Phil Nasha1fbfea2012-12-01 23:57:18 +00004789 virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions ) {
Phil Nash5bdae842013-02-19 19:47:18 +00004790 if( std::uncaught_exception() ) {
4791 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions ) );
4792 return;
4793 }
4794
Phil Nasha70fbe32012-08-31 08:10:36 +01004795 Counts assertions = m_totals.assertions - prevAssertions;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004796 bool missingAssertions = false;
Phil Nash28463672012-11-21 18:06:13 +00004797 if( assertions.total() == 0 &&
Phil Nasha70fbe32012-08-31 08:10:36 +01004798 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4799 !m_runningTest->isBranchSection() ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01004800 m_totals.assertions.failed++;
4801 assertions.failed++;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004802 missingAssertions = true;
4803
Phil Nasha70fbe32012-08-31 08:10:36 +01004804 }
Phil Nash767f1582013-03-04 12:19:15 +01004805 m_runningTest->endSection( info.name, false );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004806
Phil Nash2e7d9662013-01-16 09:44:43 +00004807 m_reporter->sectionEnded( SectionStats( info, assertions, missingAssertions ) );
Phil Nasha2773812013-02-02 20:37:58 +00004808 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004809 }
4810
Phil Nasha2773812013-02-02 20:37:58 +00004811 virtual void pushScopedMessage( ScopedMessageBuilder const& _builder ) {
4812 m_messages.push_back( _builder.build() );
Phil Nasha695eb92012-08-13 07:46:10 +01004813 }
4814
Phil Nasha2773812013-02-02 20:37:58 +00004815 virtual void popScopedMessage( ScopedMessageBuilder const& _builder ) {
4816 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), _builder ), m_messages.end() );
Phil Nasha695eb92012-08-13 07:46:10 +01004817 }
4818
4819 virtual bool shouldDebugBreak() const {
4820 return m_config.shouldDebugBreak();
4821 }
4822
4823 virtual std::string getCurrentTestName() const {
4824 return m_runningTest
Phil Nasha1fbfea2012-12-01 23:57:18 +00004825 ? m_runningTest->getTestCase().getTestCaseInfo().name
Phil Nasha695eb92012-08-13 07:46:10 +01004826 : "";
4827 }
4828
Phil Nash82acc2c2012-10-28 12:07:17 +00004829 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01004830 return &m_lastResult;
4831 }
4832
Phil Nash56d5c422012-08-23 20:08:50 +01004833 public:
4834 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01004835 bool aborting() const {
4836 return m_totals.assertions.failed == static_cast<std::size_t>( m_config.getCutoff() );
4837 }
4838
Phil Nash56d5c422012-08-23 20:08:50 +01004839 private:
4840
Phil Nash88b70822012-11-04 21:39:38 +00004841 ResultAction::Value actOnCurrentResult( const AssertionResult& result ) {
4842 m_lastResult = result;
Phil Nasha2773812013-02-02 20:37:58 +00004843 assertionEnded( m_lastResult );
Phil Nasha695eb92012-08-13 07:46:10 +01004844
Phil Nasha695eb92012-08-13 07:46:10 +01004845 ResultAction::Value action = ResultAction::None;
4846
Phil Nashd539da92012-11-13 09:44:52 +00004847 if( !m_lastResult.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004848 action = ResultAction::Failed;
4849 if( shouldDebugBreak() )
4850 action = (ResultAction::Value)( action | ResultAction::Debug );
4851 if( aborting() )
4852 action = (ResultAction::Value)( action | ResultAction::Abort );
4853 }
4854 return action;
4855 }
4856
4857 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
4858 try {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004859 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", m_runningTest->getTestCase().getTestCaseInfo().lineInfo, "", ResultDisposition::Normal );
Phil Nasha695eb92012-08-13 07:46:10 +01004860 m_runningTest->reset();
Phil Nashd768b1b2013-02-04 00:05:16 +00004861
Phil Nasha1fbfea2012-12-01 23:57:18 +00004862 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
Phil Nasha695eb92012-08-13 07:46:10 +01004863 StreamRedirect coutRedir( std::cout, redirectedCout );
4864 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
Phil Nasha1fbfea2012-12-01 23:57:18 +00004865 m_runningTest->getTestCase().invoke();
Phil Nasha695eb92012-08-13 07:46:10 +01004866 }
4867 else {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004868 m_runningTest->getTestCase().invoke();
Phil Nasha695eb92012-08-13 07:46:10 +01004869 }
4870 m_runningTest->ranToCompletion();
4871 }
4872 catch( TestFailureException& ) {
4873 // This just means the test was aborted due to failure
4874 }
4875 catch(...) {
Phil Nash88b70822012-11-04 21:39:38 +00004876 ExpressionResultBuilder exResult( ResultWas::ThrewException );
4877 exResult << translateActiveException();
4878 actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01004879 }
Phil Nash5bdae842013-02-19 19:47:18 +00004880 for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
4881 itEnd = m_unfinishedSections.end();
4882 it != itEnd;
4883 ++it )
4884 sectionEnded( it->info, it->prevAssertions );
4885 m_unfinishedSections.clear();
Phil Nashd768b1b2013-02-04 00:05:16 +00004886 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01004887 }
4888
4889 private:
Phil Nash5bdae842013-02-19 19:47:18 +00004890 struct UnfinishedSections {
4891 UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions )
4892 : info( _info ), prevAssertions( _prevAssertions )
4893 {}
4894
4895 SectionInfo info;
4896 Counts prevAssertions;
4897 };
4898
Phil Nasha1fbfea2012-12-01 23:57:18 +00004899 TestRunInfo m_runInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01004900 IMutableContext& m_context;
4901 RunningTest* m_runningTest;
Phil Nash82acc2c2012-10-28 12:07:17 +00004902 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01004903
4904 const Config& m_config;
4905 Totals m_totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004906 Ptr<IStreamingReporter> m_reporter;
Phil Nasha2773812013-02-02 20:37:58 +00004907 std::vector<MessageInfo> m_messages;
Phil Nasha695eb92012-08-13 07:46:10 +01004908 IRunner* m_prevRunner;
4909 IResultCapture* m_prevResultCapture;
4910 const IConfig* m_prevConfig;
Phil Nash88b70822012-11-04 21:39:38 +00004911 AssertionInfo m_lastAssertionInfo;
Phil Nash5bdae842013-02-19 19:47:18 +00004912 std::vector<UnfinishedSections> m_unfinishedSections;
Phil Nasha695eb92012-08-13 07:46:10 +01004913 };
4914
4915} // end namespace Catch
4916
Phil Nash7673a302012-11-15 22:15:41 +00004917// #included from: internal/catch_version.h
4918#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
4919
4920namespace Catch {
4921
4922 // Versioning information
4923 struct Version {
Phil Nasha1fbfea2012-12-01 23:57:18 +00004924 Version( unsigned int _majorVersion,
4925 unsigned int _minorVersion,
4926 unsigned int _buildNumber,
4927 std::string const& _branchName )
4928 : majorVersion( _majorVersion ),
4929 minorVersion( _minorVersion ),
4930 buildNumber( _buildNumber ),
4931 branchName( _branchName )
4932 {}
4933
4934 const unsigned int majorVersion;
4935 const unsigned int minorVersion;
4936 const unsigned int buildNumber;
4937 const std::string branchName;
Phil Nashdd26e882013-03-25 09:25:31 +00004938
4939 private:
4940 void operator=( Version const& );
Phil Nash7673a302012-11-15 22:15:41 +00004941 };
4942
4943 extern Version libraryVersion;
4944}
4945
Phil Nash89d1e6c2011-05-24 08:23:02 +01004946#include <fstream>
4947#include <stdlib.h>
4948#include <limits>
4949
Phil Nash89d2a3f2012-05-16 15:09:17 +01004950namespace Catch {
4951
Phil Nash56d5c422012-08-23 20:08:50 +01004952 class Runner2 { // This will become Runner when Runner becomes Context
Phil Nash163088a2012-05-31 19:40:26 +01004953
Phil Nash56d5c422012-08-23 20:08:50 +01004954 public:
4955 Runner2( Config& configWrapper )
4956 : m_configWrapper( configWrapper ),
4957 m_config( configWrapper.data() )
Phil Nash06e959b2012-05-25 08:52:05 +01004958 {
Phil Nash67ec8702012-09-26 18:38:26 +01004959 openStream();
Phil Nash56d5c422012-08-23 20:08:50 +01004960 makeReporter();
4961 }
Phil Nash06e959b2012-05-25 08:52:05 +01004962
Phil Nash56d5c422012-08-23 20:08:50 +01004963 Totals runTests() {
4964
4965 std::vector<TestCaseFilters> filterGroups = m_config.filters;
4966 if( filterGroups.empty() ) {
4967 TestCaseFilters filterGroup( "" );
Phil Nash56d5c422012-08-23 20:08:50 +01004968 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004969 }
Phil Nash56d5c422012-08-23 20:08:50 +01004970
4971 Runner context( m_configWrapper, m_reporter ); // This Runner will be renamed Context
4972 Totals totals;
4973
Phil Nash2e7d9662013-01-16 09:44:43 +00004974 for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) {
4975 context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() );
4976 totals += runTestsForGroup( context, filterGroups[i] );
4977 context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() );
Phil Nash56d5c422012-08-23 20:08:50 +01004978 }
4979 return totals;
4980 }
4981
4982 Totals runTestsForGroup( Runner& context, const TestCaseFilters& filterGroup ) {
4983 Totals totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00004984 std::vector<TestCase>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
4985 std::vector<TestCase>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash56d5c422012-08-23 20:08:50 +01004986 int testsRunForGroup = 0;
4987 for(; it != itEnd; ++it ) {
4988 if( filterGroup.shouldInclude( *it ) ) {
4989 testsRunForGroup++;
4990 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
4991
4992 if( context.aborting() )
4993 break;
4994
4995 totals += context.runTest( *it );
4996 m_testsAlreadyRun.insert( *it );
4997 }
Phil Nash06e959b2012-05-25 08:52:05 +01004998 }
4999 }
Phil Nash5bdae842013-02-19 19:47:18 +00005000 if( testsRunForGroup == 0 && !filterGroup.getName().empty() )
Phil Nash37186a12013-03-13 12:19:30 +00005001 m_reporter->noMatchingTestCases( filterGroup.getName() );
Phil Nash56d5c422012-08-23 20:08:50 +01005002 return totals;
5003
Phil Nash89d1e6c2011-05-24 08:23:02 +01005004 }
Phil Nash56d5c422012-08-23 20:08:50 +01005005
5006 private:
Phil Nash67ec8702012-09-26 18:38:26 +01005007 void openStream() {
5008 if( !m_config.stream.empty() )
5009 m_configWrapper.useStream( m_config.stream );
5010
Phil Nash56d5c422012-08-23 20:08:50 +01005011 // Open output file, if specified
5012 if( !m_config.outputFilename.empty() ) {
5013 m_ofs.open( m_config.outputFilename.c_str() );
5014 if( m_ofs.fail() ) {
5015 std::ostringstream oss;
5016 oss << "Unable to open file: '" << m_config.outputFilename << "'";
5017 throw std::domain_error( oss.str() );
5018 }
5019 m_configWrapper.setStreamBuf( m_ofs.rdbuf() );
5020 }
5021 }
5022 void makeReporter() {
5023 std::string reporterName = m_config.reporter.empty()
Phil Nashbcad0932012-12-10 08:54:57 +00005024 ? "console"
Phil Nash56d5c422012-08-23 20:08:50 +01005025 : m_config.reporter;
5026
Phil Nasha1fbfea2012-12-01 23:57:18 +00005027 ReporterConfig reporterConfig( m_configWrapper.stream(), m_config );
Phil Nash56d5c422012-08-23 20:08:50 +01005028
5029 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, reporterConfig );
5030 if( !m_reporter ) {
5031 std::ostringstream oss;
5032 oss << "No reporter registered with name: '" << reporterName << "'";
5033 throw std::domain_error( oss.str() );
5034 }
5035 }
5036
5037 private:
5038 Config& m_configWrapper;
5039 const ConfigData& m_config;
5040 std::ofstream m_ofs;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005041 Ptr<IStreamingReporter> m_reporter;
5042 std::set<TestCase> m_testsAlreadyRun;
Phil Nash56d5c422012-08-23 20:08:50 +01005043 };
5044
5045 inline int Main( Config& configWrapper ) {
5046 int result = 0;
5047 try
5048 {
5049 Runner2 runner( configWrapper );
5050
5051 const ConfigData& config = configWrapper.data();
5052
5053 // Handle list request
5054 if( config.listSpec != List::None ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00005055 list( config );
Phil Nash799ecf92012-09-24 08:30:13 +01005056 Catch::cleanUp();
Phil Nash56d5c422012-08-23 20:08:50 +01005057 return 0;
5058 }
5059
5060 result = static_cast<int>( runner.runTests().assertions.failed );
5061
5062 }
5063 catch( std::exception& ex ) {
5064 std::cerr << ex.what() << std::endl;
5065 result = (std::numeric_limits<int>::max)();
5066 }
5067
Phil Nash3b80af72012-08-09 07:47:30 +01005068 Catch::cleanUp();
Phil Nash371db8b2012-05-21 18:52:09 +01005069 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005070 }
5071
Phil Nash163088a2012-05-31 19:40:26 +01005072 inline void showUsage( std::ostream& os ) {
Phil Nashecf934b2012-08-27 21:42:55 +01005073 AllOptions options;
Phil Nashe2d215e2012-09-07 17:52:35 +01005074
Phil Nashecf934b2012-08-27 21:42:55 +01005075 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
5076 OptionParser& opt = **it;
5077 os << " " << opt.optionNames() << " " << opt.argsSynopsis() << "\n";
5078 }
5079 os << "\nFor more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line\n" << std::endl;
Phil Nash163088a2012-05-31 19:40:26 +01005080 }
Phil Nashe2d215e2012-09-07 17:52:35 +01005081
Phil Nashe2d215e2012-09-07 17:52:35 +01005082 inline void showHelp( const CommandParser& parser ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005083 AllOptions options;
5084 Options::HelpOptionParser helpOpt;
5085 bool displayedSpecificOption = false;
5086 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
5087 OptionParser& opt = **it;
5088 if( opt.find( parser ) && opt.optionNames() != helpOpt.optionNames() ) {
5089 displayedSpecificOption = true;
5090 std::cout << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n"
5091 << opt.optionSummary() << "\n\n"
Phil Nash38f7eef2013-03-29 13:44:33 +00005092 << LineWrapper().setIndent( 2 ).wrap( opt.optionDescription() ) << "\n" << std::endl;
Phil Nashe2d215e2012-09-07 17:52:35 +01005093 }
5094 }
5095
5096 if( !displayedSpecificOption ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00005097 std::cout << "\nCATCH v" << libraryVersion.majorVersion << "."
Phil Nasha1fbfea2012-12-01 23:57:18 +00005098 << libraryVersion.minorVersion << " build "
5099 << libraryVersion.buildNumber;
5100 if( libraryVersion.branchName != "master" )
5101 std::cout << " (" << libraryVersion.branchName << " branch)";
Phil Nash7673a302012-11-15 22:15:41 +00005102
Phil Nasha90a88a2012-11-19 19:59:10 +00005103 std::cout << "\n\n" << parser.exeName() << " is a CATCH host application. Options are as follows:\n\n";
Phil Nashe2d215e2012-09-07 17:52:35 +01005104 showUsage( std::cout );
5105 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005106 }
5107
Phil Nash89d2a3f2012-05-16 15:09:17 +01005108 inline int Main( int argc, char* const argv[], Config& config ) {
Phil Nash163088a2012-05-31 19:40:26 +01005109
Phil Nashabf27162012-07-05 18:37:58 +01005110 try {
5111 CommandParser parser( argc, argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005112
Phil Nashecf934b2012-08-27 21:42:55 +01005113 if( Command cmd = Options::HelpOptionParser().find( parser ) ) {
Phil Nashabf27162012-07-05 18:37:58 +01005114 if( cmd.argsCount() != 0 )
5115 cmd.raiseError( "Does not accept arguments" );
5116
Phil Nashe2d215e2012-09-07 17:52:35 +01005117 showHelp( parser );
Phil Nash3b80af72012-08-09 07:47:30 +01005118 Catch::cleanUp();
Phil Nashabf27162012-07-05 18:37:58 +01005119 return 0;
5120 }
5121
Phil Nashecf934b2012-08-27 21:42:55 +01005122 AllOptions options;
5123
5124 options.parseIntoConfig( parser, config.data() );
Phil Nashabf27162012-07-05 18:37:58 +01005125 }
5126 catch( std::exception& ex ) {
Phil Nash6f220862012-07-23 08:24:52 +01005127 std::cerr << ex.what() << "\n\nUsage: ...\n\n";
Phil Nash163088a2012-05-31 19:40:26 +01005128 showUsage( std::cerr );
Phil Nash3b80af72012-08-09 07:47:30 +01005129 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01005130 return (std::numeric_limits<int>::max)();
5131 }
5132
Phil Nash89d1e6c2011-05-24 08:23:02 +01005133 return Main( config );
5134 }
5135
Phil Nash89d2a3f2012-05-16 15:09:17 +01005136 inline int Main( int argc, char* const argv[] ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01005137 Config config;
Phil Nash371db8b2012-05-21 18:52:09 +01005138// !TBD: This doesn't always work, for some reason
Phil Nash89d1e6c2011-05-24 08:23:02 +01005139// if( isDebuggerActive() )
5140// config.useStream( "debug" );
Phil Nash371db8b2012-05-21 18:52:09 +01005141 return Main( argc, argv, config );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005142 }
5143
5144} // end namespace Catch
5145
Phil Nash3b80af72012-08-09 07:47:30 +01005146// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005147#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005148
5149// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005150#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005151
5152#include <vector>
5153#include <set>
5154#include <sstream>
5155#include <iostream>
5156
5157namespace Catch {
5158
5159 class TestRegistry : public ITestCaseRegistry {
5160 public:
5161 TestRegistry() : m_unnamedCount( 0 ) {}
Phil Nasha695eb92012-08-13 07:46:10 +01005162 virtual ~TestRegistry();
Phil Nash3b80af72012-08-09 07:47:30 +01005163
Phil Nasha1fbfea2012-12-01 23:57:18 +00005164 virtual void registerTest( const TestCase& testCase ) {
5165 std::string name = testCase.getTestCaseInfo().name;
5166 if( name == "" ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005167 std::ostringstream oss;
Phil Nash93906752013-03-16 20:21:51 +00005168 oss << "Anonymous test case " << ++m_unnamedCount;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005169 return registerTest( testCase.withName( oss.str() ) );
Phil Nash3b80af72012-08-09 07:47:30 +01005170 }
5171
Phil Nasha1fbfea2012-12-01 23:57:18 +00005172 if( m_functions.find( testCase ) == m_functions.end() ) {
5173 m_functions.insert( testCase );
5174 m_functionsInOrder.push_back( testCase );
5175 if( !testCase.isHidden() )
5176 m_nonHiddenFunctions.push_back( testCase );
Phil Nash3b80af72012-08-09 07:47:30 +01005177 }
5178 else {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005179 const TestCase& prev = *m_functions.find( testCase );
5180 std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
5181 << "\tFirst seen at " << SourceLineInfo( prev.getTestCaseInfo().lineInfo ) << "\n"
5182 << "\tRedefined at " << SourceLineInfo( testCase.getTestCaseInfo().lineInfo ) << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01005183 exit(1);
5184 }
5185 }
5186
Phil Nasha1fbfea2012-12-01 23:57:18 +00005187 virtual const std::vector<TestCase>& getAllTests() const {
Phil Nash3b80af72012-08-09 07:47:30 +01005188 return m_functionsInOrder;
5189 }
5190
Phil Nasha1fbfea2012-12-01 23:57:18 +00005191 virtual const std::vector<TestCase>& getAllNonHiddenTests() const {
Phil Nash5bc030d2012-08-16 18:48:50 +01005192 return m_nonHiddenFunctions;
5193 }
5194
Phil Nash56d5c422012-08-23 20:08:50 +01005195 // !TBD deprecated
Phil Nasha1fbfea2012-12-01 23:57:18 +00005196 virtual std::vector<TestCase> getMatchingTestCases( const std::string& rawTestSpec ) const {
5197 std::vector<TestCase> matchingTests;
Phil Nash5bc030d2012-08-16 18:48:50 +01005198 getMatchingTestCases( rawTestSpec, matchingTests );
5199 return matchingTests;
5200 }
5201
Phil Nash56d5c422012-08-23 20:08:50 +01005202 // !TBD deprecated
Phil Nasha1fbfea2012-12-01 23:57:18 +00005203 virtual void getMatchingTestCases( const std::string& rawTestSpec, std::vector<TestCase>& matchingTestsOut ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01005204 TestCaseFilter filter( rawTestSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01005205
Phil Nasha1fbfea2012-12-01 23:57:18 +00005206 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5207 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
Phil Nash3b80af72012-08-09 07:47:30 +01005208 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01005209 if( filter.shouldInclude( *it ) ) {
Phil Nash5bc030d2012-08-16 18:48:50 +01005210 matchingTestsOut.push_back( *it );
Phil Nash3b80af72012-08-09 07:47:30 +01005211 }
5212 }
Phil Nash3b80af72012-08-09 07:47:30 +01005213 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00005214 virtual void getMatchingTestCases( const TestCaseFilters& filters, std::vector<TestCase>& matchingTestsOut ) const {
5215 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5216 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
Phil Nash56d5c422012-08-23 20:08:50 +01005217 // !TBD: replace with algorithm
5218 for(; it != itEnd; ++it )
5219 if( filters.shouldInclude( *it ) )
5220 matchingTestsOut.push_back( *it );
5221 }
Phil Nash3b80af72012-08-09 07:47:30 +01005222
5223 private:
5224
Phil Nasha1fbfea2012-12-01 23:57:18 +00005225 std::set<TestCase> m_functions;
5226 std::vector<TestCase> m_functionsInOrder;
5227 std::vector<TestCase> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01005228 size_t m_unnamedCount;
5229 };
5230
5231 ///////////////////////////////////////////////////////////////////////////
5232
Phil Nash5bc030d2012-08-16 18:48:50 +01005233 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
Phil Nash3b80af72012-08-09 07:47:30 +01005234 public:
5235
5236 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
5237
5238 virtual void invoke() const {
5239 m_fun();
5240 }
5241
Phil Nash3b80af72012-08-09 07:47:30 +01005242 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01005243 virtual ~FreeFunctionTestCase();
5244
Phil Nash3b80af72012-08-09 07:47:30 +01005245 TestFunction m_fun;
5246 };
5247
Phil Nash88b70822012-11-04 21:39:38 +00005248 inline std::string extractClassName( const std::string& classOrQualifiedMethodName ) {
5249 std::string className = classOrQualifiedMethodName;
5250 if( className[0] == '&' )
5251 {
5252 std::size_t lastColons = className.rfind( "::" );
5253 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
5254 if( penultimateColons == std::string::npos )
5255 penultimateColons = 1;
5256 className = className.substr( penultimateColons, lastColons-penultimateColons );
5257 }
5258 return className;
5259 }
5260
Phil Nash3b80af72012-08-09 07:47:30 +01005261 ///////////////////////////////////////////////////////////////////////////
5262
5263 AutoReg::AutoReg( TestFunction function,
Phil Nash93906752013-03-16 20:21:51 +00005264 SourceLineInfo const& lineInfo,
5265 NameAndDesc const& nameAndDesc ) {
5266 registerTestCase( new FreeFunctionTestCase( function ), "global", nameAndDesc, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01005267 }
5268
5269 AutoReg::~AutoReg() {}
5270
5271 void AutoReg::registerTestCase( ITestCase* testCase,
Phil Nash93906752013-03-16 20:21:51 +00005272 char const* classOrQualifiedMethodName,
5273 NameAndDesc const& nameAndDesc,
5274 SourceLineInfo const& lineInfo ) {
Phil Nash88b70822012-11-04 21:39:38 +00005275
Phil Nash93906752013-03-16 20:21:51 +00005276 getMutableRegistryHub().registerTest
5277 ( makeTestCase( testCase,
5278 extractClassName( classOrQualifiedMethodName ),
5279 nameAndDesc.name,
5280 nameAndDesc.description,
5281 lineInfo ) );
Phil Nash3b80af72012-08-09 07:47:30 +01005282 }
5283
5284} // end namespace Catch
5285
5286// #included from: catch_reporter_registry.hpp
5287#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
5288
5289#include <map>
5290
5291namespace Catch {
5292
5293 class ReporterRegistry : public IReporterRegistry {
5294
5295 public:
5296
Phil Nasha695eb92012-08-13 07:46:10 +01005297 virtual ~ReporterRegistry() {
Phil Nash3b80af72012-08-09 07:47:30 +01005298 deleteAllValues( m_factories );
5299 }
5300
Phil Nasha1fbfea2012-12-01 23:57:18 +00005301 virtual IStreamingReporter* create( const std::string& name, const ReporterConfig& config ) const {
Phil Nash3b80af72012-08-09 07:47:30 +01005302 FactoryMap::const_iterator it = m_factories.find( name );
5303 if( it == m_factories.end() )
5304 return NULL;
5305 return it->second->create( config );
5306 }
5307
5308 void registerReporter( const std::string& name, IReporterFactory* factory ) {
5309 m_factories.insert( std::make_pair( name, factory ) );
5310 }
5311
5312 const FactoryMap& getFactories() const {
5313 return m_factories;
5314 }
5315
5316 private:
5317 FactoryMap m_factories;
5318 };
5319}
5320
5321// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005322#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005323
5324#ifdef __OBJC__
5325#import "Foundation/Foundation.h"
5326#endif
5327
5328namespace Catch {
5329
5330 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
5331 public:
5332 ~ExceptionTranslatorRegistry() {
5333 deleteAll( m_translators );
5334 }
5335
5336 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5337 m_translators.push_back( translator );
5338 }
5339
5340 virtual std::string translateActiveException() const {
5341 try {
5342#ifdef __OBJC__
5343 // In Objective-C try objective-c exceptions first
5344 @try {
5345 throw;
5346 }
5347 @catch (NSException *exception) {
5348 return toString( [exception description] );
5349 }
5350#else
5351 throw;
5352#endif
5353 }
5354 catch( std::exception& ex ) {
5355 return ex.what();
5356 }
5357 catch( std::string& msg ) {
5358 return msg;
5359 }
5360 catch( const char* msg ) {
5361 return msg;
5362 }
5363 catch(...) {
5364 return tryTranslators( m_translators.begin() );
5365 }
5366 }
5367
5368 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
5369 if( it == m_translators.end() )
5370 return "Unknown exception";
5371
5372 try {
5373 return (*it)->translate();
5374 }
5375 catch(...) {
5376 return tryTranslators( it+1 );
5377 }
5378 }
5379
5380 private:
5381 std::vector<const IExceptionTranslator*> m_translators;
5382 };
5383}
5384
5385namespace Catch {
5386
5387 namespace {
5388
5389 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
5390
5391 RegistryHub( const RegistryHub& );
5392 void operator=( const RegistryHub& );
5393
5394 public: // IRegistryHub
5395 RegistryHub() {
5396 }
5397 virtual const IReporterRegistry& getReporterRegistry() const {
5398 return m_reporterRegistry;
5399 }
5400 virtual const ITestCaseRegistry& getTestCaseRegistry() const {
5401 return m_testCaseRegistry;
5402 }
5403 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
5404 return m_exceptionTranslatorRegistry;
5405 }
5406
5407 public: // IMutableRegistryHub
5408 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) {
5409 m_reporterRegistry.registerReporter( name, factory );
5410 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00005411 virtual void registerTest( const TestCase& testInfo ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005412 m_testCaseRegistry.registerTest( testInfo );
5413 }
5414 virtual void registerTranslator( const IExceptionTranslator* translator ) {
5415 m_exceptionTranslatorRegistry.registerTranslator( translator );
5416 }
5417
5418 private:
5419 TestRegistry m_testCaseRegistry;
5420 ReporterRegistry m_reporterRegistry;
5421 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5422 };
5423
5424 // Single, global, instance
5425 inline RegistryHub*& getTheRegistryHub() {
5426 static RegistryHub* theRegistryHub = NULL;
5427 if( !theRegistryHub )
5428 theRegistryHub = new RegistryHub();
5429 return theRegistryHub;
5430 }
5431 }
5432
5433 IRegistryHub& getRegistryHub() {
5434 return *getTheRegistryHub();
5435 }
5436 IMutableRegistryHub& getMutableRegistryHub() {
5437 return *getTheRegistryHub();
5438 }
5439 void cleanUp() {
5440 delete getTheRegistryHub();
5441 getTheRegistryHub() = NULL;
5442 cleanUpContext();
5443 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005444 std::string translateActiveException() {
5445 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
5446 }
Phil Nash3b80af72012-08-09 07:47:30 +01005447
5448} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04005449
Phil Nash3b80af72012-08-09 07:47:30 +01005450// #included from: catch_notimplemented_exception.hpp
5451#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
5452
5453#include <ostream>
5454
5455namespace Catch {
5456
5457 NotImplementedException::NotImplementedException( const SourceLineInfo& lineInfo )
5458 : m_lineInfo( lineInfo ) {
5459 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +00005460 oss << lineInfo << ": function ";
Phil Nash3b80af72012-08-09 07:47:30 +01005461 oss << "not implemented";
5462 m_what = oss.str();
5463 }
5464
5465 const char* NotImplementedException::what() const throw() {
5466 return m_what.c_str();
5467 }
5468
5469} // end namespace Catch
5470
5471// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005472#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005473
Phil Nash3b80af72012-08-09 07:47:30 +01005474namespace Catch {
5475
5476 class Context : public IMutableContext {
5477
5478 Context() : m_config( NULL ) {}
5479 Context( const Context& );
5480 void operator=( const Context& );
5481
5482 public: // IContext
5483 virtual IResultCapture& getResultCapture() {
5484 return *m_resultCapture;
5485 }
5486 virtual IRunner& getRunner() {
5487 return *m_runner;
5488 }
5489 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) {
5490 return getGeneratorsForCurrentTest()
5491 .getGeneratorInfo( fileInfo, totalSize )
5492 .getCurrentIndex();
5493 }
5494 virtual bool advanceGeneratorsForCurrentTest() {
5495 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5496 return generators && generators->moveNext();
5497 }
5498
5499 virtual const IConfig* getConfig() const {
5500 return m_config;
5501 }
5502
5503 public: // IMutableContext
5504 virtual void setResultCapture( IResultCapture* resultCapture ) {
5505 m_resultCapture = resultCapture;
5506 }
5507 virtual void setRunner( IRunner* runner ) {
5508 m_runner = runner;
5509 }
5510 virtual void setConfig( const IConfig* config ) {
5511 m_config = config;
5512 }
5513
5514 friend IMutableContext& getCurrentMutableContext();
5515
5516 private:
5517 IGeneratorsForTest* findGeneratorsForCurrentTest() {
5518 std::string testName = getResultCapture().getCurrentTestName();
5519
5520 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
5521 m_generatorsByTestName.find( testName );
5522 return it != m_generatorsByTestName.end()
5523 ? it->second
5524 : NULL;
5525 }
5526
5527 IGeneratorsForTest& getGeneratorsForCurrentTest() {
5528 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5529 if( !generators ) {
5530 std::string testName = getResultCapture().getCurrentTestName();
5531 generators = createGeneratorsForTest();
5532 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
5533 }
5534 return *generators;
5535 }
5536
5537 private:
5538 IRunner* m_runner;
5539 IResultCapture* m_resultCapture;
5540 const IConfig* m_config;
5541 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
5542 };
5543
5544 namespace {
5545 Context* currentContext = NULL;
5546 }
5547 IMutableContext& getCurrentMutableContext() {
5548 if( !currentContext )
5549 currentContext = new Context();
5550 return *currentContext;
5551 }
5552 IContext& getCurrentContext() {
5553 return getCurrentMutableContext();
5554 }
5555
Phil Nash67ec8702012-09-26 18:38:26 +01005556 Stream createStream( const std::string& streamName ) {
5557 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
5558 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
5559 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
Phil Nash3b80af72012-08-09 07:47:30 +01005560
5561 throw std::domain_error( "Unknown stream: " + streamName );
5562 }
5563
5564 void cleanUpContext() {
5565 delete currentContext;
5566 currentContext = NULL;
5567 }
5568}
Matt Wozniskif29c8982012-09-17 01:42:29 -04005569
Phil Nash3b80af72012-08-09 07:47:30 +01005570// #included from: catch_console_colour_impl.hpp
5571#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
5572
Phil Nash3df6c0d2013-03-11 18:38:29 +00005573#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01005574
5575#include <windows.h>
5576
Phil Nash3df6c0d2013-03-11 18:38:29 +00005577namespace {
5578 using namespace Catch;
Phil Nash355b95f2012-10-31 18:04:22 +00005579
Phil Nash3df6c0d2013-03-11 18:38:29 +00005580 WORD mapConsoleColour( IConsoleColourCodes::Colours colour ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01005581 enum Win32Colours {
5582 Grey = FOREGROUND_INTENSITY,
5583 BrightRed = FOREGROUND_RED | FOREGROUND_INTENSITY,
5584 BrightGreen = FOREGROUND_GREEN | FOREGROUND_INTENSITY,
5585 BrightWhite = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
5586 DarkGreen = FOREGROUND_GREEN,
5587 Cyan = FOREGROUND_BLUE | FOREGROUND_GREEN,
5588 Yellow = FOREGROUND_RED | FOREGROUND_GREEN
5589 };
Phil Nash3df6c0d2013-03-11 18:38:29 +00005590 switch( colour ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01005591 case IConsoleColourCodes::FileName: return Grey;
5592 case IConsoleColourCodes::ResultError: return BrightRed;
5593 case IConsoleColourCodes::ResultSuccess: return BrightGreen;
5594 case IConsoleColourCodes::Error: return BrightRed;
5595 case IConsoleColourCodes::Success: return DarkGreen;
5596 case IConsoleColourCodes::OriginalExpression: return Cyan;
5597 case IConsoleColourCodes::ReconstructedExpression: return Yellow;
5598 case IConsoleColourCodes::SecondaryText: return Grey;
5599 case IConsoleColourCodes::Headers: return 0;
Phil Nash3df6c0d2013-03-11 18:38:29 +00005600 default: return 0;
Phil Nash3b80af72012-08-09 07:47:30 +01005601 }
5602 }
5603
Phil Nash3df6c0d2013-03-11 18:38:29 +00005604 struct WindowsConsoleColourCodes : IConsoleColourCodes {
Phil Nash3b80af72012-08-09 07:47:30 +01005605
Phil Nash3df6c0d2013-03-11 18:38:29 +00005606 WindowsConsoleColourCodes()
Phil Nash3b80af72012-08-09 07:47:30 +01005607 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
5608 wOldColorAttrs( 0 )
5609 {
5610 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
5611 wOldColorAttrs = csbiInfo.wAttributes;
5612 }
5613
Phil Nash3df6c0d2013-03-11 18:38:29 +00005614 ~WindowsConsoleColourCodes() {
Phil Nash3b80af72012-08-09 07:47:30 +01005615 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
5616 }
5617
Phil Nash3df6c0d2013-03-11 18:38:29 +00005618 void set( Colours colour ) {
Phil Nash3b80af72012-08-09 07:47:30 +01005619 WORD consoleColour = mapConsoleColour( colour );
5620 if( consoleColour > 0 )
5621 SetConsoleTextAttribute( hStdout, consoleColour );
5622 }
5623
5624 HANDLE hStdout;
5625 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
5626 WORD wOldColorAttrs;
5627 };
5628
Phil Nash3df6c0d2013-03-11 18:38:29 +00005629 inline bool shouldUseColourForPlatform() {
5630 return true;
5631 }
5632
5633 typedef WindowsConsoleColourCodes PlatformConsoleColourCodes;
5634
5635} // end anon namespace
5636
5637#else // Not Windows - assumed to be POSIX compatible //////////////////////////
5638
5639#include <unistd.h>
5640
5641namespace {
5642 using namespace Catch;
5643
5644 // use POSIX/ ANSI console terminal codes
5645 // Implementation contributed by Adam Strzelecki (http://github.com/nanoant)
5646 // https://github.com/philsquared/Catch/pull/131
5647
Phil Nash5c7d3d72013-04-01 11:27:10 +01005648 const char* WhiteOrNormal = "[0m";
5649 const char* BrightRed = "[1;31m";
5650 const char* BrightGreen = "[1;32m";
5651// const char* BrightWhite = "[1;37m";
5652 const char* Green = "[0;32m";
5653 const char* Cyan = "[0;36m";
5654 const char* Yellow = "[0;33m";
5655 const char* LightGrey = "[0;37m";
5656// const char* DarkGrey = "[1;30m";
5657
Phil Nash3df6c0d2013-03-11 18:38:29 +00005658 struct AnsiConsoleColourCodes : IConsoleColourCodes {
5659
5660 ~AnsiConsoleColourCodes() {
5661 set( None );
5662 }
5663
Phil Nash5c7d3d72013-04-01 11:27:10 +01005664 const char* escapeCodeForColour( Colours colour ) {
Phil Nash3df6c0d2013-03-11 18:38:29 +00005665 switch( colour ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01005666 case FileName: return WhiteOrNormal;
5667 case ResultError: return BrightRed;
5668 case ResultSuccess: return BrightGreen;
5669 case Error: return BrightRed;
5670 case Success: return Green;
5671 case OriginalExpression: return Cyan;
5672 case ReconstructedExpression: return Yellow;
5673 case SecondaryText: return LightGrey;
5674 case Headers: return WhiteOrNormal;
5675 case None: return WhiteOrNormal;
5676 }
5677 }
5678
5679 void set( Colours colour ) {
5680 std::cout << '\033' << escapeCodeForColour( colour );
Phil Nash3df6c0d2013-03-11 18:38:29 +00005681 }
5682 };
5683
5684 inline bool shouldUseColourForPlatform() {
5685 return isatty( fileno(stdout) );
5686 }
5687
5688 typedef AnsiConsoleColourCodes PlatformConsoleColourCodes;
5689
5690} // namespace Catch
5691
5692#endif // not Windows
5693
5694namespace {
5695 struct NoConsoleColourCodes : IConsoleColourCodes {
5696 void set( Colours ) {}
5697 };
5698}
5699
5700namespace Catch {
5701
5702 TextColour::TextColour( Colours colour ) : m_impl( NULL ) {
5703 static bool s_shouldUseColour = shouldUseColourForPlatform() &&
5704 !isDebuggerActive();
5705 if( s_shouldUseColour )
5706 m_impl = new PlatformConsoleColourCodes();
5707 else
5708 m_impl = new NoConsoleColourCodes();
5709
Phil Nash3b80af72012-08-09 07:47:30 +01005710 if( colour )
Phil Nash3df6c0d2013-03-11 18:38:29 +00005711 set( colour );
Phil Nash3b80af72012-08-09 07:47:30 +01005712 }
5713
5714 TextColour::~TextColour() {
5715 delete m_impl;
5716 }
5717
5718 void TextColour::set( Colours colour ) {
5719 m_impl->set( colour );
5720 }
5721
Phil Nash355b95f2012-10-31 18:04:22 +00005722} // end namespace Catch
5723
Phil Nash3b80af72012-08-09 07:47:30 +01005724// #included from: catch_generators_impl.hpp
5725#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
5726
5727#include <vector>
5728#include <string>
5729#include <map>
5730
5731namespace Catch {
5732
5733 struct GeneratorInfo : IGeneratorInfo {
5734
5735 GeneratorInfo( std::size_t size )
5736 : m_size( size ),
5737 m_currentIndex( 0 )
5738 {}
5739
5740 bool moveNext() {
5741 if( ++m_currentIndex == m_size ) {
5742 m_currentIndex = 0;
5743 return false;
5744 }
5745 return true;
5746 }
5747
5748 std::size_t getCurrentIndex() const {
5749 return m_currentIndex;
5750 }
5751
5752 std::size_t m_size;
5753 std::size_t m_currentIndex;
5754 };
5755
5756 ///////////////////////////////////////////////////////////////////////////
5757
5758 class GeneratorsForTest : public IGeneratorsForTest {
5759
5760 public:
5761 ~GeneratorsForTest() {
5762 deleteAll( m_generatorsInOrder );
5763 }
5764
5765 IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) {
5766 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
5767 if( it == m_generatorsByName.end() ) {
5768 IGeneratorInfo* info = new GeneratorInfo( size );
5769 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
5770 m_generatorsInOrder.push_back( info );
5771 return *info;
5772 }
5773 return *it->second;
5774 }
5775
5776 bool moveNext() {
5777 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
5778 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
5779 for(; it != itEnd; ++it ) {
5780 if( (*it)->moveNext() )
5781 return true;
5782 }
5783 return false;
5784 }
5785
5786 private:
5787 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
5788 std::vector<IGeneratorInfo*> m_generatorsInOrder;
5789 };
5790
5791 IGeneratorsForTest* createGeneratorsForTest()
5792 {
5793 return new GeneratorsForTest();
5794 }
5795
5796} // end namespace Catch
5797
Phil Nash82acc2c2012-10-28 12:07:17 +00005798// #included from: catch_assertionresult.hpp
5799#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01005800
5801namespace Catch {
5802
Phil Nashd539da92012-11-13 09:44:52 +00005803 AssertionInfo::AssertionInfo( const std::string& _macroName,
5804 const SourceLineInfo& _lineInfo,
5805 const std::string& _capturedExpression,
5806 ResultDisposition::Flags _resultDisposition )
5807 : macroName( _macroName ),
5808 lineInfo( _lineInfo ),
5809 capturedExpression( _capturedExpression ),
5810 resultDisposition( _resultDisposition )
5811 {
5812 if( shouldNegate( resultDisposition ) )
5813 capturedExpression = "!" + _capturedExpression;
5814 }
5815
Phil Nash82acc2c2012-10-28 12:07:17 +00005816 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005817
Phil Nash82acc2c2012-10-28 12:07:17 +00005818 AssertionResult::AssertionResult( const AssertionInfo& info, const AssertionResultData& data )
5819 : m_info( info ),
5820 m_resultData( data )
5821 {}
Phil Nash3b80af72012-08-09 07:47:30 +01005822
Phil Nash82acc2c2012-10-28 12:07:17 +00005823 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01005824
Phil Nashd539da92012-11-13 09:44:52 +00005825 // Result was a success
5826 bool AssertionResult::succeeded() const {
5827 return Catch::isOk( m_resultData.resultType );
5828 }
5829
5830 // Result was a success, or failure is suppressed
5831 bool AssertionResult::isOk() const {
5832 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01005833 }
5834
Phil Nash82acc2c2012-10-28 12:07:17 +00005835 ResultWas::OfType AssertionResult::getResultType() const {
5836 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01005837 }
5838
Phil Nash82acc2c2012-10-28 12:07:17 +00005839 bool AssertionResult::hasExpression() const {
5840 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005841 }
5842
Phil Nash82acc2c2012-10-28 12:07:17 +00005843 bool AssertionResult::hasMessage() const {
5844 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01005845 }
5846
Phil Nash82acc2c2012-10-28 12:07:17 +00005847 std::string AssertionResult::getExpression() const {
5848 return m_info.capturedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005849 }
5850
Phil Nash82acc2c2012-10-28 12:07:17 +00005851 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01005852 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01005853 }
5854
Phil Nash82acc2c2012-10-28 12:07:17 +00005855 std::string AssertionResult::getExpandedExpression() const {
5856 return m_resultData.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01005857 }
5858
Phil Nash82acc2c2012-10-28 12:07:17 +00005859 std::string AssertionResult::getMessage() const {
5860 return m_resultData.message;
5861 }
5862 SourceLineInfo AssertionResult::getSourceInfo() const {
5863 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01005864 }
5865
Phil Nash82acc2c2012-10-28 12:07:17 +00005866 std::string AssertionResult::getTestMacroName() const {
5867 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01005868 }
5869
5870} // end namespace Catch
5871
Phil Nash82acc2c2012-10-28 12:07:17 +00005872// #included from: catch_expressionresult_builder.hpp
5873#define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
5874
5875#include <assert.h>
Phil Nash3b80af72012-08-09 07:47:30 +01005876
5877namespace Catch {
5878
Phil Nash82acc2c2012-10-28 12:07:17 +00005879 ExpressionResultBuilder::ExpressionResultBuilder( ResultWas::OfType resultType ) {
5880 m_data.resultType = resultType;
Phil Nash67305122012-10-09 11:48:55 +01005881 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005882 ExpressionResultBuilder::ExpressionResultBuilder( const ExpressionResultBuilder& other )
5883 : m_data( other.m_data ),
5884 m_exprComponents( other.m_exprComponents )
Phil Nash67305122012-10-09 11:48:55 +01005885 {
Phil Nash82acc2c2012-10-28 12:07:17 +00005886 m_stream << other.m_stream.str();
Phil Nash3b80af72012-08-09 07:47:30 +01005887 }
Phil Nash82acc2c2012-10-28 12:07:17 +00005888 ExpressionResultBuilder& ExpressionResultBuilder::operator=(const ExpressionResultBuilder& other ) {
5889 m_data = other.m_data;
5890 m_exprComponents = other.m_exprComponents;
5891 m_stream.str("");
5892 m_stream << other.m_stream.str();
5893 return *this;
5894 }
5895 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( ResultWas::OfType result ) {
5896 m_data.resultType = result;
5897 return *this;
5898 }
5899 ExpressionResultBuilder& ExpressionResultBuilder::setResultType( bool result ) {
5900 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
5901 return *this;
5902 }
Phil Nashaf1a3212012-11-10 18:46:39 +00005903 ExpressionResultBuilder& ExpressionResultBuilder::endExpression( ResultDisposition::Flags resultDisposition ) {
Phil Nashd539da92012-11-13 09:44:52 +00005904 m_exprComponents.shouldNegate = shouldNegate( resultDisposition );
Phil Nash82acc2c2012-10-28 12:07:17 +00005905 return *this;
5906 }
5907 ExpressionResultBuilder& ExpressionResultBuilder::setLhs( const std::string& lhs ) {
5908 m_exprComponents.lhs = lhs;
5909 return *this;
5910 }
5911 ExpressionResultBuilder& ExpressionResultBuilder::setRhs( const std::string& rhs ) {
5912 m_exprComponents.rhs = rhs;
5913 return *this;
5914 }
5915 ExpressionResultBuilder& ExpressionResultBuilder::setOp( const std::string& op ) {
5916 m_exprComponents.op = op;
5917 return *this;
5918 }
5919 AssertionResult ExpressionResultBuilder::buildResult( const AssertionInfo& info ) const
5920 {
5921 assert( m_data.resultType != ResultWas::Unknown );
Phil Nash3b80af72012-08-09 07:47:30 +01005922
Phil Nash82acc2c2012-10-28 12:07:17 +00005923 AssertionResultData data = m_data;
5924
5925 // Flip bool results if shouldNegate is set
5926 if( m_exprComponents.shouldNegate && data.resultType == ResultWas::Ok )
5927 data.resultType = ResultWas::ExpressionFailed;
5928 else if( m_exprComponents.shouldNegate && data.resultType == ResultWas::ExpressionFailed )
5929 data.resultType = ResultWas::Ok;
5930
5931 data.message = m_stream.str();
5932 data.reconstructedExpression = reconstructExpression( info );
5933 if( m_exprComponents.shouldNegate ) {
5934 if( m_exprComponents.op == "" )
5935 data.reconstructedExpression = "!" + data.reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +01005936 else
Phil Nash82acc2c2012-10-28 12:07:17 +00005937 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
5938 }
5939 return AssertionResult( info, data );
5940 }
5941 std::string ExpressionResultBuilder::reconstructExpression( const AssertionInfo& info ) const {
5942 if( m_exprComponents.op == "" )
5943 return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
5944 else if( m_exprComponents.op == "matches" )
5945 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
5946 else if( m_exprComponents.op != "!" ) {
Phil Nashdd26e882013-03-25 09:25:31 +00005947 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
5948 m_exprComponents.lhs.find("\n") == std::string::npos &&
5949 m_exprComponents.rhs.find("\n") == std::string::npos )
Phil Nash82acc2c2012-10-28 12:07:17 +00005950 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
Phil Nash82acc2c2012-10-28 12:07:17 +00005951 else
Phil Nash767f1582013-03-04 12:19:15 +01005952 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
Phil Nash67305122012-10-09 11:48:55 +01005953 }
5954 else
Phil Nash82acc2c2012-10-28 12:07:17 +00005955 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 +01005956 }
5957
5958} // end namespace Catch
5959
Phil Nash5bc030d2012-08-16 18:48:50 +01005960// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005961#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01005962
5963namespace Catch {
5964
Phil Nasha1fbfea2012-12-01 23:57:18 +00005965 TestCase makeTestCase( ITestCase* _testCase,
5966 const std::string& _className,
5967 const std::string& _name,
5968 const std::string& _descOrTags,
5969 const SourceLineInfo& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +01005970 {
Phil Nasha1fbfea2012-12-01 23:57:18 +00005971 std::string desc = _descOrTags;
5972 bool isHidden( startsWith( _name, "./" ) );
5973 std::set<std::string> tags;
5974 TagExtracter( tags ).parse( desc );
5975 if( tags.find( "hide" ) != tags.end() )
5976 isHidden = true;
5977
5978 TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );
5979 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +01005980 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005981
Phil Nasha1fbfea2012-12-01 23:57:18 +00005982 TestCaseInfo::TestCaseInfo( const std::string& _name,
5983 const std::string& _className,
5984 const std::string& _description,
5985 const std::set<std::string>& _tags,
5986 bool _isHidden,
5987 const SourceLineInfo& _lineInfo )
5988 : name( _name ),
5989 className( _className ),
5990 description( _description ),
5991 tags( _tags ),
Phil Nashff03cdf2012-12-06 08:44:51 +00005992 lineInfo( _lineInfo ),
5993 isHidden( _isHidden )
Phil Nash38f7eef2013-03-29 13:44:33 +00005994 {
5995 std::ostringstream oss;
5996 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it )
5997 oss << "[" << *it << "]";
5998 tagsAsString = oss.str();
5999 }
Phil Nash5bc030d2012-08-16 18:48:50 +01006000
Phil Nashd2ec8492012-08-23 19:48:57 +01006001 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006002 : name( other.name ),
6003 className( other.className ),
6004 description( other.description ),
6005 tags( other.tags ),
Phil Nash38f7eef2013-03-29 13:44:33 +00006006 tagsAsString( other.tagsAsString ),
Phil Nashff03cdf2012-12-06 08:44:51 +00006007 lineInfo( other.lineInfo ),
6008 isHidden( other.isHidden )
Phil Nashd2ec8492012-08-23 19:48:57 +01006009 {}
6010
Phil Nasha1fbfea2012-12-01 23:57:18 +00006011 TestCase::TestCase( ITestCase* testCase, const TestCaseInfo& info ) : TestCaseInfo( info ), test( testCase ) {}
6012
6013 TestCase::TestCase( const TestCase& other )
6014 : TestCaseInfo( other ),
6015 test( other.test )
6016 {}
6017
6018 TestCase TestCase::withName( const std::string& _newName ) const {
6019 TestCase other( *this );
6020 other.name = _newName;
6021 return other;
Phil Nash5bc030d2012-08-16 18:48:50 +01006022 }
6023
Phil Nasha1fbfea2012-12-01 23:57:18 +00006024 void TestCase::invoke() const {
6025 test->invoke();
Phil Nash5bc030d2012-08-16 18:48:50 +01006026 }
6027
Phil Nasha1fbfea2012-12-01 23:57:18 +00006028 bool TestCase::isHidden() const {
6029 return TestCaseInfo::isHidden;
Phil Nashfc1baac2012-09-15 17:53:27 +01006030 }
6031
Phil Nasha1fbfea2012-12-01 23:57:18 +00006032 bool TestCase::hasTag( const std::string& tag ) const {
Phil Nashdd26e882013-03-25 09:25:31 +00006033 return tags.find( toLower( tag ) ) != tags.end();
Phil Nashfc1baac2012-09-15 17:53:27 +01006034 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006035 bool TestCase::matchesTags( const std::string& tagPattern ) const {
Phil Nash799ecf92012-09-24 08:30:13 +01006036 TagExpression exp;
6037 TagExpressionParser( exp ).parse( tagPattern );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006038 return exp.matches( tags );
Phil Nash799ecf92012-09-24 08:30:13 +01006039 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006040 const std::set<std::string>& TestCase::getTags() const {
6041 return tags;
Phil Nash5bc030d2012-08-16 18:48:50 +01006042 }
6043
Phil Nasha1fbfea2012-12-01 23:57:18 +00006044 void TestCase::swap( TestCase& other ) {
6045 test.swap( other.test );
6046 className.swap( other.className );
6047 name.swap( other.name );
6048 description.swap( other.description );
6049 std::swap( lineInfo, other.lineInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01006050 }
6051
Phil Nasha1fbfea2012-12-01 23:57:18 +00006052 bool TestCase::operator == ( const TestCase& other ) const {
6053 return test.get() == other.test.get() &&
6054 name == other.name &&
6055 className == other.className;
Phil Nash5bc030d2012-08-16 18:48:50 +01006056 }
6057
Phil Nasha1fbfea2012-12-01 23:57:18 +00006058 bool TestCase::operator < ( const TestCase& other ) const {
6059 return name < other.name;
Phil Nash5bc030d2012-08-16 18:48:50 +01006060 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006061 TestCase& TestCase::operator = ( const TestCase& other ) {
6062 TestCase temp( other );
Phil Nashd2ec8492012-08-23 19:48:57 +01006063 swap( temp );
6064 return *this;
6065 }
Phil Nash799ecf92012-09-24 08:30:13 +01006066
Phil Nasha1fbfea2012-12-01 23:57:18 +00006067 const TestCaseInfo& TestCase::getTestCaseInfo() const
6068 {
6069 return *this;
6070 }
6071
Phil Nash799ecf92012-09-24 08:30:13 +01006072} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01006073
Phil Nash7673a302012-11-15 22:15:41 +00006074// #included from: catch_version.hpp
6075#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
6076
6077namespace Catch {
6078
6079 // These numbers are maintained by a script
Phil Nash5c7d3d72013-04-01 11:27:10 +01006080 Version libraryVersion( 0, 9, 30, "integration" );
Phil Nash7673a302012-11-15 22:15:41 +00006081}
6082
Phil Nash2e7d9662013-01-16 09:44:43 +00006083// #included from: catch_line_wrap.hpp
6084#define TWOBLUECUBES_CATCH_LINE_WRAP_HPP_INCLUDED
6085
6086namespace Catch {
6087
Phil Nash38f7eef2013-03-29 13:44:33 +00006088 LineWrapper::LineWrapper()
6089 : right( CATCH_CONFIG_CONSOLE_WIDTH-1 ),
6090 nextTab( 0 ),
6091 tab( 0 ),
Phil Nash5c7d3d72013-04-01 11:27:10 +01006092 wrappableChars( " [({.,/|\\" ),
Phil Nash38f7eef2013-03-29 13:44:33 +00006093 recursionCount( 0 )
6094 {}
Phil Nash2e7d9662013-01-16 09:44:43 +00006095
Phil Nash38f7eef2013-03-29 13:44:33 +00006096 LineWrapper& LineWrapper::setIndent( std::size_t _indent ) {
6097 indent = std::string( _indent, ' ' );
6098 return *this;
6099 }
6100 LineWrapper& LineWrapper::setRight( std::size_t _right ) {
6101 right = _right;
6102 return *this;
6103 }
6104 LineWrapper& LineWrapper::wrap( std::string const& _str ) {
6105 nextTab = tab = 0;
6106 wrapInternal( _str );
6107 return *this;
6108 }
6109 bool LineWrapper::isWrapPoint( char c ) {
6110 return wrappableChars.find( c ) != std::string::npos;
6111 }
6112 void LineWrapper::wrapInternal( std::string const& _str ) {
6113 assert( ++recursionCount < 100 );
6114
6115 std::size_t width = right - indent.size();
6116 std::size_t wrapPoint = width-tab;
6117 for( std::size_t pos = 0; pos < _str.size(); ++pos ) {
6118 if( _str[pos] == '\n' )
6119 {
6120 addLine( _str.substr( 0, pos ) );
6121 nextTab = tab = 0;
6122 return wrapInternal( _str.substr( pos+1 ) );
Phil Nash2e7d9662013-01-16 09:44:43 +00006123 }
Phil Nash38f7eef2013-03-29 13:44:33 +00006124 if( pos == width-tab ) {
6125 if( _str[wrapPoint] == ' ' ) {
6126 addLine( _str.substr( 0, wrapPoint ) );
6127 while( _str[++wrapPoint] == ' ' );
6128 }
6129 else if( isWrapPoint( _str[wrapPoint] ) ) {
6130 addLine( _str.substr( 0, wrapPoint ) );
6131 }
6132 else {
6133 addLine( _str.substr( 0, --wrapPoint ) + '-' );
6134 }
6135 return wrapInternal( _str.substr( wrapPoint ) );
6136 }
6137 if( _str[pos] == '\t' ) {
6138 nextTab = pos;
6139 std::string withoutTab = _str.substr( 0, nextTab ) + _str.substr( nextTab+1 );
6140 return wrapInternal( withoutTab );
6141 }
6142 else if( pos > 0 && isWrapPoint( _str[pos] ) ) {
6143 wrapPoint = pos;
6144 }
Phil Nash2e7d9662013-01-16 09:44:43 +00006145 }
Phil Nash38f7eef2013-03-29 13:44:33 +00006146 addLine( _str );
Phil Nash2e7d9662013-01-16 09:44:43 +00006147 }
6148
Phil Nash38f7eef2013-03-29 13:44:33 +00006149 std::ostream& operator << ( std::ostream& _stream, LineWrapper const& _lineWrapper ) {
6150 for( LineWrapper::const_iterator it = _lineWrapper.begin(), itEnd = _lineWrapper.end();
6151 it != itEnd; ++it ) {
6152 if( it != _lineWrapper.begin() )
6153 _stream << "\n";
6154 _stream << *it;
Phil Nash2e7d9662013-01-16 09:44:43 +00006155 }
Phil Nash38f7eef2013-03-29 13:44:33 +00006156 return _stream;
Phil Nash2e7d9662013-01-16 09:44:43 +00006157 }
Phil Nash38f7eef2013-03-29 13:44:33 +00006158 std::string LineWrapper::toString() const {
Phil Nash2e7d9662013-01-16 09:44:43 +00006159 std::ostringstream oss;
Phil Nash38f7eef2013-03-29 13:44:33 +00006160 oss << *this;
Phil Nash2e7d9662013-01-16 09:44:43 +00006161 return oss.str();
6162 }
6163
Phil Nash38f7eef2013-03-29 13:44:33 +00006164 void LineWrapper::addLine( const std::string& _line ) {
6165 if( tab > 0 )
6166 lines.push_back( indent + std::string( tab, ' ' ) + _line );
6167 else
6168 lines.push_back( indent + _line );
6169 if( nextTab > 0 )
6170 tab = nextTab;
6171 }
6172
Phil Nash2e7d9662013-01-16 09:44:43 +00006173} // end namespace Catch
6174
Phil Nasha2773812013-02-02 20:37:58 +00006175// #included from: catch_message.hpp
6176#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
6177
6178namespace Catch {
6179
6180 MessageInfo::MessageInfo( std::string const& _macroName,
6181 SourceLineInfo const& _lineInfo,
6182 ResultWas::OfType _type )
6183 : macroName( _macroName ),
6184 lineInfo( _lineInfo ),
6185 type( _type ),
6186 sequence( ++globalCount )
6187 {}
6188
6189 // This may need protecting if threading support is added
6190 unsigned int MessageInfo::globalCount = 0;
6191
6192 ////////////////////////////////////////////////////////////////////////////
6193
6194 MessageBuilder::MessageBuilder( std::string const& _macroName,
6195 SourceLineInfo const& _lineInfo,
6196 ResultWas::OfType _type )
6197 : MessageInfo( _macroName, _lineInfo, _type )
6198 {}
6199
6200 MessageInfo MessageBuilder::build() const {
6201 MessageInfo message = *this;
6202 message.message = stream.str();
6203 return message;
6204 }
6205
6206 ////////////////////////////////////////////////////////////////////////////
6207
6208 ScopedMessageBuilder::ScopedMessageBuilder
6209 ( std::string const& _macroName,
6210 SourceLineInfo const& _lineInfo,
6211 ResultWas::OfType _type )
6212 : MessageBuilder( _macroName, _lineInfo, _type )
6213 {}
6214
6215 ScopedMessageBuilder::~ScopedMessageBuilder() {
6216 getResultCapture().popScopedMessage( *this );
6217 }
6218
6219} // end namespace Catch
6220
Phil Nash56d5c422012-08-23 20:08:50 +01006221// #included from: ../reporters/catch_reporter_basic.hpp
6222#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
6223
6224// #included from: ../internal/catch_reporter_registrars.hpp
6225#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
6226
6227namespace Catch {
6228
6229 template<typename T>
Phil Nasha1fbfea2012-12-01 23:57:18 +00006230 class LegacyReporterRegistrar {
6231
6232 class ReporterFactory : public IReporterFactory {
6233
6234 virtual IStreamingReporter* create( const ReporterConfig& config ) const {
6235 return new LegacyReporterAdapter( new T( config ), config );
6236 }
6237
6238 virtual std::string getDescription() const {
6239 return T::getDescription();
6240 }
6241 };
6242
6243 public:
6244
6245 LegacyReporterRegistrar( const std::string& name ) {
6246 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
6247 }
6248 };
6249
6250 template<typename T>
Phil Nash56d5c422012-08-23 20:08:50 +01006251 class ReporterRegistrar {
6252
6253 class ReporterFactory : public IReporterFactory {
6254
Phil Nasha1fbfea2012-12-01 23:57:18 +00006255 // *** Please Note ***:
6256 // - If you end up here looking at a compiler error because it's trying to register
6257 // your custom reporter class be aware that the native reporter interface has changed
6258 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
6259 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
6260 // However please consider updating to the new interface as the old one is now
6261 // deprecated and will probably be removed quite soon!
6262 // Please contact me via github if you have any questions at all about this.
6263 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
6264 // no idea who is actually using custom reporters at all (possibly no-one!).
6265 // The new interface is designed to minimise exposure to interface changes in the future.
6266 virtual IStreamingReporter* create( const ReporterConfig& config ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01006267 return new T( config );
6268 }
6269
6270 virtual std::string getDescription() const {
6271 return T::getDescription();
6272 }
6273 };
6274
6275 public:
6276
6277 ReporterRegistrar( const std::string& name ) {
6278 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
6279 }
6280 };
6281}
6282
Phil Nasha1fbfea2012-12-01 23:57:18 +00006283#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
6284 Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
Phil Nash56d5c422012-08-23 20:08:50 +01006285#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
6286 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
6287
6288namespace Catch {
6289
Phil Nash56d5c422012-08-23 20:08:50 +01006290 class BasicReporter : public SharedImpl<IReporter> {
6291
6292 struct SpanInfo {
6293
6294 SpanInfo()
6295 : emitted( false )
6296 {}
6297
6298 SpanInfo( const std::string& spanName )
6299 : name( spanName ),
6300 emitted( false )
6301 {}
6302
6303 SpanInfo( const SpanInfo& other )
6304 : name( other.name ),
6305 emitted( other.emitted )
6306 {}
6307
6308 std::string name;
6309 bool emitted;
6310 };
6311
6312 public:
6313 BasicReporter( const ReporterConfig& config )
6314 : m_config( config ),
6315 m_firstSectionInTestCase( true ),
6316 m_aborted( false )
6317 {}
6318
6319 virtual ~BasicReporter();
6320
6321 static std::string getDescription() {
6322 return "Reports test results as lines of text";
6323 }
6324
6325 private:
6326
6327 void ReportCounts( const std::string& label, const Counts& counts, const std::string& allPrefix = "All " ) {
6328 if( counts.passed )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006329 m_config.stream() << counts.failed << " of " << counts.total() << " " << label << "s failed";
Phil Nash56d5c422012-08-23 20:08:50 +01006330 else
Phil Nasha1fbfea2012-12-01 23:57:18 +00006331 m_config.stream() << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
Phil Nash56d5c422012-08-23 20:08:50 +01006332 }
6333
6334 void ReportCounts( const Totals& totals, const std::string& allPrefix = "All " ) {
6335 if( totals.assertions.total() == 0 ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006336 m_config.stream() << "No tests ran";
Phil Nash56d5c422012-08-23 20:08:50 +01006337 }
6338 else if( totals.assertions.failed ) {
6339 TextColour colour( TextColour::ResultError );
6340 ReportCounts( "test case", totals.testCases, allPrefix );
6341 if( totals.testCases.failed > 0 ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006342 m_config.stream() << " (";
Phil Nash56d5c422012-08-23 20:08:50 +01006343 ReportCounts( "assertion", totals.assertions, allPrefix );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006344 m_config.stream() << ")";
Phil Nash56d5c422012-08-23 20:08:50 +01006345 }
6346 }
6347 else {
6348 TextColour colour( TextColour::ResultSuccess );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006349 m_config.stream() << allPrefix << "tests passed ("
Phil Nash56d5c422012-08-23 20:08:50 +01006350 << pluralise( totals.assertions.passed, "assertion" ) << " in "
6351 << pluralise( totals.testCases.passed, "test case" ) << ")";
6352 }
6353 }
6354
6355 private: // IReporter
6356
6357 virtual bool shouldRedirectStdout() const {
6358 return false;
6359 }
6360
6361 virtual void StartTesting() {
6362 m_testingSpan = SpanInfo();
6363 }
6364
6365 virtual void Aborted() {
6366 m_aborted = true;
6367 }
6368
6369 virtual void EndTesting( const Totals& totals ) {
6370 // Output the overall test results even if "Started Testing" was not emitted
6371 if( m_aborted ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006372 m_config.stream() << "\n[Testing aborted. ";
Phil Nash56d5c422012-08-23 20:08:50 +01006373 ReportCounts( totals, "The first " );
6374 }
6375 else {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006376 m_config.stream() << "\n[Testing completed. ";
Phil Nash56d5c422012-08-23 20:08:50 +01006377 ReportCounts( totals );
6378 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006379 m_config.stream() << "]\n" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006380 }
6381
6382 virtual void StartGroup( const std::string& groupName ) {
6383 m_groupSpan = groupName;
6384 }
6385
6386 virtual void EndGroup( const std::string& groupName, const Totals& totals ) {
6387 if( m_groupSpan.emitted && !groupName.empty() ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006388 m_config.stream() << "[End of group: '" << groupName << "'. ";
Phil Nash56d5c422012-08-23 20:08:50 +01006389 ReportCounts( totals );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006390 m_config.stream() << "]\n" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006391 m_groupSpan = SpanInfo();
6392 }
6393 }
6394
6395 virtual void StartTestCase( const TestCaseInfo& testInfo ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006396 m_testSpan = testInfo.name;
Phil Nash56d5c422012-08-23 20:08:50 +01006397 }
6398
6399 virtual void StartSection( const std::string& sectionName, const std::string& ) {
6400 m_sectionSpans.push_back( SpanInfo( sectionName ) );
6401 }
6402
Phil Nasha70fbe32012-08-31 08:10:36 +01006403 virtual void NoAssertionsInSection( const std::string& sectionName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01006404 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01006405 TextColour colour( TextColour::ResultError );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006406 m_config.stream() << "\nNo assertions in section, '" << sectionName << "'\n" << std::endl;
Phil Nasha70fbe32012-08-31 08:10:36 +01006407 }
6408 virtual void NoAssertionsInTestCase( const std::string& testName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01006409 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01006410 TextColour colour( TextColour::ResultError );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006411 m_config.stream() << "\nNo assertions in test case, '" << testName << "'\n" << std::endl;
Phil Nasha70fbe32012-08-31 08:10:36 +01006412 }
6413
Phil Nash56d5c422012-08-23 20:08:50 +01006414 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01006415
Phil Nash56d5c422012-08-23 20:08:50 +01006416 SpanInfo& sectionSpan = m_sectionSpans.back();
6417 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006418 m_config.stream() << "[End of section: '" << sectionName << "' ";
Phil Nash56d5c422012-08-23 20:08:50 +01006419
6420 if( assertions.failed ) {
6421 TextColour colour( TextColour::ResultError );
6422 ReportCounts( "assertion", assertions);
6423 }
6424 else {
6425 TextColour colour( TextColour::ResultSuccess );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006426 m_config.stream() << ( assertions.passed > 1 ? "All " : "" )
Phil Nash56d5c422012-08-23 20:08:50 +01006427 << pluralise( assertions.passed, "assertion" ) << " passed" ;
6428 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006429 m_config.stream() << "]\n" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006430 }
6431 m_sectionSpans.pop_back();
6432 }
6433
Phil Nash82acc2c2012-10-28 12:07:17 +00006434 virtual void Result( const AssertionResult& assertionResult ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006435 if( !m_config.includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01006436 return;
6437
Phil Nashe2d215e2012-09-07 17:52:35 +01006438 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01006439
Phil Nash82acc2c2012-10-28 12:07:17 +00006440 if( !assertionResult.getSourceInfo().empty() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006441 TextColour colour( TextColour::FileName );
Phil Nash2e7d9662013-01-16 09:44:43 +00006442 m_config.stream() << assertionResult.getSourceInfo() << ": ";
Phil Nash56d5c422012-08-23 20:08:50 +01006443 }
6444
Phil Nash82acc2c2012-10-28 12:07:17 +00006445 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006446 TextColour colour( TextColour::OriginalExpression );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006447 m_config.stream() << assertionResult.getExpression();
Phil Nashd539da92012-11-13 09:44:52 +00006448 if( assertionResult.succeeded() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006449 TextColour successColour( TextColour::Success );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006450 m_config.stream() << " succeeded";
Phil Nash56d5c422012-08-23 20:08:50 +01006451 }
6452 else {
6453 TextColour errorColour( TextColour::Error );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006454 m_config.stream() << " failed";
Phil Nashd539da92012-11-13 09:44:52 +00006455 if( assertionResult.isOk() ) {
6456 TextColour okAnywayColour( TextColour::Success );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006457 m_config.stream() << " - but was ok";
Phil Nashd539da92012-11-13 09:44:52 +00006458 }
Phil Nash56d5c422012-08-23 20:08:50 +01006459 }
6460 }
Phil Nash82acc2c2012-10-28 12:07:17 +00006461 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006462 case ResultWas::ThrewException:
Phil Nash355b95f2012-10-31 18:04:22 +00006463 {
6464 TextColour colour( TextColour::Error );
6465 if( assertionResult.hasExpression() )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006466 m_config.stream() << " with unexpected";
Phil Nash355b95f2012-10-31 18:04:22 +00006467 else
Phil Nasha1fbfea2012-12-01 23:57:18 +00006468 m_config.stream() << "Unexpected";
6469 m_config.stream() << " exception with message: '" << assertionResult.getMessage() << "'";
Phil Nash355b95f2012-10-31 18:04:22 +00006470 }
Phil Nash56d5c422012-08-23 20:08:50 +01006471 break;
6472 case ResultWas::DidntThrowException:
Phil Nash355b95f2012-10-31 18:04:22 +00006473 {
6474 TextColour colour( TextColour::Error );
6475 if( assertionResult.hasExpression() )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006476 m_config.stream() << " because no exception was thrown where one was expected";
Phil Nash355b95f2012-10-31 18:04:22 +00006477 else
Phil Nasha1fbfea2012-12-01 23:57:18 +00006478 m_config.stream() << "No exception thrown where one was expected";
Phil Nash355b95f2012-10-31 18:04:22 +00006479 }
Phil Nash56d5c422012-08-23 20:08:50 +01006480 break;
6481 case ResultWas::Info:
Phil Nash355b95f2012-10-31 18:04:22 +00006482 {
6483 TextColour colour( TextColour::ReconstructedExpression );
6484 streamVariableLengthText( "info", assertionResult.getMessage() );
6485 }
Phil Nash56d5c422012-08-23 20:08:50 +01006486 break;
6487 case ResultWas::Warning:
Phil Nash355b95f2012-10-31 18:04:22 +00006488 {
6489 TextColour colour( TextColour::ReconstructedExpression );
6490 streamVariableLengthText( "warning", assertionResult.getMessage() );
6491 }
Phil Nash56d5c422012-08-23 20:08:50 +01006492 break;
6493 case ResultWas::ExplicitFailure:
Phil Nash355b95f2012-10-31 18:04:22 +00006494 {
6495 TextColour colour( TextColour::Error );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006496 m_config.stream() << "failed with message: '" << assertionResult.getMessage() << "'";
Phil Nash355b95f2012-10-31 18:04:22 +00006497 }
Phil Nash56d5c422012-08-23 20:08:50 +01006498 break;
6499 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
6500 case ResultWas::Ok:
6501 case ResultWas::FailureBit:
6502 case ResultWas::ExpressionFailed:
6503 case ResultWas::Exception:
Phil Nash82acc2c2012-10-28 12:07:17 +00006504 if( !assertionResult.hasExpression() ) {
Phil Nashd539da92012-11-13 09:44:52 +00006505 if( assertionResult.succeeded() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006506 TextColour colour( TextColour::Success );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006507 m_config.stream() << " succeeded";
Phil Nash56d5c422012-08-23 20:08:50 +01006508 }
6509 else {
6510 TextColour colour( TextColour::Error );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006511 m_config.stream() << " failed";
Phil Nashd539da92012-11-13 09:44:52 +00006512 if( assertionResult.isOk() ) {
6513 TextColour okAnywayColour( TextColour::Success );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006514 m_config.stream() << " - but was ok";
Phil Nashd539da92012-11-13 09:44:52 +00006515 }
Phil Nash56d5c422012-08-23 20:08:50 +01006516 }
6517 }
Phil Nash28463672012-11-21 18:06:13 +00006518 if( assertionResult.hasMessage() ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006519 m_config.stream() << "\n";
Phil Nash28463672012-11-21 18:06:13 +00006520 TextColour colour( TextColour::ReconstructedExpression );
6521 streamVariableLengthText( "with message", assertionResult.getMessage() );
6522 }
Phil Nash56d5c422012-08-23 20:08:50 +01006523 break;
6524 }
6525
Phil Nash82acc2c2012-10-28 12:07:17 +00006526 if( assertionResult.hasExpandedExpression() ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006527 m_config.stream() << " for: ";
Phil Nash5efa4bc2012-10-29 20:49:22 +00006528 if( assertionResult.getExpandedExpression().size() > 40 ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006529 m_config.stream() << "\n";
Phil Nash5efa4bc2012-10-29 20:49:22 +00006530 if( assertionResult.getExpandedExpression().size() < 70 )
Phil Nasha1fbfea2012-12-01 23:57:18 +00006531 m_config.stream() << "\t";
Phil Nash5efa4bc2012-10-29 20:49:22 +00006532 }
Phil Nash56d5c422012-08-23 20:08:50 +01006533 TextColour colour( TextColour::ReconstructedExpression );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006534 m_config.stream() << assertionResult.getExpandedExpression();
Phil Nash56d5c422012-08-23 20:08:50 +01006535 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006536 m_config.stream() << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006537 }
6538
6539 virtual void EndTestCase( const TestCaseInfo& testInfo,
6540 const Totals& totals,
6541 const std::string& stdOut,
6542 const std::string& stdErr ) {
6543 if( !stdOut.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01006544 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01006545 streamVariableLengthText( "stdout", stdOut );
6546 }
6547
6548 if( !stdErr.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01006549 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01006550 streamVariableLengthText( "stderr", stdErr );
6551 }
6552
6553 if( m_testSpan.emitted ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006554 m_config.stream() << "[Finished: '" << testInfo.name << "' ";
Phil Nash56d5c422012-08-23 20:08:50 +01006555 ReportCounts( totals );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006556 m_config.stream() << "]" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006557 }
6558 }
6559
6560 private: // helpers
6561
Phil Nashe2d215e2012-09-07 17:52:35 +01006562 void startSpansLazily() {
Phil Nash56d5c422012-08-23 20:08:50 +01006563 if( !m_testingSpan.emitted ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006564 if( m_config.name().empty() )
6565 m_config.stream() << "[Started testing]" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006566 else
Phil Nasha1fbfea2012-12-01 23:57:18 +00006567 m_config.stream() << "[Started testing: " << m_config.name() << "]" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006568 m_testingSpan.emitted = true;
6569 }
6570
6571 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006572 m_config.stream() << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006573 m_groupSpan.emitted = true;
6574 }
6575
6576 if( !m_testSpan.emitted ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006577 m_config.stream() << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006578 m_testSpan.emitted = true;
6579 }
6580
6581 if( !m_sectionSpans.empty() ) {
6582 SpanInfo& sectionSpan = m_sectionSpans.back();
6583 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
6584 if( m_firstSectionInTestCase ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006585 m_config.stream() << "\n";
Phil Nash56d5c422012-08-23 20:08:50 +01006586 m_firstSectionInTestCase = false;
6587 }
6588 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
6589 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
6590 for(; it != itEnd; ++it ) {
6591 SpanInfo& prevSpan = *it;
6592 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006593 m_config.stream() << "[Started section: '" << prevSpan.name << "']" << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01006594 prevSpan.emitted = true;
6595 }
6596 }
6597 }
6598 }
6599 }
6600
6601 void streamVariableLengthText( const std::string& prefix, const std::string& text ) {
6602 std::string trimmed = trim( text );
6603 if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006604 m_config.stream() << "[" << prefix << ": " << trimmed << "]";
Phil Nash56d5c422012-08-23 20:08:50 +01006605 }
6606 else {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006607 m_config.stream() << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
Phil Nash56d5c422012-08-23 20:08:50 +01006608 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
6609 }
6610 }
6611
6612 private:
6613 ReporterConfig m_config;
6614 bool m_firstSectionInTestCase;
6615
6616 SpanInfo m_testingSpan;
6617 SpanInfo m_groupSpan;
6618 SpanInfo m_testSpan;
6619 std::vector<SpanInfo> m_sectionSpans;
6620 bool m_aborted;
6621 };
6622
6623} // end namespace Catch
6624
6625// #included from: ../reporters/catch_reporter_xml.hpp
6626#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
6627
6628// #included from: ../internal/catch_xmlwriter.hpp
6629#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
6630
6631#include <sstream>
Phil Nash9e7e63c2012-09-29 20:54:03 +01006632#include <iostream>
Phil Nash56d5c422012-08-23 20:08:50 +01006633#include <string>
6634#include <vector>
6635
6636namespace Catch {
6637
6638 class XmlWriter {
6639 public:
6640
6641 class ScopedElement {
6642 public:
6643 ScopedElement( XmlWriter* writer )
6644 : m_writer( writer )
6645 {}
6646
6647 ScopedElement( const ScopedElement& other )
6648 : m_writer( other.m_writer ){
6649 other.m_writer = NULL;
6650 }
6651
6652 ~ScopedElement() {
6653 if( m_writer )
6654 m_writer->endElement();
6655 }
6656
Phil Nasha1fbfea2012-12-01 23:57:18 +00006657 ScopedElement& writeText( const std::string& text, bool indent = true ) {
6658 m_writer->writeText( text, indent );
Phil Nash56d5c422012-08-23 20:08:50 +01006659 return *this;
6660 }
6661
6662 template<typename T>
6663 ScopedElement& writeAttribute( const std::string& name, const T& attribute ) {
6664 m_writer->writeAttribute( name, attribute );
6665 return *this;
6666 }
6667
6668 private:
6669 mutable XmlWriter* m_writer;
6670 };
6671
6672 XmlWriter()
6673 : m_tagIsOpen( false ),
6674 m_needsNewline( false ),
6675 m_os( &std::cout )
6676 {}
6677
6678 XmlWriter( std::ostream& os )
6679 : m_tagIsOpen( false ),
6680 m_needsNewline( false ),
6681 m_os( &os )
6682 {}
6683
6684 ~XmlWriter() {
6685 while( !m_tags.empty() )
6686 endElement();
6687 }
6688
6689 XmlWriter& operator = ( const XmlWriter& other ) {
6690 XmlWriter temp( other );
6691 swap( temp );
6692 return *this;
6693 }
6694
6695 void swap( XmlWriter& other ) {
6696 std::swap( m_tagIsOpen, other.m_tagIsOpen );
6697 std::swap( m_needsNewline, other.m_needsNewline );
6698 std::swap( m_tags, other.m_tags );
6699 std::swap( m_indent, other.m_indent );
6700 std::swap( m_os, other.m_os );
6701 }
6702
6703 XmlWriter& startElement( const std::string& name ) {
6704 ensureTagClosed();
6705 newlineIfNecessary();
6706 stream() << m_indent << "<" << name;
6707 m_tags.push_back( name );
6708 m_indent += " ";
6709 m_tagIsOpen = true;
6710 return *this;
6711 }
6712
6713 ScopedElement scopedElement( const std::string& name ) {
6714 ScopedElement scoped( this );
6715 startElement( name );
6716 return scoped;
6717 }
6718
6719 XmlWriter& endElement() {
6720 newlineIfNecessary();
6721 m_indent = m_indent.substr( 0, m_indent.size()-2 );
6722 if( m_tagIsOpen ) {
6723 stream() << "/>\n";
6724 m_tagIsOpen = false;
6725 }
6726 else {
6727 stream() << m_indent << "</" << m_tags.back() << ">\n";
6728 }
6729 m_tags.pop_back();
6730 return *this;
6731 }
6732
6733 XmlWriter& writeAttribute( const std::string& name, const std::string& attribute ) {
6734 if( !name.empty() && !attribute.empty() ) {
6735 stream() << " " << name << "=\"";
6736 writeEncodedText( attribute );
6737 stream() << "\"";
6738 }
6739 return *this;
6740 }
6741
6742 XmlWriter& writeAttribute( const std::string& name, bool attribute ) {
6743 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
6744 return *this;
6745 }
6746
6747 template<typename T>
6748 XmlWriter& writeAttribute( const std::string& name, const T& attribute ) {
6749 if( !name.empty() )
6750 stream() << " " << name << "=\"" << attribute << "\"";
6751 return *this;
6752 }
6753
Phil Nasha1fbfea2012-12-01 23:57:18 +00006754 XmlWriter& writeText( const std::string& text, bool indent = true ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006755 if( !text.empty() ){
6756 bool tagWasOpen = m_tagIsOpen;
6757 ensureTagClosed();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006758 if( tagWasOpen && indent )
Phil Nash56d5c422012-08-23 20:08:50 +01006759 stream() << m_indent;
6760 writeEncodedText( text );
6761 m_needsNewline = true;
6762 }
6763 return *this;
6764 }
6765
6766 XmlWriter& writeComment( const std::string& text ) {
6767 ensureTagClosed();
6768 stream() << m_indent << "<!--" << text << "-->";
6769 m_needsNewline = true;
6770 return *this;
6771 }
6772
6773 XmlWriter& writeBlankLine() {
6774 ensureTagClosed();
6775 stream() << "\n";
6776 return *this;
6777 }
6778
6779 private:
6780
6781 std::ostream& stream() {
6782 return *m_os;
6783 }
6784
6785 void ensureTagClosed() {
6786 if( m_tagIsOpen ) {
6787 stream() << ">\n";
6788 m_tagIsOpen = false;
6789 }
6790 }
6791
6792 void newlineIfNecessary() {
6793 if( m_needsNewline ) {
6794 stream() << "\n";
6795 m_needsNewline = false;
6796 }
6797 }
6798
6799 void writeEncodedText( const std::string& text ) {
6800 static const char* charsToEncode = "<&\"";
6801 std::string mtext = text;
6802 std::string::size_type pos = mtext.find_first_of( charsToEncode );
6803 while( pos != std::string::npos ) {
6804 stream() << mtext.substr( 0, pos );
6805
6806 switch( mtext[pos] ) {
6807 case '<':
6808 stream() << "&lt;";
6809 break;
6810 case '&':
6811 stream() << "&amp;";
6812 break;
6813 case '\"':
6814 stream() << "&quot;";
6815 break;
6816 }
6817 mtext = mtext.substr( pos+1 );
6818 pos = mtext.find_first_of( charsToEncode );
6819 }
6820 stream() << mtext;
6821 }
6822
6823 bool m_tagIsOpen;
6824 bool m_needsNewline;
6825 std::vector<std::string> m_tags;
6826 std::string m_indent;
6827 std::ostream* m_os;
6828 };
6829
6830}
6831namespace Catch {
6832 class XmlReporter : public SharedImpl<IReporter> {
6833 public:
6834 XmlReporter( const ReporterConfig& config ) : m_config( config ) {}
6835
6836 static std::string getDescription() {
6837 return "Reports test results as an XML document";
6838 }
6839 virtual ~XmlReporter();
6840
6841 private: // IReporter
6842
6843 virtual bool shouldRedirectStdout() const {
6844 return true;
6845 }
6846
6847 virtual void StartTesting() {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006848 m_xml = XmlWriter( m_config.stream() );
Phil Nash56d5c422012-08-23 20:08:50 +01006849 m_xml.startElement( "Catch" );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006850 if( !m_config.name().empty() )
6851 m_xml.writeAttribute( "name", m_config.name() );
Phil Nash56d5c422012-08-23 20:08:50 +01006852 }
6853
6854 virtual void EndTesting( const Totals& totals ) {
6855 m_xml.scopedElement( "OverallResults" )
6856 .writeAttribute( "successes", totals.assertions.passed )
6857 .writeAttribute( "failures", totals.assertions.failed );
6858 m_xml.endElement();
6859 }
6860
6861 virtual void StartGroup( const std::string& groupName ) {
6862 m_xml.startElement( "Group" )
6863 .writeAttribute( "name", groupName );
6864 }
6865
6866 virtual void EndGroup( const std::string&, const Totals& totals ) {
6867 m_xml.scopedElement( "OverallResults" )
6868 .writeAttribute( "successes", totals.assertions.passed )
6869 .writeAttribute( "failures", totals.assertions.failed );
6870 m_xml.endElement();
6871 }
6872
6873 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
6874 m_xml.startElement( "Section" )
6875 .writeAttribute( "name", sectionName )
6876 .writeAttribute( "description", description );
6877 }
Phil Nasha70fbe32012-08-31 08:10:36 +01006878 virtual void NoAssertionsInSection( const std::string& ) {}
6879 virtual void NoAssertionsInTestCase( const std::string& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01006880
6881 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
6882 m_xml.scopedElement( "OverallResults" )
6883 .writeAttribute( "successes", assertions.passed )
6884 .writeAttribute( "failures", assertions.failed );
6885 m_xml.endElement();
6886 }
6887
6888 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006889 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
Phil Nash56d5c422012-08-23 20:08:50 +01006890 m_currentTestSuccess = true;
6891 }
6892
Phil Nash82acc2c2012-10-28 12:07:17 +00006893 virtual void Result( const Catch::AssertionResult& assertionResult ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006894 if( !m_config.includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok )
Phil Nash56d5c422012-08-23 20:08:50 +01006895 return;
6896
Phil Nash82acc2c2012-10-28 12:07:17 +00006897 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006898 m_xml.startElement( "Expression" )
Phil Nashd539da92012-11-13 09:44:52 +00006899 .writeAttribute( "success", assertionResult.succeeded() )
Phil Nash82acc2c2012-10-28 12:07:17 +00006900 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6901 .writeAttribute( "line", assertionResult.getSourceInfo().line );
Phil Nash56d5c422012-08-23 20:08:50 +01006902
6903 m_xml.scopedElement( "Original" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006904 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01006905 m_xml.scopedElement( "Expanded" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006906 .writeText( assertionResult.getExpandedExpression() );
Phil Nashd539da92012-11-13 09:44:52 +00006907 m_currentTestSuccess &= assertionResult.succeeded();
Phil Nash56d5c422012-08-23 20:08:50 +01006908 }
6909
Phil Nash82acc2c2012-10-28 12:07:17 +00006910 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01006911 case ResultWas::ThrewException:
6912 m_xml.scopedElement( "Exception" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006913 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
6914 .writeAttribute( "line", assertionResult.getSourceInfo().line )
6915 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006916 m_currentTestSuccess = false;
6917 break;
6918 case ResultWas::Info:
6919 m_xml.scopedElement( "Info" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006920 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006921 break;
6922 case ResultWas::Warning:
6923 m_xml.scopedElement( "Warning" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006924 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006925 break;
6926 case ResultWas::ExplicitFailure:
6927 m_xml.scopedElement( "Failure" )
Phil Nash82acc2c2012-10-28 12:07:17 +00006928 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01006929 m_currentTestSuccess = false;
6930 break;
6931 case ResultWas::Unknown:
6932 case ResultWas::Ok:
6933 case ResultWas::FailureBit:
6934 case ResultWas::ExpressionFailed:
6935 case ResultWas::Exception:
6936 case ResultWas::DidntThrowException:
6937 break;
6938 }
Phil Nash82acc2c2012-10-28 12:07:17 +00006939 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01006940 m_xml.endElement();
6941 }
6942
6943 virtual void Aborted() {
6944 // !TBD
6945 }
6946
6947 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
6948 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
6949 m_xml.endElement();
6950 }
6951
6952 private:
6953 ReporterConfig m_config;
6954 bool m_currentTestSuccess;
6955 XmlWriter m_xml;
6956 };
6957
6958} // end namespace Catch
6959
6960// #included from: ../reporters/catch_reporter_junit.hpp
6961#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
6962
Phil Nashf276a052012-12-02 00:05:51 +00006963#include <assert.h>
6964
Phil Nash56d5c422012-08-23 20:08:50 +01006965namespace Catch {
6966
6967 class JunitReporter : public SharedImpl<IReporter> {
6968
6969 struct TestStats {
6970 std::string m_element;
6971 std::string m_resultType;
6972 std::string m_message;
6973 std::string m_content;
6974 };
6975
6976 struct TestCaseStats {
6977
Phil Nash88b70822012-11-04 21:39:38 +00006978 TestCaseStats( const std::string& className, const std::string& name )
6979 : m_className( className ),
6980 m_name( name )
6981 {}
Phil Nash56d5c422012-08-23 20:08:50 +01006982
6983 double m_timeInSeconds;
6984 std::string m_status;
6985 std::string m_className;
6986 std::string m_name;
Phil Nash28463672012-11-21 18:06:13 +00006987 std::string m_stdOut;
6988 std::string m_stdErr;
Phil Nash56d5c422012-08-23 20:08:50 +01006989 std::vector<TestStats> m_testStats;
Phil Nasha1fbfea2012-12-01 23:57:18 +00006990 std::vector<TestCaseStats> m_sections;
Phil Nash56d5c422012-08-23 20:08:50 +01006991 };
6992
6993 struct Stats {
6994
6995 Stats( const std::string& name = std::string() )
6996 : m_testsCount( 0 ),
6997 m_failuresCount( 0 ),
6998 m_disabledCount( 0 ),
6999 m_errorsCount( 0 ),
7000 m_timeInSeconds( 0 ),
7001 m_name( name )
7002 {}
7003
7004 std::size_t m_testsCount;
7005 std::size_t m_failuresCount;
7006 std::size_t m_disabledCount;
7007 std::size_t m_errorsCount;
7008 double m_timeInSeconds;
7009 std::string m_name;
7010
7011 std::vector<TestCaseStats> m_testCaseStats;
7012 };
7013
7014 public:
7015 JunitReporter( const ReporterConfig& config )
7016 : m_config( config ),
7017 m_testSuiteStats( "AllTests" ),
7018 m_currentStats( &m_testSuiteStats )
7019 {}
7020 virtual ~JunitReporter();
7021
7022 static std::string getDescription() {
7023 return "Reports test results in an XML format that looks like Ant's junitreport target";
7024 }
7025
7026 private: // IReporter
7027
7028 virtual bool shouldRedirectStdout() const {
7029 return true;
7030 }
7031
7032 virtual void StartTesting(){}
7033
7034 virtual void StartGroup( const std::string& groupName ) {
Phil Nashef60d542012-11-16 08:47:03 +00007035 if( groupName.empty() )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007036 m_statsForSuites.push_back( Stats( m_config.name() ) );
Phil Nashef60d542012-11-16 08:47:03 +00007037 else
7038 m_statsForSuites.push_back( Stats( groupName ) );
Phil Nash56d5c422012-08-23 20:08:50 +01007039 m_currentStats = &m_statsForSuites.back();
7040 }
7041
7042 virtual void EndGroup( const std::string&, const Totals& totals ) {
7043 m_currentStats->m_testsCount = totals.assertions.total();
7044 m_currentStats = &m_testSuiteStats;
7045 }
7046
7047 virtual void StartSection( const std::string&, const std::string& ){}
7048
Phil Nasha70fbe32012-08-31 08:10:36 +01007049 virtual void NoAssertionsInSection( const std::string& ) {}
7050 virtual void NoAssertionsInTestCase( const std::string& ) {}
7051
7052 virtual void EndSection( const std::string&, const Counts& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01007053
7054 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007055 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.className, testInfo.name ) );
7056 m_currentTestCaseStats.push_back( &m_currentStats->m_testCaseStats.back() );
Phil Nash56d5c422012-08-23 20:08:50 +01007057 }
7058
Phil Nash82acc2c2012-10-28 12:07:17 +00007059 virtual void Result( const Catch::AssertionResult& assertionResult ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007060 if( assertionResult.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007061 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
7062 TestStats stats;
7063 std::ostringstream oss;
Phil Nash82acc2c2012-10-28 12:07:17 +00007064 if( !assertionResult.getMessage().empty() )
7065 oss << assertionResult.getMessage() << " at ";
7066 oss << assertionResult.getSourceInfo();
Phil Nash56d5c422012-08-23 20:08:50 +01007067 stats.m_content = oss.str();
Phil Nash82acc2c2012-10-28 12:07:17 +00007068 stats.m_message = assertionResult.getExpandedExpression();
7069 stats.m_resultType = assertionResult.getTestMacroName();
Phil Nash56d5c422012-08-23 20:08:50 +01007070
Phil Nash82acc2c2012-10-28 12:07:17 +00007071 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007072 case ResultWas::ThrewException:
7073 stats.m_element = "error";
7074 m_currentStats->m_errorsCount++;
7075 break;
7076 case ResultWas::Info:
7077 stats.m_element = "info"; // !TBD ?
7078 break;
7079 case ResultWas::Warning:
7080 stats.m_element = "warning"; // !TBD ?
7081 break;
7082 case ResultWas::ExplicitFailure:
7083 stats.m_element = "failure";
7084 m_currentStats->m_failuresCount++;
7085 break;
7086 case ResultWas::ExpressionFailed:
7087 stats.m_element = "failure";
7088 m_currentStats->m_failuresCount++;
7089 break;
7090 case ResultWas::Ok:
7091 stats.m_element = "success";
7092 break;
7093 case ResultWas::Unknown:
7094 case ResultWas::FailureBit:
7095 case ResultWas::Exception:
7096 case ResultWas::DidntThrowException:
7097 break;
7098 }
7099 testCaseStats.m_testStats.push_back( stats );
7100 }
7101 }
7102
7103 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string& stdOut, const std::string& stdErr ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007104 m_currentTestCaseStats.pop_back();
7105 assert( m_currentTestCaseStats.empty() );
Phil Nash28463672012-11-21 18:06:13 +00007106 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
7107 testCaseStats.m_stdOut = stdOut;
7108 testCaseStats.m_stdErr = stdErr;
Phil Nash56d5c422012-08-23 20:08:50 +01007109 if( !stdOut.empty() )
7110 m_stdOut << stdOut << "\n";
7111 if( !stdErr.empty() )
7112 m_stdErr << stdErr << "\n";
7113 }
7114
7115 virtual void Aborted() {
7116 // !TBD
7117 }
7118
7119 virtual void EndTesting( const Totals& ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007120 XmlWriter xml( m_config.stream() );
Phil Nash56d5c422012-08-23 20:08:50 +01007121
Phil Nasha1fbfea2012-12-01 23:57:18 +00007122 if( m_statsForSuites.size() > 0 )
7123 xml.startElement( "testsuites" );
Phil Nash56d5c422012-08-23 20:08:50 +01007124
Phil Nasha1fbfea2012-12-01 23:57:18 +00007125 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
7126 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
Phil Nash56d5c422012-08-23 20:08:50 +01007127
Phil Nasha1fbfea2012-12-01 23:57:18 +00007128 for(; it != itEnd; ++it ) {
7129 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
7130 xml.writeAttribute( "name", it->m_name );
7131 xml.writeAttribute( "errors", it->m_errorsCount );
7132 xml.writeAttribute( "failures", it->m_failuresCount );
7133 xml.writeAttribute( "tests", it->m_testsCount );
7134 xml.writeAttribute( "hostname", "tbd" );
7135 xml.writeAttribute( "time", "tbd" );
7136 xml.writeAttribute( "timestamp", "tbd" );
Phil Nash56d5c422012-08-23 20:08:50 +01007137
Phil Nasha1fbfea2012-12-01 23:57:18 +00007138 OutputTestCases( xml, *it );
Phil Nash56d5c422012-08-23 20:08:50 +01007139 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00007140
7141 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ), false );
7142 xml.scopedElement( "system-err" ).writeText( trim( m_stdErr.str() ), false );
Phil Nash56d5c422012-08-23 20:08:50 +01007143 }
7144
7145 void OutputTestCases( XmlWriter& xml, const Stats& stats ) {
7146 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
7147 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
7148 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01007149
7150 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
7151 xml.writeAttribute( "classname", it->m_className );
7152 xml.writeAttribute( "name", it->m_name );
7153 xml.writeAttribute( "time", "tbd" );
7154
7155 OutputTestResult( xml, *it );
Phil Nash28463672012-11-21 18:06:13 +00007156
7157 std::string stdOut = trim( it->m_stdOut );
7158 if( !stdOut.empty() )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007159 xml.scopedElement( "system-out" ).writeText( stdOut, false );
Phil Nash28463672012-11-21 18:06:13 +00007160 std::string stdErr = trim( it->m_stdErr );
7161 if( !stdErr.empty() )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007162 xml.scopedElement( "system-err" ).writeText( stdErr, false );
Phil Nash56d5c422012-08-23 20:08:50 +01007163 }
7164 }
7165
7166 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats ) {
7167 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
7168 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
7169 for(; it != itEnd; ++it ) {
7170 if( it->m_element != "success" ) {
7171 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
7172
7173 xml.writeAttribute( "message", it->m_message );
7174 xml.writeAttribute( "type", it->m_resultType );
7175 if( !it->m_content.empty() )
7176 xml.writeText( it->m_content );
7177 }
7178 }
7179 }
7180
7181 private:
7182 ReporterConfig m_config;
Phil Nash37186a12013-03-13 12:19:30 +00007183// bool m_currentTestSuccess;
Phil Nash56d5c422012-08-23 20:08:50 +01007184
7185 Stats m_testSuiteStats;
7186 Stats* m_currentStats;
7187 std::vector<Stats> m_statsForSuites;
Phil Nasha1fbfea2012-12-01 23:57:18 +00007188 std::vector<const TestCaseStats*> m_currentTestCaseStats;
Phil Nash56d5c422012-08-23 20:08:50 +01007189 std::ostringstream m_stdOut;
7190 std::ostringstream m_stdErr;
7191 };
7192
7193} // end namespace Catch
7194
Phil Nashff03cdf2012-12-06 08:44:51 +00007195// #included from: ../reporters/catch_reporter_console.hpp
7196#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
7197
7198namespace Catch {
7199
Phil Nash2e7d9662013-01-16 09:44:43 +00007200 struct ConsoleReporter : StreamingReporterBase {
Phil Nashff03cdf2012-12-06 08:44:51 +00007201 ConsoleReporter( ReporterConfig const& _config )
Phil Nash2e7d9662013-01-16 09:44:43 +00007202 : StreamingReporterBase( _config ),
Phil Nasha04981b2013-03-08 09:30:25 +00007203 m_headerPrinted( false ),
Phil Nashcf5ced52012-12-14 07:50:08 +00007204 m_atLeastOneTestCasePrinted( false )
Phil Nashff03cdf2012-12-06 08:44:51 +00007205 {}
7206
7207 virtual ~ConsoleReporter();
7208 static std::string getDescription() {
7209 return "Reports test results as plain lines of text";
7210 }
7211 virtual ReporterPreferences getPreferences() const {
7212 ReporterPreferences prefs;
7213 prefs.shouldRedirectStdOut = false;
7214 return prefs;
7215
7216 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007217
Phil Nash37186a12013-03-13 12:19:30 +00007218 virtual void noMatchingTestCases( std::string const& spec ) {
7219 stream << "No test cases matched '" << spec << "'" << std::endl;
7220 }
7221
Phil Nashbcad0932012-12-10 08:54:57 +00007222 virtual void assertionStarting( AssertionInfo const& ) {
Phil Nashff03cdf2012-12-06 08:44:51 +00007223 }
Phil Nashbcad0932012-12-10 08:54:57 +00007224
Phil Nash2e7d9662013-01-16 09:44:43 +00007225 virtual void assertionEnded( AssertionStats const& _assertionStats ) {
7226 AssertionResult const& result = _assertionStats.assertionResult;
Phil Nashbcad0932012-12-10 08:54:57 +00007227
7228 // Drop out if result was successful and we're not printing those
7229 if( !m_config.includeSuccessfulResults() && result.isOk() )
7230 return;
7231
7232 lazyPrint();
7233
Phil Nashe4756452013-01-26 20:18:30 +00007234 AssertionPrinter printer( stream, _assertionStats );
7235 printer.print();
Phil Nash2e7d9662013-01-16 09:44:43 +00007236 stream << std::endl;
7237 }
7238
Phil Nashe4756452013-01-26 20:18:30 +00007239 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
Phil Nasha04981b2013-03-08 09:30:25 +00007240 m_headerPrinted = false;
Phil Nashe4756452013-01-26 20:18:30 +00007241 StreamingReporterBase::sectionStarting( _sectionInfo );
Phil Nash2e7d9662013-01-16 09:44:43 +00007242 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007243 virtual void sectionEnded( SectionStats const& _sectionStats ) {
7244 if( _sectionStats.missingAssertions ) {
7245 lazyPrint();
7246 TextColour colour( TextColour::ResultError );
7247 stream << "\nNo assertions in section, '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
7248 }
Phil Nasha04981b2013-03-08 09:30:25 +00007249 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +00007250 StreamingReporterBase::sectionEnded( _sectionStats );
7251 }
7252
7253 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
7254
7255 if( _testCaseStats.missingAssertions ) {
7256 lazyPrint();
7257 TextColour colour( TextColour::ResultError );
7258 stream << "\nNo assertions in test case, '" << _testCaseStats.testInfo.name << "'\n" << std::endl;
7259 }
7260 StreamingReporterBase::testCaseEnded( _testCaseStats );
Phil Nasha04981b2013-03-08 09:30:25 +00007261 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +00007262 }
7263 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
7264 if( !unusedGroupInfo ) {
7265 printSummaryDivider();
7266 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
7267 printTotals( _testGroupStats.totals );
7268 stream << "\n" << std::endl;
7269 }
7270 StreamingReporterBase::testGroupEnded( _testGroupStats );
7271 }
7272 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
7273 if( m_atLeastOneTestCasePrinted )
7274 printTotalsDivider();
7275 printTotals( _testRunStats.totals );
7276 stream << "\n" << std::endl;
7277 StreamingReporterBase::testRunEnded( _testRunStats );
7278 }
7279
7280 private:
Phil Nashe4756452013-01-26 20:18:30 +00007281
7282 class AssertionPrinter {
Phil Nashdd26e882013-03-25 09:25:31 +00007283 void operator= ( AssertionPrinter const& );
Phil Nashe4756452013-01-26 20:18:30 +00007284 public:
7285 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats )
7286 : stream( _stream ),
7287 stats( _stats ),
7288 result( _stats.assertionResult ),
7289 colour( TextColour::None ),
Phil Nasha2773812013-02-02 20:37:58 +00007290 message( result.getMessage() ),
7291 messages( _stats.infoMessages )
Phil Nashe4756452013-01-26 20:18:30 +00007292 {
7293 switch( result.getResultType() ) {
7294 case ResultWas::Ok:
7295 colour = TextColour::Success;
7296 passOrFail = "PASSED";
Phil Nasha2773812013-02-02 20:37:58 +00007297 //if( result.hasMessage() )
7298 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00007299 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00007300 if( _stats.infoMessages.size() > 1 )
7301 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007302 break;
7303 case ResultWas::ExpressionFailed:
7304 if( result.isOk() ) {
7305 colour = TextColour::Success;
7306 passOrFail = "FAILED - but was ok";
7307 }
7308 else {
7309 colour = TextColour::Error;
7310 passOrFail = "FAILED";
7311 }
Phil Nasha2773812013-02-02 20:37:58 +00007312 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00007313 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00007314 if( _stats.infoMessages.size() > 1 )
7315 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007316 break;
7317 case ResultWas::ThrewException:
7318 colour = TextColour::Error;
7319 passOrFail = "FAILED";
7320 messageLabel = "due to unexpected exception with message";
7321 break;
7322 case ResultWas::DidntThrowException:
7323 colour = TextColour::Error;
7324 passOrFail = "FAILED";
7325 messageLabel = "because no exception was thrown where one was expected";
7326 break;
7327 case ResultWas::Info:
7328 messageLabel = "info";
7329 break;
7330 case ResultWas::Warning:
7331 messageLabel = "warning";
7332 break;
7333 case ResultWas::ExplicitFailure:
7334 passOrFail = "FAILED";
7335 colour = TextColour::Error;
Phil Nasha2773812013-02-02 20:37:58 +00007336 if( _stats.infoMessages.size() == 1 )
7337 messageLabel = "explicitly with message";
7338 if( _stats.infoMessages.size() > 1 )
7339 messageLabel = "explicitly with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007340 break;
7341 case ResultWas::Exception:
7342 passOrFail = "FAILED";
7343 colour = TextColour::Error;
Phil Nasha2773812013-02-02 20:37:58 +00007344 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00007345 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00007346 if( _stats.infoMessages.size() > 1 )
7347 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00007348 break;
7349
7350 // These cases are here to prevent compiler warnings
7351 case ResultWas::Unknown:
7352 case ResultWas::FailureBit:
7353 passOrFail = "** internal error **";
7354 colour = TextColour::Error;
7355 break;
7356 }
7357 }
7358
7359 void print() const {
Phil Nash767f1582013-03-04 12:19:15 +01007360 printSourceInfo();
Phil Nashe4756452013-01-26 20:18:30 +00007361 if( stats.totals.assertions.total() > 0 ) {
Phil Nash767f1582013-03-04 12:19:15 +01007362 if( result.isOk() )
7363 stream << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00007364 printResultType();
7365 printOriginalExpression();
7366 printReconstructedExpression();
7367 }
Phil Nash767f1582013-03-04 12:19:15 +01007368 else {
7369 stream << "\n";
7370 }
Phil Nashe4756452013-01-26 20:18:30 +00007371 printMessage();
Phil Nashe4756452013-01-26 20:18:30 +00007372 }
7373
7374 private:
7375 void printResultType() const {
7376 if( !passOrFail.empty() ) {
7377 TextColour colourGuard( colour );
7378 stream << passOrFail << ":\n";
7379 }
7380 }
7381 void printOriginalExpression() const {
7382 if( result.hasExpression() ) {
7383 TextColour colourGuard( TextColour::OriginalExpression );
7384 stream << " ";
7385 if( !result.getTestMacroName().empty() )
7386 stream << result.getTestMacroName() << "( ";
7387 stream << result.getExpression();
7388 if( !result.getTestMacroName().empty() )
7389 stream << " )";
7390 stream << "\n";
7391 }
7392 }
7393 void printReconstructedExpression() const {
7394 if( result.hasExpandedExpression() ) {
7395 stream << "with expansion:\n";
7396 TextColour colourGuard( TextColour::ReconstructedExpression );
Phil Nash38f7eef2013-03-29 13:44:33 +00007397 stream << LineWrapper().setIndent(2).wrap( result.getExpandedExpression() ) << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00007398 }
7399 }
7400 void printMessage() const {
7401 if( !messageLabel.empty() )
7402 stream << messageLabel << ":" << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00007403 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
7404 it != itEnd;
7405 ++it ) {
Phil Nash38f7eef2013-03-29 13:44:33 +00007406 stream << LineWrapper().setIndent(2).wrap( it->message ) << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00007407 }
Phil Nashe4756452013-01-26 20:18:30 +00007408 }
7409 void printSourceInfo() const {
7410 TextColour colourGuard( TextColour::FileName );
Phil Nash767f1582013-03-04 12:19:15 +01007411 stream << result.getSourceInfo() << ": ";
Phil Nashe4756452013-01-26 20:18:30 +00007412 }
7413
Phil Nashe4756452013-01-26 20:18:30 +00007414 std::ostream& stream;
7415 AssertionStats const& stats;
7416 AssertionResult const& result;
7417 TextColour::Colours colour;
7418 std::string passOrFail;
7419 std::string messageLabel;
7420 std::string message;
Phil Nasha2773812013-02-02 20:37:58 +00007421 std::vector<MessageInfo> messages;
Phil Nashe4756452013-01-26 20:18:30 +00007422 };
Phil Nash2e7d9662013-01-16 09:44:43 +00007423
7424 void lazyPrint() {
7425
7426 if( testRunInfo )
7427 lazyPrintRunInfo();
7428 if( unusedGroupInfo )
7429 lazyPrintGroupInfo();
Phil Nash2e7d9662013-01-16 09:44:43 +00007430
Phil Nasha04981b2013-03-08 09:30:25 +00007431 if( !m_headerPrinted ) {
7432 printTestCaseAndSectionHeader();
7433 m_headerPrinted = true;
7434 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007435 m_atLeastOneTestCasePrinted = true;
7436 }
7437 void lazyPrintRunInfo() {
Phil Nash93906752013-03-16 20:21:51 +00007438 stream << "\n" << getTildes() << "\n";
Phil Nash5c7d3d72013-04-01 11:27:10 +01007439 TextColour colour( TextColour::SecondaryText );
Phil Nash93906752013-03-16 20:21:51 +00007440 stream << testRunInfo->name
Phil Nash2e7d9662013-01-16 09:44:43 +00007441 << " is a CATCH v" << libraryVersion.majorVersion << "."
7442 << libraryVersion.minorVersion << " b"
7443 << libraryVersion.buildNumber;
7444 if( libraryVersion.branchName != "master" )
7445 stream << " (" << libraryVersion.branchName << ")";
7446 stream << " host application.\n"
7447 << "Run with -? for options\n\n";
7448
7449 testRunInfo.reset();
7450 }
7451 void lazyPrintGroupInfo() {
7452 if( !unusedGroupInfo->name.empty() && unusedGroupInfo->groupsCounts > 1 ) {
Phil Nasha04981b2013-03-08 09:30:25 +00007453 printClosedHeader( "Group: " + unusedGroupInfo->name );
Phil Nash2e7d9662013-01-16 09:44:43 +00007454 unusedGroupInfo.reset();
7455 }
7456 }
Phil Nasha04981b2013-03-08 09:30:25 +00007457 void printTestCaseAndSectionHeader() {
Phil Nash5c7d3d72013-04-01 11:27:10 +01007458 printOpenHeader( unusedTestCaseInfo->name,
7459 currentSectionInfo
7460 ? currentSectionInfo->lineInfo
7461 : unusedTestCaseInfo->lineInfo );
Phil Nasha04981b2013-03-08 09:30:25 +00007462 if( currentSectionInfo ) {
Phil Nash5c7d3d72013-04-01 11:27:10 +01007463 TextColour colourGuard( TextColour::Headers );
Phil Nasha04981b2013-03-08 09:30:25 +00007464 std::vector<ThreadedSectionInfo*> sections;
7465 for( ThreadedSectionInfo* section = currentSectionInfo.get();
7466 section;
7467 section = section->parent )
7468 sections.push_back( section );
Phil Nash2e7d9662013-01-16 09:44:43 +00007469
Phil Nasha04981b2013-03-08 09:30:25 +00007470 // Sections
7471 if( !sections.empty() ) {
7472 typedef std::vector<ThreadedSectionInfo*>::const_reverse_iterator It;
7473 for( It it = sections.rbegin(), itEnd = sections.rend(); it != itEnd; ++it )
7474 stream << " " << (*it)->name << "\n";
7475 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007476 }
Phil Nasha04981b2013-03-08 09:30:25 +00007477 stream << getDots() << "\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00007478 }
7479
Phil Nasha04981b2013-03-08 09:30:25 +00007480 void printClosedHeader( std::string const& _name ) {
7481 printOpenHeader( _name );
7482 stream << getDots() << "\n";
7483 }
Phil Nash5c7d3d72013-04-01 11:27:10 +01007484 void printOpenHeader( std::string const& _name, SourceLineInfo const& _lineInfo = SourceLineInfo() ) {
7485 stream << getDashes() << "\n";
7486 if( !_lineInfo.empty() ){
7487 TextColour colourGuard( TextColour::FileName );
7488 stream << _lineInfo << "\n\n";
7489 }
7490 {
7491 TextColour colourGuard( TextColour::Headers );
7492 stream << _name << "\n";
7493 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007494 }
7495
7496 void printTotals( const Totals& totals ) {
7497 if( totals.assertions.total() == 0 ) {
7498 stream << "No tests ran";
7499 }
7500 else if( totals.assertions.failed ) {
7501 TextColour colour( TextColour::ResultError );
7502 printCounts( "test case", totals.testCases );
7503 if( totals.testCases.failed > 0 ) {
7504 stream << " (";
7505 printCounts( "assertion", totals.assertions );
7506 stream << ")";
7507 }
Phil Nashbcad0932012-12-10 08:54:57 +00007508 }
7509 else {
Phil Nash2e7d9662013-01-16 09:44:43 +00007510 TextColour colour( TextColour::ResultSuccess );
7511 stream << "All tests passed ("
7512 << pluralise( totals.assertions.passed, "assertion" ) << " in "
7513 << pluralise( totals.testCases.passed, "test case" ) << ")";
Phil Nashbcad0932012-12-10 08:54:57 +00007514 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007515 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007516 void printCounts( std::string const& label, Counts const& counts ) {
Phil Nashf1178122012-12-11 09:03:14 +00007517 if( counts.total() == 1 ) {
7518 stream << "1 " << label << " - ";
7519 if( counts.failed )
7520 stream << "failed";
7521 else
7522 stream << "passed";
7523 }
7524 else {
7525 stream << counts.total() << " " << label << "s ";
7526 if( counts.passed ) {
7527 if( counts.failed )
7528 stream << "- " << counts.failed << " failed";
7529 else if( counts.passed == 2 )
7530 stream << "- both passed";
7531 else
7532 stream << "- all passed";
7533 }
7534 else {
7535 if( counts.failed == 2 )
7536 stream << "- both failed";
7537 else
7538 stream << "- all failed";
7539 }
7540 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007541 }
7542
Phil Nash2e7d9662013-01-16 09:44:43 +00007543 void printTotalsDivider() {
7544 stream << getDoubleDashes() << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00007545 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007546 void printSummaryDivider() {
7547 stream << getDashes() << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00007548 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007549 static std::string const& getDashes() {
Phil Nashe4756452013-01-26 20:18:30 +00007550 static const std::string dashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '-' );
Phil Nash2e7d9662013-01-16 09:44:43 +00007551 return dashes;
Phil Nashff03cdf2012-12-06 08:44:51 +00007552 }
Phil Nash3ce320d2013-01-18 08:09:28 +00007553 static std::string const& getDots() {
Phil Nashe4756452013-01-26 20:18:30 +00007554 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '.' );
Phil Nash3ce320d2013-01-18 08:09:28 +00007555 return dots;
7556 }
Phil Nash2e7d9662013-01-16 09:44:43 +00007557 static std::string const& getDoubleDashes() {
Phil Nashe4756452013-01-26 20:18:30 +00007558 static const std::string doubleDashes( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
Phil Nash2e7d9662013-01-16 09:44:43 +00007559 return doubleDashes;
Phil Nashff03cdf2012-12-06 08:44:51 +00007560 }
Phil Nash93906752013-03-16 20:21:51 +00007561 static std::string const& getTildes() {
7562 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1, '~' );
7563 return dots;
7564 }
Phil Nashff03cdf2012-12-06 08:44:51 +00007565
Phil Nashcf5ced52012-12-14 07:50:08 +00007566 private:
Phil Nasha04981b2013-03-08 09:30:25 +00007567 bool m_headerPrinted;
Phil Nashcf5ced52012-12-14 07:50:08 +00007568 bool m_atLeastOneTestCasePrinted;
Phil Nashff03cdf2012-12-06 08:44:51 +00007569 };
7570
7571 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
7572
7573} // end namespace Catch
7574
Phil Nasha695eb92012-08-13 07:46:10 +01007575namespace Catch {
7576 NonCopyable::~NonCopyable() {}
7577 IShared::~IShared() {}
7578 StreamBufBase::~StreamBufBase() {}
7579 IContext::~IContext() {}
7580 IResultCapture::~IResultCapture() {}
7581 ITestCase::~ITestCase() {}
7582 ITestCaseRegistry::~ITestCaseRegistry() {}
7583 IRegistryHub::~IRegistryHub() {}
7584 IMutableRegistryHub::~IMutableRegistryHub() {}
7585 IExceptionTranslator::~IExceptionTranslator() {}
7586 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
7587 IReporter::~IReporter() {}
7588 IReporterFactory::~IReporterFactory() {}
7589 IReporterRegistry::~IReporterRegistry() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007590 IStreamingReporter::~IStreamingReporter() {}
7591 LegacyReporterAdapter::~LegacyReporterAdapter() {}
7592 AssertionStats::~AssertionStats() {}
7593 SectionStats::~SectionStats() {}
7594 TestCaseStats::~TestCaseStats() {}
7595 TestGroupStats::~TestGroupStats() {}
7596 TestRunStats::~TestRunStats() {}
Phil Nashff03cdf2012-12-06 08:44:51 +00007597 ThreadedSectionInfo::~ThreadedSectionInfo() {}
Phil Nash2e7d9662013-01-16 09:44:43 +00007598 TestGroupNode::~TestGroupNode() {}
7599 TestRunNode::~TestRunNode() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007600
Phil Nasha695eb92012-08-13 07:46:10 +01007601 BasicReporter::~BasicReporter() {}
Phil Nash2e7d9662013-01-16 09:44:43 +00007602 StreamingReporterBase::~StreamingReporterBase() {}
Phil Nashff03cdf2012-12-06 08:44:51 +00007603 ConsoleReporter::~ConsoleReporter() {}
Phil Nasha695eb92012-08-13 07:46:10 +01007604 IRunner::~IRunner() {}
7605 IMutableContext::~IMutableContext() {}
7606 IConfig::~IConfig() {}
7607 XmlReporter::~XmlReporter() {}
7608 JunitReporter::~JunitReporter() {}
7609 TestRegistry::~TestRegistry() {}
7610 FreeFunctionTestCase::~FreeFunctionTestCase() {}
7611 IGeneratorInfo::~IGeneratorInfo() {}
7612 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash799ecf92012-09-24 08:30:13 +01007613 TagParser::~TagParser() {}
7614 TagExtracter::~TagExtracter() {}
7615 TagExpressionParser::~TagExpressionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01007616
Phil Nash9444bbc2012-10-12 07:58:17 +01007617 Matchers::Impl::StdString::Equals::~Equals() {}
7618 Matchers::Impl::StdString::Contains::~Contains() {}
7619 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
7620 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
7621
Phil Nasha695eb92012-08-13 07:46:10 +01007622 void Config::dummy() {}
7623
Phil Nasha1fbfea2012-12-01 23:57:18 +00007624 INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "basic", BasicReporter )
7625 INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
7626 INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "junit", JunitReporter )
Phil Nash56d5c422012-08-23 20:08:50 +01007627
Phil Nasha695eb92012-08-13 07:46:10 +01007628}
7629
Phil Nash5bc030d2012-08-16 18:48:50 +01007630#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01007631#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01007632#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -04007633
Phil Nash5bc030d2012-08-16 18:48:50 +01007634#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007635
7636#ifdef CATCH_CONFIG_MAIN
7637// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01007638#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007639
Phil Nash176eb812012-05-11 08:17:16 +01007640#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01007641
Phil Nash176eb812012-05-11 08:17:16 +01007642// Standard C/C++ main entry point
7643int main (int argc, char * const argv[]) {
7644 return Catch::Main( argc, argv );
7645}
7646
7647#else // __OBJC__
7648
7649// Objective-C entry point
7650int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00007651#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007652 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00007653#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007654
7655 Catch::registerTestMethods();
Phil Nash89d1e6c2011-05-24 08:23:02 +01007656 int result = Catch::Main( argc, (char* const*)argv );
7657
Phil Nash53c990a2012-03-17 18:20:06 +00007658#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007659 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00007660#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01007661
Phil Nashdd5b9c22012-02-18 09:58:30 +00007662 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01007663}
7664
Phil Nash176eb812012-05-11 08:17:16 +01007665#endif // __OBJC__
7666
Phil Nash89d1e6c2011-05-24 08:23:02 +01007667#endif
7668
Phil Nash89d1e6c2011-05-24 08:23:02 +01007669//////
7670
Phil Nash46bcd4b2012-07-20 18:43:48 +01007671// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
7672#ifdef CATCH_CONFIG_PREFIX_ALL
7673
Phil Nashaf1a3212012-11-10 18:46:39 +00007674#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
7675#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 +01007676
Phil Nashaf1a3212012-11-10 18:46:39 +00007677#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
7678#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
7679#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007680
Phil Nashaf1a3212012-11-10 18:46:39 +00007681#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
7682#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" )
7683#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
7684#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
Phil Nash7717c292012-11-13 09:45:29 +00007685#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 +01007686
Phil Nashaf1a3212012-11-10 18:46:39 +00007687#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
7688#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
7689#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007690
Phil Nashaf1a3212012-11-10 18:46:39 +00007691#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
7692#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007693
Phil Nasha2773812013-02-02 20:37:58 +00007694#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nashaf1a3212012-11-10 18:46:39 +00007695#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" )
7696#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" )
7697#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" )
Phil Nash82acc2c2012-10-28 12:07:17 +00007698#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "CATCH_SCOPED_INFO" )
Phil Nasha2773812013-02-02 20:37:58 +00007699#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nash82acc2c2012-10-28 12:07:17 +00007700#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "CATCH_SCOPED_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007701
Phil Nash93906752013-03-16 20:21:51 +00007702#ifdef CATCH_CONFIG_VARIADIC_MACROS
7703 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
7704 #define CATCH_TEST_CASE_NORETURN( ... ) INTERNAL_CATCH_TESTCASE_NORETURN( __VA_ARGS__ )
7705 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
7706 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
7707#else
7708 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
7709 #define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
7710 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
7711 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
7712#endif
7713#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007714
7715#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007716#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash46bcd4b2012-07-20 18:43:48 +01007717
7718#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
7719
Phil Nash37186a12013-03-13 12:19:30 +00007720// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +00007721#ifdef CATCH_CONFIG_VARIADIC_MACROS
7722#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
7723#else
Phil Nash37186a12013-03-13 12:19:30 +00007724#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +00007725#endif
Phil Nash37186a12013-03-13 12:19:30 +00007726#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
7727#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
7728#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
7729#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
7730#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
7731
Phil Nash46bcd4b2012-07-20 18:43:48 +01007732// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
7733#else
7734
Phil Nashaf1a3212012-11-10 18:46:39 +00007735#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
7736#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007737
Phil Nashaf1a3212012-11-10 18:46:39 +00007738#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
7739#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
7740#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007741
Phil Nashaf1a3212012-11-10 18:46:39 +00007742#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
7743#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" )
7744#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
7745#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
Phil Nashd539da92012-11-13 09:44:52 +00007746#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007747
Phil Nashaf1a3212012-11-10 18:46:39 +00007748#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
7749#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
7750#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007751
Phil Nashaf1a3212012-11-10 18:46:39 +00007752#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
7753#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +00007754
Phil Nasha2773812013-02-02 20:37:58 +00007755#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nashaf1a3212012-11-10 18:46:39 +00007756#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" )
7757#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" )
7758#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" )
Phil Nash82acc2c2012-10-28 12:07:17 +00007759#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "SCOPED_INFO" )
Phil Nasha2773812013-02-02 20:37:58 +00007760#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nash82acc2c2012-10-28 12:07:17 +00007761#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "SCOPED_CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007762
Phil Nash93906752013-03-16 20:21:51 +00007763#ifdef CATCH_CONFIG_VARIADIC_MACROS
7764 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
7765 #define TEST_CASE_NORETURN( ... ) INTERNAL_CATCH_TESTCASE_NORETURN( __VA_ARGS__ )
7766 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
7767 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
7768#else
7769 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
7770 #define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
7771 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
7772 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
7773#endif
7774#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007775
7776#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007777#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007778
7779#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
7780
Phil Nash46bcd4b2012-07-20 18:43:48 +01007781#endif
7782
7783#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01007784
Phil Nash37186a12013-03-13 12:19:30 +00007785// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +00007786#ifdef CATCH_CONFIG_VARIADIC_MACROS
7787#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
7788#else
Phil Nash37186a12013-03-13 12:19:30 +00007789#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +00007790#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00007791#define GIVEN( desc ) SECTION( " Given: " desc, "" )
7792#define WHEN( desc ) SECTION( " When: " desc, "" )
7793#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
7794#define THEN( desc ) SECTION( " Then: " desc, "" )
7795#define AND_THEN( desc ) SECTION( " And: " desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +00007796
Phil Nash89d1e6c2011-05-24 08:23:02 +01007797using Catch::Detail::Approx;
7798
Phil Nash5bc030d2012-08-16 18:48:50 +01007799#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01007800#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01007801#endif
Phil Nasha695eb92012-08-13 07:46:10 +01007802
Phil Nashaec1e5e2012-05-09 19:37:51 +01007803#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007804