blob: 36aa2f8ba6b6e7e406e0b1175acad6a4770750b0 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nash67305122012-10-09 11:48:55 +01002 * Generated: 2012-10-09 11:46:45.335978
Phil Nash4df051b2012-05-22 22:22:22 +01003 * ----------------------------------------------------------
Phil Nashaec1e5e2012-05-09 19:37:51 +01004 * This file has been merged from multiple headers. Please don't edit it directly
5 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
Phil Nash89d1e6c2011-05-24 08:23:02 +01006 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Phil Nash89d1e6c2011-05-24 08:23:02 +01009 */
Phil Nashaec1e5e2012-05-09 19:37:51 +010010#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
11#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010012
Phil Nash3b80af72012-08-09 07:47:30 +010013#define TWOBLUECUBES_CATCH_HPP_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +010014
Phil Nash5bc030d2012-08-16 18:48:50 +010015#ifdef __clang__
16#pragma clang diagnostic ignored "-Wno-global-constructors"
17
Phil Nasha695eb92012-08-13 07:46:10 +010018#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010020#endif
Phil Nasha695eb92012-08-13 07:46:10 +010021
Phil Nash3b80af72012-08-09 07:47:30 +010022// #included from: internal/catch_notimplemented_exception.h
23#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010024
Phil Nash89d1e6c2011-05-24 08:23:02 +010025// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010026#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010027
Phil Nash89d1e6c2011-05-24 08:23:02 +010028#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
29#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
30#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
31
32#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
33#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
34
35#ifdef __GNUC__
Phil Nasha695eb92012-08-13 07:46:10 +010036#define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
Phil Nash89d1e6c2011-05-24 08:23:02 +010037#else
Phil Nasha695eb92012-08-13 07:46:10 +010038#define CATCH_ATTRIBUTE_NORETURN
Phil Nash89d1e6c2011-05-24 08:23:02 +010039#endif
40
41#include <sstream>
42#include <stdexcept>
43#include <algorithm>
44
Phil Nash89d2a3f2012-05-16 15:09:17 +010045namespace Catch {
46
Phil Nashd31737f2012-05-09 19:04:00 +010047 class NonCopyable {
Phil Nash89d1e6c2011-05-24 08:23:02 +010048 NonCopyable( const NonCopyable& );
49 void operator = ( const NonCopyable& );
50 protected:
Phil Nashd31737f2012-05-09 19:04:00 +010051 NonCopyable() {}
Phil Nasha695eb92012-08-13 07:46:10 +010052 virtual ~NonCopyable();
Phil Nash89d1e6c2011-05-24 08:23:02 +010053 };
54
Phil Nash163088a2012-05-31 19:40:26 +010055 class SafeBool {
56 public:
57 typedef void (SafeBool::*type)() const;
58
59 static type makeSafe( bool value ) {
60 return value ? &SafeBool::trueValue : 0;
61 }
62 private:
63 void trueValue() const {}
64 };
65
Phil Nash89d1e6c2011-05-24 08:23:02 +010066 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010067 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010068 typename ContainerT::const_iterator it = container.begin();
69 typename ContainerT::const_iterator itEnd = container.end();
70 for(; it != itEnd; ++it )
71 {
72 delete *it;
73 }
74 }
75 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +010076 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010077 typename AssociativeContainerT::const_iterator it = container.begin();
78 typename AssociativeContainerT::const_iterator itEnd = container.end();
79 for(; it != itEnd; ++it )
80 {
81 delete it->second;
82 }
83 }
84
85 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010086 inline void forEach( ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010087 std::for_each( container.begin(), container.end(), function );
88 }
89
90 template<typename ContainerT, typename Function>
Phil Nashd31737f2012-05-09 19:04:00 +010091 inline void forEach( const ContainerT& container, Function function ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +010092 std::for_each( container.begin(), container.end(), function );
93 }
94
Phil Nash56d5c422012-08-23 20:08:50 +010095 inline bool startsWith( const std::string& s, const std::string& prefix ) {
96 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
97 }
Phil Nash4c97fc52012-08-24 08:23:50 +010098 inline bool endsWith( const std::string& s, const std::string& suffix ) {
99 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
100 }
101 inline bool contains( const std::string& s, const std::string& infix ) {
102 return s.find( infix ) != std::string::npos;
103 }
104
105 struct pluralise {
106 pluralise( std::size_t count, const std::string& label )
107 : m_count( count ),
108 m_label( label )
109 {}
110
111 friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser ) {
112 os << pluraliser.m_count << " " << pluraliser.m_label;
113 if( pluraliser.m_count != 1 )
114 os << "s";
115 return os;
116 }
117
118 std::size_t m_count;
119 std::string m_label;
120 };
Phil Nash56d5c422012-08-23 20:08:50 +0100121
Phil Nash89d2a3f2012-05-16 15:09:17 +0100122 struct SourceLineInfo {
123
Phil Nashd31737f2012-05-09 19:04:00 +0100124 SourceLineInfo() : line( 0 ){}
Phil Nash62179662012-05-11 19:06:43 +0100125 SourceLineInfo( const std::string& _file, std::size_t _line )
126 : file( _file ),
127 line( _line )
Phil Nash6e0f58d2012-02-15 18:37:21 +0000128 {}
Phil Nashabf27162012-07-05 18:37:58 +0100129 SourceLineInfo( const std::string& _function, const std::string& _file, std::size_t _line )
130 : function( _function ),
131 file( _file ),
132 line( _line )
133 {}
Phil Nashd31737f2012-05-09 19:04:00 +0100134 SourceLineInfo( const SourceLineInfo& other )
135 : file( other.file ),
136 line( other.line )
137 {}
138 void swap( SourceLineInfo& other ){
139 file.swap( other.file );
140 std::swap( line, other.line );
141 }
Phil Nash6e0f58d2012-02-15 18:37:21 +0000142
Phil Nashabf27162012-07-05 18:37:58 +0100143 std::string function;
Phil Nash6e0f58d2012-02-15 18:37:21 +0000144 std::string file;
145 std::size_t line;
146 };
147
Phil Nashd31737f2012-05-09 19:04:00 +0100148 inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) {
Phil Nash6e0f58d2012-02-15 18:37:21 +0000149#ifndef __GNUG__
150 os << info.file << "(" << info.line << "): ";
151#else
152 os << info.file << ":" << info.line << ": ";
153#endif
154 return os;
155 }
156
Phil Nasha695eb92012-08-13 07:46:10 +0100157 CATCH_ATTRIBUTE_NORETURN
158 inline void throwLogicError( const std::string& message, const SourceLineInfo& locationInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100159 std::ostringstream oss;
Phil Nasha695eb92012-08-13 07:46:10 +0100160 oss << "Internal Catch error: '" << message << "' at: " << locationInfo;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100161 throw std::logic_error( oss.str() );
162 }
163}
164
Phil Nasha695eb92012-08-13 07:46:10 +0100165#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
166#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100167
Phil Nash3b80af72012-08-09 07:47:30 +0100168#include <ostream>
169
170namespace Catch {
171
172 class NotImplementedException : public std::exception
173 {
174 public:
175 NotImplementedException( const SourceLineInfo& lineInfo );
176
177 virtual ~NotImplementedException() throw() {}
178
179 virtual const char* what() const throw();
180
181 private:
182 std::string m_what;
183 SourceLineInfo m_lineInfo;
184 };
185
186} // end namespace Catch
187
188///////////////////////////////////////////////////////////////////////////////
189#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
190
191// #included from: internal/catch_context.h
192#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
193
Phil Nasha70fbe32012-08-31 08:10:36 +0100194// #included from: catch_interfaces_generators.h
195#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100196
Phil Nasha70fbe32012-08-31 08:10:36 +0100197#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000198
Phil Nash89d2a3f2012-05-16 15:09:17 +0100199namespace Catch {
200
Phil Nasha70fbe32012-08-31 08:10:36 +0100201 struct IGeneratorInfo {
202 virtual ~IGeneratorInfo();
203 virtual bool moveNext() = 0;
204 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000205 };
206
Phil Nasha70fbe32012-08-31 08:10:36 +0100207 struct IGeneratorsForTest {
208 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100209
Phil Nasha70fbe32012-08-31 08:10:36 +0100210 virtual IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) = 0;
211 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000212 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100213
214 IGeneratorsForTest* createGeneratorsForTest();
215
216} // end namespace Catch
217
218#include <memory>
219#include <vector>
220#include <stdlib.h>
221
222namespace Catch {
223
224 class TestCaseInfo;
Phil Nash67ec8702012-09-26 18:38:26 +0100225 class Stream;
Phil Nasha70fbe32012-08-31 08:10:36 +0100226 struct IResultCapture;
227 struct IRunner;
228 struct IGeneratorsForTest;
229 struct IConfig;
230
Phil Nasha70fbe32012-08-31 08:10:36 +0100231 struct IContext
232 {
233 virtual ~IContext();
234
235 virtual IResultCapture& getResultCapture() = 0;
236 virtual IRunner& getRunner() = 0;
237 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) = 0;
238 virtual bool advanceGeneratorsForCurrentTest() = 0;
239 virtual const IConfig* getConfig() const = 0;
240 };
241
242 struct IMutableContext : IContext
243 {
244 virtual ~IMutableContext();
245 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
246 virtual void setRunner( IRunner* runner ) = 0;
247 virtual void setConfig( const IConfig* config ) = 0;
248 };
249
250 IContext& getCurrentContext();
251 IMutableContext& getCurrentMutableContext();
252 void cleanUpContext();
Phil Nash67ec8702012-09-26 18:38:26 +0100253 Stream createStream( const std::string& streamName );
Phil Nasha70fbe32012-08-31 08:10:36 +0100254
Phil Nashf7299fc2012-02-25 09:39:45 +0000255}
256
Phil Nasha70fbe32012-08-31 08:10:36 +0100257// #included from: internal/catch_test_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -0400258#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +0100259
260// #included from: catch_interfaces_testcase.h
261#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
262
Phil Nash49e6d532012-05-05 19:35:35 +0100263// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100264#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100265
Phil Nash89d2a3f2012-05-16 15:09:17 +0100266namespace Catch {
267
Phil Nash49e6d532012-05-05 19:35:35 +0100268 // An intrusive reference counting smart pointer.
269 // T must implement addRef() and release() methods
270 // typically implementing the IShared interface
271 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100272 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100273 public:
274 Ptr() : m_p( NULL ){}
275 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100276 if( m_p )
277 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100278 }
279 Ptr( const Ptr& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100280 if( m_p )
281 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100282 }
283 ~Ptr(){
284 if( m_p )
285 m_p->release();
286 }
287 Ptr& operator = ( T* p ){
288 Ptr temp( p );
289 swap( temp );
290 return *this;
291 }
Phil Nashdeb3ced2012-08-31 18:50:46 +0100292 Ptr& operator = ( const Ptr& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100293 Ptr temp( other );
294 swap( temp );
295 return *this;
296 }
297 void swap( Ptr& other ){
298 std::swap( m_p, other.m_p );
299 }
300
301 T* get(){
302 return m_p;
303 }
304 const T* get() const{
305 return m_p;
306 }
307
Phil Nash56d5c422012-08-23 20:08:50 +0100308 T& operator*() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100309 return *m_p;
310 }
311
Phil Nash56d5c422012-08-23 20:08:50 +0100312 T* operator->() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100313 return m_p;
314 }
Phil Nash56d5c422012-08-23 20:08:50 +0100315
Phil Nash61756972012-07-28 20:37:07 +0100316 bool operator !() const {
317 return m_p == NULL;
318 }
Phil Nash49e6d532012-05-05 19:35:35 +0100319
320 private:
321 T* m_p;
322 };
323
324 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100325 virtual ~IShared();
Phil Nash49e6d532012-05-05 19:35:35 +0100326 virtual void addRef() = 0;
327 virtual void release() = 0;
328 };
329
330 template<typename T>
331 struct SharedImpl : T {
332
333 SharedImpl() : m_rc( 0 ){}
334
335 virtual void addRef(){
336 ++m_rc;
337 }
338 virtual void release(){
339 if( --m_rc == 0 )
340 delete this;
341 }
342
343 int m_rc;
344 };
345
346} // end namespace Catch
347
Phil Nash0f9c5512012-06-02 23:12:42 +0100348#include <vector>
349
350namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100351
352 class TestCaseFilters;
353
Phil Nash5bc030d2012-08-16 18:48:50 +0100354 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100355 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100356 protected:
357 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100358 };
359
360 class TestCaseInfo;
361
362 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100363 virtual ~ITestCaseRegistry();
Phil Nash0f9c5512012-06-02 23:12:42 +0100364 virtual const std::vector<TestCaseInfo>& getAllTests() const = 0;
Phil Nash3b80af72012-08-09 07:47:30 +0100365 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100366 };
367}
368
Phil Nash89d2a3f2012-05-16 15:09:17 +0100369namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100370
371template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100372class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100373
Phil Nash176eb812012-05-11 08:17:16 +0100374public:
375 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100376
Phil Nash176eb812012-05-11 08:17:16 +0100377 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100378 C obj;
379 (obj.*m_method)();
380 }
381
Phil Nash89d1e6c2011-05-24 08:23:02 +0100382private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100383 virtual ~MethodTestCase() {}
384
Phil Nash89d1e6c2011-05-24 08:23:02 +0100385 void (C::*m_method)();
386};
387
388typedef void(*TestFunction)();
389
Phil Nash89d2a3f2012-05-16 15:09:17 +0100390struct AutoReg {
391
Phil Nash176eb812012-05-11 08:17:16 +0100392 AutoReg( TestFunction function,
393 const char* name,
394 const char* description,
395 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100396
Phil Nash89d1e6c2011-05-24 08:23:02 +0100397 template<typename C>
Phil Nash176eb812012-05-11 08:17:16 +0100398 AutoReg( void (C::*method)(),
399 const char* name,
400 const char* description,
401 const SourceLineInfo& lineInfo ) {
Phil Nashd31737f2012-05-09 19:04:00 +0100402 registerTestCase( new MethodTestCase<C>( method ), name, description, lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100403 }
404
Phil Nash176eb812012-05-11 08:17:16 +0100405 void registerTestCase( ITestCase* testCase,
406 const char* name,
407 const char* description,
408 const SourceLineInfo& lineInfo );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100409
Phil Nash176eb812012-05-11 08:17:16 +0100410 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100411
412private:
Phil Nash176eb812012-05-11 08:17:16 +0100413 AutoReg( const AutoReg& );
414 void operator= ( const AutoReg& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100415};
416
417} // end namespace Catch
418
419///////////////////////////////////////////////////////////////////////////////
420#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100421 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \
422 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
423 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100424
425///////////////////////////////////////////////////////////////////////////////
426#define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
Phil Nasha695eb92012-08-13 07:46:10 +0100427 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \
Phil Nashd31737f2012-05-09 19:04:00 +0100428 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
429 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100430
431///////////////////////////////////////////////////////////////////////////////
Phil Nash46bcd4b2012-07-20 18:43:48 +0100432#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +0100433 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100434
435///////////////////////////////////////////////////////////////////////////////
436#define TEST_CASE_METHOD( ClassName, TestName, Desc )\
Phil Nashfd78e0f2011-12-28 19:56:39 +0000437 namespace{ \
Phil Nashd31737f2012-05-09 19:04:00 +0100438 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
Phil Nashfd78e0f2011-12-28 19:56:39 +0000439 void test(); \
440 }; \
Phil Nashd31737f2012-05-09 19:04:00 +0100441 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, TestName, Desc, CATCH_INTERNAL_LINEINFO ); \
Phil Nashfd78e0f2011-12-28 19:56:39 +0000442 } \
Phil Nashd31737f2012-05-09 19:04:00 +0100443 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100444
445// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100446#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100447
Phil Nash89d2a3f2012-05-16 15:09:17 +0100448// #included from: catch_expression_builder.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100449#define TWOBLUECUBES_CATCH_EXPRESSION_BUILDER_HPP_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100450
Phil Nash176eb812012-05-11 08:17:16 +0100451// #included from: catch_expression.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100452#define TWOBLUECUBES_CATCH_EXPRESSION_HPP_INCLUDED
Phil Nash176eb812012-05-11 08:17:16 +0100453
Phil Nash3b80af72012-08-09 07:47:30 +0100454// #included from: catch_resultinfo_builder.h
455#define TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100456
Phil Nashd31737f2012-05-09 19:04:00 +0100457// #included from: catch_tostring.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100458#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +0100459
Phil Nashd31737f2012-05-09 19:04:00 +0100460#include <sstream>
461
Phil Nash0dc9e432012-08-01 08:17:07 +0100462#ifdef __OBJC__
463// #included from: catch_objc_arc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100464#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
Phil Nash0dc9e432012-08-01 08:17:07 +0100465
466#import <Foundation/Foundation.h>
467
468#ifdef __has_feature
469#define CATCH_ARC_ENABLED __has_feature(objc_arc)
470#else
471#define CATCH_ARC_ENABLED 0
472#endif
473
474void arcSafeRelease( NSObject* obj );
475id performOptionalSelector( id obj, SEL sel );
476
477#if !CATCH_ARC_ENABLED
478inline void arcSafeRelease( NSObject* obj ) {
479 [obj release];
480}
481inline id performOptionalSelector( id obj, SEL sel ) {
482 if( [obj respondsToSelector: sel] )
483 return [obj performSelector: sel];
484 return nil;
485}
486#define CATCH_UNSAFE_UNRETAINED
487#define CATCH_ARC_STRONG
488#else
489inline void arcSafeRelease( NSObject* ){}
490inline id performOptionalSelector( id obj, SEL sel ) {
Phil Nash5bc030d2012-08-16 18:48:50 +0100491#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100492#pragma clang diagnostic push
493#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
Phil Nash5bc030d2012-08-16 18:48:50 +0100494#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100495 if( [obj respondsToSelector: sel] )
496 return [obj performSelector: sel];
Phil Nash5bc030d2012-08-16 18:48:50 +0100497#ifdef __clang__
Phil Nash0dc9e432012-08-01 08:17:07 +0100498#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +0100499#endif
Phil Nash0dc9e432012-08-01 08:17:07 +0100500 return nil;
501}
502#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
503#define CATCH_ARC_STRONG __strong
504#endif
505
506#endif
507
Phil Nash89d2a3f2012-05-16 15:09:17 +0100508namespace Catch {
509namespace Detail {
510
Phil Nashd31737f2012-05-09 19:04:00 +0100511 struct NonStreamable {
512 template<typename T> NonStreamable( const T& ){}
513 };
514
515 // If the type does not have its own << overload for ostream then
516 // this one will be used instead
517 inline std::ostream& operator << ( std::ostream& ss, NonStreamable ){
518 return ss << "{?}";
519 }
520
521 template<typename T>
522 inline std::string makeString( const T& value ) {
523 std::ostringstream oss;
524 oss << value;
525 return oss.str();
526 }
527
528 template<typename T>
529 inline std::string makeString( T* p ) {
530 if( !p )
531 return INTERNAL_CATCH_STRINGIFY( NULL );
532 std::ostringstream oss;
533 oss << p;
534 return oss.str();
535 }
536
537 template<typename T>
538 inline std::string makeString( const T* p ) {
539 if( !p )
540 return INTERNAL_CATCH_STRINGIFY( NULL );
541 std::ostringstream oss;
542 oss << p;
543 return oss.str();
544 }
545
546} // end namespace Detail
547
548/// \brief converts any type to a string
549///
550/// The default template forwards on to ostringstream - except when an
551/// ostringstream overload does not exist - in which case it attempts to detect
552/// that and writes {?}.
553/// Overload (not specialise) this template for custom typs that you don't want
554/// to provide an ostream overload for.
555template<typename T>
556std::string toString( const T& value ) {
557 return Detail::makeString( value );
558}
559
560// Built in overloads
561
562inline std::string toString( const std::string& value ) {
563 return "\"" + value + "\"";
564}
565
566inline std::string toString( const std::wstring& value ) {
567 std::ostringstream oss;
568 oss << "\"";
569 for(size_t i = 0; i < value.size(); ++i )
570 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
571 oss << "\"";
572 return oss.str();
573}
574
575inline std::string toString( const char* const value ) {
576 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
577}
578
579inline std::string toString( char* const value ) {
580 return Catch::toString( static_cast<const char*>( value ) );
581}
582
583inline std::string toString( int value ) {
584 std::ostringstream oss;
585 oss << value;
586 return oss.str();
587}
588
589inline std::string toString( unsigned long value ) {
590 std::ostringstream oss;
591 if( value > 8192 )
592 oss << "0x" << std::hex << value;
593 else
594 oss << value;
595 return oss.str();
596}
597
598inline std::string toString( unsigned int value ) {
Phil Nash62179662012-05-11 19:06:43 +0100599 return toString( static_cast<unsigned long>( value ) );
Phil Nashd31737f2012-05-09 19:04:00 +0100600}
601
602inline std::string toString( const double value ) {
603 std::ostringstream oss;
604 oss << value;
605 return oss.str();
606}
607
608inline std::string toString( bool value ) {
609 return value ? "true" : "false";
610}
611
Phil Nash78372d02012-06-06 08:06:40 +0100612inline std::string toString( char value ) {
613 return value < ' '
614 ? toString( (unsigned int)value )
615 : Detail::makeString( value );
616}
617
618inline std::string toString( signed char value ) {
619 return toString( static_cast<char>( value ) );
620}
621
Phil Nash176eb812012-05-11 08:17:16 +0100622#ifdef CATCH_CONFIG_CPP11_NULLPTR
Phil Nash06e959b2012-05-25 08:52:05 +0100623inline std::string toString( std::nullptr_t ) {
Phil Nash176eb812012-05-11 08:17:16 +0100624 return "nullptr";
625}
626#endif
627
Phil Nash0dc9e432012-08-01 08:17:07 +0100628#ifdef __OBJC__
Phil Nash0dc9e432012-08-01 08:17:07 +0100629 inline std::string toString( NSString const * const& nsstring ) {
630 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
631 }
632 inline std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
633 return std::string( "@\"" ) + [nsstring UTF8String] + "\"";
634 }
635 inline std::string toString( NSObject* const& nsObject ) {
636 return toString( [nsObject description] );
637 }
638#endif
639
Phil Nashd31737f2012-05-09 19:04:00 +0100640} // end namespace Catch
641
Phil Nash3b80af72012-08-09 07:47:30 +0100642// #included from: catch_resultinfo.h
Matt Wozniskif29c8982012-09-17 01:42:29 -0400643#define TWOBLUECUBES_CATCH_RESULTINFO_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100644
Phil Nash89d1e6c2011-05-24 08:23:02 +0100645#include <string>
646// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100647#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100648
Phil Nash89d2a3f2012-05-16 15:09:17 +0100649namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100650
Phil Nash89d2a3f2012-05-16 15:09:17 +0100651struct ResultWas { enum OfType {
652 Unknown = -1,
653 Ok = 0,
654 Info = 1,
655 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100656
Phil Nash89d2a3f2012-05-16 15:09:17 +0100657 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100658
Phil Nash89d2a3f2012-05-16 15:09:17 +0100659 ExpressionFailed = FailureBit | 1,
660 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100661
Phil Nash89d2a3f2012-05-16 15:09:17 +0100662 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100663
Phil Nash89d2a3f2012-05-16 15:09:17 +0100664 ThrewException = Exception | 1,
665 DidntThrowException = Exception | 2
Phil Nash89d1e6c2011-05-24 08:23:02 +0100666
Phil Nash89d2a3f2012-05-16 15:09:17 +0100667}; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100668
Phil Nash67305122012-10-09 11:48:55 +0100669inline bool isOk( ResultWas::OfType resultType ) {
670 return ( resultType & ResultWas::FailureBit ) == 0;
671}
672
Phil Nash89d2a3f2012-05-16 15:09:17 +0100673struct ResultAction { enum Value {
674 None,
Phil Nash19b2aa62012-06-01 19:40:27 +0100675 Failed = 1, // Failure - but no debug break if Debug bit not set
676 Debug = 2, // If this bit is set, invoke the debugger
677 Abort = 4 // Test run should abort
Phil Nash89d2a3f2012-05-16 15:09:17 +0100678}; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100679
680}
681
682
Phil Nash89d2a3f2012-05-16 15:09:17 +0100683namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100684
Phil Nash67305122012-10-09 11:48:55 +0100685 struct ResultData
686 {
687 ResultData() : resultType( ResultWas::Unknown ) {}
688
689 std::string macroName;
690 SourceLineInfo lineInfo;
691 std::string capturedExpression;
692 std::string reconstructedExpression;
693 std::string message;
694 ResultWas::OfType resultType;
695 };
696
Phil Nash89d2a3f2012-05-16 15:09:17 +0100697 class ResultInfo {
698 public:
Phil Nash3b80af72012-08-09 07:47:30 +0100699 ResultInfo();
Phil Nash67305122012-10-09 11:48:55 +0100700 ResultInfo( const ResultData& data );
Phil Nasha695eb92012-08-13 07:46:10 +0100701 ~ResultInfo();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100702
Phil Nash3b80af72012-08-09 07:47:30 +0100703 bool ok() const;
704 ResultWas::OfType getResultType() const;
705 bool hasExpression() const;
706 bool hasMessage() const;
707 std::string getExpression() const;
708 bool hasExpandedExpression() const;
709 std::string getExpandedExpression() const;
710 std::string getMessage() const;
711 std::string getFilename() const;
712 std::size_t getLine() const;
713 std::string getTestMacroName() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100714
715 protected:
Phil Nash67305122012-10-09 11:48:55 +0100716 ResultData m_data;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100717 };
718
719} // end namespace Catch
720
Phil Nash89d1e6c2011-05-24 08:23:02 +0100721// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100722#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100723
Phil Nash89d2a3f2012-05-16 15:09:17 +0100724namespace Catch {
725namespace Internal {
726
727 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100728 IsEqualTo,
729 IsNotEqualTo,
730 IsLessThan,
731 IsGreaterThan,
732 IsLessThanOrEqualTo,
733 IsGreaterThanOrEqualTo
734 };
735
Phil Nash371db8b2012-05-21 18:52:09 +0100736 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
737 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
738 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
739 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
740 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
741 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
742 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100743
744 // So the compare overloads can be operator agnostic we convey the operator as a template
745 // enum, which is used to specialise an Evaluator for doing the comparison.
746 template<typename T1, typename T2, Operator Op>
747 class Evaluator{};
748
749 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100750 struct Evaluator<T1, T2, IsEqualTo> {
751 static bool evaluate( const T1& lhs, const T2& rhs) {
Phil Nashd31737f2012-05-09 19:04:00 +0100752 return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100753 }
754 };
755 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100756 struct Evaluator<T1, T2, IsNotEqualTo> {
757 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100758 return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
759 }
760 };
761 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100762 struct Evaluator<T1, T2, IsLessThan> {
763 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100764 return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
765 }
766 };
767 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100768 struct Evaluator<T1, T2, IsGreaterThan> {
769 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100770 return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
771 }
772 };
773 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100774 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
775 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100776 return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
777 }
778 };
779 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100780 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
781 static bool evaluate( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100782 return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
783 }
784 };
785
786 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100787 bool applyEvaluator( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100788 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
789 }
790
791 // "base" overload
792 template<Operator Op, typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100793 bool compare( const T1& lhs, const T2& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100794 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
795 }
796
797 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +0100798 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100799 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
800 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100801 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100802 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
803 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100804 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100805 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
806 }
807
808 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +0100809 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100810 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
811 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100812 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100813 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
814 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100815 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100816 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
817 }
818
819 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100820 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100821 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
822 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100823 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100824 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
825 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100826 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100827 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
828 }
829
830 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +0100831 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300832 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100833 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100834 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300835 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100836 }
Phil Nash89d2a3f2012-05-16 15:09:17 +0100837 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -0300838 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100839 }
840
Phil Nash06e959b2012-05-25 08:52:05 +0100841 // pointer to long (when comparing against NULL)
Phil Nash89d1e6c2011-05-24 08:23:02 +0100842 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100843 bool compare( long lhs, const T* rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100844 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100845 }
846
847 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100848 bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100849 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +0100850 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100851
Phil Nash6f1543b2012-05-07 19:46:19 +0100852 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100853 bool compare( const T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100854 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
855 }
856
857 template<Operator Op, typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100858 bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +0100859 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100860 }
861
Phil Nash06e959b2012-05-25 08:52:05 +0100862 // pointer to int (when comparing against NULL)
863 template<Operator Op, typename T>
864 bool compare( int lhs, const T* rhs ) {
865 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
866 }
867
868 template<Operator Op, typename T>
869 bool compare( int lhs, T* rhs ) {
870 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
871 }
872
873 template<Operator Op, typename T>
874 bool compare( const T* lhs, int rhs ) {
875 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
876 }
877
878 template<Operator Op, typename T>
879 bool compare( T* lhs, int rhs ) {
880 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
881 }
882
Phil Nash89d1e6c2011-05-24 08:23:02 +0100883} // end of namespace Internal
884} // end of namespace Catch
885
Phil Nash89d2a3f2012-05-16 15:09:17 +0100886namespace Catch {
Phil Nashf51d3162011-12-28 10:37:31 +0000887
Phil Nash89d1e6c2011-05-24 08:23:02 +0100888struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
889
Phil Nash67305122012-10-09 11:48:55 +0100890class ResultInfoBuilder {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100891public:
892
Phil Nash3b80af72012-08-09 07:47:30 +0100893 ResultInfoBuilder();
Phil Nashd31737f2012-05-09 19:04:00 +0100894
Phil Nash803f6b72012-10-04 08:14:48 +0100895 ResultInfoBuilder& setResultType( ResultWas::OfType result );
Phil Nash67305122012-10-09 11:48:55 +0100896 ResultInfoBuilder& setCapturedExpression( const std::string& capturedExpression );
897 ResultInfoBuilder& setIsFalse( bool isFalse );
Phil Nash803f6b72012-10-04 08:14:48 +0100898 ResultInfoBuilder& setMessage( const std::string& message );
899 ResultInfoBuilder& setLineInfo( const SourceLineInfo& lineInfo );
900 ResultInfoBuilder& setLhs( const std::string& lhs );
901 ResultInfoBuilder& setRhs( const std::string& rhs );
902 ResultInfoBuilder& setOp( const std::string& op );
903 ResultInfoBuilder& setMacroName( const std::string& macroName );
Phil Nash78d95a02012-03-04 21:22:36 +0000904
Phil Nash67305122012-10-09 11:48:55 +0100905 std::string reconstructExpression() const;
906
907 ResultInfo build() const;
908
909 // Disable attempts to use || and && in expressions (without parantheses)
Phil Nash89d1e6c2011-05-24 08:23:02 +0100910 template<typename RhsT>
Phil Nash803f6b72012-10-04 08:14:48 +0100911 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( const RhsT& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100912 template<typename RhsT>
Phil Nash803f6b72012-10-04 08:14:48 +0100913 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( const RhsT& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100914
Phil Nash67305122012-10-09 11:48:55 +0100915 bool getIsFalse() const {
916 return m_isNot;
917 }
918
Phil Nash89d1e6c2011-05-24 08:23:02 +0100919private:
Phil Nash67305122012-10-09 11:48:55 +0100920 ResultData m_data;
921 std::string m_lhs, m_rhs, m_op;
922 bool m_isNot;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100923};
924
Phil Nash67305122012-10-09 11:48:55 +0100925template<Internal::Operator Op, typename T1, typename T2>
926ResultInfoBuilder& captureExpression( ResultInfoBuilder& builder, const T1& lhs, const T2& rhs ) {
927 return builder
928 .setResultType( Internal::compare<Op>( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed )
929 .setLhs( Catch::toString( lhs ) )
930 .setRhs( Catch::toString( rhs ) )
931 .setOp( Internal::OperatorTraits<Op>::getName() );
932}
933
934template<Internal::Operator Op, typename T>
935ResultInfoBuilder& captureExpression( ResultInfoBuilder& builder, const T* lhs, int rhs ) {
936 return captureExpression<Op>( builder, lhs, reinterpret_cast<const T*>( rhs ) );
937}
938
Phil Nashd31737f2012-05-09 19:04:00 +0100939} // end namespace Catch
940
Phil Nash89d2a3f2012-05-16 15:09:17 +0100941namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +0100942
943template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100944class Expression {
Phil Nash176eb812012-05-11 08:17:16 +0100945 void operator = ( const Expression& );
946
947public:
948 Expression( ResultInfoBuilder& result, T lhs )
949 : m_result( result ),
950 m_lhs( lhs )
951 {}
952
953 template<typename RhsT>
954 ResultInfoBuilder& operator == ( const RhsT& rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100955 return captureExpression<Internal::IsEqualTo>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100956 }
957
958 template<typename RhsT>
959 ResultInfoBuilder& operator != ( const RhsT& rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100960 return captureExpression<Internal::IsNotEqualTo>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100961 }
962
963 template<typename RhsT>
964 ResultInfoBuilder& operator < ( const RhsT& rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100965 return captureExpression<Internal::IsLessThan>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100966 }
967
968 template<typename RhsT>
969 ResultInfoBuilder& operator > ( const RhsT& rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100970 return captureExpression<Internal::IsGreaterThan>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100971 }
972
973 template<typename RhsT>
974 ResultInfoBuilder& operator <= ( const RhsT& rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100975 return captureExpression<Internal::IsLessThanOrEqualTo>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100976 }
977
978 template<typename RhsT>
979 ResultInfoBuilder& operator >= ( const RhsT& rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100980 return captureExpression<Internal::IsGreaterThanOrEqualTo>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100981 }
982
983 ResultInfoBuilder& operator == ( bool rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100984 return captureExpression<Internal::IsEqualTo>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100985 }
986
987 ResultInfoBuilder& operator != ( bool rhs ) {
Phil Nash67305122012-10-09 11:48:55 +0100988 return captureExpression<Internal::IsNotEqualTo>( m_result, m_lhs, rhs );
Phil Nash176eb812012-05-11 08:17:16 +0100989 }
990
991 operator ResultInfoBuilder& () {
Phil Nash67305122012-10-09 11:48:55 +0100992 return m_result
993 .setLhs( Catch::toString( m_lhs ) )
994 .setOp( "" )
995 .setResultType( m_lhs ? ResultWas::Ok : ResultWas::ExpressionFailed );
Phil Nash176eb812012-05-11 08:17:16 +0100996 }
997
998 template<typename RhsT>
999 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( const RhsT& );
1000
1001 template<typename RhsT>
1002 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( const RhsT& );
1003
1004private:
1005 ResultInfoBuilder& m_result;
1006 T m_lhs;
1007};
1008
Phil Nash176eb812012-05-11 08:17:16 +01001009} // end namespace Catch
1010
Phil Nash89d2a3f2012-05-16 15:09:17 +01001011#include <sstream>
1012
1013namespace Catch {
1014
1015class ExpressionBuilder {
1016public:
1017
1018 ExpressionBuilder( const SourceLineInfo& lineInfo,
1019 const char* macroName,
1020 const char* expr = "",
1021 bool isNot = false )
Phil Nash67305122012-10-09 11:48:55 +01001022 : m_messageStream()
1023 {
1024 m_result
1025 .setCapturedExpression( expr )
1026 .setIsFalse( isNot )
1027 .setLineInfo( lineInfo )
1028 .setMacroName( macroName );
1029 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001030
1031 template<typename T>
1032 Expression<const T&> operator->* ( const T & operand ) {
1033 Expression<const T&> expr( m_result, operand );
1034 return expr;
1035 }
1036
Phil Nash89d2a3f2012-05-16 15:09:17 +01001037 Expression<bool> operator->* ( bool value ) {
1038 Expression<bool> expr( m_result, value );
1039 return expr;
1040 }
1041
1042 template<typename T>
1043 ExpressionBuilder& operator << ( const T & value ) {
1044 m_messageStream << Catch::toString( value );
1045 return *this;
1046 }
1047
1048 template<typename MatcherT, typename ArgT>
1049 ExpressionBuilder& acceptMatcher( const MatcherT& matcher,
1050 const ArgT& arg,
1051 const std::string& matcherCallAsString ) {
1052 std::string matcherAsString = Catch::toString( matcher );
1053 if( matcherAsString == "{?}" )
1054 matcherAsString = matcherCallAsString;
Phil Nash67305122012-10-09 11:48:55 +01001055 m_result
1056 .setLhs( Catch::toString( arg ) )
1057 .setRhs( matcherAsString )
1058 .setOp( "matches" )
1059 .setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001060 return *this;
1061 }
1062
1063 template<typename MatcherT, typename ArgT>
1064 ExpressionBuilder& acceptMatcher( const MatcherT& matcher,
1065 ArgT* arg,
1066 const std::string& matcherCallAsString ) {
1067 std::string matcherAsString = Catch::toString( matcher );
1068 if( matcherAsString == "{?}" )
1069 matcherAsString = matcherCallAsString;
Phil Nash67305122012-10-09 11:48:55 +01001070 m_result
1071 .setLhs( Catch::toString( arg ) )
1072 .setRhs( matcherAsString )
1073 .setOp( "matches" )
1074 .setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001075 return *this;
1076 }
1077
1078 ExpressionBuilder& setResultType( ResultWas::OfType resultType ) {
1079 m_result.setResultType( resultType );
1080 return *this;
1081 }
1082
1083 operator ResultInfoBuilder&() {
1084 m_result.setMessage( m_messageStream.str() );
1085 return m_result;
1086 }
1087
1088private:
1089 ResultInfoBuilder m_result;
1090 std::ostringstream m_messageStream;
1091};
1092
1093} // end namespace Catch
1094
Phil Nashd31737f2012-05-09 19:04:00 +01001095// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001096#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001097
Phil Nashd31737f2012-05-09 19:04:00 +01001098#include <string>
Phil Nasha70fbe32012-08-31 08:10:36 +01001099// #included from: catch_totals.hpp
1100#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1101
Phil Nash9e7e63c2012-09-29 20:54:03 +01001102#include <cstddef>
1103
Phil Nasha70fbe32012-08-31 08:10:36 +01001104namespace Catch {
1105
1106 struct Counts {
1107 Counts() : passed( 0 ), failed( 0 ) {}
1108
1109 Counts operator - ( const Counts& other ) const {
1110 Counts diff;
1111 diff.passed = passed - other.passed;
1112 diff.failed = failed - other.failed;
1113 return diff;
1114 }
1115 Counts& operator += ( const Counts& other ) {
1116 passed += other.passed;
1117 failed += other.failed;
1118 return *this;
1119 }
1120
1121 std::size_t total() const {
1122 return passed + failed;
1123 }
1124
1125 std::size_t passed;
1126 std::size_t failed;
1127 };
1128
1129 struct Totals {
1130
1131 Totals operator - ( const Totals& other ) const {
1132 Totals diff;
1133 diff.assertions = assertions - other.assertions;
1134 diff.testCases = testCases - other.testCases;
1135 return diff;
1136 }
1137
1138 Totals delta( const Totals& prevTotals ) const {
1139 Totals diff = *this - prevTotals;
1140 if( diff.assertions.failed > 0 )
1141 ++diff.testCases.failed;
1142 else
1143 ++diff.testCases.passed;
1144 return diff;
1145 }
1146
1147 Totals& operator += ( const Totals& other ) {
1148 assertions += other.assertions;
1149 testCases += other.testCases;
1150 return *this;
1151 }
1152
1153 Counts assertions;
1154 Counts testCases;
1155 };
1156}
1157
Phil Nashd31737f2012-05-09 19:04:00 +01001158
Phil Nash89d2a3f2012-05-16 15:09:17 +01001159namespace Catch {
1160
Phil Nashd31737f2012-05-09 19:04:00 +01001161 class TestCaseInfo;
1162 class ScopedInfo;
1163 class ResultInfoBuilder;
1164 class ResultInfo;
1165
Phil Nash89d2a3f2012-05-16 15:09:17 +01001166 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001167
Phil Nasha695eb92012-08-13 07:46:10 +01001168 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001169
Phil Nash89d2a3f2012-05-16 15:09:17 +01001170 virtual void testEnded( const ResultInfo& result ) = 0;
1171 virtual bool sectionStarted( const std::string& name,
1172 const std::string& description,
1173 const SourceLineInfo& lineInfo,
1174 Counts& assertions ) = 0;
1175 virtual void sectionEnded( const std::string& name, const Counts& assertions ) = 0;
1176 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0;
1177 virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0;
1178 virtual bool shouldDebugBreak() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001179
Phil Nash89d2a3f2012-05-16 15:09:17 +01001180 virtual ResultAction::Value acceptResult( bool result ) = 0;
1181 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) = 0;
1182 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) = 0;
1183 virtual void acceptMessage( const std::string& msg ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001184
Phil Nash89d2a3f2012-05-16 15:09:17 +01001185 virtual std::string getCurrentTestName() const = 0;
1186 virtual const ResultInfo* getLastResult() const = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001187 };
1188}
1189
1190// #included from: catch_debugger.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001191#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001192
Phil Nashd31737f2012-05-09 19:04:00 +01001193#include <iostream>
1194
1195#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1196#define CATCH_PLATFORM_MAC
1197#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1198#define CATCH_PLATFORM_IPHONE
1199#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1200#define CATCH_PLATFORM_WINDOWS
1201#endif
1202
1203#ifdef CATCH_PLATFORM_MAC
1204
1205 #include <assert.h>
1206 #include <stdbool.h>
1207 #include <sys/types.h>
1208 #include <unistd.h>
1209 #include <sys/sysctl.h>
1210
Phil Nash89d2a3f2012-05-16 15:09:17 +01001211 namespace Catch{
1212
Phil Nashd31737f2012-05-09 19:04:00 +01001213 // The following function is taken directly from the following technical note:
1214 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
1215
Phil Nashd31737f2012-05-09 19:04:00 +01001216 // Returns true if the current process is being debugged (either
1217 // running under the debugger or has a debugger attached post facto).
Phil Nash89d2a3f2012-05-16 15:09:17 +01001218 inline bool isDebuggerActive(){
1219
Phil Nashd31737f2012-05-09 19:04:00 +01001220 int junk;
1221 int mib[4];
1222 struct kinfo_proc info;
1223 size_t size;
1224
1225 // Initialize the flags so that, if sysctl fails for some bizarre
1226 // reason, we get a predictable result.
1227
1228 info.kp_proc.p_flag = 0;
1229
1230 // Initialize mib, which tells sysctl the info we want, in this case
1231 // we're looking for information about a specific process ID.
1232
1233 mib[0] = CTL_KERN;
1234 mib[1] = KERN_PROC;
1235 mib[2] = KERN_PROC_PID;
1236 mib[3] = getpid();
1237
1238 // Call sysctl.
1239
1240 size = sizeof(info);
1241 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1242 assert(junk == 0);
1243
1244 // We're being debugged if the P_TRACED flag is set.
1245
1246 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1247 }
1248 }
1249
1250 // The following code snippet taken from:
1251 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1252 #ifdef DEBUG
1253 #if defined(__ppc64__) || defined(__ppc__)
1254 #define BreakIntoDebugger() \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001255 if( Catch::isDebuggerActive() ) { \
Phil Nashd31737f2012-05-09 19:04:00 +01001256 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1257 : : : "memory","r0","r3","r4" ); \
1258 }
1259 #else
1260 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1261 #endif
1262 #else
1263 inline void BreakIntoDebugger(){}
1264 #endif
1265
1266#elif defined(_MSC_VER)
1267 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1268 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001269 inline bool isDebuggerActive() {
Phil Nashd31737f2012-05-09 19:04:00 +01001270 return IsDebuggerPresent() != 0;
1271 }
Phil Nash176eb812012-05-11 08:17:16 +01001272#elif defined(__MINGW32__)
1273 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1274 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
1275 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001276 inline bool isDebuggerActive() {
Phil Nash176eb812012-05-11 08:17:16 +01001277 return IsDebuggerPresent() != 0;
1278 }
Phil Nashd31737f2012-05-09 19:04:00 +01001279#else
1280 inline void BreakIntoDebugger(){}
1281 inline bool isDebuggerActive() { return false; }
1282#endif
1283
1284#ifdef CATCH_PLATFORM_WINDOWS
1285extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001286inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001287 ::OutputDebugStringA( text.c_str() );
1288}
1289#else
Phil Nash89d2a3f2012-05-16 15:09:17 +01001290inline void writeToDebugConsole( const std::string& text ) {
Phil Nashd31737f2012-05-09 19:04:00 +01001291 // !TBD: Need a version for Mac/ XCode and other IDEs
1292 std::cout << text;
1293}
1294#endif // CATCH_PLATFORM_WINDOWS
1295
Phil Nash89d2a3f2012-05-16 15:09:17 +01001296#include <ostream>
Phil Nashd31737f2012-05-09 19:04:00 +01001297
Phil Nash89d2a3f2012-05-16 15:09:17 +01001298namespace Catch {
Phil Nashd31737f2012-05-09 19:04:00 +01001299
1300struct TestFailureException{};
Phil Nashd31737f2012-05-09 19:04:00 +01001301
Phil Nash89d2a3f2012-05-16 15:09:17 +01001302class ScopedInfo {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001303public:
Phil Nashd31737f2012-05-09 19:04:00 +01001304 ScopedInfo() : m_oss() {
Phil Nash371db8b2012-05-21 18:52:09 +01001305 getCurrentContext().getResultCapture().pushScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001306 }
1307
Phil Nashd31737f2012-05-09 19:04:00 +01001308 ~ScopedInfo() {
Phil Nash371db8b2012-05-21 18:52:09 +01001309 getCurrentContext().getResultCapture().popScopedInfo( this );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001310 }
1311
Phil Nashd31737f2012-05-09 19:04:00 +01001312 template<typename T>
1313 ScopedInfo& operator << ( const T& value ) {
1314 m_oss << value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001315 return *this;
1316 }
1317
Phil Nash799ecf92012-09-24 08:30:13 +01001318 ResultInfo getInfo () const {
Phil Nash803f6b72012-10-04 08:14:48 +01001319 return ResultInfoBuilder()
1320 .setResultType( ResultWas::Info )
1321 .setMessage( m_oss.str() )
Phil Nash67305122012-10-09 11:48:55 +01001322 .setMacroName( "SCOPED_INFO" )
1323 .build();
Phil Nash89d1e6c2011-05-24 08:23:02 +01001324 }
1325
1326private:
1327 std::ostringstream m_oss;
1328};
1329
Phil Nash89d1e6c2011-05-24 08:23:02 +01001330// This is just here to avoid compiler warnings with macro constants
Phil Nashd31737f2012-05-09 19:04:00 +01001331inline bool isTrue( bool value ){ return value; }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001332
1333} // end namespace Catch
1334
1335///////////////////////////////////////////////////////////////////////////////
Phil Nashd31737f2012-05-09 19:04:00 +01001336#define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \
Phil Nashe4636872012-06-05 20:51:05 +01001337 if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) { \
Phil Nash19b2aa62012-06-01 19:40:27 +01001338 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
1339 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001340 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
Phil Nashd31737f2012-05-09 19:04:00 +01001341 if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001342 }
1343
1344///////////////////////////////////////////////////////////////////////////////
1345#define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001346 do { try { \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001347 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr, isNot )->*expr ), stopOnFailure, expr ); \
Phil Nashe4636872012-06-05 20:51:05 +01001348 } catch( Catch::TestFailureException& ) { \
Phil Nash333e6e62012-02-17 19:50:59 +00001349 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001350 } catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001351 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \
Phil Nash333e6e62012-02-17 19:50:59 +00001352 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001353 } } while( Catch::isTrue( false ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001354
1355///////////////////////////////////////////////////////////////////////////////
Phil Nasha162e222012-02-10 08:30:13 +00001356#define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \
1357 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
Phil Nash371db8b2012-05-21 18:52:09 +01001358 if( Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001359
1360///////////////////////////////////////////////////////////////////////////////
1361#define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \
1362 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
Phil Nash371db8b2012-05-21 18:52:09 +01001363 if( !Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
Phil Nasha162e222012-02-10 08:30:13 +00001364
1365///////////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001366#define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001367 try { \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001368 expr; \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001369 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001370 } \
Phil Nashe4636872012-06-05 20:51:05 +01001371 catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001372 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001373 }
1374
1375///////////////////////////////////////////////////////////////////////////////
1376#define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001377 try { \
1378 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1379 expr; \
1380 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \
1381 } \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001382 } \
Phil Nashe4636872012-06-05 20:51:05 +01001383 catch( Catch::TestFailureException& ) { \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001384 throw; \
1385 } \
Phil Nashe4636872012-06-05 20:51:05 +01001386 catch( exceptionType ) { \
Phil Nash89d2a3f2012-05-16 15:09:17 +01001387 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001388 }
1389
1390///////////////////////////////////////////////////////////////////////////////
1391#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1392 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001393 catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001394 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001395 }
1396
1397///////////////////////////////////////////////////////////////////////////////
1398#define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
Phil Nash371db8b2012-05-21 18:52:09 +01001399 Catch::getCurrentContext().getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001400
1401///////////////////////////////////////////////////////////////////////////////
1402#define INTERNAL_CATCH_SCOPED_INFO( log ) \
1403 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1404 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1405
Phil Nash78d95a02012-03-04 21:22:36 +00001406///////////////////////////////////////////////////////////////////////////////
1407#define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \
Phil Nashe4636872012-06-05 20:51:05 +01001408 do { try { \
Phil Nasha8570df2012-05-24 08:29:41 +01001409 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher, false ).acceptMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), stopOnFailure, false ); \
Phil Nashe4636872012-06-05 20:51:05 +01001410 } catch( Catch::TestFailureException& ) { \
Phil Nash78d95a02012-03-04 21:22:36 +00001411 throw; \
Phil Nashe4636872012-06-05 20:51:05 +01001412 } catch( ... ) { \
Phil Nash3b80af72012-08-09 07:47:30 +01001413 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \
Phil Nash78d95a02012-03-04 21:22:36 +00001414 throw; \
1415 }}while( Catch::isTrue( false ) )
1416
Phil Nash89d1e6c2011-05-24 08:23:02 +01001417// #included from: internal/catch_section.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001418#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001419
Phil Nash89d1e6c2011-05-24 08:23:02 +01001420#include <string>
1421
Phil Nash89d2a3f2012-05-16 15:09:17 +01001422namespace Catch {
1423
1424 class Section {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001425 public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001426 Section( const std::string& name,
1427 const std::string& description,
1428 const SourceLineInfo& lineInfo )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001429 : m_name( name ),
Phil Nash371db8b2012-05-21 18:52:09 +01001430 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) )
Phil Nash89d2a3f2012-05-16 15:09:17 +01001431 {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001432
Phil Nash89d2a3f2012-05-16 15:09:17 +01001433 ~Section() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001434 if( m_sectionIncluded )
Phil Nash371db8b2012-05-21 18:52:09 +01001435 getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001436 }
1437
Phil Nash89d1e6c2011-05-24 08:23:02 +01001438 // This indicates whether the section should be executed or not
Phil Nash89d2a3f2012-05-16 15:09:17 +01001439 operator bool() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001440 return m_sectionIncluded;
1441 }
1442
1443 private:
1444
1445 std::string m_name;
Phil Nashf7299fc2012-02-25 09:39:45 +00001446 Counts m_assertions;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001447 bool m_sectionIncluded;
1448 };
1449
1450} // end namespace Catch
1451
1452#define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashd31737f2012-05-09 19:04:00 +01001453 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001454
1455// #included from: internal/catch_generators.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001456#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001457
Phil Nash89d1e6c2011-05-24 08:23:02 +01001458#include <iterator>
1459#include <vector>
1460#include <string>
1461#include <stdlib.h>
1462
Phil Nash89d2a3f2012-05-16 15:09:17 +01001463namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001464
1465template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001466struct IGenerator {
1467 virtual ~IGenerator() {}
1468 virtual T getValue( std::size_t index ) const = 0;
1469 virtual std::size_t size () const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001470};
1471
1472template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001473class BetweenGenerator : public IGenerator<T> {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001474public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001475 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001476
Phil Nash89d2a3f2012-05-16 15:09:17 +01001477 virtual T getValue( std::size_t index ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001478 return m_from+static_cast<T>( index );
1479 }
1480
Phil Nash89d2a3f2012-05-16 15:09:17 +01001481 virtual std::size_t size() const {
Phil Nashd31737f2012-05-09 19:04:00 +01001482 return static_cast<std::size_t>( 1+m_to-m_from );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001483 }
1484
1485private:
1486
1487 T m_from;
1488 T m_to;
1489};
1490
1491template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001492class ValuesGenerator : public IGenerator<T> {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001493public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001494 ValuesGenerator(){}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001495
Phil Nash89d2a3f2012-05-16 15:09:17 +01001496 void add( T value ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001497 m_values.push_back( value );
1498 }
1499
Phil Nash89d2a3f2012-05-16 15:09:17 +01001500 virtual T getValue( std::size_t index ) const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001501 return m_values[index];
1502 }
1503
Phil Nash89d2a3f2012-05-16 15:09:17 +01001504 virtual std::size_t size() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001505 return m_values.size();
1506 }
1507
1508private:
Phil Nash89d1e6c2011-05-24 08:23:02 +01001509 std::vector<T> m_values;
1510};
1511
1512template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001513class CompositeGenerator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001514public:
Phil Nash89d2a3f2012-05-16 15:09:17 +01001515 CompositeGenerator() : m_totalSize( 0 ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +01001516
Phil Nash89d1e6c2011-05-24 08:23:02 +01001517 // *** Move semantics, similar to auto_ptr ***
1518 CompositeGenerator( CompositeGenerator& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01001519 : m_fileInfo( other.m_fileInfo ),
1520 m_totalSize( 0 )
Phil Nash89d1e6c2011-05-24 08:23:02 +01001521 {
1522 move( other );
1523 }
1524
Phil Nash89d2a3f2012-05-16 15:09:17 +01001525 CompositeGenerator& setFileInfo( const char* fileInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001526 m_fileInfo = fileInfo;
1527 return *this;
1528 }
1529
Phil Nash89d2a3f2012-05-16 15:09:17 +01001530 ~CompositeGenerator() {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001531 deleteAll( m_composed );
1532 }
1533
Phil Nash89d2a3f2012-05-16 15:09:17 +01001534 operator T () const {
Phil Nash371db8b2012-05-21 18:52:09 +01001535 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001536
1537 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1538 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1539 for( size_t index = 0; it != itEnd; ++it )
1540 {
1541 const IGenerator<T>* generator = *it;
1542 if( overallIndex >= index && overallIndex < index + generator->size() )
1543 {
1544 return generator->getValue( overallIndex-index );
1545 }
1546 index += generator->size();
1547 }
1548 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
1549 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
1550 }
1551
Phil Nash89d2a3f2012-05-16 15:09:17 +01001552 void add( const IGenerator<T>* generator ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001553 m_totalSize += generator->size();
1554 m_composed.push_back( generator );
1555 }
1556
Phil Nash89d2a3f2012-05-16 15:09:17 +01001557 CompositeGenerator& then( CompositeGenerator& other ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001558 move( other );
1559 return *this;
1560 }
1561
Phil Nash89d2a3f2012-05-16 15:09:17 +01001562 CompositeGenerator& then( T value ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001563 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1564 valuesGen->add( value );
1565 add( valuesGen );
1566 return *this;
1567 }
1568
1569private:
1570
Phil Nash89d2a3f2012-05-16 15:09:17 +01001571 void move( CompositeGenerator& other ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001572 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1573 m_totalSize += other.m_totalSize;
1574 other.m_composed.clear();
1575 }
1576
1577 std::vector<const IGenerator<T>*> m_composed;
1578 std::string m_fileInfo;
1579 size_t m_totalSize;
1580};
1581
1582namespace Generators
1583{
Phil Nash89d1e6c2011-05-24 08:23:02 +01001584 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001585 CompositeGenerator<T> between( T from, T to ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001586 CompositeGenerator<T> generators;
1587 generators.add( new BetweenGenerator<T>( from, to ) );
1588 return generators;
1589 }
1590
Phil Nash89d1e6c2011-05-24 08:23:02 +01001591 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001592 CompositeGenerator<T> values( T val1, T val2 ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001593 CompositeGenerator<T> generators;
1594 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1595 valuesGen->add( val1 );
1596 valuesGen->add( val2 );
1597 generators.add( valuesGen );
1598 return generators;
1599 }
1600
Phil Nash89d1e6c2011-05-24 08:23:02 +01001601 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001602 CompositeGenerator<T> values( T val1, T val2, T val3 ){
Phil Nash89d1e6c2011-05-24 08:23:02 +01001603 CompositeGenerator<T> generators;
1604 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1605 valuesGen->add( val1 );
1606 valuesGen->add( val2 );
1607 valuesGen->add( val3 );
1608 generators.add( valuesGen );
1609 return generators;
1610 }
1611
Phil Nash89d1e6c2011-05-24 08:23:02 +01001612 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001613 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001614 CompositeGenerator<T> generators;
1615 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
1616 valuesGen->add( val1 );
1617 valuesGen->add( val2 );
1618 valuesGen->add( val3 );
1619 valuesGen->add( val4 );
1620 generators.add( valuesGen );
1621 return generators;
1622 }
1623
1624} // end namespace Generators
1625
1626using namespace Generators;
1627
1628} // end namespace Catch
1629
1630#define INTERNAL_CATCH_LINESTR2( line ) #line
1631#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
1632
1633#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
1634
1635// #included from: internal/catch_interfaces_exception.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001636#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001637
Phil Nash89d1e6c2011-05-24 08:23:02 +01001638#include <string>
Phil Nash3b80af72012-08-09 07:47:30 +01001639// #included from: catch_interfaces_registry_hub.h
1640#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1641
Phil Nasha70fbe32012-08-31 08:10:36 +01001642// #included from: catch_interfaces_reporter.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001643#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001644
1645// #included from: catch_config.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04001646#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001647
1648// #included from: catch_test_spec.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001649#define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001650
1651// #included from: catch_test_case_info.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04001652#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nasha70fbe32012-08-31 08:10:36 +01001653
1654#include <string>
Phil Nashfc1baac2012-09-15 17:53:27 +01001655#include <set>
Phil Nasha70fbe32012-08-31 08:10:36 +01001656
1657namespace Catch {
1658
1659 struct ITestCase;
1660
1661 class TestCaseInfo {
1662 public:
1663 TestCaseInfo();
1664
1665 TestCaseInfo( ITestCase* testCase,
1666 const char* name,
1667 const char* description,
1668 const SourceLineInfo& lineInfo );
1669
1670 TestCaseInfo( const TestCaseInfo& other, const std::string& name );
1671 TestCaseInfo( const TestCaseInfo& other );
1672
1673 void invoke() const;
1674 const std::string& getName() const;
1675 const std::string& getDescription() const;
1676 const SourceLineInfo& getLineInfo() const;
1677 bool isHidden() const;
Phil Nashfc1baac2012-09-15 17:53:27 +01001678 bool hasTag( const std::string& tag ) const;
Phil Nash799ecf92012-09-24 08:30:13 +01001679 bool matchesTags( const std::string& tagPattern ) const;
Phil Nash67ec8702012-09-26 18:38:26 +01001680 const std::set<std::string>& getTags() const;
Phil Nasha70fbe32012-08-31 08:10:36 +01001681
1682 void swap( TestCaseInfo& other );
1683 bool operator == ( const TestCaseInfo& other ) const;
1684 bool operator < ( const TestCaseInfo& other ) const;
1685 TestCaseInfo& operator = ( const TestCaseInfo& other );
1686
1687 private:
1688 Ptr<ITestCase> m_test;
1689 std::string m_name;
1690 std::string m_description;
Phil Nashfc1baac2012-09-15 17:53:27 +01001691 std::set<std::string> m_tags;
Phil Nasha70fbe32012-08-31 08:10:36 +01001692 SourceLineInfo m_lineInfo;
Phil Nashfc1baac2012-09-15 17:53:27 +01001693 bool m_isHidden;
Phil Nasha70fbe32012-08-31 08:10:36 +01001694 };
1695}
1696
Phil Nash67ec8702012-09-26 18:38:26 +01001697// #included from: catch_tags.hpp
1698#define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
1699
1700#include <string>
1701#include <set>
1702#include <map>
1703#include <vector>
1704
1705#ifdef __clang__
1706#pragma clang diagnostic ignored "-Wpadded"
1707#endif
1708
1709namespace Catch {
1710 class TagParser {
1711 public:
1712 virtual ~TagParser();
1713
1714 void parse( const std::string& str ) {
1715 std::size_t pos = 0;
1716 while( pos < str.size() ) {
1717 char c = str[pos];
1718 if( c == '[' ) {
1719 std::size_t end = str.find_first_of( ']', pos );
1720 if( end != std::string::npos ) {
1721 acceptTag( str.substr( pos+1, end-pos-1 ) );
1722 pos = end+1;
1723 }
1724 else {
1725 acceptChar( c );
1726 pos++;
1727 }
1728 }
1729 else {
1730 acceptChar( c );
1731 pos++;
1732 }
1733 }
1734 endParse();
1735 }
1736
1737 protected:
1738 virtual void acceptTag( const std::string& tag ) = 0;
1739 virtual void acceptChar( char c ) = 0;
1740 virtual void endParse() {}
1741
1742 private:
1743 };
1744
1745 class TagExtracter : public TagParser {
1746 public:
1747
1748 TagExtracter( std::set<std::string>& tags )
1749 : m_tags( tags )
1750 {}
1751 virtual ~TagExtracter();
1752
1753 void parse( std::string& description ) {
1754 TagParser::parse( description );
1755 description = m_remainder;
1756 }
1757
1758 private:
1759 virtual void acceptTag( const std::string& tag ) {
1760 m_tags.insert( tag );
1761 }
1762 virtual void acceptChar( char c ) {
1763 m_remainder += c;
1764 }
1765
1766 std::set<std::string>& m_tags;
1767 std::string m_remainder;
1768 };
1769
1770 class Tag {
1771 public:
1772 Tag()
1773 : m_isNegated( false )
1774 {}
1775
1776 Tag( const std::string& name, bool isNegated )
1777 : m_name( name ),
1778 m_isNegated( isNegated )
1779 {}
1780
1781 std::string getName() const {
1782 return m_name;
1783 }
1784 bool isNegated() const {
1785 return m_isNegated;
1786 }
1787
1788 bool operator ! () const {
1789 return m_name.empty();
1790 }
1791
1792 private:
1793 std::string m_name;
1794 bool m_isNegated;
1795 };
1796
1797 class TagSet {
1798 typedef std::map<std::string, Tag> TagMap;
1799 public:
1800 void add( const Tag& tag ) {
1801 m_tags.insert( std::make_pair( tag.getName(), tag ) );
1802 }
1803
Phil Nash67ec8702012-09-26 18:38:26 +01001804 bool empty() const {
1805 return m_tags.empty();
1806 }
1807
1808 bool matches( const std::set<std::string>& tags ) const {
1809 TagMap::const_iterator it = m_tags.begin();
1810 TagMap::const_iterator itEnd = m_tags.end();
1811 for(; it != itEnd; ++it ) {
1812 bool found = tags.find( it->first ) != tags.end();
1813 if( found == it->second.isNegated() )
1814 return false;
1815 }
1816 return true;
1817 }
1818
1819 private:
1820 TagMap m_tags;
1821 };
1822
1823 class TagExpression {
1824 public:
1825 bool matches( const std::set<std::string>& tags ) const {
1826 std::vector<TagSet>::const_iterator it = m_tagSets.begin();
1827 std::vector<TagSet>::const_iterator itEnd = m_tagSets.end();
1828 for(; it != itEnd; ++it )
1829 if( it->matches( tags ) )
1830 return true;
1831 return false;
1832 }
1833
1834 private:
1835 friend class TagExpressionParser;
1836
1837 std::vector<TagSet> m_tagSets;
1838 };
1839
1840 class TagExpressionParser : public TagParser {
1841 public:
1842 TagExpressionParser( TagExpression& exp )
1843 : m_isNegated( false ),
1844 m_exp( exp )
1845 {}
1846
1847 ~TagExpressionParser();
1848
1849 private:
1850 virtual void acceptTag( const std::string& tag ) {
1851 m_currentTagSet.add( Tag( tag, m_isNegated ) );
1852 m_isNegated = false;
1853 }
1854 virtual void acceptChar( char c ) {
1855 switch( c ) {
1856 case '~':
1857 m_isNegated = true;
1858 break;
1859 case ',':
1860 m_exp.m_tagSets.push_back( m_currentTagSet );
1861 break;
1862 }
1863 }
1864 virtual void endParse() {
1865 if( !m_currentTagSet.empty() )
1866 m_exp.m_tagSets.push_back( m_currentTagSet );
1867 }
1868
1869 bool m_isNegated;
1870 TagSet m_currentTagSet;
1871 TagExpression& m_exp;
1872 };
1873
1874} // end namespace Catch
1875
Phil Nasha70fbe32012-08-31 08:10:36 +01001876#include <string>
1877#include <vector>
1878
1879namespace Catch {
1880
1881 struct IfFilterMatches{ enum DoWhat {
Phil Nashe2d215e2012-09-07 17:52:35 +01001882 AutoDetectBehaviour,
Phil Nasha70fbe32012-08-31 08:10:36 +01001883 IncludeTests,
1884 ExcludeTests
1885 }; };
1886
1887 class TestCaseFilter {
1888 enum WildcardPosition {
1889 NoWildcard = 0,
1890 WildcardAtStart = 1,
1891 WildcardAtEnd = 2,
1892 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
1893 };
1894
1895 public:
Phil Nashe2d215e2012-09-07 17:52:35 +01001896 TestCaseFilter( const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour )
Phil Nasha70fbe32012-08-31 08:10:36 +01001897 : m_stringToMatch( testSpec ),
1898 m_filterType( matchBehaviour ),
1899 m_wildcardPosition( NoWildcard )
1900 {
Phil Nashe2d215e2012-09-07 17:52:35 +01001901 if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
1902 if( startsWith( m_stringToMatch, "exclude:" ) ) {
1903 m_stringToMatch = m_stringToMatch.substr( 8 );
1904 m_filterType = IfFilterMatches::ExcludeTests;
1905 }
1906 else if( startsWith( m_stringToMatch, "~" ) ) {
1907 m_stringToMatch = m_stringToMatch.substr( 1 );
1908 m_filterType = IfFilterMatches::ExcludeTests;
1909 }
1910 else {
1911 m_filterType = IfFilterMatches::IncludeTests;
1912 }
1913 }
1914
Phil Nasha70fbe32012-08-31 08:10:36 +01001915 if( m_stringToMatch[0] == '*' ) {
1916 m_stringToMatch = m_stringToMatch.substr( 1 );
1917 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
1918 }
1919 if( m_stringToMatch[m_stringToMatch.size()-1] == '*' ) {
1920 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
1921 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
1922 }
1923 }
1924
1925 IfFilterMatches::DoWhat getFilterType() const {
1926 return m_filterType;
1927 }
1928
1929 bool shouldInclude( const TestCaseInfo& testCase ) const {
1930 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
1931 }
1932 private:
1933
1934#ifdef __clang__
1935#pragma clang diagnostic push
1936#pragma clang diagnostic ignored "-Wunreachable-code"
1937#endif
1938
1939 bool isMatch( const TestCaseInfo& testCase ) const {
1940 const std::string& name = testCase.getName();
1941
1942 switch( m_wildcardPosition ) {
1943 case NoWildcard:
1944 return m_stringToMatch == name;
1945 case WildcardAtStart:
1946 return endsWith( name, m_stringToMatch );
1947 case WildcardAtEnd:
1948 return startsWith( name, m_stringToMatch );
1949 case WildcardAtBothEnds:
1950 return contains( name, m_stringToMatch );
1951 }
1952 throw std::logic_error( "Unhandled wildcard type" );
1953 }
1954
1955#ifdef __clang__
1956#pragma clang diagnostic pop
1957#endif
1958
1959 std::string m_stringToMatch;
1960 IfFilterMatches::DoWhat m_filterType;
1961 WildcardPosition m_wildcardPosition;
1962 };
1963
1964 class TestCaseFilters {
1965 public:
1966 TestCaseFilters( const std::string& name ) : m_name( name ) {}
1967
1968 std::string getName() const {
1969 return m_name;
1970 }
1971
1972 void addFilter( const TestCaseFilter& filter ) {
1973 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
1974 m_exclusionFilters.push_back( filter );
1975 else
1976 m_inclusionFilters.push_back( filter );
1977 }
1978
Phil Nash67ec8702012-09-26 18:38:26 +01001979 void addTags( const std::string& tagPattern ) {
1980 TagExpression exp;
1981 TagExpressionParser( exp ).parse( tagPattern );
1982
1983 m_tagExpressions.push_back( exp );
1984 }
1985
Phil Nasha70fbe32012-08-31 08:10:36 +01001986 bool shouldInclude( const TestCaseInfo& testCase ) const {
Phil Nash67ec8702012-09-26 18:38:26 +01001987 if( !m_tagExpressions.empty() ) {
1988 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
1989 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
1990 for(; it != itEnd; ++it )
1991 if( it->matches( testCase.getTags() ) )
1992 break;
1993 if( it == itEnd )
1994 return false;
1995 }
1996
Phil Nasha70fbe32012-08-31 08:10:36 +01001997 if( !m_inclusionFilters.empty() ) {
1998 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
1999 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
2000 for(; it != itEnd; ++it )
2001 if( it->shouldInclude( testCase ) )
2002 break;
2003 if( it == itEnd )
2004 return false;
2005 }
Phil Nash67ec8702012-09-26 18:38:26 +01002006 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
Phil Nashfc1baac2012-09-15 17:53:27 +01002007 return !testCase.isHidden();
2008 }
2009
Phil Nasha70fbe32012-08-31 08:10:36 +01002010 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
2011 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
2012 for(; it != itEnd; ++it )
2013 if( !it->shouldInclude( testCase ) )
2014 return false;
2015 return true;
2016 }
2017 private:
Phil Nash67ec8702012-09-26 18:38:26 +01002018 std::vector<TagExpression> m_tagExpressions;
Phil Nasha70fbe32012-08-31 08:10:36 +01002019 std::vector<TestCaseFilter> m_inclusionFilters;
2020 std::vector<TestCaseFilter> m_exclusionFilters;
2021 std::string m_name;
2022 };
2023
2024}
2025
2026// #included from: catch_interfaces_config.h
2027#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
2028
2029namespace Catch {
2030
2031 struct IConfig {
2032
2033 virtual ~IConfig();
2034
2035 virtual bool allowThrows() const = 0;
2036 };
2037}
2038
Phil Nash67ec8702012-09-26 18:38:26 +01002039// #included from: catch_stream.hpp
2040#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
2041
Phil Nash9e7e63c2012-09-29 20:54:03 +01002042// #included from: catch_streambuf.h
2043#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
2044
2045#include <streambuf>
2046
2047namespace Catch {
2048
2049 class StreamBufBase : public std::streambuf {
2050 public:
2051 virtual ~StreamBufBase();
2052 };
2053}
2054
Phil Nash67ec8702012-09-26 18:38:26 +01002055#include <stdexcept>
2056#include <cstdio>
2057
2058namespace Catch {
2059
2060 template<typename WriterF, size_t bufferSize=256>
2061 class StreamBufImpl : public StreamBufBase {
2062 char data[bufferSize];
2063 WriterF m_writer;
2064
2065 public:
2066 StreamBufImpl() {
2067 setp( data, data + sizeof(data) );
2068 }
2069
2070 ~StreamBufImpl() {
2071 sync();
2072 }
2073
2074 private:
2075 int overflow( int c ) {
2076 sync();
2077
2078 if( c != EOF ) {
2079 if( pbase() == epptr() )
2080 m_writer( std::string( 1, static_cast<char>( c ) ) );
2081 else
2082 sputc( static_cast<char>( c ) );
2083 }
2084 return 0;
2085 }
2086
2087 int sync() {
2088 if( pbase() != pptr() ) {
2089 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
2090 setp( pbase(), epptr() );
2091 }
2092 return 0;
2093 }
2094 };
2095
2096 ///////////////////////////////////////////////////////////////////////////
2097
2098 struct OutputDebugWriter {
2099
2100 void operator()( const std::string &str ) {
2101 writeToDebugConsole( str );
2102 }
2103 };
2104
2105 class Stream {
2106 public:
2107 Stream()
2108 : streamBuf( NULL ), isOwned( false )
2109 {}
2110
2111 Stream( std::streambuf* _streamBuf, bool _isOwned )
2112 : streamBuf( _streamBuf ), isOwned( _isOwned )
2113 {}
2114
2115 void release() {
2116 if( isOwned ) {
2117 delete streamBuf;
2118 streamBuf = NULL;
2119 isOwned = false;
2120 }
2121 }
2122
2123 std::streambuf* streamBuf;
2124
2125 private:
2126 bool isOwned;
2127 };
2128}
2129
Phil Nasha70fbe32012-08-31 08:10:36 +01002130#include <memory>
2131#include <vector>
2132#include <string>
2133#include <iostream>
2134
2135namespace Catch {
2136
2137 struct Include { enum WhichResults {
2138 FailedOnly,
2139 SuccessfulResults
2140 }; };
2141
2142 struct List{ enum What {
2143 None = 0,
2144
2145 Reports = 1,
2146 Tests = 2,
2147 All = 3,
2148
2149 TestNames = 6,
2150
2151 WhatMask = 0xf,
2152
2153 AsText = 0x10,
2154 AsXml = 0x20,
2155
2156 AsMask = 0xf0
2157 }; };
2158
2159 struct ConfigData {
2160
2161 struct WarnAbout { enum What {
2162 Nothing = 0x00,
2163 NoAssertions = 0x01
2164 }; };
2165
2166 ConfigData()
2167 : listSpec( List::None ),
2168 shouldDebugBreak( false ),
2169 includeWhichResults( Include::FailedOnly ),
2170 cutoff( -1 ),
2171 allowThrows( true ),
2172 warnings( WarnAbout::Nothing )
2173 {}
2174
2175 std::string reporter;
2176 std::string outputFilename;
2177 List::What listSpec;
2178 std::vector<TestCaseFilters> filters;
2179 bool shouldDebugBreak;
2180 std::string stream;
2181 Include::WhichResults includeWhichResults;
2182 std::string name;
2183 int cutoff;
2184 bool allowThrows;
2185 WarnAbout::What warnings;
2186 };
2187
2188 class Config : public IConfig {
2189 private:
2190 Config( const Config& other );
2191 Config& operator = ( const Config& other );
2192 virtual void dummy();
2193 public:
2194
2195 Config()
Phil Nash67ec8702012-09-26 18:38:26 +01002196 : m_os( std::cout.rdbuf() )
Phil Nasha70fbe32012-08-31 08:10:36 +01002197 {}
2198
2199 Config( const ConfigData& data )
2200 : m_data( data ),
Phil Nasha70fbe32012-08-31 08:10:36 +01002201 m_os( std::cout.rdbuf() )
2202 {}
2203
2204 virtual ~Config() {
2205 m_os.rdbuf( std::cout.rdbuf() );
Phil Nash67ec8702012-09-26 18:38:26 +01002206 m_stream.release();
Phil Nasha70fbe32012-08-31 08:10:36 +01002207 }
2208
2209 void setFilename( const std::string& filename ) {
2210 m_data.outputFilename = filename;
2211 }
2212
2213 List::What getListSpec( void ) const {
2214 return m_data.listSpec;
2215 }
2216
2217 const std::string& getFilename() const {
2218 return m_data.outputFilename ;
2219 }
2220
2221 List::What listWhat() const {
2222 return static_cast<List::What>( m_data.listSpec & List::WhatMask );
2223 }
2224
2225 List::What listAs() const {
2226 return static_cast<List::What>( m_data.listSpec & List::AsMask );
2227 }
2228
2229 std::string getName() const {
2230 return m_data.name;
2231 }
2232
2233 bool shouldDebugBreak() const {
2234 return m_data.shouldDebugBreak;
2235 }
2236
2237 virtual std::ostream& stream() const {
2238 return m_os;
2239 }
2240
2241 void setStreamBuf( std::streambuf* buf ) {
2242 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2243 }
2244
2245 void useStream( const std::string& streamName ) {
Phil Nash67ec8702012-09-26 18:38:26 +01002246 Stream stream = createStream( streamName );
2247 setStreamBuf( stream.streamBuf );
2248 m_stream.release();
2249 m_stream = stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002250 }
2251
Phil Nashe2d215e2012-09-07 17:52:35 +01002252 void addTestSpec( const std::string& testSpec ) {
2253 TestCaseFilters filters( testSpec );
2254 filters.addFilter( TestCaseFilter( testSpec ) );
2255 m_data.filters.push_back( filters );
2256 }
2257
Phil Nasha70fbe32012-08-31 08:10:36 +01002258 virtual bool includeSuccessfulResults() const {
2259 return m_data.includeWhichResults == Include::SuccessfulResults;
2260 }
2261
2262 int getCutoff() const {
2263 return m_data.cutoff;
2264 }
2265
2266 virtual bool allowThrows() const {
2267 return m_data.allowThrows;
2268 }
2269
2270 const ConfigData& data() const {
2271 return m_data;
2272 }
2273 ConfigData& data() {
2274 return m_data;
2275 }
2276
2277 private:
2278 ConfigData m_data;
2279
2280 // !TBD Move these out of here
Phil Nash67ec8702012-09-26 18:38:26 +01002281 Stream m_stream;
Phil Nasha70fbe32012-08-31 08:10:36 +01002282 mutable std::ostream m_os;
2283 };
2284
2285} // end namespace Catch
2286
2287#include <string>
2288#include <ostream>
2289#include <map>
2290
2291namespace Catch
2292{
2293 struct ReporterConfig
2294 {
2295 ReporterConfig( const std::string& _name,
2296 std::ostream& _stream,
2297 bool _includeSuccessfulResults,
2298 const ConfigData& _fullConfig )
2299 : name( _name ),
2300 stream( _stream ),
2301 includeSuccessfulResults( _includeSuccessfulResults ),
2302 fullConfig( _fullConfig )
2303 {}
2304
Phil Nash799ecf92012-09-24 08:30:13 +01002305 ReporterConfig( const ReporterConfig& other )
2306 : name( other.name ),
2307 stream( other.stream ),
2308 includeSuccessfulResults( other.includeSuccessfulResults ),
2309 fullConfig( other.fullConfig )
2310 {}
2311
Phil Nasha70fbe32012-08-31 08:10:36 +01002312 std::string name;
2313 std::ostream& stream;
2314 bool includeSuccessfulResults;
2315 ConfigData fullConfig;
Phil Nash799ecf92012-09-24 08:30:13 +01002316
2317 private:
2318 void operator=(const ReporterConfig&);
Phil Nasha70fbe32012-08-31 08:10:36 +01002319 };
2320
2321 class TestCaseInfo;
2322 class ResultInfo;
2323
2324 struct IReporter : IShared {
2325 virtual ~IReporter();
2326 virtual bool shouldRedirectStdout() const = 0;
2327 virtual void StartTesting() = 0;
2328 virtual void EndTesting( const Totals& totals ) = 0;
2329 virtual void StartGroup( const std::string& groupName ) = 0;
2330 virtual void EndGroup( const std::string& groupName, const Totals& totals ) = 0;
2331 virtual void StartSection( const std::string& sectionName, const std::string& description ) = 0;
2332 virtual void NoAssertionsInSection( const std::string& sectionName ) = 0;
2333 virtual void NoAssertionsInTestCase( const std::string& testName ) = 0;
2334 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) = 0;
2335 virtual void StartTestCase( const TestCaseInfo& testInfo ) = 0;
2336 virtual void Aborted() = 0;
2337 virtual void EndTestCase( const TestCaseInfo& testInfo, const Totals& totals, const std::string& stdOut, const std::string& stdErr ) = 0;
2338 virtual void Result( const ResultInfo& result ) = 0;
2339 };
2340
2341 struct IReporterFactory {
2342 virtual ~IReporterFactory();
2343 virtual IReporter* create( const ReporterConfig& config ) const = 0;
2344 virtual std::string getDescription() const = 0;
2345 };
2346
2347 struct IReporterRegistry {
2348 typedef std::map<std::string, IReporterFactory*> FactoryMap;
2349
2350 virtual ~IReporterRegistry();
2351 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const = 0;
2352 virtual const FactoryMap& getFactories() const = 0;
2353 };
2354
2355 inline std::string trim( const std::string& str ) {
2356 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
2357 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
2358
2359 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
2360 }
2361}
2362
Phil Nash3b80af72012-08-09 07:47:30 +01002363#include <vector>
Phil Nash3b80af72012-08-09 07:47:30 +01002364
2365namespace Catch {
2366
2367 class TestCaseInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01002368 struct ITestCaseRegistry;
2369 struct IExceptionTranslatorRegistry;
2370 struct IExceptionTranslator;
2371
2372 struct IRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002373 virtual ~IRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01002374
2375 virtual const IReporterRegistry& getReporterRegistry() const = 0;
2376 virtual const ITestCaseRegistry& getTestCaseRegistry() const = 0;
2377 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2378 };
2379
2380 struct IMutableRegistryHub {
Phil Nasha695eb92012-08-13 07:46:10 +01002381 virtual ~IMutableRegistryHub();
Phil Nash3b80af72012-08-09 07:47:30 +01002382 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) = 0;
2383 virtual void registerTest( const TestCaseInfo& testInfo ) = 0;
2384 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2385 };
2386
2387 IRegistryHub& getRegistryHub();
2388 IMutableRegistryHub& getMutableRegistryHub();
2389 void cleanUp();
2390}
2391
Phil Nash89d1e6c2011-05-24 08:23:02 +01002392
Phil Nash89d2a3f2012-05-16 15:09:17 +01002393namespace Catch {
2394
Phil Nash89d1e6c2011-05-24 08:23:02 +01002395 typedef std::string(*exceptionTranslateFunction)();
2396
Phil Nash89d2a3f2012-05-16 15:09:17 +01002397 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002398 virtual ~IExceptionTranslator();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002399 virtual std::string translate() const = 0;
2400 };
2401
Phil Nash89d2a3f2012-05-16 15:09:17 +01002402 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002403 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002404
Phil Nash89d2a3f2012-05-16 15:09:17 +01002405 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002406 };
2407
Phil Nash89d2a3f2012-05-16 15:09:17 +01002408 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002409 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002410 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002411 public:
2412
Phil Nash89d2a3f2012-05-16 15:09:17 +01002413 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002414 : m_translateFunction( translateFunction )
2415 {}
2416
Phil Nash89d2a3f2012-05-16 15:09:17 +01002417 virtual std::string translate() const {
2418 try {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002419 throw;
2420 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002421 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002422 return m_translateFunction( ex );
2423 }
2424 }
2425
2426 protected:
2427 std::string(*m_translateFunction)( T& );
2428 };
2429
2430 public:
2431 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002432 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002433 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002434 ( new ExceptionTranslator<T>( translateFunction ) );
2435 }
2436 };
2437}
2438
2439///////////////////////////////////////////////////////////////////////////////
2440#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2441 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2442 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2443 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2444
2445// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002446#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002447
Phil Nash89d1e6c2011-05-24 08:23:02 +01002448#include <cmath>
2449#include <limits>
2450
Phil Nash89d2a3f2012-05-16 15:09:17 +01002451namespace Catch {
2452namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002453
Phil Nash89d2a3f2012-05-16 15:09:17 +01002454 class Approx {
2455 public:
2456 explicit Approx ( double value )
2457 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2458 m_scale( 1.0 ),
2459 m_value( value )
2460 {}
Phil Nashf721a962011-06-07 14:13:57 +01002461
Phil Nash89d2a3f2012-05-16 15:09:17 +01002462 Approx( const Approx& other )
2463 : m_epsilon( other.m_epsilon ),
2464 m_scale( other.m_scale ),
2465 m_value( other.m_value )
2466 {}
Phil Nashf721a962011-06-07 14:13:57 +01002467
Phil Nash89d2a3f2012-05-16 15:09:17 +01002468 static Approx custom() {
2469 return Approx( 0 );
2470 }
Phil Nashf721a962011-06-07 14:13:57 +01002471
Phil Nash89d2a3f2012-05-16 15:09:17 +01002472 Approx operator()( double value ) {
2473 Approx approx( value );
2474 approx.epsilon( m_epsilon );
2475 approx.scale( m_scale );
2476 return approx;
2477 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002478
Phil Nash89d2a3f2012-05-16 15:09:17 +01002479 friend bool operator == ( double lhs, const Approx& rhs ) {
2480 // Thanks to Richard Harris for his help refining this formula
2481 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2482 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002483
Phil Nash89d2a3f2012-05-16 15:09:17 +01002484 friend bool operator == ( const Approx& lhs, double rhs ) {
2485 return operator==( rhs, lhs );
2486 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002487
Phil Nash89d2a3f2012-05-16 15:09:17 +01002488 friend bool operator != ( double lhs, const Approx& rhs ) {
2489 return !operator==( lhs, rhs );
2490 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002491
Phil Nash89d2a3f2012-05-16 15:09:17 +01002492 friend bool operator != ( const Approx& lhs, double rhs ) {
2493 return !operator==( rhs, lhs );
2494 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002495
Phil Nash89d2a3f2012-05-16 15:09:17 +01002496 Approx& epsilon( double newEpsilon ) {
2497 m_epsilon = newEpsilon;
2498 return *this;
2499 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002500
Phil Nash89d2a3f2012-05-16 15:09:17 +01002501 Approx& scale( double newScale ) {
2502 m_scale = newScale;
2503 return *this;
2504 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002505
Phil Nash89d2a3f2012-05-16 15:09:17 +01002506 std::string toString() const {
2507 std::ostringstream oss;
Phil Nash67305122012-10-09 11:48:55 +01002508 oss << "Approx( " << m_value << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002509 return oss.str();
2510 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002511
Phil Nash89d2a3f2012-05-16 15:09:17 +01002512 private:
2513 double m_epsilon;
2514 double m_scale;
2515 double m_value;
2516 };
2517}
2518
2519template<>
2520inline std::string toString<Detail::Approx>( const Detail::Approx& value ) {
2521 return value.toString();
2522}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002523
2524} // end namespace Catch
2525
Phil Nash371db8b2012-05-21 18:52:09 +01002526// #included from: internal/catch_matchers.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002527#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002528
2529namespace Catch {
2530namespace Matchers {
2531 namespace Impl {
2532 namespace StdString {
2533
Phil Nasha8570df2012-05-24 08:29:41 +01002534 struct Equals {
2535 Equals( const std::string& str ) : m_str( str ){}
2536
2537 bool operator()( const std::string& str ) const
2538 {
2539 return str == m_str;
2540 }
2541
2542 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher )
2543 {
2544 os << "equals: \"" << matcher.m_str << "\"";
2545 return os;
2546 }
2547 std::string m_str;
2548 };
2549
Phil Nash371db8b2012-05-21 18:52:09 +01002550 struct Contains {
2551 Contains( const std::string& substr ) : m_substr( substr ){}
2552
2553 bool operator()( const std::string& str ) const
2554 {
2555 return str.find( m_substr ) != std::string::npos;
2556 }
2557
2558 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher )
2559 {
2560 os << "contains: \"" << matcher.m_substr << "\"";
2561 return os;
2562 }
2563 std::string m_substr;
2564 };
2565
2566 struct StartsWith {
2567 StartsWith( const std::string& substr ) : m_substr( substr ){}
2568
2569 bool operator()( const std::string& str ) const
2570 {
2571 return str.find( m_substr ) == 0;
2572 }
2573
2574 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher )
2575 {
2576 os << "starts with: \"" << matcher.m_substr << "\"";
2577 return os;
2578 }
2579 std::string m_substr;
2580 };
2581
2582 struct EndsWith {
2583 EndsWith( const std::string& substr ) : m_substr( substr ){}
2584
2585 bool operator()( const std::string& str ) const
2586 {
2587 return str.find( m_substr ) == str.size() - m_substr.size();
2588 }
2589
2590 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher )
2591 {
2592 os << "ends with: \"" << matcher.m_substr << "\"";
2593 return os;
2594 }
2595 std::string m_substr;
2596 };
2597 } // namespace StdString
2598 } // namespace Impl
2599
Phil Nasha8570df2012-05-24 08:29:41 +01002600 inline Impl::StdString::Equals Equals( const std::string& str ){ return Impl::StdString::Equals( str ); }
Phil Nash371db8b2012-05-21 18:52:09 +01002601 inline Impl::StdString::Contains Contains( const std::string& substr ){ return Impl::StdString::Contains( substr ); }
2602 inline Impl::StdString::StartsWith StartsWith( const std::string& substr ){ return Impl::StdString::StartsWith( substr ); }
2603 inline Impl::StdString::EndsWith EndsWith( const std::string& substr ){ return Impl::StdString::EndsWith( substr ); }
2604
2605} // namespace Matchers
2606
2607using namespace Matchers;
2608
2609} // namespace Catch
2610
Phil Nash0f9c5512012-06-02 23:12:42 +01002611// These files are included here so the single_include script doesn't put them
2612// in the conditionally compiled sections
Phil Nash0f9c5512012-06-02 23:12:42 +01002613// #included from: internal/catch_interfaces_runner.h
Matt Wozniskif29c8982012-09-17 01:42:29 -04002614#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01002615
2616#include <string>
2617
2618namespace Catch {
2619 class TestCaseInfo;
2620
2621 struct IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01002622 virtual ~IRunner();
Phil Nash0f9c5512012-06-02 23:12:42 +01002623 };
2624}
2625
2626
Phil Nash371db8b2012-05-21 18:52:09 +01002627#ifdef __OBJC__
2628// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002629#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002630
Phil Nash371db8b2012-05-21 18:52:09 +01002631#import <objc/runtime.h>
2632
2633#include <string>
2634
2635// NB. Any general catch headers included here must be included
2636// in catch.hpp first to make sure they are included by the single
2637// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01002638
Phil Nash83224e62011-08-12 18:53:28 +01002639///////////////////////////////////////////////////////////////////////////////
2640// This protocol is really only here for (self) documenting purposes, since
2641// all its methods are optional.
2642@protocol OcFixture
2643
2644@optional
2645
2646-(void) setUp;
2647-(void) tearDown;
2648
2649@end
2650
Phil Nash89d2a3f2012-05-16 15:09:17 +01002651namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01002652
Phil Nash5bc030d2012-08-16 18:48:50 +01002653 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002654
2655 public:
2656 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2657
2658 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00002659 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01002660
Phil Nash53c990a2012-03-17 18:20:06 +00002661 performOptionalSelector( obj, @selector(setUp) );
2662 performOptionalSelector( obj, m_sel );
2663 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01002664
Phil Nash53c990a2012-03-17 18:20:06 +00002665 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01002666 }
Phil Nash83224e62011-08-12 18:53:28 +01002667 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01002668 virtual ~OcMethod() {}
2669
Phil Nash83224e62011-08-12 18:53:28 +01002670 Class m_cls;
2671 SEL m_sel;
2672 };
2673
Phil Nash89d2a3f2012-05-16 15:09:17 +01002674 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01002675
Phil Nash89d2a3f2012-05-16 15:09:17 +01002676 inline bool startsWith( const std::string& str, const std::string& sub ) {
Phil Nash83224e62011-08-12 18:53:28 +01002677 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2678 }
2679
Phil Nash89d2a3f2012-05-16 15:09:17 +01002680 inline std::string getAnnotation( Class cls,
2681 const std::string& annotationName,
2682 const std::string& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01002683 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2684 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00002685 arcSafeRelease( selStr );
2686 id value = performOptionalSelector( cls, sel );
2687 if( value )
2688 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01002689 return "";
2690 }
2691 }
2692
Phil Nash89d2a3f2012-05-16 15:09:17 +01002693 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01002694 size_t noTestMethods = 0;
2695 int noClasses = objc_getClassList( NULL, 0 );
2696
Phil Nash861a1e72012-04-28 12:29:52 +01002697 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00002698 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01002699
Phil Nash89d2a3f2012-05-16 15:09:17 +01002700 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002701 Class cls = classes[c];
2702 {
2703 u_int count;
2704 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01002705 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002706 SEL selector = method_getName(methods[m]);
2707 std::string methodName = sel_getName(selector);
Phil Nash89d2a3f2012-05-16 15:09:17 +01002708 if( Detail::startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01002709 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00002710 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2711 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nash83224e62011-08-12 18:53:28 +01002712
Phil Nash3b80af72012-08-09 07:47:30 +01002713 getMutableRegistryHub().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01002714 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01002715 }
2716 }
2717 free(methods);
2718 }
2719 }
2720 return noTestMethods;
2721 }
Phil Nash78d95a02012-03-04 21:22:36 +00002722
Phil Nash89d2a3f2012-05-16 15:09:17 +01002723 namespace Matchers {
2724 namespace Impl {
2725 namespace NSStringMatchers {
2726
2727 struct StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002728 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01002729 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00002730 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002731 }
2732
2733 NSString* m_substr;
2734 };
2735
Phil Nash89d2a3f2012-05-16 15:09:17 +01002736 struct Equals : StringHolder {
Phil Nash8d18d162012-03-14 20:06:14 +00002737 Equals( NSString* substr ) : StringHolder( substr ){}
2738
Phil Nash89d2a3f2012-05-16 15:09:17 +01002739 bool operator()( NSString* str ) const {
Phil Nash8d18d162012-03-14 20:06:14 +00002740 return [str isEqualToString:m_substr];
2741 }
2742
Phil Nash89d2a3f2012-05-16 15:09:17 +01002743 friend std::ostream& operator<<( std::ostream& os, const Equals& matcher ) {
Phil Nash8d18d162012-03-14 20:06:14 +00002744 os << "equals string: " << Catch::toString( matcher.m_substr );
2745 return os;
2746 }
2747 };
2748
Phil Nash89d2a3f2012-05-16 15:09:17 +01002749 struct Contains : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002750 Contains( NSString* substr ) : StringHolder( substr ){}
2751
Phil Nash89d2a3f2012-05-16 15:09:17 +01002752 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002753 return [str rangeOfString:m_substr].location != NSNotFound;
2754 }
2755
Phil Nash89d2a3f2012-05-16 15:09:17 +01002756 friend std::ostream& operator<<( std::ostream& os, const Contains& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002757 os << "contains: " << Catch::toString( matcher.m_substr );
2758 return os;
2759 }
2760 };
2761
Phil Nash89d2a3f2012-05-16 15:09:17 +01002762 struct StartsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002763 StartsWith( NSString* substr ) : StringHolder( substr ){}
2764
Phil Nash89d2a3f2012-05-16 15:09:17 +01002765 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002766 return [str rangeOfString:m_substr].location == 0;
2767 }
2768
Phil Nash89d2a3f2012-05-16 15:09:17 +01002769 friend std::ostream& operator<<( std::ostream& os, const StartsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002770 os << "starts with: " << Catch::toString( matcher.m_substr );
2771 return os;
2772 }
2773 };
Phil Nash89d2a3f2012-05-16 15:09:17 +01002774 struct EndsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00002775 EndsWith( NSString* substr ) : StringHolder( substr ){}
2776
Phil Nash89d2a3f2012-05-16 15:09:17 +01002777 bool operator()( NSString* str ) const {
Phil Nash78d95a02012-03-04 21:22:36 +00002778 return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2779 }
2780
Phil Nash89d2a3f2012-05-16 15:09:17 +01002781 friend std::ostream& operator<<( std::ostream& os, const EndsWith& matcher ) {
Phil Nash78d95a02012-03-04 21:22:36 +00002782 os << "ends with: " << Catch::toString( matcher.m_substr );
2783 return os;
2784 }
2785 };
2786
2787 } // namespace NSStringMatchers
2788 } // namespace Impl
2789
Phil Nash8d18d162012-03-14 20:06:14 +00002790 inline Impl::NSStringMatchers::Equals
2791 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
2792
Phil Nash78d95a02012-03-04 21:22:36 +00002793 inline Impl::NSStringMatchers::Contains
2794 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002795
Phil Nash78d95a02012-03-04 21:22:36 +00002796 inline Impl::NSStringMatchers::StartsWith
2797 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00002798
Phil Nash78d95a02012-03-04 21:22:36 +00002799 inline Impl::NSStringMatchers::EndsWith
2800 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
2801
2802 } // namespace Matchers
2803
2804 using namespace Matchers;
2805
2806} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01002807
2808///////////////////////////////////////////////////////////////////////////////
2809#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00002810+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002811{\
Phil Nash53c990a2012-03-17 18:20:06 +00002812return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01002813}\
Phil Nash53c990a2012-03-17 18:20:06 +00002814+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01002815{ \
Phil Nash53c990a2012-03-17 18:20:06 +00002816return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01002817} \
2818-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2819
2820#endif
2821
2822#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
Phil Nasha695eb92012-08-13 07:46:10 +01002823// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04002824#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01002825
2826// Collect all the implementation files together here
2827// These are the equivalent of what would usually be cpp files
2828
Phil Nash5bc030d2012-08-16 18:48:50 +01002829#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01002830#pragma clang diagnostic push
2831#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01002832#endif
Phil Nasha695eb92012-08-13 07:46:10 +01002833
Phil Nash83224e62011-08-12 18:53:28 +01002834// #included from: catch_runner.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002835#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01002836
Phil Nasha695eb92012-08-13 07:46:10 +01002837// #included from: internal/catch_commandline.hpp
2838#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2839
Phil Nasha695eb92012-08-13 07:46:10 +01002840namespace Catch {
2841
2842 class Command {
2843 public:
2844 Command(){}
2845
Phil Nashecf934b2012-08-27 21:42:55 +01002846 explicit Command( const std::string& name ) : m_name( name ) {
2847 }
Phil Nasha695eb92012-08-13 07:46:10 +01002848
2849 Command& operator += ( const std::string& arg ) {
2850 m_args.push_back( arg );
2851 return *this;
2852 }
2853 Command& operator += ( const Command& other ) {
2854 std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
2855 if( m_name.empty() )
2856 m_name = other.m_name;
2857 return *this;
2858 }
2859 Command operator + ( const Command& other ) {
2860 Command newCommand( *this );
2861 newCommand += other;
2862 return newCommand;
2863 }
2864
2865 operator SafeBool::type() const {
Phil Nashe571e6f2012-08-24 18:54:56 +01002866 return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() );
Phil Nasha695eb92012-08-13 07:46:10 +01002867 }
2868
2869 std::string name() const { return m_name; }
2870 std::string operator[]( std::size_t i ) const { return m_args[i]; }
2871 std::size_t argsCount() const { return m_args.size(); }
2872
2873 CATCH_ATTRIBUTE_NORETURN
2874 void raiseError( const std::string& message ) const {
2875 std::ostringstream oss;
Phil Nashecf934b2012-08-27 21:42:55 +01002876 if( m_name.empty() )
2877 oss << "Error while parsing " << m_name << ". " << message << ".";
2878 else
2879 oss << "Error while parsing arguments. " << message << ".";
2880
Phil Nasha695eb92012-08-13 07:46:10 +01002881 if( m_args.size() > 0 )
Phil Nashecf934b2012-08-27 21:42:55 +01002882 oss << " Arguments were:";
Phil Nasha695eb92012-08-13 07:46:10 +01002883 for( std::size_t i = 0; i < m_args.size(); ++i )
2884 oss << " " << m_args[i];
2885 throw std::domain_error( oss.str() );
2886 }
2887
2888 private:
2889
2890 std::string m_name;
2891 std::vector<std::string> m_args;
2892 };
2893
2894 class CommandParser {
2895 public:
2896 CommandParser( int argc, char const * const * argv ) : m_argc( static_cast<std::size_t>( argc ) ), m_argv( argv ) {}
2897
Phil Nashe2d215e2012-09-07 17:52:35 +01002898 std::string exeName() const {
2899 return m_argv[0];
2900 }
Phil Nasha695eb92012-08-13 07:46:10 +01002901 Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
2902 return find( arg1 ) + find( arg2 ) + find( arg3 );
2903 }
2904
2905 Command find( const std::string& shortArg, const std::string& longArg ) const {
2906 return find( shortArg ) + find( longArg );
2907 }
2908 Command find( const std::string& arg ) const {
Phil Nashecf934b2012-08-27 21:42:55 +01002909 if( arg.empty() )
2910 return getArgs( "", 1 );
2911 else
2912 for( std::size_t i = 1; i < m_argc; ++i )
2913 if( m_argv[i] == arg )
2914 return getArgs( m_argv[i], i+1 );
Phil Nasha695eb92012-08-13 07:46:10 +01002915 return Command();
2916 }
Phil Nashe571e6f2012-08-24 18:54:56 +01002917 Command getDefaultArgs() const {
2918 return getArgs( "", 1 );
2919 }
Phil Nasha695eb92012-08-13 07:46:10 +01002920
2921 private:
Phil Nashe571e6f2012-08-24 18:54:56 +01002922 Command getArgs( const std::string& cmdName, std::size_t from ) const {
2923 Command command( cmdName );
2924 for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i )
Phil Nasha695eb92012-08-13 07:46:10 +01002925 command += m_argv[i];
2926 return command;
2927 }
2928
2929 std::size_t m_argc;
2930 char const * const * m_argv;
2931 };
2932
Phil Nashecf934b2012-08-27 21:42:55 +01002933 class OptionParser : public SharedImpl<IShared> {
2934 public:
2935 OptionParser( int minArgs = 0, int maxArgs = 0 )
2936 : m_minArgs( minArgs ), m_maxArgs( maxArgs )
2937 {}
Phil Nasha695eb92012-08-13 07:46:10 +01002938
Phil Nashecf934b2012-08-27 21:42:55 +01002939 virtual ~OptionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01002940
Phil Nashecf934b2012-08-27 21:42:55 +01002941 Command find( const CommandParser& parser ) const {
2942 Command cmd;
2943 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
2944 it != m_optionNames.end();
2945 ++it )
2946 cmd += parser.find( *it );
2947 return cmd;
2948 }
2949
2950 void validateArgs( const Command& args ) const {
2951 if( tooFewArgs( args ) || tooManyArgs( args ) ) {
2952 std::ostringstream oss;
2953 if( m_maxArgs == -1 )
2954 oss <<"Expected at least " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
2955 else if( m_minArgs == m_maxArgs )
2956 oss <<"Expected " << pluralise( static_cast<std::size_t>( m_minArgs ), "argument" );
Phil Nasha695eb92012-08-13 07:46:10 +01002957 else
Phil Nashecf934b2012-08-27 21:42:55 +01002958 oss <<"Expected between " << m_minArgs << " and " << m_maxArgs << " argument";
2959 args.raiseError( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01002960 }
Phil Nashecf934b2012-08-27 21:42:55 +01002961 }
2962
2963 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
2964 if( Command cmd = find( parser ) ) {
2965 validateArgs( cmd );
2966 parseIntoConfig( cmd, config );
2967 }
2968 }
2969
2970 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0;
2971 virtual std::string argsSynopsis() const = 0;
2972 virtual std::string optionSummary() const = 0;
Phil Nashe2d215e2012-09-07 17:52:35 +01002973 virtual std::string optionDescription() const { return ""; };
Phil Nashecf934b2012-08-27 21:42:55 +01002974
2975 std::string optionNames() const {
2976 std::string names;
2977 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
2978 it != m_optionNames.end();
2979 ++it ) {
2980 if( !it->empty() ) {
2981 if( !names.empty() )
2982 names += ", ";
2983 names += *it;
2984 }
2985 else {
2986 names = "[" + names;
2987 }
2988 }
2989 if( names[0] == '[' )
2990 names += "]";
2991 return names;
2992 }
2993
2994 protected:
2995
2996 bool tooFewArgs( const Command& args ) const {
2997 return args.argsCount() < static_cast<std::size_t>( m_minArgs );
2998 }
2999 bool tooManyArgs( const Command& args ) const {
3000 return m_maxArgs >= 0 && args.argsCount() > static_cast<std::size_t>( m_maxArgs );
3001 }
3002 std::vector<std::string> m_optionNames;
3003 int m_minArgs;
3004 int m_maxArgs;
3005 };
3006
3007 namespace Options {
3008
3009 class HelpOptionParser : public OptionParser {
3010 public:
3011 HelpOptionParser() {
3012 m_optionNames.push_back( "-?" );
3013 m_optionNames.push_back( "-h" );
3014 m_optionNames.push_back( "--help" );
3015 }
3016 virtual std::string argsSynopsis() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003017 return "[<option for help on> ...]";
Phil Nashecf934b2012-08-27 21:42:55 +01003018 }
3019 virtual std::string optionSummary() const {
Phil Nash67ec8702012-09-26 18:38:26 +01003020 return "Shows this usage summary, or help on a specific option, or options, if supplied";
Phil Nashe2d215e2012-09-07 17:52:35 +01003021 }
3022 virtual std::string optionDescription() const {
3023 return "";
Phil Nashecf934b2012-08-27 21:42:55 +01003024 }
3025
3026 virtual void parseIntoConfig( const Command&, ConfigData& ) {
3027 // Does not affect config
3028 }
3029 };
3030
3031 class TestCaseOptionParser : public OptionParser {
3032 public:
3033 TestCaseOptionParser() : OptionParser( 1, -1 ) {
3034 m_optionNames.push_back( "-t" );
3035 m_optionNames.push_back( "--test" );
3036 m_optionNames.push_back( "" ); // default option
3037 }
3038 virtual std::string argsSynopsis() const {
3039 return "<testspec> [<testspec>...]";
3040 }
3041 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003042 return "Specifies which test case or cases to run";
3043 }
3044
3045 // Lines are split at the nearest prior space char to the 80 char column.
3046 // Tab chars are removed from the output but their positions are used to align
3047 // subsequently wrapped lines
3048 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003049 return
3050 "This option allows one ore more test specs to be supplied. Each spec either fully "
3051 "specifies a test case or is a pattern containing wildcards to match a set of test "
3052 "cases. If this option is not provided then all test cases, except those prefixed "
3053 "by './' are run\n"
3054 "\n"
3055 "Specs must be enclosed in \"quotes\" if they contain spaces. If they do not "
3056 "contain spaces the quotes are optional.\n"
3057 "\n"
3058 "Wildcards consist of the * character at the beginning, end, or both and can substitute for "
3059 "any number of any characters (including none)\n"
3060 "\n"
3061 "If spec is prefixed with exclude: or the ~ character then the pattern matches an exclusion. "
3062 "This means that tests matching the pattern are excluded from the set - even if a prior "
Phil Nash799ecf92012-09-24 08:30:13 +01003063 "inclusion spec included them. Subsequent inclusion specs will take precedence, however. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003064 "Inclusions and exclusions are evaluated in left-to-right order.\n"
3065 "\n"
3066 "Examples:\n"
3067 "\n"
3068 " -t thisTestOnly \tMatches the test case called, 'thisTestOnly'\n"
3069 " -t \"this test only\" \tMatches the test case called, 'this test only'\n"
3070 " -t these/* \tMatches all cases starting with 'these/'\n"
3071 " -t exclude:notThis \tMatches all tests except, 'notThis'\n"
3072 " -t ~notThis \tMatches all tests except, 'notThis'\n"
3073 " -t ~*private* \tMatches all tests except those that contain 'private'\n"
3074 " -t a/* ~a/b/* a/b/c \tMatches all tests that start with 'a/', except those "
3075 "that start with 'a/b/', except 'a/b/c', which is included";
Phil Nashecf934b2012-08-27 21:42:55 +01003076 }
3077
3078 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3079 std::string groupName;
3080 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3081 if( i != 0 )
3082 groupName += " ";
3083 groupName += cmd[i];
3084 }
3085 TestCaseFilters filters( groupName );
Phil Nashe2d215e2012-09-07 17:52:35 +01003086 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3087 filters.addFilter( TestCaseFilter( cmd[i] ) );
Phil Nashecf934b2012-08-27 21:42:55 +01003088 config.filters.push_back( filters );
3089 }
3090 };
3091
Phil Nash799ecf92012-09-24 08:30:13 +01003092 class TagOptionParser : public OptionParser {
3093 public:
3094 TagOptionParser() : OptionParser( 1, -1 ) {
3095 m_optionNames.push_back( "-g" );
3096 m_optionNames.push_back( "--tag" );
3097 }
3098 virtual std::string argsSynopsis() const {
3099 return "<tagspec> [,<tagspec>...]";
3100 }
3101 virtual std::string optionSummary() const {
3102 return "Matches test cases against tags or tag patterns";
3103 }
3104
3105 // Lines are split at the nearest prior space char to the 80 char column.
3106 // Tab chars are removed from the output but their positions are used to align
3107 // subsequently wrapped lines
3108 virtual std::string optionDescription() const {
3109 return
3110 "!TBD";
3111 }
3112
3113 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
Phil Nash67ec8702012-09-26 18:38:26 +01003114 std::string groupName;
3115 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3116 if( i != 0 )
3117 groupName += " ";
3118 groupName += cmd[i];
3119 }
3120 TestCaseFilters filters( groupName );
3121 for( std::size_t i = 0; i < cmd.argsCount(); ++i )
3122 filters.addTags( cmd[i] );
3123 config.filters.push_back( filters );
Phil Nash799ecf92012-09-24 08:30:13 +01003124 }
3125 };
3126
Phil Nashecf934b2012-08-27 21:42:55 +01003127 class ListOptionParser : public OptionParser {
3128 public:
3129 ListOptionParser() : OptionParser( 0, 2 ) {
3130 m_optionNames.push_back( "-l" );
3131 m_optionNames.push_back( "--list" );
3132 }
3133 virtual std::string argsSynopsis() const {
3134 return "[all | tests | reporters [xml]]";
3135 }
3136 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003137 return "Lists available tests or reporters";
3138 }
3139
3140 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003141 return
3142 "With no arguments this option will list all registered tests - one per line.\n"
3143 "Supplying the xml argument formats the list as an xml document (which may be useful for "
3144 "consumption by other tools).\n"
3145 "Supplying the tests or reporters lists tests or reporters respectively - with descriptions.\n"
3146 "\n"
3147 "Examples:\n"
3148 "\n"
3149 " -l\n"
3150 " -l tests\n"
3151 " -l reporters xml\n"
3152 " -l xml";
Phil Nashecf934b2012-08-27 21:42:55 +01003153 }
3154
3155 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3156 config.listSpec = List::TestNames;
3157 if( cmd.argsCount() >= 1 ) {
3158 if( cmd[0] == "all" )
3159 config.listSpec = List::All;
3160 else if( cmd[0] == "tests" )
3161 config.listSpec = List::Tests;
3162 else if( cmd[0] == "reporters" )
3163 config.listSpec = List::Reports;
3164 else
3165 cmd.raiseError( "Expected [tests] or [reporters]" );
3166 }
3167 if( cmd.argsCount() >= 2 ) {
3168 if( cmd[1] == "xml" )
3169 config.listSpec = static_cast<List::What>( config.listSpec | List::AsXml );
3170 else if( cmd[1] == "text" )
3171 config.listSpec = static_cast<List::What>( config.listSpec | List::AsText );
3172 else
3173 cmd.raiseError( "Expected [xml] or [text]" );
3174 }
3175 }
3176 };
3177
3178 class ReporterOptionParser : public OptionParser {
3179 public:
3180 ReporterOptionParser() : OptionParser( 1, 1 ) {
3181 m_optionNames.push_back( "-r" );
3182 m_optionNames.push_back( "--reporter" );
3183 }
3184 virtual std::string argsSynopsis() const {
3185 return "<reporter name>";
3186 }
3187 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003188 return "Specifies type of reporter";
3189 }
3190
3191 virtual std::string optionDescription() const {
Phil Nashf7418eb2012-09-09 11:44:30 +01003192 return
3193 "A reporter is an object that formats and structures the output of running "
3194 "tests, and potentially summarises the results. By default a basic reporter "
3195 "is used that writes IDE friendly results. CATCH comes bundled with some "
3196 "alternative reporters, but more can be added in client code.\n"
3197 "\n"
3198 "The bundled reporters are:\n"
3199 " -r basic\n"
3200 " -r xml\n"
3201 " -r junit\n"
3202 "\n"
3203 "The JUnit reporter is an xml format that follows the structure of the JUnit "
3204 "XML Report ANT task, as consumed by a number of third-party tools, "
3205 "including Continuous Integration servers such as Jenkins.\n"
3206 "If not otherwise needed, the standard XML reporter is preferred as this is "
3207 "a streaming reporter, whereas the Junit reporter needs to hold all its "
3208 "results until the end so it can write the overall results into attributes "
3209 "of the root node.";
Phil Nashecf934b2012-08-27 21:42:55 +01003210 }
3211
3212 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3213 config.reporter = cmd[0];
3214 }
3215 };
3216
3217 class OutputOptionParser : public OptionParser {
3218 public:
3219 OutputOptionParser() : OptionParser( 1, 1 ) {
3220 m_optionNames.push_back( "-o" );
3221 m_optionNames.push_back( "--out" );
3222 }
3223 virtual std::string argsSynopsis() const {
3224 return "<file name>|<%stream name>";
3225 }
3226 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003227 return "Sends output to a file or stream";
Phil Nashecf934b2012-08-27 21:42:55 +01003228 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003229 virtual std::string optionDescription() const {
3230 return
3231 "Use this option to send all output to a file or a stream. By default output is "
Phil Nash799ecf92012-09-24 08:30:13 +01003232 "sent to stdout (note that uses of stdout and stderr from within test cases are "
Phil Nashf7418eb2012-09-09 11:44:30 +01003233 "redirected and included in the report - so even stderr will effectively end up "
Phil Nash799ecf92012-09-24 08:30:13 +01003234 "on stdout). If the name begins with % it is interpreted as a stream. "
Phil Nashf7418eb2012-09-09 11:44:30 +01003235 "Otherwise it is treated as a filename.\n"
3236 "\n"
3237 "Examples are:\n"
3238 "\n"
3239 " -o filename.txt\n"
3240 " -o \"long filename.txt\"\n"
3241 " -o %stdout\n"
3242 " -o %stderr\n"
3243 " -o %debug \t(The IDE's debug output window - currently only Windows' "
3244 "OutputDebugString is supported).";
3245 }
Phil Nashecf934b2012-08-27 21:42:55 +01003246 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3247 if( cmd[0][0] == '%' )
3248 config.stream = cmd[0].substr( 1 );
Phil Nasha695eb92012-08-13 07:46:10 +01003249 else
Phil Nashecf934b2012-08-27 21:42:55 +01003250 config.outputFilename = cmd[0];
Phil Nasha695eb92012-08-13 07:46:10 +01003251 }
Phil Nashecf934b2012-08-27 21:42:55 +01003252 };
Phil Nasha695eb92012-08-13 07:46:10 +01003253
Phil Nashf7418eb2012-09-09 11:44:30 +01003254 class SuccessOptionParser : public OptionParser {
Phil Nashecf934b2012-08-27 21:42:55 +01003255 public:
Phil Nashf7418eb2012-09-09 11:44:30 +01003256 SuccessOptionParser() {
Phil Nashecf934b2012-08-27 21:42:55 +01003257 m_optionNames.push_back( "-s" );
3258 m_optionNames.push_back( "--success" );
Phil Nash56d5c422012-08-23 20:08:50 +01003259 }
Phil Nashecf934b2012-08-27 21:42:55 +01003260 virtual std::string argsSynopsis() const {
3261 return "";
Phil Nash56d5c422012-08-23 20:08:50 +01003262 }
Phil Nashecf934b2012-08-27 21:42:55 +01003263 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003264 return "Shows results for successful tests";
Phil Nasha695eb92012-08-13 07:46:10 +01003265 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003266 virtual std::string optionDescription() const {
3267 return
3268 "Usually you only want to see reporting for failed tests. Sometimes it's useful "
3269 "to see all the output (especially when you don't trust that that test you just "
Phil Nash799ecf92012-09-24 08:30:13 +01003270 "added worked first time!). To see successful, as well as failing, test results "
Phil Nashf7418eb2012-09-09 11:44:30 +01003271 "just pass this option.";
3272 }
Phil Nash78c92e62012-08-27 21:48:15 +01003273 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003274 config.includeWhichResults = Include::SuccessfulResults;
3275 }
3276 };
Phil Nasha695eb92012-08-13 07:46:10 +01003277
Phil Nashecf934b2012-08-27 21:42:55 +01003278 class DebugBreakOptionParser : public OptionParser {
3279 public:
3280 DebugBreakOptionParser() {
3281 m_optionNames.push_back( "-b" );
3282 m_optionNames.push_back( "--break" );
3283 }
3284 virtual std::string argsSynopsis() const {
3285 return "";
3286 }
3287 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003288 return "Breaks into the debugger on failure";
Phil Nashecf934b2012-08-27 21:42:55 +01003289 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003290 virtual std::string optionDescription() const {
3291 return
3292 "In some IDEs (currently XCode and Visual Studio) it is possible for CATCH to "
3293 "break into the debugger on a test failure. This can be very helpful during "
3294 "debug sessions - especially when there is more than one path through a "
3295 "particular test. In addition to the command line option, ensure you have "
3296 "built your code with the DEBUG preprocessor symbol";
3297 }
Phil Nashecf934b2012-08-27 21:42:55 +01003298
Phil Nash78c92e62012-08-27 21:48:15 +01003299 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003300 config.shouldDebugBreak = true;
3301 }
3302 };
3303
3304 class NameOptionParser : public OptionParser {
3305 public:
3306 NameOptionParser() : OptionParser( 1, 1 ) {
3307 m_optionNames.push_back( "-n" );
3308 m_optionNames.push_back( "--name" );
3309 }
3310 virtual std::string argsSynopsis() const {
3311 return "<name>";
3312 }
3313 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003314 return "Names a test run";
Phil Nashecf934b2012-08-27 21:42:55 +01003315 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003316 virtual std::string optionDescription() const {
3317 return
3318 "If a name is supplied it will be used by the reporter to provide an overall "
3319 "name for the test run. This can be useful if you are sending to a file, for "
3320 "example, and need to distinguish different test runs - either from different "
3321 "Catch executables or runs of the same executable with different options.\n"
3322 "\n"
3323 "Examples:\n"
3324 "\n"
3325 " -n testRun\n"
3326 " -n \"tests of the widget component\"";
3327 }
Phil Nashecf934b2012-08-27 21:42:55 +01003328
3329 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3330 config.name = cmd[0];
3331 }
3332 };
3333
3334 class AbortOptionParser : public OptionParser {
3335 public:
3336 AbortOptionParser() : OptionParser( 0, 1 ) {
3337 m_optionNames.push_back( "-a" );
3338 m_optionNames.push_back( "--abort" );
3339 }
3340 virtual std::string argsSynopsis() const {
3341 return "[#]";
3342 }
3343 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003344 return "Aborts after a certain number of failures";
Phil Nashecf934b2012-08-27 21:42:55 +01003345 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003346 virtual std::string optionDescription() const {
3347 return
3348 "If a REQUIRE assertion fails the test case aborts, but subsequent test cases "
3349 "are still run. If a CHECK assertion fails even the current test case is not "
3350 "aborted.\n"
3351 "\n"
3352 "Sometimes this results in a flood of failure messages and you'd rather just "
3353 "see the first few. Specifying -a or --abort on its own will abort the whole "
3354 "test run on the first failed assertion of any kind. Following it with a "
3355 "number causes it to abort after that number of assertion failures.";
3356 }
Phil Nashecf934b2012-08-27 21:42:55 +01003357
3358 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3359 int threshold = 1;
3360 if( cmd.argsCount() == 1 ) {
3361 std::stringstream ss;
3362 ss << cmd[0];
3363 ss >> threshold;
3364 if( ss.fail() || threshold <= 0 )
3365 cmd.raiseError( "threshold must be a number greater than zero" );
3366 }
3367 config.cutoff = threshold;
3368 }
3369 };
3370
3371 class NoThrowOptionParser : public OptionParser {
3372 public:
3373 NoThrowOptionParser() {
3374 m_optionNames.push_back( "-nt" );
3375 m_optionNames.push_back( "--nothrow" );
3376 }
3377 virtual std::string argsSynopsis() const {
3378 return "";
3379 }
3380 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003381 return "Elides assertions expected to throw";
Phil Nashecf934b2012-08-27 21:42:55 +01003382 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003383 virtual std::string optionDescription() const {
3384 return
3385 "Skips all assertions that test that an exception is thrown, "
3386 "e.g. REQUIRE_THROWS.\n"
3387 "\n"
3388 "These can be a nuisance in certain debugging environments that may break when "
3389 "exceptions are thrown (while this is usually optional for handled exceptions, "
3390 "it can be useful to have enabled if you are trying to track down something "
3391 "unexpected).\n"
3392 "\n"
3393 "When running with this option the throw checking assertions are skipped so "
3394 "as not to contribute additional noise.";
3395 }
Phil Nashecf934b2012-08-27 21:42:55 +01003396
Phil Nash78c92e62012-08-27 21:48:15 +01003397 virtual void parseIntoConfig( const Command&, ConfigData& config ) {
Phil Nashecf934b2012-08-27 21:42:55 +01003398 config.allowThrows = false;
3399 }
3400 };
Phil Nasha70fbe32012-08-31 08:10:36 +01003401
3402 class WarningsOptionParser : public OptionParser {
3403 public:
3404 WarningsOptionParser() : OptionParser( 1, -1 ) {
3405 m_optionNames.push_back( "-w" );
3406 m_optionNames.push_back( "--warnings" );
3407 }
3408 virtual std::string argsSynopsis() const {
3409 return "<warning>";
3410 }
3411 virtual std::string optionSummary() const {
Phil Nashe2d215e2012-09-07 17:52:35 +01003412 return "Enable warnings";
Phil Nasha70fbe32012-08-31 08:10:36 +01003413 }
Phil Nashf7418eb2012-09-09 11:44:30 +01003414 virtual std::string optionDescription() const {
3415 return
3416 "Enables the named warnings. If the warnings are violated the test case is "
3417 "failed.\n"
3418 "\n"
3419 "At present only one warning has been provided: NoAssertions. If this warning "
3420 "is enabled then any test case that completes without an assertions (CHECK, "
3421 "REQUIRE etc) being encountered violates the warning.\n"
3422 "\n"
3423 "e.g.:\n"
3424 "\n"
3425 " -w NoAssertions";
3426 }
Phil Nasha70fbe32012-08-31 08:10:36 +01003427
3428 virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
3429 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
3430 if( cmd[i] == "NoAssertions" )
3431 config.warnings = (ConfigData::WarnAbout::What)( config.warnings | ConfigData::WarnAbout::NoAssertions );
3432 else
3433 cmd.raiseError( "Unrecognised warning: " + cmd[i] );
3434 }
3435 }
3436 };
Phil Nasha695eb92012-08-13 07:46:10 +01003437 }
3438
Phil Nashecf934b2012-08-27 21:42:55 +01003439 class AllOptions
3440 {
3441 public:
3442 typedef std::vector<Ptr<OptionParser> > Parsers;
3443 typedef Parsers::const_iterator const_iterator;
3444 typedef Parsers::const_iterator iterator;
3445
3446 AllOptions() {
Phil Nasha70fbe32012-08-31 08:10:36 +01003447 add<Options::TestCaseOptionParser>(); // Keep this one first
3448
Phil Nash67ec8702012-09-26 18:38:26 +01003449 add<Options::TagOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003450 add<Options::ListOptionParser>();
3451 add<Options::ReporterOptionParser>();
3452 add<Options::OutputOptionParser>();
Phil Nashf7418eb2012-09-09 11:44:30 +01003453 add<Options::SuccessOptionParser>();
Phil Nashecf934b2012-08-27 21:42:55 +01003454 add<Options::DebugBreakOptionParser>();
3455 add<Options::NameOptionParser>();
3456 add<Options::AbortOptionParser>();
3457 add<Options::NoThrowOptionParser>();
Phil Nasha70fbe32012-08-31 08:10:36 +01003458 add<Options::WarningsOptionParser>();
3459
3460 add<Options::HelpOptionParser>(); // Keep this one last
Phil Nashecf934b2012-08-27 21:42:55 +01003461 }
3462
3463 void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
3464 for( const_iterator it = m_parsers.begin(); it != m_parsers.end(); ++it )
3465 (*it)->parseIntoConfig( parser, config );
3466 }
3467
3468 const_iterator begin() const {
3469 return m_parsers.begin();
3470 }
3471 const_iterator end() const {
3472 return m_parsers.end();
3473 }
3474 private:
3475
3476 template<typename T>
3477 void add() {
3478 m_parsers.push_back( new T() );
3479 }
3480 Parsers m_parsers;
3481
3482 };
3483
Phil Nasha695eb92012-08-13 07:46:10 +01003484} // end namespace Catch
3485
3486// #included from: internal/catch_list.hpp
3487#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
3488
3489#include <limits>
3490
3491namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +01003492 inline bool matchesFilters( const std::vector<TestCaseFilters>& filters, const TestCaseInfo& testCase ) {
3493 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
3494 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
3495 for(; it != itEnd; ++it )
3496 if( !it->shouldInclude( testCase ) )
3497 return false;
3498 return true;
3499 }
3500 inline void List( const ConfigData& config ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003501
Phil Nash5bc030d2012-08-16 18:48:50 +01003502 if( config.listSpec & List::Reports ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003503 std::cout << "Available reports:\n";
3504 IReporterRegistry::FactoryMap::const_iterator it = getRegistryHub().getReporterRegistry().getFactories().begin();
3505 IReporterRegistry::FactoryMap::const_iterator itEnd = getRegistryHub().getReporterRegistry().getFactories().end();
3506 for(; it != itEnd; ++it ) {
3507 // !TBD: consider listAs()
3508 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
3509 }
3510 std::cout << std::endl;
3511 }
3512
Phil Nash5bc030d2012-08-16 18:48:50 +01003513 if( config.listSpec & List::Tests ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003514 if( config.filters.empty() )
Phil Nash4c97fc52012-08-24 08:23:50 +01003515 std::cout << "All available test cases:\n";
Phil Nash56d5c422012-08-23 20:08:50 +01003516 else
Phil Nash4c97fc52012-08-24 08:23:50 +01003517 std::cout << "Matching test cases:\n";
Phil Nasha695eb92012-08-13 07:46:10 +01003518 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
3519 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
Phil Nash4c97fc52012-08-24 08:23:50 +01003520 std::size_t matchedTests = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01003521 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003522 if( matchesFilters( config.filters, *it ) ) {
Phil Nash4c97fc52012-08-24 08:23:50 +01003523 matchedTests++;
Phil Nash56d5c422012-08-23 20:08:50 +01003524 // !TBD: consider listAs()
3525 std::cout << "\t" << it->getName() << "\n";
3526 if( ( config.listSpec & List::TestNames ) != List::TestNames )
3527 std::cout << "\t\t '" << it->getDescription() << "'\n";
3528 }
Phil Nasha695eb92012-08-13 07:46:10 +01003529 }
Phil Nash4c97fc52012-08-24 08:23:50 +01003530 if( config.filters.empty() )
3531 std::cout << pluralise( matchedTests, "test case" ) << std::endl;
3532 else
3533 std::cout << pluralise( matchedTests, "matching test case" ) << std::endl;
Phil Nasha695eb92012-08-13 07:46:10 +01003534 }
3535
Phil Nash5bc030d2012-08-16 18:48:50 +01003536 if( ( config.listSpec & List::All ) == 0 ) {
Phil Nash56d5c422012-08-23 20:08:50 +01003537 std::ostringstream oss;
3538 oss << "Unknown list type";
3539 throw std::domain_error( oss.str() );
Phil Nasha695eb92012-08-13 07:46:10 +01003540 }
Phil Nasha695eb92012-08-13 07:46:10 +01003541 }
3542
3543} // end namespace Catch
3544
3545// #included from: internal/catch_runner_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003546#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003547
3548// #included from: catch_running_test.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003549#define TWOBLUECUBES_CATCH_RUNNING_TEST_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003550
3551// #included from: catch_section_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003552#define TWOBLUECUBES_CATCH_SECTION_INFO_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003553
3554#include <map>
3555#include <string>
3556
3557namespace Catch {
3558
3559 class SectionInfo {
3560 public:
3561
3562 enum Status {
3563 Root,
3564 Unknown,
3565 Branch,
3566 TestedBranch,
3567 TestedLeaf
3568 };
3569
3570 SectionInfo( SectionInfo* parent )
3571 : m_status( Unknown ),
3572 m_parent( parent )
3573 {}
3574
3575 SectionInfo()
3576 : m_status( Root ),
3577 m_parent( NULL )
3578 {}
3579
3580 ~SectionInfo() {
3581 deleteAllValues( m_subSections );
3582 }
3583
3584 bool shouldRun() const {
3585 return m_status < TestedBranch;
3586 }
3587
3588 bool ran() {
3589 if( m_status < Branch ) {
3590 m_status = TestedLeaf;
3591 return true;
3592 }
3593 return false;
3594 }
3595
Phil Nasha70fbe32012-08-31 08:10:36 +01003596 bool isBranch() const {
3597 return m_status == Branch;
3598 }
3599
Phil Nasha695eb92012-08-13 07:46:10 +01003600 void ranToCompletion() {
3601 if( m_status == Branch && !hasUntestedSections() )
3602 m_status = TestedBranch;
3603 }
3604
3605 SectionInfo* findSubSection( const std::string& name ) {
3606 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
3607 return it != m_subSections.end()
3608 ? it->second
3609 : NULL;
3610 }
3611
3612 SectionInfo* addSubSection( const std::string& name ) {
3613 SectionInfo* subSection = new SectionInfo( this );
3614 m_subSections.insert( std::make_pair( name, subSection ) );
3615 m_status = Branch;
3616 return subSection;
3617 }
3618
3619 SectionInfo* getParent() {
3620 return m_parent;
3621 }
3622
3623 bool hasUntestedSections() const {
3624 if( m_status == Unknown )
3625 return true;
3626
3627 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3628 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3629 for(; it != itEnd; ++it ) {
3630 if( it->second->hasUntestedSections() )
3631 return true;
3632 }
3633 return false;
3634 }
3635
3636 private:
3637 Status m_status;
3638 std::map<std::string, SectionInfo*> m_subSections;
3639 SectionInfo* m_parent;
3640 };
3641}
3642
3643namespace Catch {
3644
3645 class RunningTest {
3646
3647 enum RunStatus {
3648 NothingRun,
3649 EncounteredASection,
3650 RanAtLeastOneSection,
3651 RanToCompletionWithSections,
3652 RanToCompletionWithNoSections
3653 };
3654
3655 public:
3656 explicit RunningTest( const TestCaseInfo* info = NULL )
3657 : m_info( info ),
3658 m_runStatus( RanAtLeastOneSection ),
3659 m_currentSection( &m_rootSection ),
3660 m_changed( false )
3661 {}
3662
3663 bool wasSectionSeen() const {
3664 return m_runStatus == RanAtLeastOneSection ||
3665 m_runStatus == RanToCompletionWithSections;
3666 }
3667
Phil Nasha70fbe32012-08-31 08:10:36 +01003668 bool isBranchSection() const {
3669 return m_currentSection &&
3670 m_currentSection->isBranch();
3671 }
3672
3673 bool hasSections() const {
3674 return m_runStatus == RanAtLeastOneSection ||
3675 m_runStatus == RanToCompletionWithSections ||
3676 m_runStatus == EncounteredASection;
3677 }
3678
Phil Nasha695eb92012-08-13 07:46:10 +01003679 void reset() {
3680 m_runStatus = NothingRun;
3681 m_changed = false;
3682 m_lastSectionToRun = NULL;
3683 }
3684
3685 void ranToCompletion() {
3686 if( m_runStatus == RanAtLeastOneSection ||
3687 m_runStatus == EncounteredASection ) {
3688 m_runStatus = RanToCompletionWithSections;
3689 if( m_lastSectionToRun ) {
3690 m_lastSectionToRun->ranToCompletion();
3691 m_changed = true;
3692 }
3693 }
3694 else {
3695 m_runStatus = RanToCompletionWithNoSections;
3696 }
3697 }
3698
3699 bool addSection( const std::string& name ) {
3700 if( m_runStatus == NothingRun )
3701 m_runStatus = EncounteredASection;
3702
3703 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3704 if( !thisSection ) {
3705 thisSection = m_currentSection->addSubSection( name );
3706 m_changed = true;
3707 }
3708
3709 if( !wasSectionSeen() && thisSection->shouldRun() ) {
3710 m_currentSection = thisSection;
3711 m_lastSectionToRun = NULL;
3712 return true;
3713 }
3714 return false;
3715 }
3716
3717 void endSection( const std::string& ) {
3718 if( m_currentSection->ran() ) {
3719 m_runStatus = RanAtLeastOneSection;
3720 m_changed = true;
3721 }
3722 else if( m_runStatus == EncounteredASection ) {
3723 m_runStatus = RanAtLeastOneSection;
3724 m_lastSectionToRun = m_currentSection;
3725 }
3726 m_currentSection = m_currentSection->getParent();
3727 }
3728
3729 const TestCaseInfo& getTestCaseInfo() const {
3730 return *m_info;
3731 }
3732
3733 bool hasUntestedSections() const {
3734 return m_runStatus == RanAtLeastOneSection ||
3735 ( m_rootSection.hasUntestedSections() && m_changed );
3736 }
3737
3738 private:
3739 const TestCaseInfo* m_info;
3740 RunStatus m_runStatus;
3741 SectionInfo m_rootSection;
3742 SectionInfo* m_currentSection;
3743 SectionInfo* m_lastSectionToRun;
3744 bool m_changed;
3745 };
3746}
3747
3748#include <set>
3749#include <string>
3750
3751namespace Catch {
3752
3753 class StreamRedirect {
3754
3755 public:
3756 StreamRedirect( std::ostream& stream, std::string& targetString )
3757 : m_stream( stream ),
3758 m_prevBuf( stream.rdbuf() ),
3759 m_targetString( targetString )
3760 {
3761 stream.rdbuf( m_oss.rdbuf() );
3762 }
3763
3764 ~StreamRedirect() {
3765 m_targetString += m_oss.str();
3766 m_stream.rdbuf( m_prevBuf );
3767 }
3768
3769 private:
3770 std::ostream& m_stream;
3771 std::streambuf* m_prevBuf;
3772 std::ostringstream m_oss;
3773 std::string& m_targetString;
3774 };
3775
3776 ///////////////////////////////////////////////////////////////////////////
3777
3778 class Runner : public IResultCapture, public IRunner {
3779
3780 Runner( const Runner& );
3781 void operator =( const Runner& );
3782
3783 public:
3784
Phil Nash56d5c422012-08-23 20:08:50 +01003785 explicit Runner( const Config& config, const Ptr<IReporter>& reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01003786 : m_context( getCurrentMutableContext() ),
3787 m_runningTest( NULL ),
3788 m_config( config ),
3789 m_reporter( reporter ),
3790 m_prevRunner( &m_context.getRunner() ),
3791 m_prevResultCapture( &m_context.getResultCapture() ),
3792 m_prevConfig( m_context.getConfig() )
3793 {
3794 m_context.setRunner( this );
3795 m_context.setConfig( &m_config );
3796 m_context.setResultCapture( this );
3797 m_reporter->StartTesting();
3798 }
3799
3800 virtual ~Runner() {
3801 m_reporter->EndTesting( m_totals );
3802 m_context.setRunner( m_prevRunner );
3803 m_context.setConfig( NULL );
3804 m_context.setResultCapture( m_prevResultCapture );
3805 m_context.setConfig( m_prevConfig );
3806 }
3807
Phil Nash56d5c422012-08-23 20:08:50 +01003808 Totals runMatching( const std::string& testSpec ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003809
Phil Nash56d5c422012-08-23 20:08:50 +01003810 std::vector<TestCaseInfo> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01003811
3812 Totals totals;
Phil Nash5bc030d2012-08-16 18:48:50 +01003813
Phil Nash56d5c422012-08-23 20:08:50 +01003814 m_reporter->StartGroup( testSpec );
3815
3816 std::vector<TestCaseInfo>::const_iterator it = matchingTests.begin();
3817 std::vector<TestCaseInfo>::const_iterator itEnd = matchingTests.end();
3818 for(; it != itEnd; ++it )
3819 totals += runTest( *it );
3820 // !TBD use std::accumulate?
3821
3822 m_reporter->EndGroup( testSpec, totals );
Phil Nash5bc030d2012-08-16 18:48:50 +01003823 return totals;
3824 }
3825
3826 Totals runTest( const TestCaseInfo& testInfo ) {
Phil Nasha695eb92012-08-13 07:46:10 +01003827 Totals prevTotals = m_totals;
3828
3829 std::string redirectedCout;
3830 std::string redirectedCerr;
3831
3832 m_reporter->StartTestCase( testInfo );
3833
3834 m_runningTest = new RunningTest( &testInfo );
3835
3836 do {
3837 do {
Phil Nasha695eb92012-08-13 07:46:10 +01003838 m_currentResult.setLineInfo( m_runningTest->getTestCaseInfo().getLineInfo() );
3839 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01003840 }
3841 while( m_runningTest->hasUntestedSections() && !aborting() );
3842 }
3843 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
3844
3845 delete m_runningTest;
3846 m_runningTest = NULL;
3847
3848 Totals deltaTotals = m_totals.delta( prevTotals );
3849 m_totals.testCases += deltaTotals.testCases;
3850 m_reporter->EndTestCase( testInfo, deltaTotals, redirectedCout, redirectedCerr );
Phil Nash5bc030d2012-08-16 18:48:50 +01003851 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01003852 }
3853
3854 const Config& config() const {
3855 return m_config;
3856 }
3857
3858 private: // IResultCapture
3859
3860 virtual ResultAction::Value acceptResult( bool result ) {
3861 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
3862 }
3863
3864 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) {
3865 m_currentResult.setResultType( result );
3866 return actOnCurrentResult();
3867 }
3868
3869 virtual ResultAction::Value acceptExpression( const ResultInfoBuilder& resultInfo ) {
3870 m_currentResult = resultInfo;
3871 return actOnCurrentResult();
3872 }
3873
3874 virtual void acceptMessage( const std::string& msg ) {
3875 m_currentResult.setMessage( msg );
3876 }
3877
3878 virtual void testEnded( const ResultInfo& result ) {
3879 if( result.getResultType() == ResultWas::Ok ) {
3880 m_totals.assertions.passed++;
3881 }
3882 else if( !result.ok() ) {
3883 m_totals.assertions.failed++;
3884
Phil Nash799ecf92012-09-24 08:30:13 +01003885 {
3886 std::vector<ScopedInfo*>::const_iterator it = m_scopedInfos.begin();
3887 std::vector<ScopedInfo*>::const_iterator itEnd = m_scopedInfos.end();
3888 for(; it != itEnd; ++it )
3889 m_reporter->Result( (*it)->getInfo() );
3890 }
3891 {
3892 std::vector<ResultInfo>::const_iterator it = m_info.begin();
3893 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
3894 for(; it != itEnd; ++it )
3895 m_reporter->Result( *it );
3896 }
Phil Nasha695eb92012-08-13 07:46:10 +01003897 m_info.clear();
3898 }
3899
3900 if( result.getResultType() == ResultWas::Info )
3901 m_info.push_back( result );
3902 else
3903 m_reporter->Result( result );
3904 }
3905
3906 virtual bool sectionStarted (
3907 const std::string& name,
3908 const std::string& description,
3909 const SourceLineInfo& lineInfo,
3910 Counts& assertions
3911 )
3912 {
3913 std::ostringstream oss;
3914 oss << name << "@" << lineInfo;
3915
3916 if( !m_runningTest->addSection( oss.str() ) )
3917 return false;
3918
3919 m_currentResult.setLineInfo( lineInfo );
3920 m_reporter->StartSection( name, description );
3921 assertions = m_totals.assertions;
3922
3923 return true;
3924 }
3925
3926 virtual void sectionEnded( const std::string& name, const Counts& prevAssertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01003927 Counts assertions = m_totals.assertions - prevAssertions;
3928 if( assertions.total() == 0 &&
3929 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
3930 !m_runningTest->isBranchSection() ) {
3931 m_reporter->NoAssertionsInSection( name );
3932 m_totals.assertions.failed++;
3933 assertions.failed++;
3934 }
Phil Nasha695eb92012-08-13 07:46:10 +01003935 m_runningTest->endSection( name );
Phil Nasha70fbe32012-08-31 08:10:36 +01003936 m_reporter->EndSection( name, assertions );
Phil Nasha695eb92012-08-13 07:46:10 +01003937 }
3938
3939 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
3940 m_scopedInfos.push_back( scopedInfo );
3941 }
3942
3943 virtual void popScopedInfo( ScopedInfo* scopedInfo ) {
3944 if( m_scopedInfos.back() == scopedInfo )
3945 m_scopedInfos.pop_back();
3946 }
3947
3948 virtual bool shouldDebugBreak() const {
3949 return m_config.shouldDebugBreak();
3950 }
3951
3952 virtual std::string getCurrentTestName() const {
3953 return m_runningTest
3954 ? m_runningTest->getTestCaseInfo().getName()
3955 : "";
3956 }
3957
3958 virtual const ResultInfo* getLastResult() const {
3959 return &m_lastResult;
3960 }
3961
Phil Nash56d5c422012-08-23 20:08:50 +01003962 public:
3963 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01003964 bool aborting() const {
3965 return m_totals.assertions.failed == static_cast<std::size_t>( m_config.getCutoff() );
3966 }
3967
Phil Nash56d5c422012-08-23 20:08:50 +01003968 private:
3969
Phil Nasha695eb92012-08-13 07:46:10 +01003970 ResultAction::Value actOnCurrentResult() {
Phil Nash67305122012-10-09 11:48:55 +01003971 m_lastResult = m_currentResult.build();
3972 testEnded( m_lastResult );
Phil Nasha695eb92012-08-13 07:46:10 +01003973
3974 m_currentResult = ResultInfoBuilder();
3975
3976 ResultAction::Value action = ResultAction::None;
3977
3978 if( !m_lastResult.ok() ) {
3979 action = ResultAction::Failed;
3980 if( shouldDebugBreak() )
3981 action = (ResultAction::Value)( action | ResultAction::Debug );
3982 if( aborting() )
3983 action = (ResultAction::Value)( action | ResultAction::Abort );
3984 }
3985 return action;
3986 }
3987
3988 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
3989 try {
3990 m_runningTest->reset();
Phil Nasha70fbe32012-08-31 08:10:36 +01003991 Counts prevAssertions = m_totals.assertions;
Phil Nasha695eb92012-08-13 07:46:10 +01003992 if( m_reporter->shouldRedirectStdout() ) {
3993 StreamRedirect coutRedir( std::cout, redirectedCout );
3994 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
3995 m_runningTest->getTestCaseInfo().invoke();
3996 }
3997 else {
3998 m_runningTest->getTestCaseInfo().invoke();
3999 }
Phil Nasha70fbe32012-08-31 08:10:36 +01004000 Counts assertions = m_totals.assertions - prevAssertions;
4001 if( assertions.total() == 0 &&
4002 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
4003 !m_runningTest->hasSections() ) {
4004 m_totals.assertions.failed++;
4005 m_reporter->NoAssertionsInTestCase( m_runningTest->getTestCaseInfo().getName() );
4006 }
Phil Nasha695eb92012-08-13 07:46:10 +01004007 m_runningTest->ranToCompletion();
4008 }
4009 catch( TestFailureException& ) {
4010 // This just means the test was aborted due to failure
4011 }
4012 catch(...) {
4013 acceptMessage( getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() );
4014 acceptResult( ResultWas::ThrewException );
4015 }
4016 m_info.clear();
4017 }
4018
4019 private:
4020 IMutableContext& m_context;
4021 RunningTest* m_runningTest;
4022 ResultInfoBuilder m_currentResult;
4023 ResultInfo m_lastResult;
4024
4025 const Config& m_config;
4026 Totals m_totals;
4027 Ptr<IReporter> m_reporter;
4028 std::vector<ScopedInfo*> m_scopedInfos;
4029 std::vector<ResultInfo> m_info;
4030 IRunner* m_prevRunner;
4031 IResultCapture* m_prevResultCapture;
4032 const IConfig* m_prevConfig;
4033 };
4034
4035} // end namespace Catch
4036
Phil Nash89d1e6c2011-05-24 08:23:02 +01004037#include <fstream>
4038#include <stdlib.h>
4039#include <limits>
4040
Phil Nash89d2a3f2012-05-16 15:09:17 +01004041namespace Catch {
4042
Phil Nash56d5c422012-08-23 20:08:50 +01004043 class Runner2 { // This will become Runner when Runner becomes Context
Phil Nash163088a2012-05-31 19:40:26 +01004044
Phil Nash56d5c422012-08-23 20:08:50 +01004045 public:
4046 Runner2( Config& configWrapper )
4047 : m_configWrapper( configWrapper ),
4048 m_config( configWrapper.data() )
Phil Nash06e959b2012-05-25 08:52:05 +01004049 {
Phil Nash67ec8702012-09-26 18:38:26 +01004050 openStream();
Phil Nash56d5c422012-08-23 20:08:50 +01004051 makeReporter();
4052 }
Phil Nash06e959b2012-05-25 08:52:05 +01004053
Phil Nash56d5c422012-08-23 20:08:50 +01004054 Totals runTests() {
4055
4056 std::vector<TestCaseFilters> filterGroups = m_config.filters;
4057 if( filterGroups.empty() ) {
4058 TestCaseFilters filterGroup( "" );
Phil Nash56d5c422012-08-23 20:08:50 +01004059 filterGroups.push_back( filterGroup );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004060 }
Phil Nash56d5c422012-08-23 20:08:50 +01004061
4062 Runner context( m_configWrapper, m_reporter ); // This Runner will be renamed Context
4063 Totals totals;
4064
4065 std::vector<TestCaseFilters>::const_iterator it = filterGroups.begin();
4066 std::vector<TestCaseFilters>::const_iterator itEnd = filterGroups.end();
Phil Nashe2d215e2012-09-07 17:52:35 +01004067 for(; it != itEnd && !context.aborting(); ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004068 m_reporter->StartGroup( it->getName() );
Phil Nash62b70392012-08-31 18:46:13 +01004069 totals += runTestsForGroup( context, *it );
Phil Nash56d5c422012-08-23 20:08:50 +01004070 if( context.aborting() )
4071 m_reporter->Aborted();
4072 m_reporter->EndGroup( it->getName(), totals );
4073 }
4074 return totals;
4075 }
4076
4077 Totals runTestsForGroup( Runner& context, const TestCaseFilters& filterGroup ) {
4078 Totals totals;
4079 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
4080 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
4081 int testsRunForGroup = 0;
4082 for(; it != itEnd; ++it ) {
4083 if( filterGroup.shouldInclude( *it ) ) {
4084 testsRunForGroup++;
4085 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
4086
4087 if( context.aborting() )
4088 break;
4089
4090 totals += context.runTest( *it );
4091 m_testsAlreadyRun.insert( *it );
4092 }
Phil Nash06e959b2012-05-25 08:52:05 +01004093 }
4094 }
Phil Nash56d5c422012-08-23 20:08:50 +01004095 if( testsRunForGroup == 0 )
4096 std::cerr << "\n[No test cases matched with: " << filterGroup.getName() << "]" << std::endl;
4097 return totals;
4098
Phil Nash89d1e6c2011-05-24 08:23:02 +01004099 }
Phil Nash56d5c422012-08-23 20:08:50 +01004100
4101 private:
Phil Nash67ec8702012-09-26 18:38:26 +01004102 void openStream() {
4103 if( !m_config.stream.empty() )
4104 m_configWrapper.useStream( m_config.stream );
4105
Phil Nash56d5c422012-08-23 20:08:50 +01004106 // Open output file, if specified
4107 if( !m_config.outputFilename.empty() ) {
4108 m_ofs.open( m_config.outputFilename.c_str() );
4109 if( m_ofs.fail() ) {
4110 std::ostringstream oss;
4111 oss << "Unable to open file: '" << m_config.outputFilename << "'";
4112 throw std::domain_error( oss.str() );
4113 }
4114 m_configWrapper.setStreamBuf( m_ofs.rdbuf() );
4115 }
4116 }
4117 void makeReporter() {
4118 std::string reporterName = m_config.reporter.empty()
4119 ? "basic"
4120 : m_config.reporter;
4121
Phil Nasha70fbe32012-08-31 08:10:36 +01004122 ReporterConfig reporterConfig( m_config.name, m_configWrapper.stream(), m_config.includeWhichResults == Include::SuccessfulResults, m_config );
Phil Nash56d5c422012-08-23 20:08:50 +01004123
4124 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, reporterConfig );
4125 if( !m_reporter ) {
4126 std::ostringstream oss;
4127 oss << "No reporter registered with name: '" << reporterName << "'";
4128 throw std::domain_error( oss.str() );
4129 }
4130 }
4131
4132 private:
4133 Config& m_configWrapper;
4134 const ConfigData& m_config;
4135 std::ofstream m_ofs;
4136 Ptr<IReporter> m_reporter;
4137 std::set<TestCaseInfo> m_testsAlreadyRun;
4138 };
4139
4140 inline int Main( Config& configWrapper ) {
4141 int result = 0;
4142 try
4143 {
4144 Runner2 runner( configWrapper );
4145
4146 const ConfigData& config = configWrapper.data();
4147
4148 // Handle list request
4149 if( config.listSpec != List::None ) {
4150 List( config );
Phil Nash799ecf92012-09-24 08:30:13 +01004151 Catch::cleanUp();
Phil Nash56d5c422012-08-23 20:08:50 +01004152 return 0;
4153 }
4154
4155 result = static_cast<int>( runner.runTests().assertions.failed );
4156
4157 }
4158 catch( std::exception& ex ) {
4159 std::cerr << ex.what() << std::endl;
4160 result = (std::numeric_limits<int>::max)();
4161 }
4162
Phil Nash3b80af72012-08-09 07:47:30 +01004163 Catch::cleanUp();
Phil Nash371db8b2012-05-21 18:52:09 +01004164 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004165 }
4166
Phil Nash163088a2012-05-31 19:40:26 +01004167 inline void showUsage( std::ostream& os ) {
Phil Nashecf934b2012-08-27 21:42:55 +01004168 AllOptions options;
Phil Nashe2d215e2012-09-07 17:52:35 +01004169
Phil Nashecf934b2012-08-27 21:42:55 +01004170 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4171 OptionParser& opt = **it;
4172 os << " " << opt.optionNames() << " " << opt.argsSynopsis() << "\n";
4173 }
4174 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 +01004175 }
Phil Nashe2d215e2012-09-07 17:52:35 +01004176
4177 inline void addIndent( std::ostream& os, std::size_t indent ) {
4178 while( indent-- > 0 )
4179 os << ' ';
4180 }
4181
4182 inline void recursivelyWrapLine( std::ostream& os, std::string paragraph, std::size_t columns, std::size_t indent ) {
4183 std::size_t width = columns-indent;
4184 std::size_t tab = 0;
4185 std::size_t wrapPoint = width;
4186 for( std::size_t pos = 0; pos < paragraph.size(); ++pos ) {
4187 if( pos == width ) {
4188 addIndent( os, indent );
4189 os << paragraph.substr( 0, wrapPoint ) << "\n";
4190 return recursivelyWrapLine( os, paragraph.substr( wrapPoint+1 ), columns, indent+tab );
4191 }
4192 if( paragraph[pos] == '\t' ) {
4193 tab = pos;
4194 paragraph = paragraph.substr( 0, tab ) + paragraph.substr( tab+1 );
4195 pos--;
4196 }
4197 else if( paragraph[pos] == ' ' ) {
4198 wrapPoint = pos;
4199 }
4200 }
4201 addIndent( os, indent );
4202 os << paragraph << "\n";
4203 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004204
Phil Nashe2d215e2012-09-07 17:52:35 +01004205 inline std::string addLineBreaks( const std::string& str, std::size_t columns, std::size_t indent = 0 ) {
4206 std::ostringstream oss;
4207 std::string::size_type pos = 0;
4208 std::string::size_type newline = str.find_first_of( '\n' );
4209 while( newline != std::string::npos ) {
4210 std::string paragraph = str.substr( pos, newline-pos );
4211 recursivelyWrapLine( oss, paragraph, columns, indent );
4212 pos = newline+1;
4213 newline = str.find_first_of( '\n', pos );
4214 }
Phil Nashf7418eb2012-09-09 11:44:30 +01004215 if( pos != str.size() )
4216 recursivelyWrapLine( oss, str.substr( pos, str.size()-pos ), columns, indent );
4217
Phil Nashe2d215e2012-09-07 17:52:35 +01004218 return oss.str();
4219 }
4220
4221 inline void showHelp( const CommandParser& parser ) {
4222 std::string exeName = parser.exeName();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004223 std::string::size_type pos = exeName.find_last_of( "/\\" );
Phil Nash89d2a3f2012-05-16 15:09:17 +01004224 if( pos != std::string::npos ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004225 exeName = exeName.substr( pos+1 );
4226 }
4227
Phil Nashe2d215e2012-09-07 17:52:35 +01004228 AllOptions options;
4229 Options::HelpOptionParser helpOpt;
4230 bool displayedSpecificOption = false;
4231 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
4232 OptionParser& opt = **it;
4233 if( opt.find( parser ) && opt.optionNames() != helpOpt.optionNames() ) {
4234 displayedSpecificOption = true;
4235 std::cout << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n"
4236 << opt.optionSummary() << "\n\n"
4237
4238 << addLineBreaks( opt.optionDescription(), 80, 2 ) << "\n" << std::endl;
4239 }
4240 }
4241
4242 if( !displayedSpecificOption ) {
4243 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n";
4244 showUsage( std::cout );
4245 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004246 }
4247
Phil Nash89d2a3f2012-05-16 15:09:17 +01004248 inline int Main( int argc, char* const argv[], Config& config ) {
Phil Nash163088a2012-05-31 19:40:26 +01004249
Phil Nashabf27162012-07-05 18:37:58 +01004250 try {
4251 CommandParser parser( argc, argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004252
Phil Nashecf934b2012-08-27 21:42:55 +01004253 if( Command cmd = Options::HelpOptionParser().find( parser ) ) {
Phil Nashabf27162012-07-05 18:37:58 +01004254 if( cmd.argsCount() != 0 )
4255 cmd.raiseError( "Does not accept arguments" );
4256
Phil Nashe2d215e2012-09-07 17:52:35 +01004257 showHelp( parser );
Phil Nash3b80af72012-08-09 07:47:30 +01004258 Catch::cleanUp();
Phil Nashabf27162012-07-05 18:37:58 +01004259 return 0;
4260 }
4261
Phil Nashecf934b2012-08-27 21:42:55 +01004262 AllOptions options;
4263
4264 options.parseIntoConfig( parser, config.data() );
Phil Nashabf27162012-07-05 18:37:58 +01004265 }
4266 catch( std::exception& ex ) {
Phil Nash6f220862012-07-23 08:24:52 +01004267 std::cerr << ex.what() << "\n\nUsage: ...\n\n";
Phil Nash163088a2012-05-31 19:40:26 +01004268 showUsage( std::cerr );
Phil Nash3b80af72012-08-09 07:47:30 +01004269 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01004270 return (std::numeric_limits<int>::max)();
4271 }
4272
Phil Nash89d1e6c2011-05-24 08:23:02 +01004273 return Main( config );
4274 }
4275
Phil Nash89d2a3f2012-05-16 15:09:17 +01004276 inline int Main( int argc, char* const argv[] ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01004277 Config config;
Phil Nash371db8b2012-05-21 18:52:09 +01004278// !TBD: This doesn't always work, for some reason
Phil Nash89d1e6c2011-05-24 08:23:02 +01004279// if( isDebuggerActive() )
4280// config.useStream( "debug" );
Phil Nash371db8b2012-05-21 18:52:09 +01004281 return Main( argc, argv, config );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004282 }
4283
4284} // end namespace Catch
4285
Phil Nash3b80af72012-08-09 07:47:30 +01004286// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004287#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004288
4289// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004290#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004291
4292#include <vector>
4293#include <set>
4294#include <sstream>
4295#include <iostream>
4296
4297namespace Catch {
4298
4299 class TestRegistry : public ITestCaseRegistry {
4300 public:
4301 TestRegistry() : m_unnamedCount( 0 ) {}
Phil Nasha695eb92012-08-13 07:46:10 +01004302 virtual ~TestRegistry();
Phil Nash3b80af72012-08-09 07:47:30 +01004303
4304 virtual void registerTest( const TestCaseInfo& testInfo ) {
4305 if( testInfo.getName() == "" ) {
4306 std::ostringstream oss;
4307 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
4308 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
4309 }
4310
4311 if( m_functions.find( testInfo ) == m_functions.end() ) {
4312 m_functions.insert( testInfo );
4313 m_functionsInOrder.push_back( testInfo );
Phil Nash5bc030d2012-08-16 18:48:50 +01004314 if( !testInfo.isHidden() )
4315 m_nonHiddenFunctions.push_back( testInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01004316 }
4317 else {
4318 const TestCaseInfo& prev = *m_functions.find( testInfo );
4319 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n"
4320 << "\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) << "\n"
4321 << "\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl;
4322 exit(1);
4323 }
4324 }
4325
4326 virtual const std::vector<TestCaseInfo>& getAllTests() const {
4327 return m_functionsInOrder;
4328 }
4329
Phil Nash5bc030d2012-08-16 18:48:50 +01004330 virtual const std::vector<TestCaseInfo>& getAllNonHiddenTests() const {
4331 return m_nonHiddenFunctions;
4332 }
4333
Phil Nash56d5c422012-08-23 20:08:50 +01004334 // !TBD deprecated
Phil Nash3b80af72012-08-09 07:47:30 +01004335 virtual std::vector<TestCaseInfo> getMatchingTestCases( const std::string& rawTestSpec ) const {
Phil Nash5bc030d2012-08-16 18:48:50 +01004336 std::vector<TestCaseInfo> matchingTests;
4337 getMatchingTestCases( rawTestSpec, matchingTests );
4338 return matchingTests;
4339 }
4340
Phil Nash56d5c422012-08-23 20:08:50 +01004341 // !TBD deprecated
Phil Nash5bc030d2012-08-16 18:48:50 +01004342 virtual void getMatchingTestCases( const std::string& rawTestSpec, std::vector<TestCaseInfo>& matchingTestsOut ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01004343 TestCaseFilter filter( rawTestSpec );
Phil Nash5bc030d2012-08-16 18:48:50 +01004344
Phil Nash3b80af72012-08-09 07:47:30 +01004345 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4346 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4347 for(; it != itEnd; ++it ) {
Phil Nash56d5c422012-08-23 20:08:50 +01004348 if( filter.shouldInclude( *it ) ) {
Phil Nash5bc030d2012-08-16 18:48:50 +01004349 matchingTestsOut.push_back( *it );
Phil Nash3b80af72012-08-09 07:47:30 +01004350 }
4351 }
Phil Nash3b80af72012-08-09 07:47:30 +01004352 }
Phil Nash56d5c422012-08-23 20:08:50 +01004353 virtual void getMatchingTestCases( const TestCaseFilters& filters, std::vector<TestCaseInfo>& matchingTestsOut ) const {
4354 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
4355 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
4356 // !TBD: replace with algorithm
4357 for(; it != itEnd; ++it )
4358 if( filters.shouldInclude( *it ) )
4359 matchingTestsOut.push_back( *it );
4360 }
Phil Nash3b80af72012-08-09 07:47:30 +01004361
4362 private:
4363
4364 std::set<TestCaseInfo> m_functions;
4365 std::vector<TestCaseInfo> m_functionsInOrder;
Phil Nash5bc030d2012-08-16 18:48:50 +01004366 std::vector<TestCaseInfo> m_nonHiddenFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01004367 size_t m_unnamedCount;
4368 };
4369
4370 ///////////////////////////////////////////////////////////////////////////
4371
Phil Nash5bc030d2012-08-16 18:48:50 +01004372 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
Phil Nash3b80af72012-08-09 07:47:30 +01004373 public:
4374
4375 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
4376
4377 virtual void invoke() const {
4378 m_fun();
4379 }
4380
Phil Nash3b80af72012-08-09 07:47:30 +01004381 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01004382 virtual ~FreeFunctionTestCase();
4383
Phil Nash3b80af72012-08-09 07:47:30 +01004384 TestFunction m_fun;
4385 };
4386
4387 ///////////////////////////////////////////////////////////////////////////
4388
4389 AutoReg::AutoReg( TestFunction function,
4390 const char* name,
4391 const char* description,
4392 const SourceLineInfo& lineInfo ) {
4393 registerTestCase( new FreeFunctionTestCase( function ), name, description, lineInfo );
4394 }
4395
4396 AutoReg::~AutoReg() {}
4397
4398 void AutoReg::registerTestCase( ITestCase* testCase,
4399 const char* name,
4400 const char* description,
4401 const SourceLineInfo& lineInfo ) {
4402 getMutableRegistryHub().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) );
4403 }
4404
4405} // end namespace Catch
4406
4407// #included from: catch_reporter_registry.hpp
4408#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
4409
4410#include <map>
4411
4412namespace Catch {
4413
4414 class ReporterRegistry : public IReporterRegistry {
4415
4416 public:
4417
Phil Nasha695eb92012-08-13 07:46:10 +01004418 virtual ~ReporterRegistry() {
Phil Nash3b80af72012-08-09 07:47:30 +01004419 deleteAllValues( m_factories );
4420 }
4421
4422 virtual IReporter* create( const std::string& name, const ReporterConfig& config ) const {
4423 FactoryMap::const_iterator it = m_factories.find( name );
4424 if( it == m_factories.end() )
4425 return NULL;
4426 return it->second->create( config );
4427 }
4428
4429 void registerReporter( const std::string& name, IReporterFactory* factory ) {
4430 m_factories.insert( std::make_pair( name, factory ) );
4431 }
4432
4433 const FactoryMap& getFactories() const {
4434 return m_factories;
4435 }
4436
4437 private:
4438 FactoryMap m_factories;
4439 };
4440}
4441
4442// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004443#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004444
4445#ifdef __OBJC__
4446#import "Foundation/Foundation.h"
4447#endif
4448
4449namespace Catch {
4450
4451 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
4452 public:
4453 ~ExceptionTranslatorRegistry() {
4454 deleteAll( m_translators );
4455 }
4456
4457 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4458 m_translators.push_back( translator );
4459 }
4460
4461 virtual std::string translateActiveException() const {
4462 try {
4463#ifdef __OBJC__
4464 // In Objective-C try objective-c exceptions first
4465 @try {
4466 throw;
4467 }
4468 @catch (NSException *exception) {
4469 return toString( [exception description] );
4470 }
4471#else
4472 throw;
4473#endif
4474 }
4475 catch( std::exception& ex ) {
4476 return ex.what();
4477 }
4478 catch( std::string& msg ) {
4479 return msg;
4480 }
4481 catch( const char* msg ) {
4482 return msg;
4483 }
4484 catch(...) {
4485 return tryTranslators( m_translators.begin() );
4486 }
4487 }
4488
4489 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
4490 if( it == m_translators.end() )
4491 return "Unknown exception";
4492
4493 try {
4494 return (*it)->translate();
4495 }
4496 catch(...) {
4497 return tryTranslators( it+1 );
4498 }
4499 }
4500
4501 private:
4502 std::vector<const IExceptionTranslator*> m_translators;
4503 };
4504}
4505
4506namespace Catch {
4507
4508 namespace {
4509
4510 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
4511
4512 RegistryHub( const RegistryHub& );
4513 void operator=( const RegistryHub& );
4514
4515 public: // IRegistryHub
4516 RegistryHub() {
4517 }
4518 virtual const IReporterRegistry& getReporterRegistry() const {
4519 return m_reporterRegistry;
4520 }
4521 virtual const ITestCaseRegistry& getTestCaseRegistry() const {
4522 return m_testCaseRegistry;
4523 }
4524 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
4525 return m_exceptionTranslatorRegistry;
4526 }
4527
4528 public: // IMutableRegistryHub
4529 virtual void registerReporter( const std::string& name, IReporterFactory* factory ) {
4530 m_reporterRegistry.registerReporter( name, factory );
4531 }
4532 virtual void registerTest( const TestCaseInfo& testInfo ) {
4533 m_testCaseRegistry.registerTest( testInfo );
4534 }
4535 virtual void registerTranslator( const IExceptionTranslator* translator ) {
4536 m_exceptionTranslatorRegistry.registerTranslator( translator );
4537 }
4538
4539 private:
4540 TestRegistry m_testCaseRegistry;
4541 ReporterRegistry m_reporterRegistry;
4542 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
4543 };
4544
4545 // Single, global, instance
4546 inline RegistryHub*& getTheRegistryHub() {
4547 static RegistryHub* theRegistryHub = NULL;
4548 if( !theRegistryHub )
4549 theRegistryHub = new RegistryHub();
4550 return theRegistryHub;
4551 }
4552 }
4553
4554 IRegistryHub& getRegistryHub() {
4555 return *getTheRegistryHub();
4556 }
4557 IMutableRegistryHub& getMutableRegistryHub() {
4558 return *getTheRegistryHub();
4559 }
4560 void cleanUp() {
4561 delete getTheRegistryHub();
4562 getTheRegistryHub() = NULL;
4563 cleanUpContext();
4564 }
4565
4566} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04004567
Phil Nash3b80af72012-08-09 07:47:30 +01004568// #included from: catch_notimplemented_exception.hpp
4569#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
4570
4571#include <ostream>
4572
4573namespace Catch {
4574
4575 NotImplementedException::NotImplementedException( const SourceLineInfo& lineInfo )
4576 : m_lineInfo( lineInfo ) {
4577 std::ostringstream oss;
4578 oss << lineInfo << "function ";
4579 if( !lineInfo.function.empty() )
4580 oss << lineInfo.function << " ";
4581 oss << "not implemented";
4582 m_what = oss.str();
4583 }
4584
4585 const char* NotImplementedException::what() const throw() {
4586 return m_what.c_str();
4587 }
4588
4589} // end namespace Catch
4590
4591// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004592#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004593
Phil Nash3b80af72012-08-09 07:47:30 +01004594namespace Catch {
4595
4596 class Context : public IMutableContext {
4597
4598 Context() : m_config( NULL ) {}
4599 Context( const Context& );
4600 void operator=( const Context& );
4601
4602 public: // IContext
4603 virtual IResultCapture& getResultCapture() {
4604 return *m_resultCapture;
4605 }
4606 virtual IRunner& getRunner() {
4607 return *m_runner;
4608 }
4609 virtual size_t getGeneratorIndex( const std::string& fileInfo, size_t totalSize ) {
4610 return getGeneratorsForCurrentTest()
4611 .getGeneratorInfo( fileInfo, totalSize )
4612 .getCurrentIndex();
4613 }
4614 virtual bool advanceGeneratorsForCurrentTest() {
4615 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4616 return generators && generators->moveNext();
4617 }
4618
4619 virtual const IConfig* getConfig() const {
4620 return m_config;
4621 }
4622
4623 public: // IMutableContext
4624 virtual void setResultCapture( IResultCapture* resultCapture ) {
4625 m_resultCapture = resultCapture;
4626 }
4627 virtual void setRunner( IRunner* runner ) {
4628 m_runner = runner;
4629 }
4630 virtual void setConfig( const IConfig* config ) {
4631 m_config = config;
4632 }
4633
4634 friend IMutableContext& getCurrentMutableContext();
4635
4636 private:
4637 IGeneratorsForTest* findGeneratorsForCurrentTest() {
4638 std::string testName = getResultCapture().getCurrentTestName();
4639
4640 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
4641 m_generatorsByTestName.find( testName );
4642 return it != m_generatorsByTestName.end()
4643 ? it->second
4644 : NULL;
4645 }
4646
4647 IGeneratorsForTest& getGeneratorsForCurrentTest() {
4648 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4649 if( !generators ) {
4650 std::string testName = getResultCapture().getCurrentTestName();
4651 generators = createGeneratorsForTest();
4652 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4653 }
4654 return *generators;
4655 }
4656
4657 private:
4658 IRunner* m_runner;
4659 IResultCapture* m_resultCapture;
4660 const IConfig* m_config;
4661 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
4662 };
4663
4664 namespace {
4665 Context* currentContext = NULL;
4666 }
4667 IMutableContext& getCurrentMutableContext() {
4668 if( !currentContext )
4669 currentContext = new Context();
4670 return *currentContext;
4671 }
4672 IContext& getCurrentContext() {
4673 return getCurrentMutableContext();
4674 }
4675
Phil Nash67ec8702012-09-26 18:38:26 +01004676 Stream createStream( const std::string& streamName ) {
4677 if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false );
4678 if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false );
4679 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
Phil Nash3b80af72012-08-09 07:47:30 +01004680
4681 throw std::domain_error( "Unknown stream: " + streamName );
4682 }
4683
4684 void cleanUpContext() {
4685 delete currentContext;
4686 currentContext = NULL;
4687 }
4688}
Matt Wozniskif29c8982012-09-17 01:42:29 -04004689
Phil Nash3b80af72012-08-09 07:47:30 +01004690// #included from: catch_console_colour_impl.hpp
4691#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
4692
Phil Nash56d5c422012-08-23 20:08:50 +01004693// #included from: catch_console_colour.hpp
4694#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4695
4696namespace Catch {
4697
4698 struct ConsoleColourImpl;
4699
4700 class TextColour : NonCopyable {
4701 public:
4702
4703 enum Colours {
4704 None,
4705
4706 FileName,
4707 ResultError,
4708 ResultSuccess,
4709
4710 Error,
4711 Success,
4712
4713 OriginalExpression,
4714 ReconstructedExpression
4715 };
4716
4717 TextColour( Colours colour = None );
4718 void set( Colours colour );
4719 ~TextColour();
4720
4721 private:
4722 ConsoleColourImpl* m_impl;
4723 };
4724
4725} // end namespace Catch
4726
Phil Nash3b80af72012-08-09 07:47:30 +01004727#ifdef CATCH_PLATFORM_WINDOWS
4728
4729#include <windows.h>
4730
4731namespace Catch {
4732
4733 namespace {
4734
4735 WORD mapConsoleColour( TextColour::Colours colour ) {
4736 switch( colour ) {
4737 case TextColour::FileName:
4738 return FOREGROUND_INTENSITY; // greyed out
4739 case TextColour::ResultError:
4740 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
4741 case TextColour::ResultSuccess:
4742 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
4743 case TextColour::Error:
4744 return FOREGROUND_RED; // dark red
4745 case TextColour::Success:
4746 return FOREGROUND_GREEN; // dark green
4747 case TextColour::OriginalExpression:
4748 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
4749 case TextColour::ReconstructedExpression:
4750 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
4751 default: return 0;
4752 }
4753 }
4754 }
4755
4756 struct ConsoleColourImpl {
4757
4758 ConsoleColourImpl()
4759 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
4760 wOldColorAttrs( 0 )
4761 {
4762 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
4763 wOldColorAttrs = csbiInfo.wAttributes;
4764 }
4765
4766 ~ConsoleColourImpl() {
4767 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
4768 }
4769
4770 void set( TextColour::Colours colour ) {
4771 WORD consoleColour = mapConsoleColour( colour );
4772 if( consoleColour > 0 )
4773 SetConsoleTextAttribute( hStdout, consoleColour );
4774 }
4775
4776 HANDLE hStdout;
4777 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
4778 WORD wOldColorAttrs;
4779 };
4780
4781 TextColour::TextColour( Colours colour )
4782 : m_impl( new ConsoleColourImpl() )
4783 {
4784 if( colour )
4785 m_impl->set( colour );
4786 }
4787
4788 TextColour::~TextColour() {
4789 delete m_impl;
4790 }
4791
4792 void TextColour::set( Colours colour ) {
4793 m_impl->set( colour );
4794 }
4795
4796} // end namespace Catch
4797
4798#else
4799
4800namespace Catch {
4801 TextColour::TextColour( Colours ){}
4802 TextColour::~TextColour(){}
4803 void TextColour::set( Colours ){}
4804
4805} // end namespace Catch
4806
4807#endif
4808
4809// #included from: catch_generators_impl.hpp
4810#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
4811
4812#include <vector>
4813#include <string>
4814#include <map>
4815
4816namespace Catch {
4817
4818 struct GeneratorInfo : IGeneratorInfo {
4819
4820 GeneratorInfo( std::size_t size )
4821 : m_size( size ),
4822 m_currentIndex( 0 )
4823 {}
4824
4825 bool moveNext() {
4826 if( ++m_currentIndex == m_size ) {
4827 m_currentIndex = 0;
4828 return false;
4829 }
4830 return true;
4831 }
4832
4833 std::size_t getCurrentIndex() const {
4834 return m_currentIndex;
4835 }
4836
4837 std::size_t m_size;
4838 std::size_t m_currentIndex;
4839 };
4840
4841 ///////////////////////////////////////////////////////////////////////////
4842
4843 class GeneratorsForTest : public IGeneratorsForTest {
4844
4845 public:
4846 ~GeneratorsForTest() {
4847 deleteAll( m_generatorsInOrder );
4848 }
4849
4850 IGeneratorInfo& getGeneratorInfo( const std::string& fileInfo, std::size_t size ) {
4851 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
4852 if( it == m_generatorsByName.end() ) {
4853 IGeneratorInfo* info = new GeneratorInfo( size );
4854 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
4855 m_generatorsInOrder.push_back( info );
4856 return *info;
4857 }
4858 return *it->second;
4859 }
4860
4861 bool moveNext() {
4862 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
4863 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
4864 for(; it != itEnd; ++it ) {
4865 if( (*it)->moveNext() )
4866 return true;
4867 }
4868 return false;
4869 }
4870
4871 private:
4872 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
4873 std::vector<IGeneratorInfo*> m_generatorsInOrder;
4874 };
4875
4876 IGeneratorsForTest* createGeneratorsForTest()
4877 {
4878 return new GeneratorsForTest();
4879 }
4880
4881} // end namespace Catch
4882
4883// #included from: catch_resultinfo.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04004884#define TWOBLUECUBES_CATCH_RESULTINFO_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01004885
4886namespace Catch {
4887
Phil Nash67305122012-10-09 11:48:55 +01004888 ResultInfo::ResultInfo() {}
Phil Nash3b80af72012-08-09 07:47:30 +01004889
Phil Nash67305122012-10-09 11:48:55 +01004890 ResultInfo::ResultInfo( const ResultData& data ) : m_data( data ) {}
Phil Nash3b80af72012-08-09 07:47:30 +01004891
4892 ResultInfo::~ResultInfo() {}
4893
4894 bool ResultInfo::ok() const {
Phil Nash67305122012-10-09 11:48:55 +01004895 return isOk( m_data.resultType );
Phil Nash3b80af72012-08-09 07:47:30 +01004896 }
4897
4898 ResultWas::OfType ResultInfo::getResultType() const {
Phil Nash67305122012-10-09 11:48:55 +01004899 return m_data.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01004900 }
4901
4902 bool ResultInfo::hasExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01004903 return !m_data.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01004904 }
4905
4906 bool ResultInfo::hasMessage() const {
Phil Nash67305122012-10-09 11:48:55 +01004907 return !m_data.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01004908 }
4909
4910 std::string ResultInfo::getExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01004911 return m_data.capturedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01004912 }
4913
4914 bool ResultInfo::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01004915 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01004916 }
4917
4918 std::string ResultInfo::getExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01004919 return m_data.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01004920 }
4921
4922 std::string ResultInfo::getMessage() const {
Phil Nash67305122012-10-09 11:48:55 +01004923 return m_data.message;
Phil Nash3b80af72012-08-09 07:47:30 +01004924 }
4925
4926 std::string ResultInfo::getFilename() const {
Phil Nash67305122012-10-09 11:48:55 +01004927 return m_data.lineInfo.file;
Phil Nash3b80af72012-08-09 07:47:30 +01004928 }
4929
4930 std::size_t ResultInfo::getLine() const {
Phil Nash67305122012-10-09 11:48:55 +01004931 return m_data.lineInfo.line;
Phil Nash3b80af72012-08-09 07:47:30 +01004932 }
4933
4934 std::string ResultInfo::getTestMacroName() const {
Phil Nash67305122012-10-09 11:48:55 +01004935 return m_data.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01004936 }
4937
4938} // end namespace Catch
4939
4940// #included from: catch_resultinfo_builder.hpp
4941#define TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_HPP_INCLUDED
4942
4943namespace Catch {
4944
Phil Nash803f6b72012-10-04 08:14:48 +01004945 ResultInfoBuilder::ResultInfoBuilder() {}
4946
4947 ResultInfoBuilder& ResultInfoBuilder::setResultType( ResultWas::OfType result ) {
Phil Nash3b80af72012-08-09 07:47:30 +01004948 // Flip bool results if isNot is set
4949 if( m_isNot && result == ResultWas::Ok )
Phil Nash67305122012-10-09 11:48:55 +01004950 m_data.resultType = ResultWas::ExpressionFailed;
Phil Nash3b80af72012-08-09 07:47:30 +01004951 else if( m_isNot && result == ResultWas::ExpressionFailed )
Phil Nash67305122012-10-09 11:48:55 +01004952 m_data.resultType = ResultWas::Ok;
Phil Nash3b80af72012-08-09 07:47:30 +01004953 else
Phil Nash67305122012-10-09 11:48:55 +01004954 m_data.resultType = result;
4955 return *this;
4956 }
4957 ResultInfoBuilder& ResultInfoBuilder::setCapturedExpression( const std::string& capturedExpression ) {
4958 m_data.capturedExpression = capturedExpression;
4959 return *this;
4960 }
4961 ResultInfoBuilder& ResultInfoBuilder::setIsFalse( bool isFalse ) {
4962 m_isNot = isFalse;
Phil Nash803f6b72012-10-04 08:14:48 +01004963 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01004964 }
4965
Phil Nash803f6b72012-10-04 08:14:48 +01004966 ResultInfoBuilder& ResultInfoBuilder::setMessage( const std::string& message ) {
Phil Nash67305122012-10-09 11:48:55 +01004967 m_data.message = message;
Phil Nash803f6b72012-10-04 08:14:48 +01004968 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01004969 }
4970
Phil Nash803f6b72012-10-04 08:14:48 +01004971 ResultInfoBuilder& ResultInfoBuilder::setLineInfo( const SourceLineInfo& lineInfo ) {
Phil Nash67305122012-10-09 11:48:55 +01004972 m_data.lineInfo = lineInfo;
4973 return *this;
4974 }
4975
4976 ResultInfoBuilder& ResultInfoBuilder::setMacroName( const std::string& macroName ) {
4977 m_data.macroName = macroName;
Phil Nash803f6b72012-10-04 08:14:48 +01004978 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01004979 }
4980
Phil Nash803f6b72012-10-04 08:14:48 +01004981 ResultInfoBuilder& ResultInfoBuilder::setLhs( const std::string& lhs ) {
Phil Nash3b80af72012-08-09 07:47:30 +01004982 m_lhs = lhs;
Phil Nash803f6b72012-10-04 08:14:48 +01004983 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01004984 }
4985
Phil Nash803f6b72012-10-04 08:14:48 +01004986 ResultInfoBuilder& ResultInfoBuilder::setRhs( const std::string& rhs ) {
Phil Nash3b80af72012-08-09 07:47:30 +01004987 m_rhs = rhs;
Phil Nash803f6b72012-10-04 08:14:48 +01004988 return *this;
Phil Nash3b80af72012-08-09 07:47:30 +01004989 }
4990
Phil Nash803f6b72012-10-04 08:14:48 +01004991 ResultInfoBuilder& ResultInfoBuilder::setOp( const std::string& op ) {
Phil Nash3b80af72012-08-09 07:47:30 +01004992 m_op = op;
Phil Nash803f6b72012-10-04 08:14:48 +01004993 return *this;
4994 }
4995
Phil Nash67305122012-10-09 11:48:55 +01004996 ResultInfo ResultInfoBuilder::build() const
4997 {
4998 ResultData data = m_data;
4999 data.reconstructedExpression = reconstructExpression();
5000 if( m_isNot ) {
5001 if( m_op == "" ) {
5002 data.capturedExpression = "!" + data.capturedExpression;
5003 data.reconstructedExpression = "!" + data.reconstructedExpression;
5004 }
5005 else {
5006 data.capturedExpression = "!(" + data.capturedExpression + ")";
5007 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
5008 }
5009 }
5010 return ResultInfo( data );
Phil Nash3b80af72012-08-09 07:47:30 +01005011 }
5012
Phil Nash67305122012-10-09 11:48:55 +01005013 std::string ResultInfoBuilder::reconstructExpression() const {
5014 if( m_op == "" )
5015 return m_lhs.empty() ? m_data.capturedExpression : m_op + m_lhs;
5016 else if( m_op == "matches" )
5017 return m_lhs + " " + m_rhs;
5018 else if( m_op != "!" ) {
5019 if( m_lhs.size() + m_rhs.size() < 30 )
5020 return m_lhs + " " + m_op + " " + m_rhs;
5021 else if( m_lhs.size() < 70 && m_rhs.size() < 70 )
5022 return "\n\t" + m_lhs + "\n\t" + m_op + "\n\t" + m_rhs;
5023 else
5024 return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n";
5025 }
5026 else
5027 return "{can't expand - use " + m_data.macroName + "_FALSE( " + m_data.capturedExpression.substr(1) + " ) instead of " + m_data.macroName + "( " + m_data.capturedExpression + " ) for better diagnostics}";
Phil Nash3b80af72012-08-09 07:47:30 +01005028 }
5029
5030} // end namespace Catch
5031
Phil Nash5bc030d2012-08-16 18:48:50 +01005032// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005033#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01005034
5035namespace Catch {
5036
5037 TestCaseInfo::TestCaseInfo( ITestCase* testCase,
5038 const char* name,
5039 const char* description,
5040 const SourceLineInfo& lineInfo )
5041 : m_test( testCase ),
5042 m_name( name ),
5043 m_description( description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005044 m_lineInfo( lineInfo ),
5045 m_isHidden( startsWith( name, "./" ) )
5046 {
Phil Nash799ecf92012-09-24 08:30:13 +01005047 TagExtracter( m_tags ).parse( m_description );
Phil Nashfc1baac2012-09-15 17:53:27 +01005048 if( hasTag( "hide" ) )
5049 m_isHidden = true;
5050 }
Phil Nash5bc030d2012-08-16 18:48:50 +01005051
5052 TestCaseInfo::TestCaseInfo()
5053 : m_test( NULL ),
5054 m_name(),
Phil Nashfc1baac2012-09-15 17:53:27 +01005055 m_description(),
5056 m_isHidden( false )
Phil Nash5bc030d2012-08-16 18:48:50 +01005057 {}
5058
5059 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other, const std::string& name )
5060 : m_test( other.m_test ),
5061 m_name( name ),
5062 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005063 m_tags( other.m_tags ),
5064 m_lineInfo( other.m_lineInfo ),
5065 m_isHidden( other.m_isHidden )
Phil Nash5bc030d2012-08-16 18:48:50 +01005066 {}
5067
Phil Nashd2ec8492012-08-23 19:48:57 +01005068 TestCaseInfo::TestCaseInfo( const TestCaseInfo& other )
5069 : m_test( other.m_test ),
5070 m_name( other.m_name ),
5071 m_description( other.m_description ),
Phil Nashfc1baac2012-09-15 17:53:27 +01005072 m_tags( other.m_tags ),
5073 m_lineInfo( other.m_lineInfo ),
5074 m_isHidden( other.m_isHidden )
Phil Nashd2ec8492012-08-23 19:48:57 +01005075 {}
5076
Phil Nash5bc030d2012-08-16 18:48:50 +01005077 void TestCaseInfo::invoke() const {
5078 m_test->invoke();
5079 }
5080
5081 const std::string& TestCaseInfo::getName() const {
5082 return m_name;
5083 }
5084
5085 const std::string& TestCaseInfo::getDescription() const {
5086 return m_description;
5087 }
5088
5089 const SourceLineInfo& TestCaseInfo::getLineInfo() const {
5090 return m_lineInfo;
5091 }
5092
5093 bool TestCaseInfo::isHidden() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005094 return m_isHidden;
5095 }
5096
5097 bool TestCaseInfo::hasTag( const std::string& tag ) const {
5098 return m_tags.find( tag ) != m_tags.end();
5099 }
Phil Nash799ecf92012-09-24 08:30:13 +01005100 bool TestCaseInfo::matchesTags( const std::string& tagPattern ) const {
5101 TagExpression exp;
5102 TagExpressionParser( exp ).parse( tagPattern );
5103 return exp.matches( m_tags );
5104 }
Phil Nash67ec8702012-09-26 18:38:26 +01005105 const std::set<std::string>& TestCaseInfo::getTags() const {
Phil Nashfc1baac2012-09-15 17:53:27 +01005106 return m_tags;
Phil Nash5bc030d2012-08-16 18:48:50 +01005107 }
5108
5109 void TestCaseInfo::swap( TestCaseInfo& other ) {
5110 m_test.swap( other.m_test );
5111 m_name.swap( other.m_name );
5112 m_description.swap( other.m_description );
5113 m_lineInfo.swap( other.m_lineInfo );
5114 }
5115
5116 bool TestCaseInfo::operator == ( const TestCaseInfo& other ) const {
5117 return m_test.get() == other.m_test.get() && m_name == other.m_name;
5118 }
5119
5120 bool TestCaseInfo::operator < ( const TestCaseInfo& other ) const {
5121 return m_name < other.m_name;
5122 }
Phil Nashd2ec8492012-08-23 19:48:57 +01005123 TestCaseInfo& TestCaseInfo::operator = ( const TestCaseInfo& other ) {
5124 TestCaseInfo temp( other );
5125 swap( temp );
5126 return *this;
5127 }
Phil Nash799ecf92012-09-24 08:30:13 +01005128
5129} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01005130
Phil Nash56d5c422012-08-23 20:08:50 +01005131// #included from: ../reporters/catch_reporter_basic.hpp
5132#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
5133
5134// #included from: ../internal/catch_reporter_registrars.hpp
5135#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
5136
5137namespace Catch {
5138
5139 template<typename T>
5140 class ReporterRegistrar {
5141
5142 class ReporterFactory : public IReporterFactory {
5143
5144 virtual IReporter* create( const ReporterConfig& config ) const {
5145 return new T( config );
5146 }
5147
5148 virtual std::string getDescription() const {
5149 return T::getDescription();
5150 }
5151 };
5152
5153 public:
5154
5155 ReporterRegistrar( const std::string& name ) {
5156 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
5157 }
5158 };
5159}
5160
5161#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
5162 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
5163
5164namespace Catch {
5165
Phil Nash56d5c422012-08-23 20:08:50 +01005166 class BasicReporter : public SharedImpl<IReporter> {
5167
5168 struct SpanInfo {
5169
5170 SpanInfo()
5171 : emitted( false )
5172 {}
5173
5174 SpanInfo( const std::string& spanName )
5175 : name( spanName ),
5176 emitted( false )
5177 {}
5178
5179 SpanInfo( const SpanInfo& other )
5180 : name( other.name ),
5181 emitted( other.emitted )
5182 {}
5183
5184 std::string name;
5185 bool emitted;
5186 };
5187
5188 public:
5189 BasicReporter( const ReporterConfig& config )
5190 : m_config( config ),
5191 m_firstSectionInTestCase( true ),
5192 m_aborted( false )
5193 {}
5194
5195 virtual ~BasicReporter();
5196
5197 static std::string getDescription() {
5198 return "Reports test results as lines of text";
5199 }
5200
5201 private:
5202
5203 void ReportCounts( const std::string& label, const Counts& counts, const std::string& allPrefix = "All " ) {
5204 if( counts.passed )
5205 m_config.stream << counts.failed << " of " << counts.total() << " " << label << "s failed";
5206 else
5207 m_config.stream << ( counts.failed > 1 ? allPrefix : "" ) << pluralise( counts.failed, label ) << " failed";
5208 }
5209
5210 void ReportCounts( const Totals& totals, const std::string& allPrefix = "All " ) {
5211 if( totals.assertions.total() == 0 ) {
5212 m_config.stream << "No tests ran";
5213 }
5214 else if( totals.assertions.failed ) {
5215 TextColour colour( TextColour::ResultError );
5216 ReportCounts( "test case", totals.testCases, allPrefix );
5217 if( totals.testCases.failed > 0 ) {
5218 m_config.stream << " (";
5219 ReportCounts( "assertion", totals.assertions, allPrefix );
5220 m_config.stream << ")";
5221 }
5222 }
5223 else {
5224 TextColour colour( TextColour::ResultSuccess );
5225 m_config.stream << allPrefix << "tests passed ("
5226 << pluralise( totals.assertions.passed, "assertion" ) << " in "
5227 << pluralise( totals.testCases.passed, "test case" ) << ")";
5228 }
5229 }
5230
5231 private: // IReporter
5232
5233 virtual bool shouldRedirectStdout() const {
5234 return false;
5235 }
5236
5237 virtual void StartTesting() {
5238 m_testingSpan = SpanInfo();
5239 }
5240
5241 virtual void Aborted() {
5242 m_aborted = true;
5243 }
5244
5245 virtual void EndTesting( const Totals& totals ) {
5246 // Output the overall test results even if "Started Testing" was not emitted
5247 if( m_aborted ) {
5248 m_config.stream << "\n[Testing aborted. ";
5249 ReportCounts( totals, "The first " );
5250 }
5251 else {
5252 m_config.stream << "\n[Testing completed. ";
5253 ReportCounts( totals );
5254 }
5255 m_config.stream << "]\n" << std::endl;
5256 }
5257
5258 virtual void StartGroup( const std::string& groupName ) {
5259 m_groupSpan = groupName;
5260 }
5261
5262 virtual void EndGroup( const std::string& groupName, const Totals& totals ) {
5263 if( m_groupSpan.emitted && !groupName.empty() ) {
5264 m_config.stream << "[End of group: '" << groupName << "'. ";
5265 ReportCounts( totals );
5266 m_config.stream << "]\n" << std::endl;
5267 m_groupSpan = SpanInfo();
5268 }
5269 }
5270
5271 virtual void StartTestCase( const TestCaseInfo& testInfo ) {
5272 m_testSpan = testInfo.getName();
5273 }
5274
5275 virtual void StartSection( const std::string& sectionName, const std::string& ) {
5276 m_sectionSpans.push_back( SpanInfo( sectionName ) );
5277 }
5278
Phil Nasha70fbe32012-08-31 08:10:36 +01005279 virtual void NoAssertionsInSection( const std::string& sectionName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005280 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005281 TextColour colour( TextColour::ResultError );
5282 m_config.stream << "\nNo assertions in section, '" << sectionName << "'\n" << std::endl;
5283 }
5284 virtual void NoAssertionsInTestCase( const std::string& testName ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005285 startSpansLazily();
Phil Nasha70fbe32012-08-31 08:10:36 +01005286 TextColour colour( TextColour::ResultError );
5287 m_config.stream << "\nNo assertions in test case, '" << testName << "'\n" << std::endl;
5288 }
5289
Phil Nash56d5c422012-08-23 20:08:50 +01005290 virtual void EndSection( const std::string& sectionName, const Counts& assertions ) {
Phil Nasha70fbe32012-08-31 08:10:36 +01005291
Phil Nash56d5c422012-08-23 20:08:50 +01005292 SpanInfo& sectionSpan = m_sectionSpans.back();
5293 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
5294 m_config.stream << "[End of section: '" << sectionName << "' ";
5295
5296 if( assertions.failed ) {
5297 TextColour colour( TextColour::ResultError );
5298 ReportCounts( "assertion", assertions);
5299 }
5300 else {
5301 TextColour colour( TextColour::ResultSuccess );
5302 m_config.stream << ( assertions.passed > 1 ? "All " : "" )
5303 << pluralise( assertions.passed, "assertion" ) << " passed" ;
5304 }
5305 m_config.stream << "]\n" << std::endl;
5306 }
5307 m_sectionSpans.pop_back();
5308 }
5309
5310 virtual void Result( const ResultInfo& resultInfo ) {
5311 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
5312 return;
5313
Phil Nashe2d215e2012-09-07 17:52:35 +01005314 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005315
5316 if( !resultInfo.getFilename().empty() ) {
5317 TextColour colour( TextColour::FileName );
5318 m_config.stream << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
5319 }
5320
5321 if( resultInfo.hasExpression() ) {
5322 TextColour colour( TextColour::OriginalExpression );
5323 m_config.stream << resultInfo.getExpression();
5324 if( resultInfo.ok() ) {
5325 TextColour successColour( TextColour::Success );
5326 m_config.stream << " succeeded";
5327 }
5328 else {
5329 TextColour errorColour( TextColour::Error );
5330 m_config.stream << " failed";
5331 }
5332 }
5333 switch( resultInfo.getResultType() ) {
5334 case ResultWas::ThrewException:
5335 {
5336 TextColour colour( TextColour::Error );
5337 if( resultInfo.hasExpression() )
5338 m_config.stream << " with unexpected";
5339 else
5340 m_config.stream << "Unexpected";
5341 m_config.stream << " exception with message: '" << resultInfo.getMessage() << "'";
5342 }
5343 break;
5344 case ResultWas::DidntThrowException:
5345 {
5346 TextColour colour( TextColour::Error );
5347 if( resultInfo.hasExpression() )
5348 m_config.stream << " because no exception was thrown where one was expected";
5349 else
5350 m_config.stream << "No exception thrown where one was expected";
5351 }
5352 break;
5353 case ResultWas::Info:
5354 streamVariableLengthText( "info", resultInfo.getMessage() );
5355 break;
5356 case ResultWas::Warning:
5357 m_config.stream << "warning:\n'" << resultInfo.getMessage() << "'";
5358 break;
5359 case ResultWas::ExplicitFailure:
5360 {
5361 TextColour colour( TextColour::Error );
5362 m_config.stream << "failed with message: '" << resultInfo.getMessage() << "'";
5363 }
5364 break;
5365 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
5366 case ResultWas::Ok:
5367 case ResultWas::FailureBit:
5368 case ResultWas::ExpressionFailed:
5369 case ResultWas::Exception:
5370 if( !resultInfo.hasExpression() ) {
5371 if( resultInfo.ok() ) {
5372 TextColour colour( TextColour::Success );
5373 m_config.stream << " succeeded";
5374 }
5375 else {
5376 TextColour colour( TextColour::Error );
5377 m_config.stream << " failed";
5378 }
5379 }
5380 break;
5381 }
5382
5383 if( resultInfo.hasExpandedExpression() ) {
5384 m_config.stream << " for: ";
5385 TextColour colour( TextColour::ReconstructedExpression );
5386 m_config.stream << resultInfo.getExpandedExpression();
5387 }
5388 m_config.stream << std::endl;
5389 }
5390
5391 virtual void EndTestCase( const TestCaseInfo& testInfo,
5392 const Totals& totals,
5393 const std::string& stdOut,
5394 const std::string& stdErr ) {
5395 if( !stdOut.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005396 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005397 streamVariableLengthText( "stdout", stdOut );
5398 }
5399
5400 if( !stdErr.empty() ) {
Phil Nashe2d215e2012-09-07 17:52:35 +01005401 startSpansLazily();
Phil Nash56d5c422012-08-23 20:08:50 +01005402 streamVariableLengthText( "stderr", stdErr );
5403 }
5404
5405 if( m_testSpan.emitted ) {
5406 m_config.stream << "[Finished: '" << testInfo.getName() << "' ";
5407 ReportCounts( totals );
5408 m_config.stream << "]" << std::endl;
5409 }
5410 }
5411
5412 private: // helpers
5413
Phil Nashe2d215e2012-09-07 17:52:35 +01005414 void startSpansLazily() {
Phil Nash56d5c422012-08-23 20:08:50 +01005415 if( !m_testingSpan.emitted ) {
5416 if( m_config.name.empty() )
5417 m_config.stream << "[Started testing]" << std::endl;
5418 else
5419 m_config.stream << "[Started testing: " << m_config.name << "]" << std::endl;
5420 m_testingSpan.emitted = true;
5421 }
5422
5423 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
5424 m_config.stream << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
5425 m_groupSpan.emitted = true;
5426 }
5427
5428 if( !m_testSpan.emitted ) {
5429 m_config.stream << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
5430 m_testSpan.emitted = true;
5431 }
5432
5433 if( !m_sectionSpans.empty() ) {
5434 SpanInfo& sectionSpan = m_sectionSpans.back();
5435 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
5436 if( m_firstSectionInTestCase ) {
5437 m_config.stream << "\n";
5438 m_firstSectionInTestCase = false;
5439 }
5440 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
5441 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
5442 for(; it != itEnd; ++it ) {
5443 SpanInfo& prevSpan = *it;
5444 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
5445 m_config.stream << "[Started section: '" << prevSpan.name << "']" << std::endl;
5446 prevSpan.emitted = true;
5447 }
5448 }
5449 }
5450 }
5451 }
5452
5453 void streamVariableLengthText( const std::string& prefix, const std::string& text ) {
5454 std::string trimmed = trim( text );
5455 if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) {
5456 m_config.stream << "[" << prefix << ": " << trimmed << "]\n";
5457 }
5458 else {
5459 m_config.stream << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5460 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
5461 }
5462 }
5463
5464 private:
5465 ReporterConfig m_config;
5466 bool m_firstSectionInTestCase;
5467
5468 SpanInfo m_testingSpan;
5469 SpanInfo m_groupSpan;
5470 SpanInfo m_testSpan;
5471 std::vector<SpanInfo> m_sectionSpans;
5472 bool m_aborted;
5473 };
5474
5475} // end namespace Catch
5476
5477// #included from: ../reporters/catch_reporter_xml.hpp
5478#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
5479
5480// #included from: ../internal/catch_xmlwriter.hpp
5481#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
5482
5483#include <sstream>
Phil Nash9e7e63c2012-09-29 20:54:03 +01005484#include <iostream>
Phil Nash56d5c422012-08-23 20:08:50 +01005485#include <string>
5486#include <vector>
5487
5488namespace Catch {
5489
5490 class XmlWriter {
5491 public:
5492
5493 class ScopedElement {
5494 public:
5495 ScopedElement( XmlWriter* writer )
5496 : m_writer( writer )
5497 {}
5498
5499 ScopedElement( const ScopedElement& other )
5500 : m_writer( other.m_writer ){
5501 other.m_writer = NULL;
5502 }
5503
5504 ~ScopedElement() {
5505 if( m_writer )
5506 m_writer->endElement();
5507 }
5508
5509 ScopedElement& writeText( const std::string& text ) {
5510 m_writer->writeText( text );
5511 return *this;
5512 }
5513
5514 template<typename T>
5515 ScopedElement& writeAttribute( const std::string& name, const T& attribute ) {
5516 m_writer->writeAttribute( name, attribute );
5517 return *this;
5518 }
5519
5520 private:
5521 mutable XmlWriter* m_writer;
5522 };
5523
5524 XmlWriter()
5525 : m_tagIsOpen( false ),
5526 m_needsNewline( false ),
5527 m_os( &std::cout )
5528 {}
5529
5530 XmlWriter( std::ostream& os )
5531 : m_tagIsOpen( false ),
5532 m_needsNewline( false ),
5533 m_os( &os )
5534 {}
5535
5536 ~XmlWriter() {
5537 while( !m_tags.empty() )
5538 endElement();
5539 }
5540
5541 XmlWriter& operator = ( const XmlWriter& other ) {
5542 XmlWriter temp( other );
5543 swap( temp );
5544 return *this;
5545 }
5546
5547 void swap( XmlWriter& other ) {
5548 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5549 std::swap( m_needsNewline, other.m_needsNewline );
5550 std::swap( m_tags, other.m_tags );
5551 std::swap( m_indent, other.m_indent );
5552 std::swap( m_os, other.m_os );
5553 }
5554
5555 XmlWriter& startElement( const std::string& name ) {
5556 ensureTagClosed();
5557 newlineIfNecessary();
5558 stream() << m_indent << "<" << name;
5559 m_tags.push_back( name );
5560 m_indent += " ";
5561 m_tagIsOpen = true;
5562 return *this;
5563 }
5564
5565 ScopedElement scopedElement( const std::string& name ) {
5566 ScopedElement scoped( this );
5567 startElement( name );
5568 return scoped;
5569 }
5570
5571 XmlWriter& endElement() {
5572 newlineIfNecessary();
5573 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5574 if( m_tagIsOpen ) {
5575 stream() << "/>\n";
5576 m_tagIsOpen = false;
5577 }
5578 else {
5579 stream() << m_indent << "</" << m_tags.back() << ">\n";
5580 }
5581 m_tags.pop_back();
5582 return *this;
5583 }
5584
5585 XmlWriter& writeAttribute( const std::string& name, const std::string& attribute ) {
5586 if( !name.empty() && !attribute.empty() ) {
5587 stream() << " " << name << "=\"";
5588 writeEncodedText( attribute );
5589 stream() << "\"";
5590 }
5591 return *this;
5592 }
5593
5594 XmlWriter& writeAttribute( const std::string& name, bool attribute ) {
5595 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5596 return *this;
5597 }
5598
5599 template<typename T>
5600 XmlWriter& writeAttribute( const std::string& name, const T& attribute ) {
5601 if( !name.empty() )
5602 stream() << " " << name << "=\"" << attribute << "\"";
5603 return *this;
5604 }
5605
5606 XmlWriter& writeText( const std::string& text ) {
5607 if( !text.empty() ){
5608 bool tagWasOpen = m_tagIsOpen;
5609 ensureTagClosed();
5610 if( tagWasOpen )
5611 stream() << m_indent;
5612 writeEncodedText( text );
5613 m_needsNewline = true;
5614 }
5615 return *this;
5616 }
5617
5618 XmlWriter& writeComment( const std::string& text ) {
5619 ensureTagClosed();
5620 stream() << m_indent << "<!--" << text << "-->";
5621 m_needsNewline = true;
5622 return *this;
5623 }
5624
5625 XmlWriter& writeBlankLine() {
5626 ensureTagClosed();
5627 stream() << "\n";
5628 return *this;
5629 }
5630
5631 private:
5632
5633 std::ostream& stream() {
5634 return *m_os;
5635 }
5636
5637 void ensureTagClosed() {
5638 if( m_tagIsOpen ) {
5639 stream() << ">\n";
5640 m_tagIsOpen = false;
5641 }
5642 }
5643
5644 void newlineIfNecessary() {
5645 if( m_needsNewline ) {
5646 stream() << "\n";
5647 m_needsNewline = false;
5648 }
5649 }
5650
5651 void writeEncodedText( const std::string& text ) {
5652 static const char* charsToEncode = "<&\"";
5653 std::string mtext = text;
5654 std::string::size_type pos = mtext.find_first_of( charsToEncode );
5655 while( pos != std::string::npos ) {
5656 stream() << mtext.substr( 0, pos );
5657
5658 switch( mtext[pos] ) {
5659 case '<':
5660 stream() << "&lt;";
5661 break;
5662 case '&':
5663 stream() << "&amp;";
5664 break;
5665 case '\"':
5666 stream() << "&quot;";
5667 break;
5668 }
5669 mtext = mtext.substr( pos+1 );
5670 pos = mtext.find_first_of( charsToEncode );
5671 }
5672 stream() << mtext;
5673 }
5674
5675 bool m_tagIsOpen;
5676 bool m_needsNewline;
5677 std::vector<std::string> m_tags;
5678 std::string m_indent;
5679 std::ostream* m_os;
5680 };
5681
5682}
5683namespace Catch {
5684 class XmlReporter : public SharedImpl<IReporter> {
5685 public:
5686 XmlReporter( const ReporterConfig& config ) : m_config( config ) {}
5687
5688 static std::string getDescription() {
5689 return "Reports test results as an XML document";
5690 }
5691 virtual ~XmlReporter();
5692
5693 private: // IReporter
5694
5695 virtual bool shouldRedirectStdout() const {
5696 return true;
5697 }
5698
5699 virtual void StartTesting() {
5700 m_xml = XmlWriter( m_config.stream );
5701 m_xml.startElement( "Catch" );
5702 if( !m_config.name.empty() )
5703 m_xml.writeAttribute( "name", m_config.name );
5704 }
5705
5706 virtual void EndTesting( const Totals& totals ) {
5707 m_xml.scopedElement( "OverallResults" )
5708 .writeAttribute( "successes", totals.assertions.passed )
5709 .writeAttribute( "failures", totals.assertions.failed );
5710 m_xml.endElement();
5711 }
5712
5713 virtual void StartGroup( const std::string& groupName ) {
5714 m_xml.startElement( "Group" )
5715 .writeAttribute( "name", groupName );
5716 }
5717
5718 virtual void EndGroup( const std::string&, const Totals& totals ) {
5719 m_xml.scopedElement( "OverallResults" )
5720 .writeAttribute( "successes", totals.assertions.passed )
5721 .writeAttribute( "failures", totals.assertions.failed );
5722 m_xml.endElement();
5723 }
5724
5725 virtual void StartSection( const std::string& sectionName, const std::string& description ) {
5726 m_xml.startElement( "Section" )
5727 .writeAttribute( "name", sectionName )
5728 .writeAttribute( "description", description );
5729 }
Phil Nasha70fbe32012-08-31 08:10:36 +01005730 virtual void NoAssertionsInSection( const std::string& ) {}
5731 virtual void NoAssertionsInTestCase( const std::string& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01005732
5733 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) {
5734 m_xml.scopedElement( "OverallResults" )
5735 .writeAttribute( "successes", assertions.passed )
5736 .writeAttribute( "failures", assertions.failed );
5737 m_xml.endElement();
5738 }
5739
5740 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
5741 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
5742 m_currentTestSuccess = true;
5743 }
5744
5745 virtual void Result( const Catch::ResultInfo& resultInfo ) {
5746 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
5747 return;
5748
5749 if( resultInfo.hasExpression() ) {
5750 m_xml.startElement( "Expression" )
5751 .writeAttribute( "success", resultInfo.ok() )
5752 .writeAttribute( "filename", resultInfo.getFilename() )
5753 .writeAttribute( "line", resultInfo.getLine() );
5754
5755 m_xml.scopedElement( "Original" )
5756 .writeText( resultInfo.getExpression() );
5757 m_xml.scopedElement( "Expanded" )
5758 .writeText( resultInfo.getExpandedExpression() );
5759 m_currentTestSuccess &= resultInfo.ok();
5760 }
5761
5762 switch( resultInfo.getResultType() ) {
5763 case ResultWas::ThrewException:
5764 m_xml.scopedElement( "Exception" )
5765 .writeAttribute( "filename", resultInfo.getFilename() )
5766 .writeAttribute( "line", resultInfo.getLine() )
5767 .writeText( resultInfo.getMessage() );
5768 m_currentTestSuccess = false;
5769 break;
5770 case ResultWas::Info:
5771 m_xml.scopedElement( "Info" )
5772 .writeText( resultInfo.getMessage() );
5773 break;
5774 case ResultWas::Warning:
5775 m_xml.scopedElement( "Warning" )
5776 .writeText( resultInfo.getMessage() );
5777 break;
5778 case ResultWas::ExplicitFailure:
5779 m_xml.scopedElement( "Failure" )
5780 .writeText( resultInfo.getMessage() );
5781 m_currentTestSuccess = false;
5782 break;
5783 case ResultWas::Unknown:
5784 case ResultWas::Ok:
5785 case ResultWas::FailureBit:
5786 case ResultWas::ExpressionFailed:
5787 case ResultWas::Exception:
5788 case ResultWas::DidntThrowException:
5789 break;
5790 }
5791 if( resultInfo.hasExpression() )
5792 m_xml.endElement();
5793 }
5794
5795 virtual void Aborted() {
5796 // !TBD
5797 }
5798
5799 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) {
5800 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
5801 m_xml.endElement();
5802 }
5803
5804 private:
5805 ReporterConfig m_config;
5806 bool m_currentTestSuccess;
5807 XmlWriter m_xml;
5808 };
5809
5810} // end namespace Catch
5811
5812// #included from: ../reporters/catch_reporter_junit.hpp
5813#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
5814
5815namespace Catch {
5816
5817 class JunitReporter : public SharedImpl<IReporter> {
5818
5819 struct TestStats {
5820 std::string m_element;
5821 std::string m_resultType;
5822 std::string m_message;
5823 std::string m_content;
5824 };
5825
5826 struct TestCaseStats {
5827
5828 TestCaseStats( const std::string& name = std::string() ) :m_name( name ){}
5829
5830 double m_timeInSeconds;
5831 std::string m_status;
5832 std::string m_className;
5833 std::string m_name;
5834 std::vector<TestStats> m_testStats;
5835 };
5836
5837 struct Stats {
5838
5839 Stats( const std::string& name = std::string() )
5840 : m_testsCount( 0 ),
5841 m_failuresCount( 0 ),
5842 m_disabledCount( 0 ),
5843 m_errorsCount( 0 ),
5844 m_timeInSeconds( 0 ),
5845 m_name( name )
5846 {}
5847
5848 std::size_t m_testsCount;
5849 std::size_t m_failuresCount;
5850 std::size_t m_disabledCount;
5851 std::size_t m_errorsCount;
5852 double m_timeInSeconds;
5853 std::string m_name;
5854
5855 std::vector<TestCaseStats> m_testCaseStats;
5856 };
5857
5858 public:
5859 JunitReporter( const ReporterConfig& config )
5860 : m_config( config ),
5861 m_testSuiteStats( "AllTests" ),
5862 m_currentStats( &m_testSuiteStats )
5863 {}
5864 virtual ~JunitReporter();
5865
5866 static std::string getDescription() {
5867 return "Reports test results in an XML format that looks like Ant's junitreport target";
5868 }
5869
5870 private: // IReporter
5871
5872 virtual bool shouldRedirectStdout() const {
5873 return true;
5874 }
5875
5876 virtual void StartTesting(){}
5877
5878 virtual void StartGroup( const std::string& groupName ) {
5879 m_statsForSuites.push_back( Stats( groupName ) );
5880 m_currentStats = &m_statsForSuites.back();
5881 }
5882
5883 virtual void EndGroup( const std::string&, const Totals& totals ) {
5884 m_currentStats->m_testsCount = totals.assertions.total();
5885 m_currentStats = &m_testSuiteStats;
5886 }
5887
5888 virtual void StartSection( const std::string&, const std::string& ){}
5889
Phil Nasha70fbe32012-08-31 08:10:36 +01005890 virtual void NoAssertionsInSection( const std::string& ) {}
5891 virtual void NoAssertionsInTestCase( const std::string& ) {}
5892
5893 virtual void EndSection( const std::string&, const Counts& ) {}
Phil Nash56d5c422012-08-23 20:08:50 +01005894
5895 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) {
5896 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
5897 }
5898
5899 virtual void Result( const Catch::ResultInfo& resultInfo ) {
5900 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults ) {
5901 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
5902 TestStats stats;
5903 std::ostringstream oss;
5904 if( !resultInfo.getMessage().empty() )
5905 oss << resultInfo.getMessage() << " at ";
5906 oss << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
5907 stats.m_content = oss.str();
5908 stats.m_message = resultInfo.getExpandedExpression();
5909 stats.m_resultType = resultInfo.getTestMacroName();
5910
5911 switch( resultInfo.getResultType() ) {
5912 case ResultWas::ThrewException:
5913 stats.m_element = "error";
5914 m_currentStats->m_errorsCount++;
5915 break;
5916 case ResultWas::Info:
5917 stats.m_element = "info"; // !TBD ?
5918 break;
5919 case ResultWas::Warning:
5920 stats.m_element = "warning"; // !TBD ?
5921 break;
5922 case ResultWas::ExplicitFailure:
5923 stats.m_element = "failure";
5924 m_currentStats->m_failuresCount++;
5925 break;
5926 case ResultWas::ExpressionFailed:
5927 stats.m_element = "failure";
5928 m_currentStats->m_failuresCount++;
5929 break;
5930 case ResultWas::Ok:
5931 stats.m_element = "success";
5932 break;
5933 case ResultWas::Unknown:
5934 case ResultWas::FailureBit:
5935 case ResultWas::Exception:
5936 case ResultWas::DidntThrowException:
5937 break;
5938 }
5939 testCaseStats.m_testStats.push_back( stats );
5940 }
5941 }
5942
5943 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string& stdOut, const std::string& stdErr ) {
5944 if( !stdOut.empty() )
5945 m_stdOut << stdOut << "\n";
5946 if( !stdErr.empty() )
5947 m_stdErr << stdErr << "\n";
5948 }
5949
5950 virtual void Aborted() {
5951 // !TBD
5952 }
5953
5954 virtual void EndTesting( const Totals& ) {
5955 std::ostream& str = m_config.stream;
5956 {
5957 XmlWriter xml( str );
5958
5959 if( m_statsForSuites.size() > 0 )
5960 xml.startElement( "testsuites" );
5961
5962 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
5963 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
5964
5965 for(; it != itEnd; ++it ) {
5966 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
5967 xml.writeAttribute( "name", it->m_name );
5968 xml.writeAttribute( "errors", it->m_errorsCount );
5969 xml.writeAttribute( "failures", it->m_failuresCount );
5970 xml.writeAttribute( "tests", it->m_testsCount );
5971 xml.writeAttribute( "hostname", "tbd" );
5972 xml.writeAttribute( "time", "tbd" );
5973 xml.writeAttribute( "timestamp", "tbd" );
5974
5975 OutputTestCases( xml, *it );
5976 }
5977
5978 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
5979 xml.scopedElement( "system-err" ).writeText( trim( m_stdErr.str() ) );
5980 }
5981 }
5982
5983 void OutputTestCases( XmlWriter& xml, const Stats& stats ) {
5984 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
5985 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
5986 for(; it != itEnd; ++it ) {
5987 xml.writeBlankLine();
5988 xml.writeComment( "Test case" );
5989
5990 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
5991 xml.writeAttribute( "classname", it->m_className );
5992 xml.writeAttribute( "name", it->m_name );
5993 xml.writeAttribute( "time", "tbd" );
5994
5995 OutputTestResult( xml, *it );
5996 }
5997 }
5998
5999 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats ) {
6000 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
6001 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
6002 for(; it != itEnd; ++it ) {
6003 if( it->m_element != "success" ) {
6004 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
6005
6006 xml.writeAttribute( "message", it->m_message );
6007 xml.writeAttribute( "type", it->m_resultType );
6008 if( !it->m_content.empty() )
6009 xml.writeText( it->m_content );
6010 }
6011 }
6012 }
6013
6014 private:
6015 ReporterConfig m_config;
6016 bool m_currentTestSuccess;
6017
6018 Stats m_testSuiteStats;
6019 Stats* m_currentStats;
6020 std::vector<Stats> m_statsForSuites;
6021 std::ostringstream m_stdOut;
6022 std::ostringstream m_stdErr;
6023 };
6024
6025} // end namespace Catch
6026
Phil Nasha695eb92012-08-13 07:46:10 +01006027namespace Catch {
6028 NonCopyable::~NonCopyable() {}
6029 IShared::~IShared() {}
6030 StreamBufBase::~StreamBufBase() {}
6031 IContext::~IContext() {}
6032 IResultCapture::~IResultCapture() {}
6033 ITestCase::~ITestCase() {}
6034 ITestCaseRegistry::~ITestCaseRegistry() {}
6035 IRegistryHub::~IRegistryHub() {}
6036 IMutableRegistryHub::~IMutableRegistryHub() {}
6037 IExceptionTranslator::~IExceptionTranslator() {}
6038 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
6039 IReporter::~IReporter() {}
6040 IReporterFactory::~IReporterFactory() {}
6041 IReporterRegistry::~IReporterRegistry() {}
6042 BasicReporter::~BasicReporter() {}
6043 IRunner::~IRunner() {}
6044 IMutableContext::~IMutableContext() {}
6045 IConfig::~IConfig() {}
6046 XmlReporter::~XmlReporter() {}
6047 JunitReporter::~JunitReporter() {}
6048 TestRegistry::~TestRegistry() {}
6049 FreeFunctionTestCase::~FreeFunctionTestCase() {}
6050 IGeneratorInfo::~IGeneratorInfo() {}
6051 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash799ecf92012-09-24 08:30:13 +01006052 TagParser::~TagParser() {}
6053 TagExtracter::~TagExtracter() {}
6054 TagExpressionParser::~TagExpressionParser() {}
Phil Nasha695eb92012-08-13 07:46:10 +01006055
6056 void Config::dummy() {}
6057
Phil Nash56d5c422012-08-23 20:08:50 +01006058 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
6059 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
6060 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
6061
Phil Nasha695eb92012-08-13 07:46:10 +01006062}
6063
Phil Nash5bc030d2012-08-16 18:48:50 +01006064#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006065#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +01006066#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -04006067
Phil Nash5bc030d2012-08-16 18:48:50 +01006068#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006069
6070#ifdef CATCH_CONFIG_MAIN
6071// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01006072#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006073
Phil Nash176eb812012-05-11 08:17:16 +01006074#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +01006075
Phil Nash176eb812012-05-11 08:17:16 +01006076// Standard C/C++ main entry point
6077int main (int argc, char * const argv[]) {
6078 return Catch::Main( argc, argv );
6079}
6080
6081#else // __OBJC__
6082
6083// Objective-C entry point
6084int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +00006085#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006086 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +00006087#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006088
6089 Catch::registerTestMethods();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006090 int result = Catch::Main( argc, (char* const*)argv );
6091
Phil Nash53c990a2012-03-17 18:20:06 +00006092#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006093 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +00006094#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01006095
Phil Nashdd5b9c22012-02-18 09:58:30 +00006096 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006097}
6098
Phil Nash176eb812012-05-11 08:17:16 +01006099#endif // __OBJC__
6100
Phil Nash89d1e6c2011-05-24 08:23:02 +01006101#endif
6102
Phil Nash89d1e6c2011-05-24 08:23:02 +01006103//////
6104
Phil Nash46bcd4b2012-07-20 18:43:48 +01006105// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
6106#ifdef CATCH_CONFIG_PREFIX_ALL
6107
6108#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "CATCH_REQUIRE" )
6109#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "CATCH_REQUIRE_FALSE" )
6110
6111#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "CATCH_REQUIRE_THROWS" )
6112#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "CATCH_REQUIRE_THROWS_AS" )
6113#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "CATCH_REQUIRE_NOTHROW" )
6114
6115#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CATCH_CHECK" )
6116#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CATCH_CHECK_FALSE" )
6117#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CATCH_CHECKED_IF" )
6118#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CATCH_CHECKED_ELSE" )
6119
6120#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CATCH_CHECK_THROWS" )
6121#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CATCH_CHECK_THROWS_AS" )
6122#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CATCH_CHECK_NOTHROW" )
6123
6124#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CATCH_CHECK_THAT" )
6125#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "CATCH_REQUIRE_THAT" )
6126
6127#define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "CATCH_INFO" )
6128#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "CATCH_WARN" )
6129#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "CATCH_FAIL" )
Phil Nash74d1d312012-08-31 18:37:47 +01006130#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, false, "CATCH_SUCCEED" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006131#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
6132#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CATCH_CAPTURE" )
Phil Nash803f6b72012-10-04 08:14:48 +01006133#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006134
6135#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6136
6137#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6138#define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6139#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
6140#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
6141
6142#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
6143
6144#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6145
6146///////////////
6147// Still to be implemented
6148//#define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test
6149
6150// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
6151#else
6152
Phil Nash89d1e6c2011-05-24 08:23:02 +01006153#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
6154#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
6155
6156#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
6157#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
6158#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
6159
6160#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
6161#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
Phil Nasha162e222012-02-10 08:30:13 +00006162#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" )
6163#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006164
6165#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
6166#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
6167#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
6168
Phil Nash78d95a02012-03-04 21:22:36 +00006169#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CHECK_THAT" )
6170#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "REQUIRE_THAT" )
6171
Phil Nash89d1e6c2011-05-24 08:23:02 +01006172#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
6173#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
6174#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
Phil Nasha70fbe32012-08-31 08:10:36 +01006175#define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, false, "SUCCEED" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006176#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
6177#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
Phil Nash803f6b72012-10-04 08:14:48 +01006178#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006179
6180#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6181
6182#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6183#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6184#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
Phil Nash46bcd4b2012-07-20 18:43:48 +01006185#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006186
6187#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006188
6189#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6190
Phil Nash46bcd4b2012-07-20 18:43:48 +01006191#endif
6192
6193#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006194
6195using Catch::Detail::Approx;
6196
Phil Nash5bc030d2012-08-16 18:48:50 +01006197#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01006198#pragma clang diagnostic pop
Phil Nash5bc030d2012-08-16 18:48:50 +01006199#endif
Phil Nasha695eb92012-08-13 07:46:10 +01006200
Phil Nashaec1e5e2012-05-09 19:37:51 +01006201#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006202